#Issue #1216 with pull
#1348#
##Issue##
As @satyr pointed out, the #1216 patch (pull #1348) broke some ?=
:
a = 1; console.log a ?= 2
would output
var a;
a = 1;
console.log(a == null ? a = 2 : void 0);
instead of
var a;
a = 1;
console.log(a == null ? a = 2 : a);
##Solution##
CoffeeScript will compile If
objects into either a statement (if(a){b} else{c}
) or an expression (a = b ? c : d
) depending on whether either bodies need to be a statement. My patch failed to test for this functionality.
This actually helped me frame the problem better:
if we're creating a ?= Assignment
AND if the resulting If object is a statement (NOT an expression)
invert the condition (a != null -> a == null)
take the alternative and use it as the consequent (make the else the body)
remove the else body
- I reverted the
Op.compileExistence
method body to the previously working version - I removed the @isExistentialEquals property on
Op
, making it a property on theo
options object instead. - When an
If
compiles into astatement
, I check ifo.isExistentialEquals
. - If it is:
- I create a new
If
object on the fly - with the
Existence
@condition
propinverted
- and with the
elseBodyNode
in place of the currentbody
- I then use that new
If
object's compilation output as the output ofcompileStatement
- I create a new
##Watch for## With the following expression:
a ?= b ?= 1
a ?=
will compile into a for
statement, but the b ?=
will compile into a ternary expression.
if (typeof a === "undefined" || a === null) {
a = typeof b !== "undefined" && b !== null ? b : b = 1;
};
Might not play well with If
's compile methods that can compile the if
into a statement
or expression
?
##Tests##
bin/coffee -be 'a = 1; a ?= b ?= 2; console.log a'
should = 1
was as of 6c9ef76
var a;
a = 1;
if (a != null) {
a;
} else {
a = typeof b !== "undefined" && b !== null ? b : b = 2;
};
alert(a);
now
var a;
a = 1;
if (a == null) {
a = typeof b !== "undefined" && b !== null ? b : b = 2;
};
console.log(a);
bin/coffee -be 'a ?= b ?= 1; console.log a'
should = 1
was as of 6c9ef76
if (typeof a !== "undefined" && a !== null) {
a;
} else {
a = typeof b !== "undefined" && b !== null ? b : b = 1;
};
console.log(a);
now
if (typeof a === "undefined" || a === null) {
a = typeof b !== "undefined" && b !== null ? b : b = 1;
};
bin/coffee -be 'c = 2; a = 1; a ?= b ?= c ?= 1; console.log a'
should = 1
was as of 6c9ef76
var a, c;
c = 2;
a = 1;
if (a != null) {
a;
} else {
a = typeof b !== "undefined" && b !== null ? b : b = c != null ? c : c = 1;
};
console.log(a);
now
var a, c;
c = 2;
a = 1;
if (a == null) {
a = typeof b !== "undefined" && b !== null ? b : b = c != null ? c : c = 1;
};
bin/coffee -be 'c = 2; a ?= b ?= c ?= 1; console.log a'
should = 2
was as of 6c9ef76
var c;
c = 2;
if (typeof a !== "undefined" && a !== null) {
a;
} else {
a = typeof b !== "undefined" && b !== null ? b : b = c != null ? c : c = 1;
};
console.log(a)
now
var c;
c = 2;
if (typeof a === "undefined" || a === null) {
a = typeof b !== "undefined" && b !== null ? b : b = c != null ? c : c = 1;
};
console.log(a);
bin/coffee -be 'a = 1;if a then a ?= 2; console.log a'
should = 1
was as of 6c9ef76
var a;
a = 1;
if (a) {
if (a != null) {
a;
} else {
a = 2;
};
alert(a);
}
now
var a;
a = 1;
if (a) {
if (a == null) {
a = 2;
};
console.log(a);
}