Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelficarra committed Jan 16, 2012
2 parents b6310d0 + e207c98 commit 6e1e77d
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 4 deletions.
18 changes: 17 additions & 1 deletion lib/coffee-script/nodes.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions src/nodes.coffee
Expand Up @@ -386,6 +386,7 @@ exports.Value = class Value extends Base
isComplex : -> @hasProperties() or @base.isComplex()
isAssignable : -> @hasProperties() or @base.isAssignable()
isSimpleNumber : -> @base instanceof Literal and SIMPLENUM.test @base.value
isString : -> @base instanceof Literal and IS_STRING.test @base.value
isAtomic : ->
for node in @properties.concat @base
return no if node.soak or node instanceof Call
Expand Down Expand Up @@ -916,6 +917,16 @@ exports.Class = class Class extends Base
exps[i] = @addProperties node, name, o
child.expressions = exps = flatten exps

# `use strict` (and other directives) must be the first expression statement(s)
# of a function body. This method ensures the prologue is correctly positioned
# above the `constructor`.
hoistDirectivePrologue: ->
index = 0
{expressions} = @body
++index while (node = expressions[index]) and node instanceof Comment or
node instanceof Value and node.isString()
@directives = expressions.splice 0, index

# Make sure that a constructor is defined for the class, and properly
# configured.
ensureConstructor: (name) ->
Expand All @@ -938,6 +949,7 @@ exports.Class = class Class extends Base
name = "_#{name}" if name.reserved
lname = new Literal name

@hoistDirectivePrologue()
@setContext name
@walkBody name, o
@ensureConstructor name
Expand All @@ -946,6 +958,7 @@ exports.Class = class Class extends Base
if decl
@body.expressions.unshift new Assign (new Value (new Literal name), [new Access new Literal 'name']), (new Literal "'#{name}'")
@body.expressions.push lname
@body.expressions.unshift @directives...
@addBoundFunctions o

call = Closure.wrap @body
Expand Down
66 changes: 63 additions & 3 deletions test/classes.coffee
Expand Up @@ -612,10 +612,70 @@ test "#1966: external constructors should produce their return value", ->
ok (new A) not instanceof A

test "#1980: regression with an inherited class with static function members", ->

class A

class B extends A
@static: => 'value'

eq B.static(), 'value'

eq B.static(), 'value'

test "#1534: class then 'use strict'", ->
# [14.1 Directive Prologues and the Use Strict Directive](http://es5.github.com/#x14.1)
nonce = {}
error = 'do -> ok this'
strictTest = "do ->'use strict';#{error}"
return unless (try CoffeeScript.run strictTest, bare: yes catch e then nonce) is nonce

throws -> CoffeeScript.run "class then 'use strict';#{error}", bare: yes
doesNotThrow -> CoffeeScript.run "class then #{error}", bare: yes
doesNotThrow -> CoffeeScript.run "class then #{error};'use strict'", bare: yes

# comments are ignored in the Directive Prologue
comments = ["""
class
### comment ###
'use strict'
#{error}""",
"""
class
### comment 1 ###
### comment 2 ###
'use strict'
#{error}""",
"""
class
### comment 1 ###
### comment 2 ###
'use strict'
#{error}
### comment 3 ###"""
]
throws (-> CoffeeScript.run comment, bare: yes) for comment in comments

# [ES5 §14.1](http://es5.github.com/#x14.1) allows for other directives
directives = ["""
class
'directive 1'
'use strict'
#{error}""",
"""
class
'use strict'
'directive 2'
#{error}""",
"""
class
### comment 1 ###
'directive 1'
'use strict'
#{error}""",
"""
class
### comment 1 ###
'directive 1'
### comment 2 ###
'use strict'
#{error}"""
]
throws (-> CoffeeScript.run directive, bare: yes) for directive in directives

0 comments on commit 6e1e77d

Please sign in to comment.