From 1018c513595fc64a96d619251544590da949c524 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Sun, 18 Dec 2011 20:00:09 -0500 Subject: [PATCH] Fixes #494: Forcing named classes in CoffeeScript (named functions) ... even in IE. --- lib/coffee-script/lexer.js | 2 +- lib/coffee-script/nodes.js | 61 ++++++++++++++++++++++++++++++++++- lib/coffee-script/optparse.js | 2 +- lib/coffee-script/rewriter.js | 2 +- lib/coffee-script/scope.js | 2 +- src/nodes.coffee | 1 + test/classes.coffee | 12 ++++++- 7 files changed, 76 insertions(+), 6 deletions(-) diff --git a/lib/coffee-script/lexer.js b/lib/coffee-script/lexer.js index 1dd3b046..0af3cc05 100644 --- a/lib/coffee-script/lexer.js +++ b/lib/coffee-script/lexer.js @@ -7,7 +7,7 @@ _ref2 = require('./helpers'), count = _ref2.count, starts = _ref2.starts, compact = _ref2.compact, last = _ref2.last; exports.Lexer = Lexer = (function() { - + Lexer.name = 'Lexer'; function Lexer() {} Lexer.prototype.tokenize = function(code, opts) { diff --git a/lib/coffee-script/nodes.js b/lib/coffee-script/nodes.js index 151da284..7c2b96d4 100644 --- a/lib/coffee-script/nodes.js +++ b/lib/coffee-script/nodes.js @@ -30,7 +30,7 @@ }; exports.Base = Base = (function() { - + Base.name = 'Base'; function Base() {} Base.prototype.compile = function(o, lvl) { @@ -191,6 +191,8 @@ __extends(Block, _super); + Block.name = 'Block'; + function Block(nodes) { this.expressions = compact(flatten(nodes || [])); } @@ -385,6 +387,8 @@ __extends(Literal, _super); + Literal.name = 'Literal'; + function Literal(value) { this.value = value; } @@ -441,6 +445,8 @@ __extends(Return, _super); + Return.name = 'Return'; + function Return(expr) { if (expr && !expr.unwrap().isUndefined) this.expression = expr; } @@ -475,6 +481,8 @@ __extends(Value, _super); + Value.name = 'Value'; + function Value(base, props, tag) { if (!props && base instanceof Value) return base; this.base = base; @@ -623,6 +631,8 @@ __extends(Comment, _super); + Comment.name = 'Comment'; + function Comment(comment) { this.comment = comment; } @@ -646,6 +656,8 @@ __extends(Call, _super); + Call.name = 'Call'; + function Call(variable, args, soak) { this.args = args != null ? args : []; this.soak = soak; @@ -815,6 +827,8 @@ __extends(Extends, _super); + Extends.name = 'Extends'; + function Extends(child, parent) { this.child = child; this.parent = parent; @@ -834,6 +848,8 @@ __extends(Access, _super); + Access.name = 'Access'; + function Access(name, tag) { this.name = name; this.name.asKey = true; @@ -862,6 +878,8 @@ __extends(Index, _super); + Index.name = 'Index'; + function Index(index) { this.index = index; } @@ -884,6 +902,8 @@ __extends(Range, _super); + Range.name = 'Range'; + Range.prototype.children = ['from', 'to']; function Range(from, to, tag) { @@ -963,6 +983,8 @@ __extends(Slice, _super); + Slice.name = 'Slice'; + Slice.prototype.children = ['range']; function Slice(range) { @@ -989,6 +1011,8 @@ __extends(Obj, _super); + Obj.name = 'Obj'; + function Obj(props, generated) { this.generated = generated != null ? generated : false; this.objects = this.properties = props || []; @@ -1055,6 +1079,8 @@ __extends(Arr, _super); + Arr.name = 'Arr'; + function Arr(objs) { this.objects = objs || []; } @@ -1103,6 +1129,8 @@ __extends(Class, _super); + Class.name = 'Class'; + function Class(variable, parent, body) { this.variable = variable; this.parent = parent; @@ -1235,6 +1263,9 @@ this.ensureConstructor(name); this.body.spaced = true; if (!(this.ctor instanceof Code)) this.body.expressions.unshift(this.ctor); + if (decl) { + this.body.expressions.unshift(new Literal("" + name + ".name = '" + name + "'")); + } this.body.expressions.push(lname); this.addBoundFunctions(o); call = Closure.wrap(this.body); @@ -1257,6 +1288,8 @@ __extends(Assign, _super); + Assign.name = 'Assign'; + function Assign(variable, value, context, options) { this.variable = variable; this.value = value; @@ -1455,6 +1488,8 @@ __extends(Code, _super); + Code.name = 'Code'; + function Code(params, body, tag) { this.params = params || []; this.body = body || new Block; @@ -1567,6 +1602,8 @@ __extends(Param, _super); + Param.name = 'Param'; + function Param(name, value, splat) { this.name = name; this.value = value; @@ -1606,6 +1643,8 @@ __extends(Splat, _super); + Splat.name = 'Splat'; + Splat.prototype.children = ['name']; Splat.prototype.isAssignable = YES; @@ -1672,6 +1711,8 @@ __extends(While, _super); + While.name = 'While'; + function While(condition, options) { this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition; this.guard = options != null ? options.guard : void 0; @@ -1745,6 +1786,8 @@ __extends(Op, _super); + Op.name = 'Op'; + function Op(op, first, second, flip) { var call; if (op === 'in') return new In(first, second); @@ -1896,6 +1939,8 @@ __extends(In, _super); + In.name = 'In'; + function In(object, array) { this.object = object; this.array = array; @@ -1968,6 +2013,8 @@ __extends(Try, _super); + Try.name = 'Try'; + function Try(attempt, error, recovery, ensure) { this.attempt = attempt; this.error = error; @@ -2008,6 +2055,8 @@ __extends(Throw, _super); + Throw.name = 'Throw'; + function Throw(expression) { this.expression = expression; } @@ -2032,6 +2081,8 @@ __extends(Existence, _super); + Existence.name = 'Existence'; + function Existence(expression) { this.expression = expression; } @@ -2065,6 +2116,8 @@ __extends(Parens, _super); + Parens.name = 'Parens'; + function Parens(body) { this.body = body; } @@ -2103,6 +2156,8 @@ __extends(For, _super); + For.name = 'For'; + function For(body, source) { var _ref2; this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index; @@ -2236,6 +2291,8 @@ __extends(Switch, _super); + Switch.name = 'Switch'; + function Switch(subject, cases, otherwise) { this.subject = subject; this.cases = cases; @@ -2311,6 +2368,8 @@ __extends(If, _super); + If.name = 'If'; + function If(condition, body, options) { this.body = body; if (options == null) options = {}; diff --git a/lib/coffee-script/optparse.js b/lib/coffee-script/optparse.js index 5e0114c9..a73f7e7c 100644 --- a/lib/coffee-script/optparse.js +++ b/lib/coffee-script/optparse.js @@ -2,7 +2,7 @@ var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments; exports.OptionParser = OptionParser = (function() { - + OptionParser.name = 'OptionParser'; function OptionParser(rules, banner) { this.banner = banner; this.rules = buildRules(rules); diff --git a/lib/coffee-script/rewriter.js b/lib/coffee-script/rewriter.js index d3da4dd1..4f977d5a 100644 --- a/lib/coffee-script/rewriter.js +++ b/lib/coffee-script/rewriter.js @@ -4,7 +4,7 @@ __slice = Array.prototype.slice; exports.Rewriter = (function() { - + Rewriter.name = 'Rewriter'; function Rewriter() {} Rewriter.prototype.rewrite = function(tokens) { diff --git a/lib/coffee-script/scope.js b/lib/coffee-script/scope.js index 2162853b..11440c0e 100644 --- a/lib/coffee-script/scope.js +++ b/lib/coffee-script/scope.js @@ -4,7 +4,7 @@ _ref = require('./helpers'), extend = _ref.extend, last = _ref.last; exports.Scope = Scope = (function() { - + Scope.name = 'Scope'; Scope.root = null; function Scope(parent, expressions, method) { diff --git a/src/nodes.coffee b/src/nodes.coffee index 1a35eee3..4f569d69 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -928,6 +928,7 @@ exports.Class = class Class extends Base @ensureConstructor name @body.spaced = yes @body.expressions.unshift @ctor unless @ctor instanceof Code + @body.expressions.unshift new Literal "#{name}.name = '#{name}'" if decl @body.expressions.push lname @addBoundFunctions o diff --git a/test/classes.coffee b/test/classes.coffee index 3a315866..23a7ea00 100644 --- a/test/classes.coffee +++ b/test/classes.coffee @@ -593,4 +593,14 @@ test "#1813: Passing class definitions as expressions", -> x = 1 eq result, B - \ No newline at end of file + +test "#494: Named classes", -> + + class A + eq A.name, 'A' + + class A.B + eq A.B.name, 'B' + + class A.B["C"] + ok A.B.C.name isnt 'C'