Skip to content

Instantly share code, notes, and snippets.

@geraldalewis
Created May 11, 2011 13:21
Show Gist options
  • Save geraldalewis/966438 to your computer and use it in GitHub Desktop.
Save geraldalewis/966438 to your computer and use it in GitHub Desktop.
Production notes for issue #1216 and pull #1348

#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 the o options object instead.
  • When an If compiles into a statement, I check if o.isExistentialEquals.
  • If it is:
    • I create a new If object on the fly
    • with the Existence @condition prop inverted
    • and with the elseBodyNode in place of the current body
    • I then use that new If object's compilation output as the output of compileStatement

##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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment