mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
182 lines
5.8 KiB
CoffeeScript
182 lines
5.8 KiB
CoffeeScript
# Strict Early Errors
|
||
# -------------------
|
||
|
||
# The following are prohibited under ES5’s `strict` mode
|
||
# * `Octal Integer Literals`
|
||
# * `Octal Escape Sequences`
|
||
# * duplicate property definitions in `Object Literal`s
|
||
# * duplicate formal parameter
|
||
# * `delete` operand is a variable
|
||
# * `delete` operand is a parameter
|
||
# * `delete` operand is `undefined`
|
||
# * `Future Reserved Word`s as identifiers: implements, interface, let, package, private, protected, public, static, yield
|
||
# * `eval` or `arguments` as `catch` identifier
|
||
# * `eval` or `arguments` as formal parameter
|
||
# * `eval` or `arguments` as function declaration identifier
|
||
# * `eval` or `arguments` as LHS of assignment
|
||
# * `eval` or `arguments` as the operand of a post/pre-fix inc/dec-rement expression
|
||
|
||
# helper to assert that code complies with strict prohibitions
|
||
strict = (code, msg) ->
|
||
throws (-> CoffeeScript.compile code), null, msg ? code
|
||
strictOk = (code, msg) ->
|
||
doesNotThrow (-> CoffeeScript.compile code), msg ? code
|
||
|
||
|
||
test "octal integer literals prohibited", ->
|
||
strict '01'
|
||
strict '07777'
|
||
# decimals with a leading '0' are also prohibited
|
||
strict '09'
|
||
strict '079'
|
||
strictOk '`01`'
|
||
|
||
test "octal escape sequences prohibited", ->
|
||
strict '"\\1"'
|
||
strict '"\\7"'
|
||
strict '"\\001"'
|
||
strict '"\\777"'
|
||
strict '"_\\1"'
|
||
strict '"\\1_"'
|
||
strict '"_\\1_"'
|
||
strict '"\\\\\\1"'
|
||
strictOk '"\\0"'
|
||
eq "\x00", "\0"
|
||
strictOk '"\\08"'
|
||
eq "\x008", "\08"
|
||
strictOk '"\\0\\8"'
|
||
eq "\x008", "\0\8"
|
||
strictOk '"\\8"'
|
||
eq "8", "\8"
|
||
strictOk '"\\\\1"'
|
||
eq "\\" + "1", "\\1"
|
||
strictOk '"\\\\\\\\1"'
|
||
eq "\\\\" + "1", "\\\\1"
|
||
strictOk "`'\\1'`"
|
||
eq "\\" + "1", `"\\1"`
|
||
|
||
# Also test other string types.
|
||
strict "'\\\\\\1'"
|
||
eq "\x008", '\08'
|
||
eq "\\\\" + "1", '\\\\1'
|
||
strict "'''\\\\\\1'''"
|
||
eq "\x008", '''\08'''
|
||
eq "\\\\" + "1", '''\\\\1'''
|
||
strict '"""\\\\\\1"""'
|
||
eq "\x008", """\08"""
|
||
eq "\\\\" + "1", """\\\\1"""
|
||
|
||
test "duplicate formal parameters are prohibited", ->
|
||
nonce = {}
|
||
# a Param can be an Identifier, ThisProperty( @-param ), Array, or Object
|
||
# a Param can also be a splat (...) or an assignment (param=value)
|
||
# the following function expressions should throw errors
|
||
strict '(_,_)->', 'param, param'
|
||
strict '(_,_...)->', 'param, param...'
|
||
strict '(_,_ = true)->', 'param, param='
|
||
strict '(@_,@_)->', 'two @params'
|
||
strict '(@case,@case)->', 'two @reserved'
|
||
strict '(_,{_})->', 'param, {param}'
|
||
strict '(_,{_=true})->', 'param, {param=}'
|
||
strict '({_,_})->', '{param, param}'
|
||
strict '({_=true,_})->', '{param=, param}'
|
||
strict '(_,[_])->', 'param, [param]'
|
||
strict '(_,[_=true])->', 'param, [param=]'
|
||
strict '([_,_])->', '[param, param]'
|
||
strict '([_=true,_])->', '[param=, param]'
|
||
strict '(_,[_]=true)->', 'param, [param]='
|
||
strict '(_,[_=true]=true)->', 'param, [param=]='
|
||
strict '(_,[@_,{_}])->', 'param, [@param, {param}]'
|
||
strict '(_,[_,{@_}])->', 'param, [param, {@param}]'
|
||
strict '(_,[_,{@_=true}])->', 'param, [param, {@param=}]'
|
||
strict '(_,[_,{_}])->', 'param, [param, {param}]'
|
||
strict '(_,[_,{__}])->', 'param, [param, {param2}]'
|
||
strict '(_,[__,{_}])->', 'param, [param2, {param}]'
|
||
strict '(__,[_,{_}])->', 'param, [param2, {param2}]'
|
||
strict '({0:a,1:a})->', '{0:param,1:param}'
|
||
strict '(a=b=true,a)->', 'param=assignment, param'
|
||
strict '({a=b=true},a)->', '{param=assignment}, param'
|
||
# the following function expressions should **not** throw errors
|
||
strictOk '(_,@_)->'
|
||
strictOk '(@_,_...)->'
|
||
strictOk '(_,@_ = true)->'
|
||
strictOk '(@_,{_})->'
|
||
strictOk '({_,@_})->'
|
||
strictOk '({_,@_ = true})->'
|
||
strictOk '([_,@_])->'
|
||
strictOk '([_,@_ = true])->'
|
||
strictOk '({},_arg)->'
|
||
strictOk '({},{})->'
|
||
strictOk '([]...,_arg)->'
|
||
strictOk '({}...,_arg)->'
|
||
strictOk '({}...,[],_arg)->'
|
||
strictOk '([]...,{},_arg)->'
|
||
strictOk '(@case,_case)->'
|
||
strictOk '(@case,_case...)->'
|
||
strictOk '(@case...,_case)->'
|
||
strictOk '(_case,@case)->'
|
||
strictOk '(_case,@case...)->'
|
||
strictOk '({a:a})->'
|
||
strictOk '({a:a,a:b})->'
|
||
|
||
test "`delete` operand restrictions", ->
|
||
strict 'a = 1; delete a'
|
||
strictOk 'delete a' #noop
|
||
strict '(a) -> delete a'
|
||
strict '(a...) -> delete a'
|
||
strict '(a = 1) -> delete a'
|
||
strict '([a]) -> delete a'
|
||
strict '({a}) -> delete a'
|
||
|
||
test "`Future Reserved Word`s, `eval` and `arguments` restrictions", ->
|
||
|
||
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}"
|
||
destruct = (keyword, check = strict) ->
|
||
check "{#{keyword}}"
|
||
check "o = {#{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'.split ' '
|
||
for keyword in future
|
||
access keyword
|
||
assign keyword
|
||
destruct keyword
|
||
invoke keyword
|
||
fnDecl keyword
|
||
param keyword
|
||
prop keyword, strictOk
|
||
tryCatch keyword
|
||
|
||
for keyword in ['eval', 'arguments']
|
||
access keyword, strictOk
|
||
assign keyword
|
||
destruct keyword, strictOk
|
||
invoke keyword, strictOk
|
||
fnDecl keyword
|
||
param keyword
|
||
prop keyword, strictOk
|
||
tryCatch keyword
|