Issue #1547 'use strict' eval and arguments use restricted

This commit is contained in:
Gerald Lewis 2012-01-09 13:02:15 -05:00
parent 0b7cfba94a
commit 8b179fb391
3 changed files with 62 additions and 33 deletions

View File

@ -106,7 +106,7 @@ exports.Lexer = class Lexer
@tokens.pop()
id = '!' + id
if id in ['eval', 'arguments'].concat JS_FORBIDDEN
if id in JS_FORBIDDEN
if forcedIdentifier
tag = 'IDENTIFIER'
id = new String id
@ -576,11 +576,14 @@ RESERVED = [
'private', 'protected', 'public', 'static', 'yield'
]
STRICT_PROSCRIBED = ['arguments', 'eval']
# The superset of both JavaScript keywords and reserved words, none of which may
# be used as identifiers or properties.
JS_FORBIDDEN = JS_KEYWORDS.concat RESERVED
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS)
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED)
exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED
# Token matching regexes.
IDENTIFIER = /// ^

View File

@ -4,7 +4,7 @@
# the syntax tree into a string of JavaScript code, call `compile()` on the root.
{Scope} = require './scope'
{RESERVED} = require './lexer'
{RESERVED, STRICT_PROSCRIBED} = require './lexer'
# Import the helpers we plan to use.
{compact, flatten, extend, merge, del, starts, ends, last} = require './helpers'
@ -329,7 +329,7 @@ exports.Literal = class Literal extends Base
if o.level >= LEVEL_ACCESS then '(void 0)' else 'void 0'
else if @value is 'this'
if o.scope.method?.bound then o.scope.method.context else @value
else if @value.reserved and "#{@value}" not in ['eval', 'arguments']
else if @value.reserved
"\"#{@value}\""
else
@value
@ -862,6 +862,8 @@ exports.Class = class Class extends Base
tail instanceof Access and tail.name.value
else
@variable.base.value
if decl in STRICT_PROSCRIBED
throw SyntaxError 'variable name may not be eval or arguments'
decl and= IDENTIFIER.test(decl) and decl
# For all `this`-references and bound functions in the class definition,
@ -990,6 +992,8 @@ exports.Assign = class Assign extends Base
constructor: (@variable, @value, @context, options) ->
@param = options and options.param
@subpattern = options and options.subpattern
if @variable.unwrapAll().value in STRICT_PROSCRIBED
throw SyntaxError 'variable name may not be "eval" or "arguments"'
children: ['variable', 'value']
@ -1055,7 +1059,7 @@ exports.Assign = class Assign extends Base
acc = IDENTIFIER.test idx.unwrap().value or 0
value = new Value value
value.properties.push new (if acc then Access else Index) idx
if obj.unwrap().value in ['arguments','eval'].concat RESERVED
if obj.unwrap().value in RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{value.compile o}"
return new Assign(obj, value, null, param: @param).compile o, LEVEL_TOP
vvar = value.compile o, LEVEL_LIST
@ -1100,7 +1104,7 @@ exports.Assign = class Assign extends Base
else
acc = isObject and IDENTIFIER.test idx.unwrap().value or 0
val = new Value new Literal(vvar), [new (if acc then Access else Index) idx]
if name? and name in ['arguments','eval'].concat RESERVED
if name? and name in RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{val.compile o}"
assigns.push new Assign(obj, val, null, param: @param, subpattern: yes).compile o, LEVEL_LIST
assigns.push vvar unless top or @subpattern
@ -1224,6 +1228,8 @@ exports.Code = class Code extends Base
# as well as be a splat, gathering up a group of parameters into an array.
exports.Param = class Param extends Base
constructor: (@name, @value, @splat) ->
if @name.unwrapAll().value in STRICT_PROSCRIBED
throw SyntaxError 'parameter name eval or arguments is not allowed'
children: ['name', 'value']
@ -1575,6 +1581,8 @@ exports.Try = class Try extends Base
tryPart = @attempt.compile o, LEVEL_TOP
catchPart = if @recovery
if @error.value in STRICT_PROSCRIBED
throw SyntaxError "catch variable may not be eval or arguments"
o.scope.add @error.value, 'param' unless o.scope.check @error.value
" catch#{errorPart}{\n#{ @recovery.compile o, LEVEL_TOP }\n#{@tab}}"
else unless @ensure or @recovery

View File

@ -100,32 +100,50 @@ test "`delete` operand restrictions", ->
strict '([a]) -> delete a'
strict '({a}) -> delete a'
test "`Future Reserved Word`s as identifiers prohibited", ->
futures = 'implements interface let package private protected public static yield'.split ' '
for keyword in futures
strict "#{keyword} = 1"
strict "class #{keyword}"
strict "try new Error catch #{keyword}"
strict "(#{keyword}) ->"
strict "{keyword}++"
strict "++{keyword}"
strict "{keyword}--"
strict "--{keyword}"
test "`Future Reserved Word`s, `eval` and `arguments` restrictions", ->
test "`eval` and `arguments` use restricted", ->
proscribeds = 'eval arguments'.split ' '
for proscribed in proscribeds
strict "#{proscribed} = 1"
strict "class #{proscribed}"
strict "try new Error catch #{proscribed}"
strict "(#{proscribed}) ->"
strict "{proscribed}++"
strict "++{proscribed}"
strict "{proscribed}--"
strict "--{proscribed}"
strictOk "eval 'true'"
strictOk "-> arguments[0]"
access = (keyword, check = strict) ->
check "#{keyword}.a = 1"
check "#{keyword}[0] = 1"
assign = (keyword, check = strict) ->
check "#{keyword} = 1"
check "#{keyword} += 1"
check "#{keyword} -= 1"
check "#{keyword} *= 1"
check "#{keyword} /= 1"
check "#{keyword} ?= 1"
check "{keyword}++"
check "++{keyword}"
check "{keyword}--"
check "--{keyword}"
invoke = (keyword, check = strict) ->
check "#{keyword} yes"
check "do #{keyword}"
fnDecl = (keyword, check = strict) ->
check "class #{keyword}"
param = (keyword, check = strict) ->
check "(#{keyword}) ->"
check "({#{keyword}}) ->"
prop = (keyword, check = strict) ->
check "a.#{keyword} = 1"
tryCatch = (keyword, check = strict) ->
check "try new Error catch #{keyword}"
future = 'implements interface let package private protected public static yield'.split ' '
for keyword in future
access keyword
assign keyword
invoke keyword
fnDecl keyword
param keyword
prop keyword, strictOk
tryCatch keyword
for keyword in ['eval', 'arguments']
access keyword, strictOk
assign keyword
invoke keyword, strictOk
fnDecl keyword
param keyword
prop keyword, strictOk
tryCatch keyword