test262: Completion values for control flow do not match the spec
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Jun 2017 22:04:20 +0000 (22:04 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Jun 2017 22:04:20 +0000 (22:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171265

Patch by Joseph Pecoraro <pecoraro@apple.com> on 2017-06-19
Reviewed by Saam Barati.

JSTests:

* stress/completion-value.js:
Condensed test for completion values in top level statements.

* stress/super-get-by-id.js:
ClassDeclaration when evaled no longer produce values. Convert
these to ClassExpressions so they produce the class value.

* ChakraCore/test/GlobalFunctions/evalreturns3.baseline-jsc:
This is a progression for currect spec behavior.

* mozilla/mozilla-tests.yaml:
This test is now outdated, so mark it as failing for that reason.

* test262.yaml:
Passing all "cptn" completion value tests.

Source/JavaScriptCore:

* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::shouldBeConcernedWithCompletionValue):
When we care about having proper completion values (global code
in programs, modules, and eval) insert undefined results for
control flow statements.

* bytecompiler/NodesCodegen.cpp:
(JSC::SourceElements::emitBytecode):
Reduce writing a default `undefined` value to the completion result to
only once before the last statement we know will produce a value.

(JSC::IfElseNode::emitBytecode):
(JSC::WithNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ForInNode::emitBytecode):
(JSC::ForOfNode::emitBytecode):
(JSC::SwitchNode::emitBytecode):
Insert an undefined to handle cases where code may break out of an
if/else or with statement (break/continue).

(JSC::TryNode::emitBytecode):
Same handling for break cases. Also, finally block statement completion
values are always ignored for the try statement result.

(JSC::ClassDeclNode::emitBytecode):
Class declarations, like function declarations, produce an empty result.

* parser/Nodes.cpp:
(JSC::SourceElements::lastStatement):
(JSC::SourceElements::hasCompletionValue):
(JSC::SourceElements::hasEarlyBreakOrContinue):
(JSC::BlockNode::lastStatement):
(JSC::BlockNode::singleStatement):
(JSC::BlockNode::hasCompletionValue):
(JSC::BlockNode::hasEarlyBreakOrContinue):
(JSC::ScopeNode::singleStatement):
(JSC::ScopeNode::hasCompletionValue):
(JSC::ScopeNode::hasEarlyBreakOrContinue):
The only non-trivial cases need to loop through their list of statements
to determine if this has a completion value or not. Likewise for
determining if there is an early break / continue, meaning a break or
continue statement with no preceding statement that has a completion value.

* parser/Nodes.h:
(JSC::StatementNode::next):
(JSC::StatementNode::hasCompletionValue):
Helper to check if a statement nodes produces a completion value or not.

Tools:

* Scripts/run-jsc-stress-tests:
Include a :failDueToOutdatedOrBadTest to mark failures with justification.

LayoutTests:

* js/eval-throw-return-expected.txt:
* js/kde/completion-expected.txt:
* js/kde/script-tests/completion.js:
* js/script-tests/eval-throw-return.js:
* sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A9-expected.txt:
* sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A9.1-expected.txt:
Rebaseline expectations. These are all outdated. In fact the sputnik
tests were imported into test262 and modified for ES2015.

* js/script-tests/function-toString-vs-name.js:
ClassDeclarations on their own don't produce a value. So output
the class value so the test behaves as expected.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@218512 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
JSTests/ChakraCore/test/GlobalFunctions/evalreturns3.baseline-jsc
JSTests/ChangeLog
JSTests/mozilla/mozilla-tests.yaml
JSTests/stress/completion-value.js [new file with mode: 0644]
JSTests/stress/super-get-by-id.js
JSTests/test262.yaml
LayoutTests/ChangeLog
LayoutTests/js/eval-throw-return-expected.txt
LayoutTests/js/kde/completion-expected.txt
LayoutTests/js/kde/script-tests/completion.js
LayoutTests/js/script-tests/eval-throw-return.js
LayoutTests/js/script-tests/function-toString-vs-name.js
LayoutTests/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A9-expected.txt
LayoutTests/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A9.1-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/parser/Nodes.cpp
Source/JavaScriptCore/parser/Nodes.h
Tools/ChangeLog
Tools/Scripts/run-jsc-stress-tests

index eeb88c7..d7ad9eb 100644 (file)
@@ -5,14 +5,14 @@ undefined
 1
 0
 2
-hello
+undefined
 1
 undefined
 1
 hello
-goodbye
+hello
+undefined
 undefined
-good night
 function () { }
 function () { }
 2
index 627cbfe..48970b7 100644 (file)
@@ -1,3 +1,26 @@
+2017-06-19  Joseph Pecoraro  <pecoraro@apple.com>
+
+        test262: Completion values for control flow do not match the spec
+        https://bugs.webkit.org/show_bug.cgi?id=171265
+
+        Reviewed by Saam Barati.
+
+        * stress/completion-value.js:
+        Condensed test for completion values in top level statements.
+
+        * stress/super-get-by-id.js:
+        ClassDeclaration when evaled no longer produce values. Convert
+        these to ClassExpressions so they produce the class value.
+        
+        * ChakraCore/test/GlobalFunctions/evalreturns3.baseline-jsc:
+        This is a progression for currect spec behavior.
+
+        * mozilla/mozilla-tests.yaml:
+        This test is now outdated, so mark it as failing for that reason.
+
+        * test262.yaml:
+        Passing all "cptn" completion value tests.
+
 2017-06-17  Keith Miller  <keith_miller@apple.com>
 
         ArrayBuffer constructor needs to create subclass structures before its buffer
index 0ae372c..b7b7abc 100644 (file)
 - path: ecma/Statements/12.6.3-19.js
   cmd: defaultRunMozillaTest :normal, "../shell.js"
 - path: ecma/Statements/12.6.3-2.js
-  cmd: defaultRunMozillaTest :normal, "../shell.js"
+  cmd: defaultRunMozillaTest :failDueToOutdatedOrBadTest, "../shell.js"
 - path: ecma/Statements/12.6.3-3.js
   cmd: defaultRunMozillaTest :normal, "../shell.js"
 - path: ecma/Statements/12.6.3-4.js
diff --git a/JSTests/stress/completion-value.js b/JSTests/stress/completion-value.js
new file mode 100644 (file)
index 0000000..c75526e
--- /dev/null
@@ -0,0 +1,288 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldBeWithValueCheck(actual, callback) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+// Basic.
+shouldBe(eval(), undefined);
+shouldBe(eval(""), undefined);
+shouldBe(eval(`1`), 1);
+shouldBe(eval(`1; 2`), 2);
+
+// Types of statements:
+// https://tc39.github.io/ecma262/#prod-Statement
+
+// Statements that produce an (empty) completion value do not affect results:
+//   - EmptyStatement
+//   - DebuggerStatement
+//   - BlockStatement (with no substatement)
+//   - DeclarationStatements (variables, functions, classes)
+//   - LabelledStatement (with an empty statement)
+//   - ContinueStatement / BreakStatement (tested below)
+shouldBe(eval(`42;`), 42);
+shouldBe(eval(`42;;;;;`), 42);
+shouldBe(eval(`42; var x;`), 42);
+shouldBe(eval(`42; let x;`), 42);
+shouldBe(eval(`42; const x = 1;`), 42);
+shouldBe(eval(`42; var x = 1;`), 42);
+shouldBe(eval(`42; var x = 1, y = 2;`), 42);
+shouldBe(eval(`42; debugger;`), 42);
+shouldBe(eval(`42; { }`), 42);
+shouldBe(eval(`42; class foo {}`), 42);
+shouldBe(eval(`42; function foo() {}`), 42);
+shouldBe(eval(`42; function* foo() {}`), 42);
+shouldBe(eval(`42; async function foo() {}`), 42);
+shouldBe(eval(`42; label: {}`), 42);
+shouldBe(eval(`42; { { var x; } var y; { { debugger } ;; } function foo() {} }`), 42);
+
+// ExpressionStatement
+shouldBe(eval(`99; 42`), 42);
+shouldBe(eval(`99; { 42 }`), 42);
+shouldBe(eval(`99; label: { 42 }`), 42);
+shouldBe(eval(`99; x = 42`), 42);
+shouldBe(eval(`99; x = 42; x`), 42);
+shouldBe(eval(`99; 1, 2, 3, 42`), 42);
+shouldBe(eval(`99; x = 41; ++x`), 42);
+shouldBe(eval(`99; x = 42; x++`), 42);
+shouldBe(eval(`99; true ? 42 : -1`), 42);
+shouldBe(eval(`99; false ? -1 : 42`), 42);
+shouldBe(Array.isArray(eval(`99; [x,y] = [1,2]`)), true);
+shouldBe(typeof eval(`99; ({})`), "object");
+shouldBe(typeof eval(`99; (function foo() {})`), "function");
+shouldBe(typeof eval(`99; (function* foo() {})`), "function");
+shouldBe(typeof eval(`99; (async function foo() {})`), "function");
+shouldBe(typeof eval(`99; (class foo {})`), "function");
+
+// IfStatement
+shouldBe(eval(`99; if (true);`), undefined);
+shouldBe(eval(`99; if (false);`), undefined);
+shouldBe(eval(`99; if (true) 42;`), 42);
+shouldBe(eval(`99; if (false) -1;`), undefined);
+shouldBe(eval(`99; if (true) {}`), undefined);
+shouldBe(eval(`99; if (true) {42}`), 42);
+shouldBe(eval(`99; if (false) {}`), undefined);
+shouldBe(eval(`99; if (false) {42}`), undefined);
+shouldBe(eval(`99; if (false) {-1} else {}`), undefined);
+shouldBe(eval(`99; if (false) {-1} else {42}`), 42);
+shouldBe(eval(`99; if (false) {-1} else if (true) {}`), undefined);
+shouldBe(eval(`99; if (false) {-1} else if (true) {42}`), 42);
+shouldBe(eval(`99; if (false) {-1} else if (true) {} else {-2}`), undefined);
+shouldBe(eval(`99; if (false) {-1} else if (true) {42} else {-2}`), 42);
+shouldBe(eval(`99; if (false) {-1} else if (false) {-2} else {}`), undefined);
+shouldBe(eval(`99; if (false) {-1} else if (false) {-2} else {42}`), 42);
+
+// DoWhile
+shouldBe(eval(`99; do; while (false);`), undefined);
+shouldBe(eval(`99; do 42; while (false);`), 42);
+shouldBe(eval(`99; do {} while (false);`), undefined);
+shouldBe(eval(`99; do break; while (true);`), undefined);
+shouldBe(eval(`99; do { break } while (true);`), undefined);
+shouldBe(eval(`99; do { 42 } while (false);`), 42);
+shouldBe(eval(`let x = 1; do { x } while (x++ !== (5+5));`), 10);
+shouldBe(eval(`let x = 1; do { x; 42 } while (x++ !== (5+5));`), 42);
+shouldBe(eval(`let x = 1; do { x; break } while (x++ !== (5+5));`), 1);
+shouldBe(eval(`let x = 1; do { x; continue } while (x++ !== (5+5));`), 10);
+
+// While
+shouldBe(eval(`99; while (false);`), undefined);
+shouldBe(eval(`99; while (false) {};`), undefined);
+shouldBe(eval(`99; while (true) break;`), undefined);
+shouldBe(eval(`99; while (true) { break };`), undefined);
+shouldBe(eval(`99; while (true) { 42; break };`), 42);
+shouldBe(eval(`let x = 1; while (x++ !== (5+5)) ;`), undefined);
+shouldBe(eval(`let x = 1; while (x++ !== (5+5)) { }`), undefined);
+shouldBe(eval(`let x = 1; while (x++ !== (5+5)) { x }`), 10);
+shouldBe(eval(`let x = 1; while (x++ !== (5+5)) { x; 42 }`), 42);
+shouldBe(eval(`let x = 1; while (x++ !== (5+5)) { x; break }`), 2);
+shouldBe(eval(`let x = 1; while (x++ !== (5+5)) { x; continue }`), 10);
+
+// For
+shouldBe(eval(`99; for (;false;);`), undefined);
+shouldBe(eval(`99; for (;false;) {}`), undefined);
+shouldBe(eval(`99; for (var x = 1;false;);`), undefined);
+shouldBe(eval(`99; for (x = 1;false;) {}`), undefined);
+shouldBe(eval(`99; for (;;) break;`), undefined);
+shouldBe(eval(`99; for (;;) { break }`), undefined);
+shouldBe(eval(`99; for (;;) { 42; break }`), 42);
+shouldBe(eval(`99; for (;;) { 42; break; 3 }`), 42);
+shouldBe(eval(`99; for (x = 1; x !== (5+5); x++) x;`), 9);
+shouldBe(eval(`99; for (x = 1; x !== (5+5); x++) { x; }`), 9);
+shouldBe(eval(`99; for (x = 1; x !== (5+5); x++) { x; 42 }`), 42);
+shouldBe(eval(`99; for (x = 1; x !== (5+5); x++) { x; break }`), 1);
+shouldBe(eval(`99; for (x = 1; x !== (5+5); x++) { x; break; 3 }`), 1);
+shouldBe(eval(`99; for (x = 1; x !== (5+5); x++) { x; continue }`), 9);
+shouldBe(eval(`99; for (x = 1; x !== (5+5); x++) { x; continue; 3 }`), 9);
+
+// ForOf
+shouldBe(eval(`99; for (var x of []) -1;`), undefined);
+shouldBe(eval(`99; for (x of []) -1;`), undefined);
+shouldBe(eval(`99; for (var x of [1,2]);`), undefined);
+shouldBe(eval(`99; for (x of [1,2]);`), undefined);
+shouldBe(eval(`99; for (x of [1,2]) {}`), undefined);
+shouldBe(eval(`99; for (x of [1,2]) break;`), undefined);
+shouldBe(eval(`99; for (x of [1,2]) { break; }`), undefined);
+shouldBe(eval(`99; for (x of [1,2]) { break; 3; }`), undefined);
+shouldBe(eval(`99; for (x of [1,2]) x`), 2);
+shouldBe(eval(`99; for (x of [1,2]) { x }`), 2);
+shouldBe(eval(`99; for (x of [1,2]) { x; break }`), 1);
+shouldBe(eval(`99; for (x of [1,2]) { x; break; 3 }`), 1);
+shouldBe(eval(`99; for (x of [1,2]) { x; continue }`), 2);
+shouldBe(eval(`99; for (x of [1,2]) { x; continue; 3 }`), 2);
+
+// ForIn
+shouldBe(eval(`99; for (var x in {}) -1;`), undefined);
+shouldBe(eval(`99; for (x in {}) -1;`), undefined);
+shouldBe(eval(`99; for (var x in {a:1,b:2});`), undefined);
+shouldBe(eval(`99; for (x in {a:1,b:2});`), undefined);
+shouldBe(eval(`99; for (x in {a:1,b:2}) {}`), undefined);
+shouldBe(eval(`99; for (x in {a:1,b:2}) break;`), undefined);
+shouldBe(eval(`99; for (x in {a:1,b:2}) { break; }`), undefined);
+shouldBe(eval(`99; for (x in {a:1,b:2}) { break; 3; }`), undefined);
+shouldBe(eval(`99; for (x in {a:1,b:2}) x`), "b");
+shouldBe(eval(`99; for (x in {a:1,b:2}) { x }`), "b");
+shouldBe(eval(`99; for (x in {a:1,b:2}) { x; break }`), "a");
+shouldBe(eval(`99; for (x in {a:1,b:2}) { x; break; 3 }`), "a");
+shouldBe(eval(`99; for (x in {a:1,b:2}) { x; continue }`), "b");
+shouldBe(eval(`99; for (x in {a:1,b:2}) { x; continue; 3 }`), "b");
+
+// SwitchStatement
+shouldBe(eval(`99; switch (1) { }`), undefined);
+shouldBe(eval(`99; switch (1) { default:}`), undefined);
+shouldBe(eval(`99; switch (1) { default:42}`), 42);
+shouldBe(eval(`99; switch (1) { default:break;}`), undefined);
+shouldBe(eval(`99; switch (1) { case 1: /* empty */ }`), undefined);
+shouldBe(eval(`99; switch (1) { case 1: 42 }`), 42);
+shouldBe(eval(`99; switch (1) { case 1: break; }`), undefined);
+shouldBe(eval(`99; switch (1) { case 1: break; }`), undefined);
+shouldBe(eval(`99; switch (1) { case 2: case 1: /* empty */ }`), undefined);
+shouldBe(eval(`99; switch (1) { case 2: case 1: 42 }`), 42);
+shouldBe(eval(`99; switch (1) { case 2: case 1: break; }`), undefined);
+shouldBe(eval(`99; switch (1) { case 2: case 1: 42; break; }`), 42);
+shouldBe(eval(`99; switch (1) { case 1: case 2: /* empty */ }`), undefined);
+shouldBe(eval(`99; switch (1) { case 1: case 2: 42 }`), 42);
+shouldBe(eval(`99; switch (1) { case 1: case 2: break; }`), undefined);
+shouldBe(eval(`99; switch (1) { case 1: case 2: 42; break; }`), 42);
+shouldBe(eval(`99; switch (1) { case 1: 42; case 2: /* empty */ }`), 42);
+shouldBe(eval(`99; switch (1) { case 1: -1; case 2: 42 }`), 42);
+shouldBe(eval(`99; switch (1) { case 1: 42; case 2: break; }`), 42);
+shouldBe(eval(`99; switch (1) { case 1: -1; case 2: 42; break; }`), 42);
+shouldBe(eval(`99; switch (1) { case 0: -1; break; case 1: 42; break; default: -1; break; }`), 42);
+shouldBe(eval(`99; switch (1) { case 0: -1; break; case 1: /* empty */; break; default: -1; break; }`), undefined);
+shouldBe(eval(`99; switch (1) { case 0: -1; break; case 1: 42; break; default: -1; break; }`), 42);
+
+// WithStatement
+shouldBe(eval(`99; with (true);`), undefined);
+shouldBe(eval(`99; with (true) {}`), undefined);
+shouldBe(eval(`99; with (true) 42;`), 42);
+shouldBe(eval(`99; with (true) { 42 }`), 42);
+
+// TryCatchFinally / ThrowStatement
+shouldBe(eval(`99; try {} catch (e) {-1};`), undefined);
+shouldBe(eval(`99; try {} catch (e) {-1} finally {-2};`), undefined);
+shouldBe(eval(`99; try {42} catch (e) {-1};`), 42);
+shouldBe(eval(`99; try {42} catch (e) {-1} finally {-2};`), 42);
+shouldBe(eval(`99; try { [].x.x } catch (e) {};`), undefined);
+shouldBe(eval(`99; try { [].x.x } catch (e) {42} finally {-2};`), 42);
+shouldBe(eval(`99; try { throw 42 } catch (e) {e};`), 42);
+shouldBe(eval(`99; try { throw 42 } catch (e) {e} finally {-2};`), 42);
+
+// Break Statement where it is not normally available.
+shouldBe(eval(`99; do { -99; if (true) { break; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (true) { 42; break; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; if (false) { } else { break; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (false) { } else { 42; break; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; with (true) { break; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; with (true) { 42; break; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { break; } catch (e) { -1 }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; break; } catch (e) { -1 }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { break; } catch (e) {-1} finally {-2}; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; break; } catch (e) {-1} finally {-2}; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { break; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; break; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { break; } finally {-2}; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; break; } finally {-2}; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { 42 } catch (e) { -1 } finally { -2; break; -3 }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; } finally { -2; break; -3 }; } while (false);`), 42);
+
+// Break Statement where it is not normally available with other surrounding statements.
+shouldBe(eval(`99; do { -99; if (true) { break; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (true) { 42; break; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; if (false) { } else { break; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (false) { } else { 42; break; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; with (true) { break; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; with (true) { 42; break; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { break; } catch (e) { -1 }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; break; } catch (e) { -1 }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { break; } catch (e) {-1} finally {-2}; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; break; } catch (e) {-1} finally {-2}; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { break; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; break; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { break; } finally {-2}; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; break; } finally {-2}; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { 42 } catch (e) { -1 } finally { -2; break; -3 }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; } finally { -2; break; -3 }; -77 } while (false);`), 42);
+
+// Continue Statement where it is not normally available.
+shouldBe(eval(`99; do { -99; if (true) { continue; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (true) { 42; continue; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; if (false) { } else { continue; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (false) { } else { 42; continue; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; with (true) { continue; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; with (true) { 42; continue; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { continue; } catch (e) { -1 }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; continue; } catch (e) { -1 }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { continue; } catch (e) {-1} finally {-2}; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; continue; } catch (e) {-1} finally {-2}; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { continue; }; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; continue; }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { continue; } finally {-2}; } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; continue; } finally {-2}; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { 42 } catch (e) { -1 } finally { -2; continue; -3 }; } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; } finally { -2; continue; -3 }; } while (false);`), 42);
+
+// Continue Statement where it is not normally available with other surrounding statements.
+shouldBe(eval(`99; do { -99; if (true) { continue; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (true) { 42; continue; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; if (false) { } else { continue; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; if (false) { } else { 42; continue; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; with (true) { continue; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; with (true) { 42; continue; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { continue; } catch (e) { -1 }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; continue; } catch (e) { -1 }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { continue; } catch (e) {-1} finally {-2}; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { 42; continue; } catch (e) {-1} finally {-2}; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { continue; }; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; continue; }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { continue; } finally {-2}; -77 } while (false);`), undefined);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; continue; } finally {-2}; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { 42 } catch (e) { -1 } finally { -2; continue; -3 }; -77 } while (false);`), 42);
+shouldBe(eval(`99; do { -99; try { [].x.x } catch (e) { 42; } finally { -2; continue; -3 }; -77 } while (false);`), 42);
+
+// Early break to a label.
+shouldBe(eval(`99; label: do { 1; if (true) { break label; 2; }; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; if (true) { break label; 2; }; 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; with (true) { break label; 2; }; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; with (true) { break label; 2; }; 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; do { break label; 2; } while (false); } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; do { break label; 2; } while (false); 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; try { break label; 2; } catch (e) {-1;} while (false); } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; try { break label; 2; } catch (e) {-1;} while (false); 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; while (true) { break label; 2; }; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; while (true) { break label; 2; }; 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; for (;;) { break label; 2; }; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; for (;;) { break label; 2; }; 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; for (var x in {a:77}) { break label; 2; }; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; for (var x in {a:77}) { break label; 2; }; 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; for (var x of [77]) { break label; 2; }; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; for (var x of [77]) { break label; 2; }; 3; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; switch (true) { default: break label; 2; }; } while (false);`), undefined);
+shouldBe(eval(`99; label: do { 1; switch (true) { default: break label; 2; }; 3; } while (false);`), undefined);
+
+// FIXME: Module Only Statements:
+// FIXME: ImportStatement
+// FIXME: ExportStatement
index 86c8be3..265895f 100644 (file)
@@ -44,9 +44,9 @@ let numPolymorphicClasses = 4;
 let subclasses = new Array(numPolymorphicClasses);
 for (let i = 0; i < numPolymorphicClasses; i++) {
     let BaseCode = `
-       class Base${i} {
+        (class Base${i} {
             get value() { return this._value; }
-        };
+        });
     `;
 
     let Base = eval(BaseCode);
@@ -72,9 +72,9 @@ class MegamorphicSubclass {
 subclasses = new Array(nClasses);
 for (let i = 0; i < nClasses; i++) {
     let BaseCode = `
-       class Base${i + 4} {
+        (class Base${i + 4} {
             get value() { return this._value; }
-        };
+        });
     `;
 
     let Base = eval(BaseCode);
index e73ab63..2a65772 100644 (file)
 - path: test262/test/language/statements/do-while/S12.6.1_A9.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/do-while/cptn-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/do-while/cptn-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/do-while/cptn-normal.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/do-while/cptn-normal.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/do-while/decl-cls.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/do-while/decl-cls.js
 - path: test262/test/language/statements/for/S12.6.3_A8_T3.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for/S12.6.3_A9.1.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for/S12.6.3_A9.1.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for/S12.6.3_A9.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for/S12.6.3_A9.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for/cptn-decl-expr-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for/cptn-decl-expr-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for/cptn-decl-expr-no-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for/cptn-decl-expr-no-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for/cptn-expr-expr-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for/cptn-expr-expr-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for/cptn-expr-expr-no-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for/cptn-expr-expr-no-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for/decl-cls.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for/decl-cls.js
 - path: test262/test/language/statements/for-in/S12.6.4_A7_T2.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-decl-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-decl-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-decl-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-decl-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-decl-skip-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-decl-skip-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-decl-zero-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-decl-zero-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-expr-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-expr-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-expr-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-expr-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-expr-skip-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-expr-skip-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/cptn-expr-zero-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/cptn-expr-zero-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-in/decl-cls.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-in/decl-cls.js
 - path: test262/test/language/statements/for-of/continue.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-of/cptn-decl-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-of/cptn-decl-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-of/cptn-decl-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-of/cptn-decl-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-of/cptn-decl-no-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-of/cptn-decl-no-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-of/cptn-expr-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-of/cptn-expr-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-of/cptn-expr-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-of/cptn-expr-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-of/cptn-expr-no-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-of/cptn-expr-no-itr.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/for-of/decl-cls.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/for-of/decl-cls.js
 - path: test262/test/language/statements/if/S12.5_A8.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/cptn-else-false-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/cptn-else-false-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/cptn-else-false-nrml.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/cptn-else-false-nrml.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/cptn-else-true-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/cptn-else-true-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/cptn-else-true-nrml.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/cptn-else-true-nrml.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/cptn-no-else-false.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/cptn-no-else-false.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/cptn-no-else-true-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/cptn-no-else-true-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/cptn-no-else-true-nrml.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/cptn-no-else-true-nrml.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/if/if-cls-else-cls.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/if/if-cls-else-cls.js
 - path: test262/test/language/statements/switch/S12.11_A4_T1.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-a-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-a-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-a-fall-thru-abrupt-empty.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-a-fall-thru-abrupt-empty.js
 - path: test262/test/language/statements/switch/cptn-a-fall-thru-nrml.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-b-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-b-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-b-fall-thru-abrupt-empty.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-b-fall-thru-abrupt-empty.js
 - path: test262/test/language/statements/switch/cptn-b-fall-thru-nrml.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-b-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-b-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-dflt-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-dflt-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-dflt-b-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-dflt-b-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-dflt-b-fall-thru-abrupt-empty.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-dflt-b-fall-thru-abrupt-empty.js
 - path: test262/test/language/statements/switch/cptn-dflt-b-fall-thru-nrml.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-dflt-b-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-dflt-b-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-dflt-fall-thru-abrupt-empty.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-dflt-fall-thru-abrupt-empty.js
 - path: test262/test/language/statements/switch/cptn-dflt-fall-thru-nrml.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-dflt-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-dflt-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-no-dflt-match-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-no-dflt-match-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-no-dflt-match-fall-thru-abrupt-empty.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-no-dflt-match-fall-thru-abrupt-empty.js
 - path: test262/test/language/statements/switch/cptn-no-dflt-match-fall-thru-nrml.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-no-dflt-match-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-no-dflt-match-final.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/cptn-no-dflt-no-match.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/cptn-no-dflt-no-match.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/switch/early-lex-dup.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/switch/early-lex-dup.js
 - path: test262/test/language/statements/try/S12.14_A9_T5.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/try/cptn-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/try/cptn-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/try/cptn-finally-from-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/try/cptn-finally-from-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/try/cptn-finally-skip-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/try/cptn-finally-skip-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/try/cptn-finally-wo-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/try/cptn-finally-wo-catch.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/try/cptn-try.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/try/cptn-try.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/try/dstr-ary-init-iter-close.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/try/dstr-ary-init-iter-close.js
 - path: test262/test/language/statements/while/S12.6.2_A9.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/while/cptn-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/while/cptn-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/while/cptn-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/while/cptn-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/while/cptn-no-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/while/cptn-no-iter.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
 - path: test262/test/language/statements/while/decl-cls.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/while/decl-cls.js
 - path: test262/test/language/statements/with/binding-not-blocked-by-unscopables-non-obj.js
   cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/with/cptn-abrupt-empty.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/with/cptn-nrml.js
-  cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/with/decl-cls.js
   cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
 - path: test262/test/language/statements/with/decl-const.js
index 6bf0d6f..91873ec 100644 (file)
@@ -1,3 +1,23 @@
+2017-06-19  Joseph Pecoraro  <pecoraro@apple.com>
+
+        test262: Completion values for control flow do not match the spec
+        https://bugs.webkit.org/show_bug.cgi?id=171265
+
+        Reviewed by Saam Barati.
+
+        * js/eval-throw-return-expected.txt:
+        * js/kde/completion-expected.txt:
+        * js/kde/script-tests/completion.js:
+        * js/script-tests/eval-throw-return.js:
+        * sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A9-expected.txt:
+        * sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A9.1-expected.txt:
+        Rebaseline expectations. These are all outdated. In fact the sputnik
+        tests were imported into test262 and modified for ES2015.
+        
+        * js/script-tests/function-toString-vs-name.js:
+        ClassDeclarations on their own don't produce a value. So output
+        the class value so the test behaves as expected.
+
 2017-06-19  Sam Weinig  <sam@webkit.org>
 
         [WebIDL] Add support for serializers that have members that are themselves serializers (or inherit being a serializer from a parent)
index a638b1d..b223edc 100644 (file)
@@ -4,19 +4,19 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS eval("1;") is 1
-PASS eval("1; try { foo = [2,3,throwFunc(), 4]; } catch (e){}") is 1
-PASS eval("1; try { 2; throw \"\"; } catch (e){}") is 2
-PASS eval("1; try { 2; throwFunc(); } catch (e){}") is 2
+PASS eval("1; try { foo = [2,3,throwFunc(), 4]; } catch (e){}") is undefined
+PASS eval("1; try { 2; throw \"\"; } catch (e){}") is undefined
+PASS eval("1; try { 2; throwFunc(); } catch (e){}") is undefined
 PASS eval("1; try { 2; throwFunc(); } catch (e){3;} finally {}") is 3
-PASS eval("1; try { 2; throwFunc(); } catch (e){3;} finally {4;}") is 4
+PASS eval("1; try { 2; throwFunc(); } catch (e){3;} finally {4;}") is 3
 PASS eval("function blah() { 1; }\n blah();") is undefined
 PASS eval("var x = 1;") is undefined
 PASS eval("if (true) { 1; } else { 2; }") is 1
 PASS eval("if (false) { 1; } else { 2; }") is 2
-PASS eval("try{1; if (true) { 2; throw \"\"; } else { 2; }} catch(e){}") is 2
+PASS eval("try{1; if (true) { 2; throw \"\"; } else { 2; }} catch(e){}") is undefined
 PASS eval("1; var i = 0; do { ++i; 2; } while(i!=1);") is 2
-PASS eval("try{1; var i = 0; do { ++i; 2; throw \"\"; } while(i!=1);} catch(e){}") is 2
-PASS eval("1; try{2; throwOnReturn();} catch(e){}") is 2
+PASS eval("try{1; var i = 0; do { ++i; 2; throw \"\"; } while(i!=1);} catch(e){}") is undefined
+PASS eval("1; try{2; throwOnReturn();} catch(e){}") is undefined
 PASS eval("1; twoFunc();") is undefined
 PASS eval("1; with ( { a: 0 } ) { 2; }") is 2
 PASS successfullyParsed is true
index 56fbb8e..a722e31 100644 (file)
@@ -7,7 +7,7 @@ PASS foo(), i is 2
 PASS caught is true
 PASS val is 11
 PASS val is 12
-PASS val is 13
+PASS val is undefined
 PASS val is 14
 PASS val is 15
 PASS successfullyParsed is true
index 1dd7344..57e29e3 100644 (file)
@@ -18,7 +18,7 @@ shouldBe("val", "11");
 val = eval("12; ;");
 shouldBe("val", "12");
 val = eval("13; if(false);");
-shouldBe("val", "13");
+shouldBe("val", "undefined");
 val = eval("14; function f() {}");
 shouldBe("val", "14");
 val = eval("15; var v = 0");
index d55eade..de1b5a7 100644 (file)
@@ -14,18 +14,18 @@ function twoFunc() {
 }
 
 shouldBe('eval("1;")', "1");
-shouldBe('eval("1; try { foo = [2,3,throwFunc(), 4]; } catch (e){}")', "1");
-shouldBe('eval("1; try { 2; throw \\"\\"; } catch (e){}")', "2");
-shouldBe('eval("1; try { 2; throwFunc(); } catch (e){}")', "2");
+shouldBe('eval("1; try { foo = [2,3,throwFunc(), 4]; } catch (e){}")', "undefined");
+shouldBe('eval("1; try { 2; throw \\"\\"; } catch (e){}")', "undefined");
+shouldBe('eval("1; try { 2; throwFunc(); } catch (e){}")', "undefined");
 shouldBe('eval("1; try { 2; throwFunc(); } catch (e){3;} finally {}")', "3");
-shouldBe('eval("1; try { 2; throwFunc(); } catch (e){3;} finally {4;}")', "4");
+shouldBe('eval("1; try { 2; throwFunc(); } catch (e){3;} finally {4;}")', "3");
 shouldBe('eval("function blah() { 1; }\\n blah();")', "undefined");
 shouldBe('eval("var x = 1;")', "undefined");
 shouldBe('eval("if (true) { 1; } else { 2; }")', "1");
 shouldBe('eval("if (false) { 1; } else { 2; }")', "2");
-shouldBe('eval("try{1; if (true) { 2; throw \\"\\"; } else { 2; }} catch(e){}")', "2");
+shouldBe('eval("try{1; if (true) { 2; throw \\"\\"; } else { 2; }} catch(e){}")', "undefined");
 shouldBe('eval("1; var i = 0; do { ++i; 2; } while(i!=1);")', "2");
-shouldBe('eval("try{1; var i = 0; do { ++i; 2; throw \\"\\"; } while(i!=1);} catch(e){}")', "2");
-shouldBe('eval("1; try{2; throwOnReturn();} catch(e){}")', "2");
+shouldBe('eval("try{1; var i = 0; do { ++i; 2; throw \\"\\"; } while(i!=1);} catch(e){}")', "undefined");
+shouldBe('eval("1; try{2; throwOnReturn();} catch(e){}")', "undefined");
 shouldBe('eval("1; twoFunc();")', "undefined");
 shouldBe('eval("1; with ( { a: 0 } ) { 2; }")', "2");
index 118bfa3..b4bcaf9 100644 (file)
@@ -446,11 +446,11 @@ section = "class statements in eval";
 // Checking if there are CodeCache badness that can result from class statements in
 // identical eval statements.
 (function () {
-    let body1 = "class foo { constructor(x) { return x; } stuff() { return 5; } }";
+    let body1 = "class foo { constructor(x) { return x; } stuff() { return 5; } }; foo";
     // Identical class body as body1.
-    let body2 = "class foo { constructor(x) { return x; } stuff() { return 5; } }";
+    let body2 = "class foo { constructor(x) { return x; } stuff() { return 5; } }; foo";
     // Identical constructor as body1 & body2, but different otherwise.
-    let body3 = "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }";
+    let body3 = "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }; foo3";
 
     let bar1 = eval(body1);
     let bar2 = eval(body2);
index 405d982..f6f215c 100644 (file)
@@ -1,3 +1,59 @@
+2017-06-19  Joseph Pecoraro  <pecoraro@apple.com>
+
+        test262: Completion values for control flow do not match the spec
+        https://bugs.webkit.org/show_bug.cgi?id=171265
+
+        Reviewed by Saam Barati.
+
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::shouldBeConcernedWithCompletionValue):
+        When we care about having proper completion values (global code
+        in programs, modules, and eval) insert undefined results for
+        control flow statements.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::SourceElements::emitBytecode):
+        Reduce writing a default `undefined` value to the completion result to
+        only once before the last statement we know will produce a value.
+
+        (JSC::IfElseNode::emitBytecode):
+        (JSC::WithNode::emitBytecode):
+        (JSC::WhileNode::emitBytecode):
+        (JSC::ForNode::emitBytecode):
+        (JSC::ForInNode::emitBytecode):
+        (JSC::ForOfNode::emitBytecode):
+        (JSC::SwitchNode::emitBytecode):
+        Insert an undefined to handle cases where code may break out of an
+        if/else or with statement (break/continue).
+
+        (JSC::TryNode::emitBytecode):
+        Same handling for break cases. Also, finally block statement completion
+        values are always ignored for the try statement result.
+
+        (JSC::ClassDeclNode::emitBytecode):
+        Class declarations, like function declarations, produce an empty result.
+
+        * parser/Nodes.cpp:
+        (JSC::SourceElements::lastStatement):
+        (JSC::SourceElements::hasCompletionValue):
+        (JSC::SourceElements::hasEarlyBreakOrContinue):
+        (JSC::BlockNode::lastStatement):
+        (JSC::BlockNode::singleStatement):
+        (JSC::BlockNode::hasCompletionValue):
+        (JSC::BlockNode::hasEarlyBreakOrContinue):
+        (JSC::ScopeNode::singleStatement):
+        (JSC::ScopeNode::hasCompletionValue):
+        (JSC::ScopeNode::hasEarlyBreakOrContinue):
+        The only non-trivial cases need to loop through their list of statements
+        to determine if this has a completion value or not. Likewise for
+        determining if there is an early break / continue, meaning a break or
+        continue statement with no preceding statement that has a completion value.
+
+        * parser/Nodes.h:
+        (JSC::StatementNode::next):
+        (JSC::StatementNode::hasCompletionValue):
+        Helper to check if a statement nodes produces a completion value or not.
+
 2017-06-19  Adrian Perez de Castro  <aperez@igalia.com>
 
         Missing <functional> includes make builds fail with GCC 7.x
index 9c349ac..04a8090 100644 (file)
@@ -915,7 +915,9 @@ namespace JSC {
 
         CodeType codeType() const { return m_codeType; }
 
-        bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
+        bool shouldBeConcernedWithCompletionValue() const { return m_codeType != FunctionCode; }
+
+        bool shouldEmitDebugHooks() const { return m_shouldEmitDebugHooks; }
         
         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
 
index df08966..cb2ca84 100644 (file)
@@ -2448,30 +2448,25 @@ RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 
 // ------------------------------ SourceElements -------------------------------
 
-
-inline StatementNode* SourceElements::lastStatement() const
-{
-    return m_tail;
-}
-
 inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    for (StatementNode* statement = m_head; statement; statement = statement->next())
+    StatementNode* lastStatementWithCompletionValue = nullptr;
+    if (generator.shouldBeConcernedWithCompletionValue()) {
+        for (StatementNode* statement = m_head; statement; statement = statement->next()) {
+            if (statement->hasCompletionValue())
+                lastStatementWithCompletionValue = statement;
+        }
+    }
+
+    for (StatementNode* statement = m_head; statement; statement = statement->next()) {
+        if (statement == lastStatementWithCompletionValue)
+            generator.emitLoad(dst, jsUndefined());
         generator.emitNodeInTailPosition(dst, statement);
+    }
 }
 
 // ------------------------------ BlockNode ------------------------------------
 
-inline StatementNode* BlockNode::lastStatement() const
-{
-    return m_statements ? m_statements->lastStatement() : 0;
-}
-
-StatementNode* BlockNode::singleStatement() const
-{
-    return m_statements ? m_statements->singleStatement() : 0;
-}
-
 void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     if (!m_statements)
@@ -2595,6 +2590,11 @@ bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, Statement
 
 void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (generator.shouldBeConcernedWithCompletionValue()) {
+        if (m_ifBlock->hasEarlyBreakOrContinue() || (m_elseBlock && m_elseBlock->hasEarlyBreakOrContinue()))
+            generator.emitLoad(dst, jsUndefined());
+    }
+
     Ref<Label> beforeThen = generator.newLabel();
     Ref<Label> beforeElse = generator.newLabel();
     Ref<Label> afterElse = generator.newLabel();
@@ -2630,6 +2630,9 @@ void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
 void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
+        generator.emitLoad(dst, jsUndefined());
+
     Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
 
     Ref<Label> topOfLoop = generator.newLabel();
@@ -2648,6 +2651,9 @@ void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
 void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
+        generator.emitLoad(dst, jsUndefined());
+
     Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
     Ref<Label> topOfLoop = generator.newLabel();
 
@@ -2672,6 +2678,9 @@ void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
 void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
+        generator.emitLoad(dst, jsUndefined());
+
     Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
 
     RegisterID* forLoopSymbolTable = nullptr;
@@ -2821,6 +2830,9 @@ void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
         return;
     }
 
+    if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
+        generator.emitLoad(dst, jsUndefined());
+
     Ref<Label> end = generator.newLabel();
 
     RegisterID* forLoopSymbolTable = nullptr;
@@ -2975,6 +2987,9 @@ void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
         return;
     }
 
+    if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
+        generator.emitLoad(dst, jsUndefined());
+
     RegisterID* forLoopSymbolTable = nullptr;
     generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
     auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
@@ -3128,6 +3143,8 @@ void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     RefPtr<RegisterID> scope = generator.emitNode(m_expr);
     generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
     generator.emitPushWithScope(scope.get());
+    if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
+        generator.emitLoad(dst, jsUndefined());
     generator.emitNodeInTailPosition(dst, m_statement);
     generator.emitPopWithScope();
 }
@@ -3296,6 +3313,9 @@ void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterI
 
 void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (generator.shouldBeConcernedWithCompletionValue())
+        generator.emitLoad(dst, jsUndefined());
+
     Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
 
     RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
@@ -3340,6 +3360,9 @@ void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     // NOTE: The catch and finally blocks must be labeled explicitly, so the
     // optimizer knows they may be jumped to from anywhere.
 
+    if (generator.shouldBeConcernedWithCompletionValue() && m_tryBlock->hasEarlyBreakOrContinue())
+        generator.emitLoad(dst, jsUndefined());
+
     ASSERT(m_catchBlock || m_finallyBlock);
     BytecodeGenerator::CompletionRecordScope completionRecordScope(generator, m_finallyBlock);
 
@@ -3431,7 +3454,7 @@ void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
         int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
         generator.emitProfileControlFlow(finallyStartOffset);
-        generator.emitNodeInTailPosition(dst, m_finallyBlock);
+        generator.emitNodeInTailPosition(m_finallyBlock);
 
         generator.emitFinallyCompletion(finallyContext, savedCompletionTypeRegister.get(), *finallyEndLabel);
         generator.emitLabel(*finallyEndLabel);
@@ -3706,9 +3729,9 @@ RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID
 
 // ------------------------------ ClassDeclNode ---------------------------------
 
-void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
 {
-    generator.emitNode(dst, m_classDeclaration);
+    generator.emitNode(m_classDeclaration);
 }
 
 // ------------------------------ ClassExprNode ---------------------------------
index 3a08b63..1dfff42 100644 (file)
@@ -65,6 +65,55 @@ StatementNode* SourceElements::singleStatement() const
     return m_head == m_tail ? m_head : nullptr;
 }
 
+StatementNode* SourceElements::lastStatement() const
+{
+    return m_tail;
+}
+
+bool SourceElements::hasCompletionValue() const
+{
+    for (StatementNode* statement = m_head; statement; statement = statement->next()) {
+        if (statement->hasCompletionValue())
+            return true;
+    }
+
+    return false;
+}
+
+bool SourceElements::hasEarlyBreakOrContinue() const
+{
+    for (StatementNode* statement = m_head; statement; statement = statement->next()) {
+        if (statement->isBreak() || statement->isContinue())
+            return true;
+        if (statement->hasCompletionValue())
+            return false;
+    }
+
+    return false;
+}
+
+// ------------------------------ BlockNode ------------------------------------
+
+StatementNode* BlockNode::lastStatement() const
+{
+    return m_statements ? m_statements->lastStatement() : nullptr;
+}
+
+StatementNode* BlockNode::singleStatement() const
+{
+    return m_statements ? m_statements->singleStatement() : nullptr;
+}
+
+bool BlockNode::hasCompletionValue() const
+{
+    return m_statements ? m_statements->hasCompletionValue() : false;
+}
+
+bool BlockNode::hasEarlyBreakOrContinue() const
+{
+    return m_statements ? m_statements->hasEarlyBreakOrContinue() : false;
+}
+
 // ------------------------------ ScopeNode -----------------------------
 
 ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext)
@@ -99,7 +148,17 @@ ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocat
 
 StatementNode* ScopeNode::singleStatement() const
 {
-    return m_statements ? m_statements->singleStatement() : 0;
+    return m_statements ? m_statements->singleStatement() : nullptr;
+}
+
+bool ScopeNode::hasCompletionValue() const
+{
+    return m_statements ? m_statements->hasCompletionValue() : false;
+}
+
+bool ScopeNode::hasEarlyBreakOrContinue() const
+{
+    return m_statements ? m_statements->hasEarlyBreakOrContinue() : false;
 }
 
 // ------------------------------ ProgramNode -----------------------------
index cdc2ce9..8336198 100644 (file)
@@ -210,9 +210,12 @@ namespace JSC {
         void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset);
         unsigned lastLine() const { return m_lastLine; }
 
-        StatementNode* next() { return m_next; }
+        StatementNode* next() const { return m_next; }
         void setNext(StatementNode* next) { m_next = next; }
 
+        virtual bool hasCompletionValue() const { return true; }
+        virtual bool hasEarlyBreakOrContinue() const { return false; }
+
         virtual bool isEmptyStatement() const { return false; }
         virtual bool isDebuggerStatement() const { return false; }
         virtual bool isFunctionNode() const { return false; }
@@ -1342,6 +1345,9 @@ namespace JSC {
         StatementNode* singleStatement() const;
         StatementNode* lastStatement() const;
 
+        bool hasCompletionValue() const;
+        bool hasEarlyBreakOrContinue() const;
+
         void emitBytecode(BytecodeGenerator&, RegisterID* destination);
         void analyzeModule(ModuleAnalyzer&);
 
@@ -1362,6 +1368,9 @@ namespace JSC {
     private:
         void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool hasCompletionValue() const override;
+        bool hasEarlyBreakOrContinue() const override;
+
         bool isBlock() const override { return true; }
 
         SourceElements* m_statements;
@@ -1374,6 +1383,7 @@ namespace JSC {
     private:
         void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool hasCompletionValue() const override { return false; }
         bool isEmptyStatement() const override { return true; }
     };
     
@@ -1381,6 +1391,7 @@ namespace JSC {
     public:
         DebuggerStatementNode(const JSTokenLocation&);
 
+        bool hasCompletionValue() const override { return false; }
         bool isDebuggerStatement() const override { return true; }
         
     private:
@@ -1407,6 +1418,8 @@ namespace JSC {
     private:
         void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool hasCompletionValue() const override { return false; }
+
         ExpressionNode* m_expr;
     };
 
@@ -1524,6 +1537,7 @@ namespace JSC {
         Label* trivialTarget(BytecodeGenerator&);
         
     private:
+        bool hasCompletionValue() const override { return false; }
         bool isContinue() const override { return true; }
         void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
@@ -1536,6 +1550,7 @@ namespace JSC {
         Label* trivialTarget(BytecodeGenerator&);
         
     private:
+        bool hasCompletionValue() const override { return false; }
         bool isBreak() const override { return true; }
         void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
@@ -1576,6 +1591,7 @@ namespace JSC {
         bool isLabel() const override { return true; }
 
     private:
+        bool hasCompletionValue() const override { return m_statement->hasCompletionValue(); }
         void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
         const Identifier& m_name;
@@ -1660,6 +1676,9 @@ namespace JSC {
 
         StatementNode* singleStatement() const;
 
+        bool hasCompletionValue() const override;
+        bool hasEarlyBreakOrContinue() const override;
+
         void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination);
         
         void analyzeModule(ModuleAnalyzer&);
@@ -1769,6 +1788,7 @@ namespace JSC {
     class ModuleDeclarationNode : public StatementNode {
     public:
         virtual void analyzeModule(ModuleAnalyzer&) = 0;
+        bool hasCompletionValue() const override { return false; }
         bool isModuleDeclarationNode() const override { return true; }
 
     protected:
@@ -2249,6 +2269,7 @@ namespace JSC {
     public:
         FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&);
 
+        bool hasCompletionValue() const override { return false; }
         bool isFuncDeclNode() const override { return true; }
         FunctionMetadataNode* metadata() { return m_metadata; }
 
@@ -2265,6 +2286,8 @@ namespace JSC {
     private:
         void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool hasCompletionValue() const override { return false; }
+
         ExpressionNode* m_classDeclaration;
     };
 
index ba82ccf..649839e 100644 (file)
@@ -1,3 +1,13 @@
+2017-06-19  Joseph Pecoraro  <pecoraro@apple.com>
+
+        test262: Completion values for control flow do not match the spec
+        https://bugs.webkit.org/show_bug.cgi?id=171265
+
+        Reviewed by Saam Barati.
+
+        * Scripts/run-jsc-stress-tests:
+        Include a :failDueToOutdatedOrBadTest to mark failures with justification.
+
 2017-06-19  Zalan Bujtas  <zalan@apple.com>
 
         Opening certain mails brings up a mail that grows indefinitely.
index d832838..ac3863a 100755 (executable)
@@ -1445,6 +1445,8 @@ def runMozillaTest(kind, mode, extraFiles, *options)
         errorHandler = mozillaExit3ErrorHandler
     when :fail
         errorHandler = mozillaFailErrorHandler
+    when :failDueToOutdatedOrBadTest
+        errorHandler = mozillaFailErrorHandler
     when :skip
         return
     else