Revert "Issue #619. 'new' operator misbehavior."

This reverts commit e7834de929.
This commit is contained in:
Jeremy Ashkenas 2010-08-21 19:16:02 -04:00
parent e7834de929
commit 117204a784
7 changed files with 20 additions and 59 deletions

View File

@ -43,7 +43,7 @@
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), { CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
fileName: 'Cakefile' fileName: 'Cakefile'
}); });
oparse = new (optparse.OptionParser)(switches); oparse = new optparse.OptionParser(switches);
if (!(args.length)) { if (!(args.length)) {
return printTasks(); return printTasks();
} }

View File

@ -219,7 +219,7 @@
}; };
parseOptions = function() { parseOptions = function() {
var o; var o;
optionParser = new (optparse.OptionParser)(SWITCHES, BANNER); optionParser = new optparse.OptionParser(SWITCHES, BANNER);
o = (opts = optionParser.parse(process.argv.slice(2, process.argv.length))); o = (opts = optionParser.parse(process.argv.slice(2, process.argv.length)));
o.compile || (o.compile = (!!o.output)); o.compile || (o.compile = (!!o.output));
o.run = !(o.compile || o.print || o.lint); o.run = !(o.compile || o.print || o.lint);

View File

@ -398,9 +398,9 @@
], ],
Loop: [ Loop: [
o("LOOP Block", function() { o("LOOP Block", function() {
return (new WhileNode(new LiteralNode('true'))).addBody($2); return new WhileNode(new LiteralNode('true')).addBody($2);
}), o("LOOP Expression", function() { }), o("LOOP Expression", function() {
return (new WhileNode(new LiteralNode('true'))).addBody(Expressions.wrap([$2])); return new WhileNode(new LiteralNode('true')).addBody(Expressions.wrap([$2]));
}) })
], ],
For: [ For: [

View File

@ -481,7 +481,7 @@
})()); })());
}; };
CallNode.prototype.compileNode = function(o) { CallNode.prototype.compileNode = function(o) {
var _b, _c, _d, _e, _f, _g, _h, arg, args, compilation, value; var _b, _c, _d, _e, _f, _g, _h, arg, args, compilation;
if (!(o.chainRoot)) { if (!(o.chainRoot)) {
o.chainRoot = this; o.chainRoot = this;
} }
@ -504,17 +504,7 @@
} }
return _e; return _e;
}).call(this); }).call(this);
compilation = (function() { compilation = this.isSuper ? this.compileSuper(args.join(', '), o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + (args.join(', ')) + ")");
if (this.isSuper) {
return this.compileSuper(args.join(', '), o);
} else {
value = this.variable.compile(o);
if (this.isNew && this.variable instanceof ValueNode && this.variable.hasProperties()) {
value = ("(" + (value) + ")");
}
return "" + (this.prefix()) + (value) + "(" + (args.join(', ')) + ")";
}
}).call(this);
} }
return compilation; return compilation;
}; };
@ -886,7 +876,7 @@
})) + ';'; })) + ';';
props = !props.empty() ? '\n' + props.compile(o) : ''; props = !props.empty() ? '\n' + props.compile(o) : '';
extension = extension ? '\n' + this.idt() + extension.compile(o) + ';' : ''; extension = extension ? '\n' + this.idt() + extension.compile(o) + ';' : '';
returns = this.returns ? '\n' + (new ReturnNode(this.variable)).compile(o) : ''; returns = this.returns ? '\n' + new ReturnNode(this.variable).compile(o) : '';
return construct + extension + props + returns; return construct + extension + props + returns;
}; };
return ClassNode; return ClassNode;
@ -990,7 +980,7 @@
} }
val = new ValueNode(literal(valVar), [new accessClass(idx)]); val = new ValueNode(literal(valVar), [new accessClass(idx)]);
} }
assigns.push((new AssignNode(obj, val)).compile(o)); assigns.push(new AssignNode(obj, val).compile(o));
} }
code = assigns.join("\n"); code = assigns.join("\n");
return code; return code;
@ -1254,7 +1244,7 @@
this.body = Expressions.wrap([new IfNode(this.guard, this.body)]); this.body = Expressions.wrap([new IfNode(this.guard, this.body)]);
} }
if (this.returns) { if (this.returns) {
post = '\n' + (new ReturnNode(literal(rvar))).compile(merge(o, { post = '\n' + new ReturnNode(literal(rvar)).compile(merge(o, {
indent: this.idt() indent: this.idt()
})); }));
} else { } else {
@ -1591,7 +1581,7 @@
}; };
ForNode.prototype.compileReturnValue = function(val, o) { ForNode.prototype.compileReturnValue = function(val, o) {
if (this.returns) { if (this.returns) {
return '\n' + (new ReturnNode(literal(val))).compile(o); return '\n' + new ReturnNode(literal(val)).compile(o);
} }
if (val) { if (val) {
return '\n' + val; return '\n' + val;
@ -1640,7 +1630,7 @@
svar = scope.freeVariable(); svar = scope.freeVariable();
sourcePart = ("" + (svar) + " = " + (this.source.compile(o)) + ";"); sourcePart = ("" + (svar) + " = " + (this.source.compile(o)) + ";");
if (this.pattern) { if (this.pattern) {
namePart = (new AssignNode(this.name, literal("" + (svar) + "[" + (ivar) + "]"))).compile(merge(o, { namePart = new AssignNode(this.name, literal("" + (svar) + "[" + (ivar) + "]")).compile(merge(o, {
indent: this.idt(1), indent: this.idt(1),
top: true top: true
})) + '\n'; })) + '\n';

View File

@ -429,8 +429,8 @@ grammar =
] ]
Loop: [ Loop: [
o "LOOP Block", -> (new WhileNode(new LiteralNode 'true')).addBody $2 o "LOOP Block", -> new WhileNode(new LiteralNode 'true').addBody $2
o "LOOP Expression", -> (new WhileNode(new LiteralNode 'true')).addBody Expressions.wrap [$2] o "LOOP Expression", -> new WhileNode(new LiteralNode 'true').addBody Expressions.wrap [$2]
] ]
# Array, object, and range comprehensions, at the most generic level. # Array, object, and range comprehensions, at the most generic level.

View File

@ -449,9 +449,7 @@ exports.CallNode = class CallNode extends BaseNode
compilation = if @isSuper compilation = if @isSuper
@compileSuper(args.join(', '), o) @compileSuper(args.join(', '), o)
else else
value = @variable.compile o "#{@prefix()}#{@variable.compile(o)}(#{ args.join(', ') })"
value = "(#{value})" if @isNew and @variable instanceof ValueNode and @variable.hasProperties()
"#{@prefix()}#{value}(#{ args.join(', ') })"
compilation compilation
# `super()` is converted into a call against the superclass's implementation # `super()` is converted into a call against the superclass's implementation
@ -762,7 +760,7 @@ exports.ClassNode = class ClassNode extends BaseNode
construct = @idt() + (new AssignNode(@variable, constructor)).compile(merge o, {sharedScope: constScope}) + ';' construct = @idt() + (new AssignNode(@variable, constructor)).compile(merge o, {sharedScope: constScope}) + ';'
props = if !props.empty() then '\n' + props.compile(o) else '' props = if !props.empty() then '\n' + props.compile(o) else ''
extension = if extension then '\n' + @idt() + extension.compile(o) + ';' else '' extension = if extension then '\n' + @idt() + extension.compile(o) + ';' else ''
returns = if @returns then '\n' + (new ReturnNode(@variable)).compile(o) else '' returns = if @returns then '\n' + new ReturnNode(@variable).compile(o) else ''
construct + extension + props + returns construct + extension + props + returns
#### AssignNode #### AssignNode
@ -852,7 +850,7 @@ exports.AssignNode = class AssignNode extends BaseNode
else else
idx = literal(if splat then "#{valVar}.length - #{olength - idx}" else idx) if typeof idx isnt 'object' idx = literal(if splat then "#{valVar}.length - #{olength - idx}" else idx) if typeof idx isnt 'object'
val = new ValueNode(literal(valVar), [new accessClass(idx)]) val = new ValueNode(literal(valVar), [new accessClass(idx)])
assigns.push((new AssignNode(obj, val)).compile(o)) assigns.push(new AssignNode(obj, val).compile(o))
code = assigns.join("\n") code = assigns.join("\n")
code code
@ -1070,7 +1068,7 @@ exports.WhileNode = class WhileNode extends BaseNode
pre = "#{set}#{@tab}while (#{cond})" pre = "#{set}#{@tab}while (#{cond})"
@body = Expressions.wrap([new IfNode(@guard, @body)]) if @guard @body = Expressions.wrap([new IfNode(@guard, @body)]) if @guard
if @returns if @returns
post = '\n' + (new ReturnNode(literal(rvar))).compile merge o, indent: @idt() post = '\n' + new ReturnNode(literal(rvar)).compile(merge(o, indent: @idt()))
else else
post = '' post = ''
"#{pre} {\n#{ @body.compile(o) }\n#{@tab}}#{post}" "#{pre} {\n#{ @body.compile(o) }\n#{@tab}}#{post}"
@ -1344,7 +1342,7 @@ exports.ForNode = class ForNode extends BaseNode
this this
compileReturnValue: (val, o) -> compileReturnValue: (val, o) ->
return '\n' + (new ReturnNode(literal(val))).compile(o) if @returns return '\n' + new ReturnNode(literal(val)).compile(o) if @returns
return '\n' + val if val return '\n' + val if val
'' ''
@ -1374,7 +1372,7 @@ exports.ForNode = class ForNode extends BaseNode
svar = scope.freeVariable() svar = scope.freeVariable()
sourcePart = "#{svar} = #{ @source.compile(o) };" sourcePart = "#{svar} = #{ @source.compile(o) };"
if @pattern if @pattern
namePart = (new AssignNode(@name, literal("#{svar}[#{ivar}]"))).compile(merge o, {indent: @idt(1), top: true}) + '\n' namePart = new AssignNode(@name, literal("#{svar}[#{ivar}]")).compile(merge o, {indent: @idt(1), top: true}) + '\n'
else else
namePart = "#{name} = #{svar}[#{ivar}]" if name namePart = "#{name} = #{svar}[#{ivar}]" if name
unless @object unless @object

View File

@ -234,31 +234,4 @@ obj =
method: -> 'value' method: -> 'value'
instance = new obj.klass instance = new obj.klass
ok instance.method() is 'value' ok instance.method() is 'value'
# Ensure that nested classes are safely wrapped in parentheses when instantiated
# to avoid JS problems with operator precedence:
class1 = ->
@name = 'class1'
this
class1.class2 = ->
@name = 'class2'
this
factory = (arg) ->
return { class2: class1.class2 }
obj1 = new class1
obj2_1 = new class1.class2
obj2_2 = new factory('dummy').class2
obj2_3 = new (factory('dummy')).class2
obj2_4 = new (factory('dummy').class2)
ok obj1.name is 'class1'
ok obj2_1.name is 'class2'
ok obj2_2.name is 'class2'
ok obj2_3.name is 'class2'
ok obj2_4.name is 'class2'
ok obj2_2.class2 is undefined