test reorganization waypoint 3
This commit is contained in:
parent
fb201976b8
commit
dcbe62b9b9
|
@ -1,26 +0,0 @@
|
|||
# Ensure that carriage returns don't break compilation on Windows.
|
||||
eq CoffeeScript.compile('one\r\ntwo', bare: on), 'one;\ntwo;'
|
||||
|
||||
# `globals: on` removes `var`s
|
||||
eq CoffeeScript.compile('x = y', bare: on, globals: on), 'x = y;'
|
||||
|
||||
ok 'passed' is CoffeeScript.eval '"passed"', bare: on, fileName: 'test'
|
||||
|
||||
#750
|
||||
try ok not CoffeeScript.nodes 'f(->'
|
||||
catch e then eq e.message, 'unclosed CALL_START on line 1'
|
||||
|
||||
eq CoffeeScript.compile('for k of o then', bare: on, globals: on),
|
||||
'for (k in o) {}'
|
||||
|
||||
# Compilations that should fail.
|
||||
cantCompile = (code) ->
|
||||
throws -> CoffeeScript.compile code
|
||||
|
||||
cantCompile 'a = (break)'
|
||||
|
||||
cantCompile 'a = (return 5 for item in list)'
|
||||
|
||||
cantCompile 'a = (return 5 while condition)'
|
||||
|
||||
cantCompile 'a = for x in y\n return 5'
|
|
@ -1,192 +0,0 @@
|
|||
|
||||
okFunc = (f) -> ok(f())
|
||||
okFunc -> true
|
||||
|
||||
|
||||
|
||||
# Ensure that functions with the same name don't clash with helper functions.
|
||||
del = -> 5
|
||||
ok del() is 5
|
||||
|
||||
|
||||
# Test for inline functions with parentheses and implicit calls.
|
||||
combine = (func, num) -> func() * num
|
||||
result = combine (-> 1 + 2), 3
|
||||
|
||||
ok result is 9
|
||||
|
||||
|
||||
# Test for calls/parens/multiline-chains.
|
||||
f = (x) -> x
|
||||
result = (f 1).toString()
|
||||
.length
|
||||
|
||||
ok result is 1
|
||||
|
||||
|
||||
# Test implicit calls in functions in parens:
|
||||
result = ((val) ->
|
||||
[].push val
|
||||
val
|
||||
)(10)
|
||||
|
||||
ok result is 10
|
||||
|
||||
|
||||
# More paren compilation tests:
|
||||
reverse = (obj) -> obj.reverse()
|
||||
ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
|
||||
|
||||
|
||||
|
||||
# This is a crazy one.
|
||||
x = (obj, func) -> func obj
|
||||
ident = (x) -> x
|
||||
result = x {one: ident 1}, (obj) ->
|
||||
inner = ident(obj)
|
||||
ident inner
|
||||
ok result.one is 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Ensure that constructors invoked with splats return a new object.
|
||||
args = [1, 2, 3]
|
||||
Type = (@args) ->
|
||||
type = new Type args
|
||||
|
||||
ok type and type instanceof Type
|
||||
ok type.args and type.args instanceof Array
|
||||
ok v is args[i] for v, i in type.args
|
||||
|
||||
Type1 = (@a, @b, @c) ->
|
||||
type1 = new Type1 args...
|
||||
|
||||
ok type1 instanceof Type1
|
||||
eq type1.constructor, Type1
|
||||
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
|
||||
|
||||
|
||||
# Ensure that constructors invoked with splats cache the function.
|
||||
called = 0
|
||||
get = -> if called++ then false else class Type
|
||||
new get() args...
|
||||
|
||||
|
||||
# Chained blocks, with proper indentation levels:
|
||||
counter =
|
||||
results: []
|
||||
tick: (func) ->
|
||||
@results.push func()
|
||||
this
|
||||
counter
|
||||
.tick ->
|
||||
3
|
||||
.tick ->
|
||||
2
|
||||
.tick ->
|
||||
1
|
||||
eq counter.results.join(' '), '3 2 1'
|
||||
|
||||
|
||||
|
||||
# Ensure that chained calls with indented implicit object literals below are
|
||||
# alright.
|
||||
result = null
|
||||
obj =
|
||||
method: (val) -> this
|
||||
second: (hash) -> result = hash.three
|
||||
|
||||
|
||||
obj
|
||||
.method(
|
||||
101
|
||||
).second(
|
||||
one:
|
||||
two: 2
|
||||
three: 3
|
||||
)
|
||||
|
||||
eq result, 3
|
||||
|
||||
|
||||
# Test newline-supressed call chains with nested functions.
|
||||
obj =
|
||||
call: -> this
|
||||
func = ->
|
||||
obj
|
||||
.call ->
|
||||
one two
|
||||
.call ->
|
||||
three four
|
||||
101
|
||||
|
||||
eq func(), 101
|
||||
|
||||
|
||||
# `new` shouldn't add extra parens
|
||||
ok new Date().constructor is Date
|
||||
|
||||
|
||||
# `new` works against bare function
|
||||
eq Date, new ->
|
||||
eq this, new => this
|
||||
Date
|
||||
|
||||
|
||||
# Implicit objects with number arguments.
|
||||
func = (x, y) -> y
|
||||
obj =
|
||||
prop: func "a", 1
|
||||
|
||||
ok obj.prop is 1
|
||||
|
||||
|
||||
# Non-spaced unary and binary operators should cause a function call.
|
||||
func = (val) -> val + 1
|
||||
ok (func +5) is 6
|
||||
ok (func -5) is -4
|
||||
|
||||
|
||||
# Prefix unary assignment operators are allowed in parenless calls.
|
||||
val = 5
|
||||
ok (func --val) is 5
|
||||
|
||||
|
||||
eq ok, new ->
|
||||
ok
|
||||
### Should `return` implicitly ###
|
||||
### even with trailing comments. ###
|
||||
|
||||
|
||||
#855: execution context for `func arr...` should be `null`
|
||||
(->
|
||||
global = @
|
||||
contextTest = -> ok global is @
|
||||
array = []
|
||||
contextTest array
|
||||
contextTest.apply null, array
|
||||
contextTest array...
|
||||
)()
|
||||
|
||||
|
||||
# #894: Splatting against constructor-chained functions.
|
||||
x = null
|
||||
|
||||
class Foo
|
||||
bar: (y) -> x = y
|
||||
|
||||
new Foo().bar([101]...)
|
||||
|
||||
eq x, 101
|
||||
|
||||
|
||||
test "#904: Destructuring function arguments with same-named variables in scope", ->
|
||||
a = b = nonce = {}
|
||||
fn = ([a,b]) -> {a:a,b:b}
|
||||
result = fn([c={},d={}])
|
||||
eq c, result.a
|
||||
eq d, result.b
|
||||
eq nonce, a
|
||||
eq nonce, b
|
|
@ -1,141 +1,9 @@
|
|||
a = [((x) -> x), ((x) -> x * x)]
|
||||
|
||||
ok a.length is 2
|
||||
|
||||
|
||||
neg = (3 -4)
|
||||
|
||||
ok neg is -1
|
||||
|
||||
|
||||
# Decimal number literals.
|
||||
value = .25 + .75
|
||||
ok value is 1
|
||||
value = 0.0 + -.25 - -.75 + 0.0
|
||||
ok value is 0.5
|
||||
|
||||
|
||||
# Can call methods directly on numbers.
|
||||
4.valueOf() is 4
|
||||
|
||||
|
||||
func = ->
|
||||
return if true
|
||||
|
||||
ok func() is undefined
|
||||
|
||||
|
||||
trailingComma = [1, 2, 3,]
|
||||
ok (trailingComma[0] is 1) and (trailingComma[2] is 3) and (trailingComma.length is 3)
|
||||
|
||||
trailingComma = [
|
||||
1, 2, 3,
|
||||
4, 5, 6
|
||||
7, 8, 9,
|
||||
]
|
||||
(sum = (sum or 0) + n) for n in trailingComma
|
||||
|
||||
trailingComma = {k1: "v1", k2: 4, k3: (-> true),}
|
||||
ok trailingComma.k3() and (trailingComma.k2 is 4) and (trailingComma.k1 is "v1")
|
||||
|
||||
|
||||
ok {a: (num) -> num is 10 }.a 10
|
||||
|
||||
|
||||
moe = {
|
||||
name: 'Moe'
|
||||
greet: (salutation) ->
|
||||
salutation + " " + @name
|
||||
hello: ->
|
||||
@['greet'] "Hello"
|
||||
10: 'number'
|
||||
}
|
||||
|
||||
ok moe.hello() is "Hello Moe"
|
||||
ok moe[10] is 'number'
|
||||
|
||||
moe.hello = ->
|
||||
this['greet'] "Hello"
|
||||
|
||||
ok moe.hello() is 'Hello Moe'
|
||||
|
||||
|
||||
obj = {
|
||||
is: -> yes,
|
||||
'not': -> no,
|
||||
}
|
||||
|
||||
ok obj.is()
|
||||
ok not obj.not()
|
||||
|
||||
|
||||
### Top-level object literal... ###
|
||||
obj: 1
|
||||
### ...doesn't break things. ###
|
||||
|
||||
# Funky indentation within non-comma-seperated arrays.
|
||||
result = [['a']
|
||||
{b: 'c'}]
|
||||
|
||||
ok result[0][0] is 'a'
|
||||
ok result[1]['b'] is 'c'
|
||||
|
||||
|
||||
# Object literals should be able to include keywords.
|
||||
obj = {class: 'höt'}
|
||||
obj.function = 'dog'
|
||||
|
||||
ok obj.class + obj.function is 'hötdog'
|
||||
|
||||
|
||||
# But keyword assignment should be smart enough not to stringify variables.
|
||||
func = ->
|
||||
this == 'this'
|
||||
|
||||
ok func() is false
|
||||
|
||||
|
||||
# New fancy implicit objects:
|
||||
config =
|
||||
development:
|
||||
server: 'localhost'
|
||||
timeout: 10
|
||||
|
||||
production:
|
||||
server: 'dreamboat'
|
||||
timeout: 1000
|
||||
|
||||
ok config.development.server is 'localhost'
|
||||
ok config.production.server is 'dreamboat'
|
||||
ok config.development.timeout is 10
|
||||
ok config.production.timeout is 1000
|
||||
|
||||
third = (a, b, c) -> c
|
||||
obj =
|
||||
a: 1
|
||||
b: 2
|
||||
|
||||
ok obj.a is 1
|
||||
ok obj.b is 2
|
||||
|
||||
obj =
|
||||
a: 1,
|
||||
b: 2,
|
||||
|
||||
ok obj.a is 1
|
||||
ok obj.b is 2
|
||||
|
||||
|
||||
# Implicit objects nesting.
|
||||
obj =
|
||||
options:
|
||||
value: yes
|
||||
|
||||
fn: ->
|
||||
{}
|
||||
null
|
||||
|
||||
ok obj.options.value is yes
|
||||
ok obj.fn() is null
|
||||
one: 'one'
|
||||
two: third 'one', 'two', 'three'
|
||||
ok obj.one is 'one'
|
||||
ok obj.two is 'three'
|
||||
|
||||
|
||||
# Implicit arguments to function calls:
|
||||
|
@ -144,28 +12,17 @@ func2 = -> arguments
|
|||
|
||||
result = func
|
||||
a: 10
|
||||
|
||||
ok result is 10
|
||||
|
||||
result = func
|
||||
"a": 20
|
||||
|
||||
ok result is 20
|
||||
|
||||
third = (a, b, c) -> c
|
||||
obj =
|
||||
one: 'one'
|
||||
two: third 'one', 'two', 'three'
|
||||
|
||||
ok obj.one is 'one'
|
||||
ok obj.two is 'three'
|
||||
|
||||
a = b = undefined
|
||||
|
||||
result = func
|
||||
b:1
|
||||
a
|
||||
|
||||
ok result is undefined
|
||||
|
||||
result = func
|
||||
|
@ -178,40 +35,9 @@ result = func2
|
|||
a:1
|
||||
b
|
||||
c:1
|
||||
|
||||
ok result.length is 3
|
||||
ok result[2].c is 1
|
||||
|
||||
# Implicit objects with wacky indentation:
|
||||
obj =
|
||||
'reverse': (obj) ->
|
||||
Array.prototype.reverse.call obj
|
||||
abc: ->
|
||||
@reverse(
|
||||
@reverse @reverse ['a', 'b', 'c'].reverse()
|
||||
)
|
||||
one: [1, 2,
|
||||
a: 'b'
|
||||
3, 4]
|
||||
red:
|
||||
orange:
|
||||
yellow:
|
||||
green: 'blue'
|
||||
indigo: 'violet'
|
||||
misdent: [[],
|
||||
[],
|
||||
[],
|
||||
[]]
|
||||
|
||||
ok obj.abc().join(' ') is 'a b c'
|
||||
ok obj.one.length is 5
|
||||
ok obj.one[4] is 4
|
||||
ok obj.one[2].a is 'b'
|
||||
ok (key for key of obj.red).length is 2
|
||||
ok obj.red.orange.yellow.green is 'blue'
|
||||
ok obj.red.indigo is 'violet'
|
||||
ok obj.misdent.toString() is ',,,'
|
||||
|
||||
second = (x, y) -> y
|
||||
obj = then second 'the',
|
||||
1: 1
|
||||
|
@ -220,55 +46,5 @@ obj = then second 'the',
|
|||
four five,
|
||||
six: seven
|
||||
three: 3
|
||||
|
||||
ok obj[1] is 1
|
||||
ok obj.three is 3
|
||||
|
||||
|
||||
# Implicit objects as part of chained calls.
|
||||
pluck = (x) -> x.a
|
||||
eq 100, pluck pluck pluck a: a: a: 100
|
||||
|
||||
|
||||
eq '\\`', `
|
||||
// Inline JS
|
||||
"\\\`"
|
||||
`
|
||||
|
||||
|
||||
# Shorthand objects with property references.
|
||||
obj =
|
||||
### comment one ###
|
||||
### comment two ###
|
||||
one: 1
|
||||
two: 2
|
||||
object: -> {@one, @two}
|
||||
list: -> [@one, @two]
|
||||
|
||||
|
||||
result = obj.object()
|
||||
eq result.one, 1
|
||||
eq result.two, 2
|
||||
eq result.two, obj.list()[1]
|
||||
|
||||
|
||||
#542: Objects leading expression statement should be parenthesized.
|
||||
{f: -> ok yes }.f() + 1
|
||||
|
||||
|
||||
#764: Boolean/Number should be indexable.
|
||||
ok 42['toString']
|
||||
ok on['toString']
|
||||
|
||||
|
||||
# String-keyed objects shouldn't suppress newlines.
|
||||
one =
|
||||
'>!': 3
|
||||
six: -> 10
|
||||
|
||||
ok not one.six
|
||||
|
||||
|
||||
# Issue #986: Unicode identifiers.
|
||||
λ = 5
|
||||
eq λ, 5
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
# Splats
|
||||
# ------
|
||||
# note: splats in parameter lists of function definitions are tested in `arguments.coffee`
|
||||
|
||||
# shared identity function
|
||||
id = (_) -> if arguments.length is 1 then _ else Array::slice.call(arguments)
|
||||
|
||||
test "passing splats to functions", ->
|
||||
arrayEq [0..4], id id [0..4]...
|
||||
|
||||
fn = (a, b, c..., d) -> [a, b, c, d]
|
||||
[first, second, others, last] = fn [0..3]..., 4, [5...8]...
|
||||
eq 0, first
|
||||
eq 1, second
|
||||
arrayEq [2..6], others
|
||||
eq 7, last
|
||||
|
||||
|
||||
obj =
|
||||
name: 'moe'
|
||||
accessor: (args...) ->
|
||||
[@name].concat(args).join(' ')
|
||||
getNames: ->
|
||||
args = ['jane', 'ted']
|
||||
@accessor(args...)
|
||||
index: 0
|
||||
0: {method: -> this is obj[0]}
|
||||
|
||||
ok obj.getNames() is 'moe jane ted'
|
||||
ok obj[obj.index++].method([]...), 'should cache base value'
|
||||
|
||||
#crowd = [
|
||||
# contenders...
|
||||
# "Mighty Mouse"
|
||||
#]
|
||||
#
|
||||
#bests = [
|
||||
# "Mighty Mouse"
|
||||
# contenders.slice(0, 4)...
|
||||
#]
|
||||
#
|
||||
#ok crowd[0] is contenders[0]
|
||||
#ok crowd[10] is "Mighty Mouse"
|
||||
#
|
||||
#ok bests[1] is contenders[0]
|
||||
#ok bests[4] is contenders[3]
|
||||
|
||||
|
||||
# Finally, splats with super() within classes.
|
||||
|
||||
class Parent
|
||||
meth: (args...) ->
|
||||
args
|
||||
|
||||
class Child extends Parent
|
||||
meth: ->
|
||||
nums = [3, 2, 1]
|
||||
super nums...
|
||||
|
||||
ok (new Child).meth().join(' ') is '3 2 1'
|
||||
|
||||
|
||||
# Functions with splats being called with too few arguments.
|
||||
pen = null
|
||||
method = (first, variable..., penultimate, ultimate) ->
|
||||
pen = penultimate
|
||||
|
||||
method 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||
ok pen is 8
|
||||
|
||||
method 1, 2, 3
|
||||
ok pen is 2
|
||||
|
||||
method 1, 2
|
||||
ok pen is 2
|
||||
|
||||
|
||||
# Array splat expansions with assigns.
|
||||
nums = [1, 2, 3]
|
||||
list = [a = 0, nums..., b = 4]
|
||||
ok a is 0
|
||||
ok b is 4
|
||||
ok list.join(' ') is '0 1 2 3 4'
|
||||
|
||||
|
||||
# Splat on a line by itself is invalid.
|
||||
failed = true
|
||||
try
|
||||
CoffeeScript.compile "x 'a'\n...\n"
|
||||
failed = false
|
||||
catch err
|
||||
ok failed
|
||||
|
||||
|
||||
# multiple generated references
|
||||
(->
|
||||
a = {b: []}
|
||||
a.b[true] = -> this == a.b
|
||||
c = 0
|
||||
d = []
|
||||
ok a.b[0<++c<2] d...
|
||||
)()
|
|
@ -3,3 +3,34 @@
|
|||
|
||||
# * Array Literals
|
||||
# * Splats in Array Literals
|
||||
|
||||
# TODO: refactor array literal tests
|
||||
|
||||
trailingComma = [1, 2, 3,]
|
||||
ok (trailingComma[0] is 1) and (trailingComma[2] is 3) and (trailingComma.length is 3)
|
||||
|
||||
trailingComma = [
|
||||
1, 2, 3,
|
||||
4, 5, 6
|
||||
7, 8, 9,
|
||||
]
|
||||
(sum = (sum or 0) + n) for n in trailingComma
|
||||
|
||||
a = [((x) -> x), ((x) -> x * x)]
|
||||
ok a.length is 2
|
||||
|
||||
# Funky indentation within non-comma-seperated arrays.
|
||||
result = [['a']
|
||||
{b: 'c'}]
|
||||
ok result[0][0] is 'a'
|
||||
ok result[1]['b'] is 'c'
|
||||
|
||||
|
||||
#### Splats in Array Literals
|
||||
|
||||
test "array splat expansions with assignments", ->
|
||||
nums = [1, 2, 3]
|
||||
list = [a = 0, nums..., b = 4]
|
||||
eq 0, a
|
||||
eq 4, b
|
||||
arrayEq [0,1,2,3,4], list
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
#764: Boolean should be indexable
|
||||
eq Boolean::toString, true['toString']
|
||||
eq Boolean::toString, false['toString']
|
||||
eq Boolean::toString, yes['toString']
|
||||
eq Boolean::toString, no['toString']
|
||||
eq Boolean::toString, on['toString']
|
||||
eq Boolean::toString, off['toString']
|
||||
|
||||
eq Boolean::toString, true.toString
|
||||
eq Boolean::toString, false.toString
|
||||
eq Boolean::toString, yes.toString
|
||||
eq Boolean::toString, no.toString
|
||||
eq Boolean::toString, on.toString
|
||||
eq Boolean::toString, off.toString
|
|
@ -379,3 +379,35 @@ makeClass = ->
|
|||
makeClass.call A
|
||||
|
||||
eq (new B()).func(), 'A B'
|
||||
|
||||
|
||||
|
||||
|
||||
# Ensure that constructors invoked with splats return a new object.
|
||||
args = [1, 2, 3]
|
||||
Type = (@args) ->
|
||||
type = new Type args
|
||||
|
||||
ok type and type instanceof Type
|
||||
ok type.args and type.args instanceof Array
|
||||
ok v is args[i] for v, i in type.args
|
||||
|
||||
Type1 = (@a, @b, @c) ->
|
||||
type1 = new Type1 args...
|
||||
|
||||
ok type1 instanceof Type1
|
||||
eq type1.constructor, Type1
|
||||
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
|
||||
|
||||
# Ensure that constructors invoked with splats cache the function.
|
||||
called = 0
|
||||
get = -> if called++ then false else class Type
|
||||
new get() args...
|
||||
|
||||
# `new` shouldn't add extra parens
|
||||
ok new Date().constructor is Date
|
||||
|
||||
# `new` works against bare function
|
||||
eq Date, new ->
|
||||
eq this, new => this
|
||||
Date
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# Compilation
|
||||
# -----------
|
||||
|
||||
# TODO: refactor compilation tests
|
||||
|
||||
# helper to assert that a string should fail compilation
|
||||
cantCompile = (code) ->
|
||||
throws -> CoffeeScript.compile code
|
||||
|
||||
|
||||
# Ensure that carriage returns don't break compilation on Windows.
|
||||
doesNotThrow -> CoffeeScript.compile 'one\r\ntwo', bare: on
|
||||
|
||||
# `globals: on` removes `var`s
|
||||
eq -1, CoffeeScript.compile('x = y', bare: on, globals: on).indexOf 'var'
|
||||
|
||||
ok 'passed' is CoffeeScript.eval '"passed"', bare: on, fileName: 'test'
|
||||
|
||||
# multiple generated references
|
||||
(->
|
||||
a = {b: []}
|
||||
a.b[true] = -> this == a.b
|
||||
c = 0
|
||||
d = []
|
||||
ok a.b[0<++c<2] d...
|
||||
)()
|
||||
|
||||
# Splat on a line by itself is invalid.
|
||||
cantCompile "x 'a'\n...\n"
|
||||
|
||||
#750
|
||||
cantCompile 'f(->'
|
||||
|
||||
cantCompile 'a = (break)'
|
||||
|
||||
cantCompile 'a = (return 5 for item in list)'
|
||||
|
||||
cantCompile 'a = (return 5 while condition)'
|
||||
|
||||
cantCompile 'a = for x in y\n return 5'
|
||||
|
||||
# Issue #986: Unicode identifiers.
|
||||
λ = 5
|
||||
eq λ, 5
|
||||
|
||||
test "don't accidentally stringify keywords", ->
|
||||
ok (-> this == 'this')() is false
|
|
@ -45,6 +45,10 @@ test "optional parens can be used in a nested fashion", ->
|
|||
add 5, 5
|
||||
ok result is 10
|
||||
|
||||
func = ->
|
||||
return if true
|
||||
eq undefined, func()
|
||||
|
||||
result = ("hello".slice) 3
|
||||
ok result is 'lo'
|
||||
|
||||
|
@ -57,6 +61,9 @@ ok result is 25
|
|||
fn = (arg) -> arg
|
||||
ok fn(fn {prop: 101}).prop is 101
|
||||
|
||||
okFunc = (f) -> ok(f())
|
||||
okFunc -> true
|
||||
|
||||
# Multi-blocks with optional parens.
|
||||
result = fn( ->
|
||||
fn ->
|
||||
|
@ -131,3 +138,161 @@ result = sum(1
|
|||
, 2)
|
||||
ok result is 3
|
||||
|
||||
# Chained blocks, with proper indentation levels:
|
||||
counter =
|
||||
results: []
|
||||
tick: (func) ->
|
||||
@results.push func()
|
||||
this
|
||||
counter
|
||||
.tick ->
|
||||
3
|
||||
.tick ->
|
||||
2
|
||||
.tick ->
|
||||
1
|
||||
arrayEq [3,2,1], counter.results
|
||||
|
||||
# This is a crazy one.
|
||||
x = (obj, func) -> func obj
|
||||
ident = (x) -> x
|
||||
result = x {one: ident 1}, (obj) ->
|
||||
inner = ident(obj)
|
||||
ident inner
|
||||
ok result.one is 1
|
||||
|
||||
# More paren compilation tests:
|
||||
reverse = (obj) -> obj.reverse()
|
||||
ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
|
||||
|
||||
# Test for inline functions with parentheses and implicit calls.
|
||||
combine = (func, num) -> func() * num
|
||||
result = combine (-> 1 + 2), 3
|
||||
ok result is 9
|
||||
|
||||
# Test for calls/parens/multiline-chains.
|
||||
f = (x) -> x
|
||||
result = (f 1).toString()
|
||||
.length
|
||||
ok result is 1
|
||||
|
||||
# Test implicit calls in functions in parens:
|
||||
result = ((val) ->
|
||||
[].push val
|
||||
val
|
||||
)(10)
|
||||
ok result is 10
|
||||
|
||||
# Ensure that chained calls with indented implicit object literals below are
|
||||
# alright.
|
||||
result = null
|
||||
obj =
|
||||
method: (val) -> this
|
||||
second: (hash) -> result = hash.three
|
||||
obj
|
||||
.method(
|
||||
101
|
||||
).second(
|
||||
one:
|
||||
two: 2
|
||||
three: 3
|
||||
)
|
||||
eq result, 3
|
||||
|
||||
# Test newline-supressed call chains with nested functions.
|
||||
obj =
|
||||
call: -> this
|
||||
func = ->
|
||||
obj
|
||||
.call ->
|
||||
one two
|
||||
.call ->
|
||||
three four
|
||||
101
|
||||
eq func(), 101
|
||||
|
||||
# Implicit objects with number arguments.
|
||||
func = (x, y) -> y
|
||||
obj =
|
||||
prop: func "a", 1
|
||||
ok obj.prop is 1
|
||||
|
||||
# Non-spaced unary and binary operators should cause a function call.
|
||||
func = (val) -> val + 1
|
||||
ok (func +5) is 6
|
||||
ok (func -5) is -4
|
||||
|
||||
# Prefix unary assignment operators are allowed in parenless calls.
|
||||
val = 5
|
||||
ok (func --val) is 5
|
||||
|
||||
test "#855: execution context for `func arr...` should be `null`", ->
|
||||
global = @
|
||||
contextTest = -> ok global is @
|
||||
array = []
|
||||
contextTest array
|
||||
contextTest.apply null, array
|
||||
contextTest array...
|
||||
|
||||
test "#904: Destructuring function arguments with same-named variables in scope", ->
|
||||
a = b = nonce = {}
|
||||
fn = ([a,b]) -> {a:a,b:b}
|
||||
result = fn([c={},d={}])
|
||||
eq c, result.a
|
||||
eq d, result.b
|
||||
eq nonce, a
|
||||
eq nonce, b
|
||||
|
||||
obj =
|
||||
index: 0
|
||||
0: {method: -> this is obj[0]}
|
||||
ok obj[obj.index++].method([]...), 'should cache base value'
|
||||
|
||||
|
||||
#### Splats in Function Invocations
|
||||
|
||||
test "passing splats to functions", ->
|
||||
arrayEq [0..4], id id [0..4]...
|
||||
fn = (a, b, c..., d) -> [a, b, c, d]
|
||||
range = [0..3]
|
||||
[first, second, others, last] = fn range..., 4, [5...8]...
|
||||
eq 0, first
|
||||
eq 1, second
|
||||
arrayEq [2..6], others
|
||||
eq 7, last
|
||||
|
||||
#894: Splatting against constructor-chained functions.
|
||||
x = null
|
||||
class Foo
|
||||
bar: (y) -> x = y
|
||||
new Foo().bar([101]...)
|
||||
eq x, 101
|
||||
|
||||
# Functions with splats being called with too few arguments.
|
||||
pen = null
|
||||
method = (first, variable..., penultimate, ultimate) ->
|
||||
pen = penultimate
|
||||
method 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||
ok pen is 8
|
||||
method 1, 2, 3
|
||||
ok pen is 2
|
||||
method 1, 2
|
||||
ok pen is 2
|
||||
|
||||
# Finally, splats with super() within classes.
|
||||
class Parent
|
||||
meth: (args...) ->
|
||||
args
|
||||
class Child extends Parent
|
||||
meth: ->
|
||||
nums = [3, 2, 1]
|
||||
super nums...
|
||||
ok (new Child).meth().join(' ') is '3 2 1'
|
||||
|
||||
|
||||
#### Implicit Return
|
||||
|
||||
eq ok, new ->
|
||||
ok
|
||||
### Should `return` implicitly ###
|
||||
### even with trailing comments. ###
|
||||
|
|
|
@ -39,6 +39,10 @@ func = ->
|
|||
obj.key - 5
|
||||
eq func(), 5
|
||||
|
||||
# Ensure that functions with the same name don't clash with helper functions.
|
||||
del = -> 5
|
||||
ok del() is 5
|
||||
|
||||
|
||||
#### Bound Function Definition
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# Javascript Literals
|
||||
# -------------------
|
||||
|
||||
# TODO: refactor javascript literal tests
|
||||
|
||||
eq '\\`', `
|
||||
// Inline JS
|
||||
"\\\`"
|
||||
`
|
|
@ -7,3 +7,33 @@
|
|||
# * Scientific Notation Integer Literals
|
||||
# * Scientific Notation Non-Integer Literals
|
||||
# * Non-Integer Literals
|
||||
|
||||
|
||||
#### Decimal Integer Literals
|
||||
|
||||
test "call methods directly on numbers", ->
|
||||
eq 4, 4.valueOf()
|
||||
eq '11', 4.toString 3
|
||||
|
||||
eq -1, 3 -4
|
||||
|
||||
#764: Numbers should be indexable
|
||||
eq Number::toString, 42['toString']
|
||||
|
||||
eq Number::toString, 42.toString
|
||||
|
||||
|
||||
#### Non-Integer Literals
|
||||
|
||||
# Decimal number literals.
|
||||
value = .25 + .75
|
||||
ok value is 1
|
||||
value = 0.0 + -.25 - -.75 + 0.0
|
||||
ok value is 0.5
|
||||
|
||||
#764: Numbers should be indexable
|
||||
eq Number::toString, 4.2['toString']
|
||||
eq Number::toString, .42['toString']
|
||||
|
||||
eq Number::toString, 4.2.toString
|
||||
eq Number::toString, .42.toString
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
# Object Literals
|
||||
# ---------------
|
||||
|
||||
# TODO: refactor object literal tests
|
||||
|
||||
trailingComma = {k1: "v1", k2: 4, k3: (-> true),}
|
||||
ok trailingComma.k3() and (trailingComma.k2 is 4) and (trailingComma.k1 is "v1")
|
||||
|
||||
ok {a: (num) -> num is 10 }.a 10
|
||||
|
||||
moe = {
|
||||
name: 'Moe'
|
||||
greet: (salutation) ->
|
||||
salutation + " " + @name
|
||||
hello: ->
|
||||
@['greet'] "Hello"
|
||||
10: 'number'
|
||||
}
|
||||
ok moe.hello() is "Hello Moe"
|
||||
ok moe[10] is 'number'
|
||||
moe.hello = ->
|
||||
this['greet'] "Hello"
|
||||
ok moe.hello() is 'Hello Moe'
|
||||
|
||||
obj = {
|
||||
is: -> yes,
|
||||
'not': -> no,
|
||||
}
|
||||
ok obj.is()
|
||||
ok not obj.not()
|
||||
|
||||
### Top-level object literal... ###
|
||||
obj: 1
|
||||
### ...doesn't break things. ###
|
||||
|
||||
# Object literals should be able to include keywords.
|
||||
obj = {class: 'höt'}
|
||||
obj.function = 'dog'
|
||||
ok obj.class + obj.function is 'hötdog'
|
||||
|
||||
# Implicit objects as part of chained calls.
|
||||
pluck = (x) -> x.a
|
||||
eq 100, pluck pluck pluck a: a: a: 100
|
||||
|
||||
|
||||
test "YAML-style object literals", ->
|
||||
obj =
|
||||
a: 1
|
||||
b: 2
|
||||
eq 1, obj.a
|
||||
eq 2, obj.b
|
||||
|
||||
config =
|
||||
development:
|
||||
server: 'localhost'
|
||||
timeout: 10
|
||||
|
||||
production:
|
||||
server: 'dreamboat'
|
||||
timeout: 1000
|
||||
|
||||
ok config.development.server is 'localhost'
|
||||
ok config.production.server is 'dreamboat'
|
||||
ok config.development.timeout is 10
|
||||
ok config.production.timeout is 1000
|
||||
|
||||
obj =
|
||||
a: 1,
|
||||
b: 2,
|
||||
ok obj.a is 1
|
||||
ok obj.b is 2
|
||||
|
||||
# Implicit objects nesting.
|
||||
obj =
|
||||
options:
|
||||
value: yes
|
||||
fn: ->
|
||||
{}
|
||||
null
|
||||
ok obj.options.value is yes
|
||||
ok obj.fn() is null
|
||||
|
||||
# Implicit objects with wacky indentation:
|
||||
obj =
|
||||
'reverse': (obj) ->
|
||||
Array.prototype.reverse.call obj
|
||||
abc: ->
|
||||
@reverse(
|
||||
@reverse @reverse ['a', 'b', 'c'].reverse()
|
||||
)
|
||||
one: [1, 2,
|
||||
a: 'b'
|
||||
3, 4]
|
||||
red:
|
||||
orange:
|
||||
yellow:
|
||||
green: 'blue'
|
||||
indigo: 'violet'
|
||||
misdent: [[],
|
||||
[],
|
||||
[],
|
||||
[]]
|
||||
ok obj.abc().join(' ') is 'a b c'
|
||||
ok obj.one.length is 5
|
||||
ok obj.one[4] is 4
|
||||
ok obj.one[2].a is 'b'
|
||||
ok (key for key of obj.red).length is 2
|
||||
ok obj.red.orange.yellow.green is 'blue'
|
||||
ok obj.red.indigo is 'violet'
|
||||
ok obj.misdent.toString() is ',,,'
|
||||
|
||||
#542: Objects leading expression statement should be parenthesized.
|
||||
{f: -> ok yes }.f() + 1
|
||||
|
||||
# String-keyed objects shouldn't suppress newlines.
|
||||
one =
|
||||
'>!': 3
|
||||
six: -> 10
|
||||
ok not one.six
|
||||
|
||||
# Shorthand objects with property references.
|
||||
obj =
|
||||
### comment one ###
|
||||
### comment two ###
|
||||
one: 1
|
||||
two: 2
|
||||
object: -> {@one, @two}
|
||||
list: -> [@one, @two]
|
||||
result = obj.object()
|
||||
eq result.one, 1
|
||||
eq result.two, 2
|
||||
eq result.two, obj.list()[1]
|
||||
|
||||
third = (a, b, c) -> c
|
||||
obj =
|
||||
one: 'one'
|
||||
two: third 'one', 'two', 'three'
|
||||
ok obj.one is 'one'
|
||||
ok obj.two is 'three'
|
|
@ -26,9 +26,6 @@ test "division is not confused for a regular expression", ->
|
|||
eq 2, (4)/2/i
|
||||
eq 1, i/i/i
|
||||
|
||||
test "backslash escapes", ->
|
||||
eq "\\/\\\\", /\/\\/.source
|
||||
|
||||
test "#764: regular expressions should be indexable", ->
|
||||
eq /0/['source'], ///#{0}///['source']
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
# TODO: refactor string literal tests
|
||||
|
||||
test "backslash escapes", ->
|
||||
eq "\\/\\\\", /\/\\/.source
|
||||
|
||||
eq '(((dollars)))', '\(\(\(dollars\)\)\)'
|
||||
eq 'one two three', "one
|
||||
two
|
||||
|
|
Loading…
Reference in New Issue