| Index: test/mjsunit/strong/mutually-recursive-classes.js
|
| diff --git a/test/mjsunit/strong/mutually-recursive-classes.js b/test/mjsunit/strong/mutually-recursive-classes.js
|
| index c8d6fad260fd9fad4cfc8bc7d2ca1868df8143e3..c8cf9788ba232db00e94f19fb897a22e513cc3a6 100644
|
| --- a/test/mjsunit/strong/mutually-recursive-classes.js
|
| +++ b/test/mjsunit/strong/mutually-recursive-classes.js
|
| @@ -2,23 +2,20 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -// Flags: --strong-mode
|
| +// Flags: --strong-mode --harmony-arrow-functions
|
| +"use strict"
|
|
|
| -// Note that it's essential for these tests that the reference is inside dead
|
| -// code (because we already produce ReferenceErrors for run-time unresolved
|
| -// variables and don't want to confuse those with strong mode errors). But the
|
| -// errors should *not* be inside lazy, unexecuted functions, since lazy parsing
|
| -// doesn't produce strong mode scoping errors).
|
| +let prologue_dead = "(function outer() { if (false) { ";
|
| +let epilogue_dead = " } })();";
|
|
|
| -// In addition, assertThrows will call eval and that changes variable binding
|
| -// types (see e.g., UNBOUND_EVAL_SHADOWED). We can avoid unwanted side effects
|
| -// by wrapping the code to be tested inside an outer function.
|
| -function assertThrowsHelper(code) {
|
| - "use strict";
|
| - let prologue_dead = "(function outer() { if (false) { ";
|
| - let epilogue_dead = " } })();";
|
| +let prologue_live = "(function outer() { ";
|
| +let epilogue_live = "})();";
|
|
|
| - assertThrows("'use strong'; " + prologue_dead + code + epilogue_dead, ReferenceError);
|
| +// For code which already throws a run-time error in non-strong mode; we assert
|
| +// that we now get the error already compilation time.
|
| +function assertLateErrorsBecomeEarly(code) {
|
| + assertThrows("'use strong'; " + prologue_dead + code + epilogue_dead,
|
| + ReferenceError);
|
|
|
| // Make sure the error happens only in strong mode (note that we need strict
|
| // mode here because of let).
|
| @@ -26,24 +23,35 @@ function assertThrowsHelper(code) {
|
|
|
| // But if we don't put the references inside a dead code, it throws a run-time
|
| // error (also in strict mode).
|
| - let prologue_live = "(function outer() { ";
|
| - let epilogue_live = "})();";
|
| + assertThrows("'use strong'; " + prologue_live + code + epilogue_live,
|
| + ReferenceError);
|
| + assertThrows("'use strict'; " + prologue_live + code + epilogue_live,
|
| + ReferenceError);
|
| +}
|
| +
|
| +// For code which doesn't throw an error at all in non-strong mode.
|
| +function assertNonErrorsBecomeEarly(code) {
|
| + assertThrows("'use strong'; " + prologue_dead + code + epilogue_dead,
|
| + ReferenceError);
|
| + assertDoesNotThrow("'use strict'; " + prologue_dead + code + epilogue_dead);
|
|
|
| - assertThrows("'use strong'; " + prologue_live + code + epilogue_live, ReferenceError);
|
| - assertThrows("'use strict'; " + prologue_live + code + epilogue_live, ReferenceError);
|
| + assertThrows("'use strong'; " + prologue_live + code + epilogue_live,
|
| + ReferenceError);
|
| + assertDoesNotThrow("'use strict'; " + prologue_live + code + epilogue_live,
|
| + ReferenceError);
|
| }
|
|
|
| (function InitTimeReferenceForward() {
|
| // It's never OK to have an init time reference to a class which hasn't been
|
| // declared.
|
| - assertThrowsHelper(
|
| - `class A extends B { };
|
| + assertLateErrorsBecomeEarly(
|
| + `class A extends B { }
|
| class B {}`);
|
|
|
| - assertThrowsHelper(
|
| + assertLateErrorsBecomeEarly(
|
| `class A {
|
| [B.sm()]() { }
|
| - };
|
| + }
|
| class B {
|
| static sm() { return 0; }
|
| }`);
|
| @@ -54,7 +62,7 @@ function assertThrowsHelper(code) {
|
| "use strong";
|
| class A {
|
| static sm() { return 0; }
|
| - };
|
| + }
|
| let i = "making these classes non-consecutive";
|
| class B extends A {};
|
| "by inserting statements and declarations in between";
|
| @@ -68,10 +76,154 @@ function assertThrowsHelper(code) {
|
| class A {
|
| m() { B; }
|
| static sm() { B; }
|
| - };
|
| + }
|
| // No statements or declarations between the classes.
|
| class B {
|
| m() { A; }
|
| static sm() { A; }
|
| - };
|
| + }
|
| +})();
|
| +
|
| +(function MutualRecursionWithMoreClasses() {
|
| + "use strong";
|
| + class A {
|
| + m() { B; C; }
|
| + static sm() { B; C; }
|
| + }
|
| + class B {
|
| + m() { A; C; }
|
| + static sm() { A; C; }
|
| + }
|
| + class C {
|
| + m() { A; B; }
|
| + static sm() { A; B; }
|
| + }
|
| +})();
|
| +
|
| +(function ReferringForwardInDeeperScopes() {
|
| + "use strong";
|
| +
|
| + function foo() {
|
| + class A1 {
|
| + m() { B1; }
|
| + }
|
| + class B1 { }
|
| + }
|
| +
|
| + class Outer {
|
| + m() {
|
| + class A2 {
|
| + m() { B2; }
|
| + }
|
| + class B2 { }
|
| + }
|
| + }
|
| +
|
| + for (let i = 0; i < 1; ++i) {
|
| + class A3 {
|
| + m() { B3; }
|
| + }
|
| + class B3 { }
|
| + }
|
| +
|
| + (a, b) => {
|
| + class A4 {
|
| + m() { B4; }
|
| + }
|
| + class B4 { }
|
| + }
|
| +})();
|
| +
|
| +(function ReferringForwardButClassesNotConsecutive() {
|
| + assertNonErrorsBecomeEarly(
|
| + `class A {
|
| + m() { B; }
|
| + }
|
| + ;
|
| + class B {}`);
|
| +
|
| + assertNonErrorsBecomeEarly(
|
| + `let A = class {
|
| + m() { B; }
|
| + }
|
| + class B {}`);
|
| +
|
| + assertNonErrorsBecomeEarly(
|
| + `class A {
|
| + m() { B1; } // Just a normal use-before-declaration.
|
| + }
|
| + let B1 = class B2 {}`);
|
| +
|
| + assertNonErrorsBecomeEarly(
|
| + `class A {
|
| + m() { B; }
|
| + }
|
| + let i = 0;
|
| + class B {}`);
|
| +
|
| + assertNonErrorsBecomeEarly(
|
| + `class A {
|
| + m() { B; }
|
| + }
|
| + function foo() {}
|
| + class B {}`);
|
| +
|
| + assertNonErrorsBecomeEarly(
|
| + `function foo() {
|
| + class A {
|
| + m() { B; }
|
| + }
|
| + }
|
| + class B {}`);
|
| +
|
| + assertNonErrorsBecomeEarly(
|
| + `class A extends class B { m() { C; } } {
|
| + }
|
| + class C { }`);
|
| +
|
| + assertLateErrorsBecomeEarly(
|
| + `class A extends class B { [C.sm()]() { } } {
|
| + }
|
| + class C { static sm() { return 'a';} }`);
|
| +
|
| + assertLateErrorsBecomeEarly(
|
| + `class A extends class B extends C { } {
|
| + }
|
| + class C { }`);
|
| +})();
|
| +
|
| +
|
| +(function RegressionForClassResolution() {
|
| + assertNonErrorsBecomeEarly(
|
| + `let A = class B {
|
| + m() { C; }
|
| + }
|
| + ;;;;
|
| + class C {}
|
| + class B {}`);
|
| +})();
|
| +
|
| +
|
| +(function TestMultipleMethodScopes() {
|
| + "use strong";
|
| +
|
| + // Test cases where the reference is inside multiple method scopes.
|
| + class A1 {
|
| + m() {
|
| + class C1 {
|
| + m() { B1; }
|
| + }
|
| + }
|
| + }
|
| + class B1 { }
|
| +
|
| + ;
|
| +
|
| + class A2 {
|
| + m() {
|
| + class C2 extends B2 {
|
| + }
|
| + }
|
| + }
|
| + class B2 { }
|
| })();
|
|
|