diff --git a/docs/v2/test.html b/docs/v2/test.html index db84a5af..b251e1f4 100644 --- a/docs/v2/test.html +++ b/docs/v2/test.html @@ -1066,8 +1066,8 @@ test "async methods in classes", -> eq await new Base().method(), 2 class Child extends Base - @static: -> super - method: -> super + @static: -> super() + method: -> super() eq await Child.static(), 1 eq await new Child().method(), 2 @@ -1140,13 +1140,6 @@ test "classes with a four-level inheritance chain", -> ok result is 'zero/one/two/three/four' ok Base.static('word') is 'static/word' - FirstChild::func = (string) -> - super('one/').length + string - - result = (new ThirdChild).func 'four' - - ok result is '9two/three/four' - ok (new ThirdChild).array.join(' ') is '1 2 3' @@ -1169,56 +1162,46 @@ test "constructors with inheritance and super", -> ok (new SubClass).prop is 'top-super-sub' -test "basic classes, again, but in the manual prototype style", -> +test "'super' with accessors", -> + class Base + m: -> 4 + n: -> 5 + o: -> 6 - Base = -> - Base::func = (string) -> - 'zero/' + string - Base::['func-func'] = (string) -> - "dynamic-#{string}" + name = 'o' + class A extends Base + m: -> super() + n: -> super.n() + "#{name}": -> super() + p: -> super[name]() - FirstChild = -> - SecondChild = -> - ThirdChild = -> - @array = [1, 2, 3] - this - - ThirdChild extends SecondChild extends FirstChild extends Base - - FirstChild::func = (string) -> - super('one/') + string - - SecondChild::func = (string) -> - super('two/') + string - - ThirdChild::func = (string) -> - super('three/') + string - - result = (new ThirdChild).func 'four' - - ok result is 'zero/one/two/three/four' - - ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing' + a = new A + eq 4, a.m() + eq 5, a.n() + eq 6, a.o() + eq 6, a.p() -test "super with plain ol' prototypes", -> +test "soaked 'super' invocation", -> + class Base + method: -> 2 - TopClass = -> - TopClass::func = (arg) -> - 'top-' + arg + class A extends Base + method: -> super?() + noMethod: -> super?() - SuperClass = -> - SuperClass extends TopClass - SuperClass::func = (arg) -> - super 'super-' + arg + a = new A + eq 2, a.method() + eq undefined, a.noMethod() - SubClass = -> - SubClass extends SuperClass - SubClass::func = -> - super 'sub' - - eq (new SubClass).func(), 'top-super-sub' + name = 'noMethod' + class B extends Base + "#{'method'}": -> super?() + "#{'noMethod'}": -> super?() ? super['method']() + b = new B + eq 2, b.method() + eq 2, b.noMethod() test "'@' referring to the current instance, and not being coerced into a call", -> @@ -1236,7 +1219,7 @@ test "super() calls in constructors of classes that are defined as object proper constructor: (name) -> @name = name class Hive.Bee extends Hive - constructor: (name) -> super + constructor: (name) -> super name maya = new Hive.Bee 'Maya' ok maya.name is 'Maya' @@ -1310,7 +1293,7 @@ test "calling super and passing along all arguments", -> method: (args...) -> @args = args class Child extends Parent - method: -> super + method: -> super arguments... c = new Child c.method 1, 2, 3, 4 @@ -1521,7 +1504,7 @@ test "`class extends this`", -> B = null makeClass = -> B = class extends this - func: -> super + ' B' + func: -> super() + ' B' makeClass.call A @@ -1583,7 +1566,7 @@ test "#1313: misplaced __extends", -> class A class B extends A prop: nonce - constructor: -> super + constructor: -> super() eq nonce, B::prop test "#1182: execution order needs to be considered as well", -> @@ -1610,11 +1593,11 @@ test "#1372: bound class methods with reserved names", -> test "#1380: `super` with reserved names", -> class C - do: -> super + do: -> super() ok C::do class B - 0: -> super + 0: -> super() ok B::[0] test "#1464: bound class methods should keep context", -> @@ -1650,7 +1633,7 @@ test "#1598: super works for static methods too", -> class Child extends Parent @method: -> - 'pass? ' + super + 'pass? ' + super() eq Child.method(), 'pass? yes' @@ -1832,7 +1815,7 @@ test "extending native objects works with and without defining a constructor", - ok 'yes!', myArray.method() class OverrideArray extends Array - constructor: -> super + constructor: -> super() method: -> 'yes!' overrideArray = new OverrideArray @@ -1902,7 +1885,7 @@ test "#2949: super in static method with reserved name", -> @static: -> 'baz' class Bar extends Foo - @static: -> super + @static: -> super() eq Bar.static(), 'baz' @@ -1912,8 +1895,8 @@ test "#3232: super in static methods (not object-assigned)", -> @qux = -> true class Bar extends Foo - @baz = -> super - Bar.qux = -> super + @baz = -> super() + Bar.qux = -> super() ok Bar.baz() ok Bar.qux() @@ -1925,44 +1908,53 @@ test "#1392 calling `super` in methods defined on namespaced classes", -> namespace = A: -> B: -> - namespace.A extends Base + class namespace.A extends Base + m: -> super() - namespace.A::m = -> super eq 5, (new namespace.A).m() namespace.B::m = namespace.A::m namespace.A::m = null eq 5, (new namespace.B).m() - count = 0 - getNamespace = -> count++; namespace - getNamespace().A::n = -> super - eq 4, (new namespace.A).n() - eq 1, count - class C - @a: (->) - @a extends Base - @a::m = -> super + @a: class extends Base + m: -> super() eq 5, (new C.a).m() + +test "dynamic method names", -> + class A + "#{name = 'm'}": -> 1 + eq 1, new A().m() + + class B extends A + "#{name = 'm'}": -> super() + eq 1, new B().m() + + getName = -> 'm' + class C + "#{name = getName()}": -> 1 + eq 1, new C().m() + + test "dynamic method names and super", -> class Base @m: -> 6 m: -> 5 m2: -> 4.5 n: -> 4 - A = -> - A extends Base + + name = -> count++; 'n' + count = 0 m = 'm' - A::[m] = -> super + class A extends Base + "#{m}": -> super() + "#{name()}": -> super() + m = 'n' eq 5, (new A).m() - name = -> count++; 'n' - - count = 0 - A::[name()] = -> super eq 4, (new A).n() eq 1, count @@ -1970,9 +1962,9 @@ test "dynamic method names and super", -> m2 = 'm2' count = 0 class B extends Base - @[name()] = -> super - @::[m] = -> super - "#{m2}": -> super + @[name()] = -> super() + "#{m}": -> super() + "#{m2}": -> super() b = new B m = m2 = 'n' eq 6, B.m() @@ -1981,7 +1973,7 @@ test "dynamic method names and super", -> eq 1, count class C extends B - m: -> super + m: -> super() eq 5, (new C).m() # ES2015+ class interoperability @@ -2150,11 +2142,16 @@ test "`@`-params and bound methods with multiple `super` paths (expressions)", - test "constructor super in arrow functions", -> class Test extends (class) constructor: (@param) -> - do => super + do => super() eq @param, nonce new Test nonce = {} +# TODO Some of these tests use CoffeeScript.compile and CoffeeScript.run when they could use +# regular test mechanics. +# TODO Some of these tests might be better placed in `test/error_messages.coffee`. +# TODO Some of these tests are duplicates. + # Ensure that we always throw if we experience more than one super() # call in a constructor. This ends up being a runtime error. # Should be caught at compile time. @@ -2314,24 +2311,6 @@ test "super and external constructors", -> throws -> CoffeeScript.compile throwsC, bare: yes -test "super in external prototype", -> - class A - constructor: (@drink) -> - make: -> "Making a #{@drink}" - - class B extends A - B::make = (@flavor) -> super() + " with #{@flavor}" - b = new B('Machiato') - eq b.make('caramel'), "Making a Machiato with caramel" - - # Fails, bound - # TODO: Could this throw a compile error? - class C extends A - C::make = (@flavor) => super() + " with #{@flavor}" - c = new C('Machiato') - ok c.make('caramel') isnt "Making a Machiato with caramel" - - test "bound functions without super", -> # Bound function with @ # Throw on compile, since bound @@ -2359,7 +2338,7 @@ test "super in a bound function", -> class B extends A make: (@flavor) => - super + " with #{@flavor}" + super() + " with #{@flavor}" b = new B('Machiato') eq b.make('vanilla'), "Making a Machiato with vanilla" @@ -2368,7 +2347,7 @@ test "super in a bound function", -> class C extends A make: (@flavor) => func = () => - super + " with #{@flavor}" + super() + " with #{@flavor}" func() c = new C('Machiato') @@ -2396,13 +2375,13 @@ test "super in a try/catch", -> class B extends A constructor: -> try - super + super() """ throwsC = """ ctor = -> try - super + super() class C extends A constructor: ctor @@ -2786,7 +2765,7 @@ test "CS6 Class extends a CS1 compiled class with super()", -> constructor: (@shots) -> super('caramel') make: () -> - super + " and #{@shots} shots of espresso" + super() + " and #{@shots} shots of espresso" eq B.className(), 'ExtendedCS1' b = new B('three') @@ -3897,6 +3876,16 @@ test "#2274: Allow @values as loop variables", -> obj.method() eq obj.item, 3 +test "#4411: Allow @values as loop indices", -> + obj = + index: null + get: -> @index + method: -> + @get() for _, @index in [1, 2, 3] + eq obj.index, null + arrayEq obj.method(), [0, 1, 2] + eq obj.index, 3 + test "#2525, #1187, #1208, #1758, looping over an array forwards", -> list = [0, 1, 2, 3, 4] @@ -4473,9 +4462,21 @@ test "compiler error formatting", -> ''' if require? + os = require 'os' fs = require 'fs' path = require 'path' + test "patchStackTrace line patching", -> + err = new Error 'error' + ok err.stack.match /test[\/\\]error_messages\.coffee:\d+:\d+\b/ + + test "patchStackTrace stack prelude consistent with V8", -> + err = new Error + ok err.stack.match /^Error\n/ # Notice no colon when no message. + + err = new Error 'error' + ok err.stack.match /^Error: error\n/ + test "#2849: compilation error in a require()d file", -> # Create a temporary file to require(). ok not fs.existsSync 'test/syntax-error.coffee' @@ -4493,6 +4494,57 @@ if require? finally fs.unlinkSync 'test/syntax-error.coffee' + test "#3890 Error.prepareStackTrace doesn't throw an error if a compiled file is deleted", -> + # Adapted from https://github.com/atom/coffee-cash/blob/master/spec/coffee-cash-spec.coffee + filePath = path.join os.tmpdir(), 'PrepareStackTraceTestFile.coffee' + fs.writeFileSync filePath, "module.exports = -> throw new Error('hello world')" + throwsAnError = require filePath + fs.unlinkSync filePath + + try + throwsAnError() + catch error + + eq error.message, 'hello world' + doesNotThrow(-> error.stack) + notEqual error.stack.toString().indexOf(filePath), -1 + + test "#4418 stack traces for compiled files reference the correct line number", -> + filePath = path.join os.tmpdir(), 'StackTraceLineNumberTestFile.coffee' + fileContents = """ + testCompiledFileStackTraceLineNumber = -> + # `a` on the next line is undefined and should throw a ReferenceError + console.log a if true + + do testCompiledFileStackTraceLineNumber + """ + fs.writeFileSync filePath, fileContents + + try + require filePath + catch error + fs.unlinkSync filePath + + # Make sure the line number reported is line 3 (the original Coffee source) + # and not line 6 (the generated JavaScript). + eq /StackTraceLineNumberTestFile.coffee:(\d)/.exec(error.stack.toString())[1], '3' + + +test "#4418 stack traces for compiled strings reference the correct line number", -> + try + CoffeeScript.run """ + testCompiledStringStackTraceLineNumber = -> + # `a` on the next line is undefined and should throw a ReferenceError + console.log a if true + + do testCompiledStringStackTraceLineNumber + """ + catch error + + # Make sure the line number reported is line 3 (the original Coffee source) + # and not line 6 (the generated JavaScript). + eq /at testCompiledStringStackTraceLineNumber.*:(\d):/.exec(error.stack.toString())[1], '3' + test "#1096: unexpected generated tokens", -> # Implicit ends @@ -5652,10 +5704,10 @@ test "constructor functions can't be generators", -> ''' test "non-derived constructors can't call super", -> - assertErrorFormat 'class then constructor: -> super', ''' + assertErrorFormat 'class then constructor: -> super()', ''' [stdin]:1:28: error: 'super' is only allowed in derived class constructors - class then constructor: -> super - ^^^^^ + class then constructor: -> super() + ^^^^^^^ ''' test "derived constructors can't reference `this` before calling super", -> @@ -5673,10 +5725,39 @@ test "derived constructors can't use @params without calling super", -> ''' test "'super' is not allowed in constructor parameter defaults", -> - assertErrorFormat 'class extends A then constructor: (a = super) ->', ''' + assertErrorFormat 'class extends A then constructor: (a = super()) ->', ''' [stdin]:1:40: error: 'super' is not allowed in constructor parameter defaults - class extends A then constructor: (a = super) -> - ^^^^^ + class extends A then constructor: (a = super()) -> + ^^^^^^^ + ''' + +test "can't use pattern matches for loop indices", -> + assertErrorFormat 'a for b, {c} in d', ''' + [stdin]:1:10: error: index cannot be a pattern matching expression + a for b, {c} in d + ^^^ + ''' + +test "bare 'super' is no longer allowed", -> + # TODO Improve this error message (it should at least be 'unexpected super') + assertErrorFormat 'class extends A then constructor: -> super', ''' + [stdin]:1:35: error: unexpected -> + class extends A then constructor: -> super + ^^ + ''' + +test "soaked 'super' in constructor", -> + assertErrorFormat 'class extends A then constructor: -> super?()', ''' + [stdin]:1:38: error: Unsupported reference to 'super' + class extends A then constructor: -> super?() + ^^^^^ + ''' + +test "new with 'super'", -> + assertErrorFormat 'class extends A then foo: -> new super()', ''' + [stdin]:1:34: error: Unsupported reference to 'super' + class extends A then foo: -> new super() + ^^^^^ ''' @@ -7206,6 +7287,17 @@ test "#1038 Optimize trailing return statements", -> return """) +test "#4406 Destructured parameter default evaluation order with incrementing variable", -> + i = 0 + f = ({ a = ++i }, b = ++i) -> [a, b] + arrayEq f({}), [1, 2] + +test "#4406 Destructured parameter default evaluation order with generator function", -> + current = 0 + next = -> ++current + foo = ({ a = next() }, b = next()) -> [ a, b ] + arrayEq foo({}), [1, 2] +