JSTests:
authormsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Jul 2019 06:01:12 +0000 (06:01 +0000)
committermsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Jul 2019 06:01:12 +0000 (06:01 +0000)
Exception from For..of loop assignment eliminates TDZ checks in subsequent code
https://bugs.webkit.org/show_bug.cgi?id=199395

Reviewed by Filip Pizlo.

New regession test.

* stress/for-of-tdz-with-try-catch.js: Added.
(test):
(i.catch):

Source/JavaScriptCore:
Exception from For..of loop destructured assignment eliminates TDZ checks in subsequent code
https://bugs.webkit.org/show_bug.cgi?id=199395

Reviewed by Filip Pizlo.

For destructuring assignmests, the assignment might throw a reference error if
the RHS cannot be coerced.  The current bytecode generated for such assignments
optimizes out the TDZ check after the coercible check.

By saving the current state of the TDZ stack before processing the setting of
target destructured values and then restoring afterwards, we won't optimize out
later TDZ check(s).

A similar change of saving / restoring the TDZ stack where exceptions might
happen was done for for..in loops in change set r232219.

* bytecompiler/NodesCodegen.cpp:
(JSC::ObjectPatternNode::bindValue const):

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

JSTests/ChangeLog
JSTests/stress/for-of-tdz-with-try-catch.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

index fbb5927..c6d1889 100644 (file)
@@ -1,3 +1,16 @@
+2019-07-02  Michael Saboff  <msaboff@apple.com>
+
+        Exception from For..of loop assignment eliminates TDZ checks in subsequent code
+        https://bugs.webkit.org/show_bug.cgi?id=199395
+
+        Reviewed by Filip Pizlo.
+
+        New regession test.
+
+        * stress/for-of-tdz-with-try-catch.js: Added.
+        (test):
+        (i.catch):
+
 2019-07-02  Keith Miller  <keith_miller@apple.com>
 
         Frozen Arrays length assignment should throw in strict mode
diff --git a/JSTests/stress/for-of-tdz-with-try-catch.js b/JSTests/stress/for-of-tdz-with-try-catch.js
new file mode 100644 (file)
index 0000000..baa90de
--- /dev/null
@@ -0,0 +1,22 @@
+// This regression test checks that a let in the TDZ state is handled properly
+// with a for-of in a try as well as the ensuing catch block.
+
+function test() {
+    try {
+        for ({o} of [, 0])
+            ;
+    } catch (e) {
+        o[0] = 1.5;
+    }
+    let o = {
+    };
+}
+
+for (i = 0; i < 1000; i++) {
+    try {
+        test();
+    } catch(e) {
+        if (e != "ReferenceError: Cannot access uninitialized variable.")
+            throw "Expected \"ReferenceError: Cannot access uninitialized variable.\", but got \"" + e +"\"";
+    }
+}
index 11304a7..41d8d9a 100644 (file)
@@ -1,3 +1,24 @@
+2019-07-02  Michael Saboff  <msaboff@apple.com>
+
+        Exception from For..of loop destructured assignment eliminates TDZ checks in subsequent code
+        https://bugs.webkit.org/show_bug.cgi?id=199395
+
+        Reviewed by Filip Pizlo.
+
+        For destructuring assignmests, the assignment might throw a reference error if
+        the RHS cannot be coerced.  The current bytecode generated for such assignments
+        optimizes out the TDZ check after the coercible check.
+
+        By saving the current state of the TDZ stack before processing the setting of 
+        target destructured values and then restoring afterwards, we won't optimize out
+        later TDZ check(s).
+
+        A similar change of saving / restoring the TDZ stack where exceptions might
+        happen was done for for..in loops in change set r232219.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ObjectPatternNode::bindValue const):
+
 2019-07-02  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r247041.
index addb342..7ff7b58 100644 (file)
@@ -4304,6 +4304,9 @@ void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs)
         addMethod = generator.emitGetById(generator.newTemporary(), excludedList.get(), generator.propertyNames().builtinNames().addPrivateName());
     }
 
+    BytecodeGenerator::PreservedTDZStack preservedTDZStack;
+    generator.preserveTDZStack(preservedTDZStack);
+
     for (size_t i = 0; i < m_targetPatterns.size(); i++) {
         const auto& target = m_targetPatterns[i];
         if (target.bindingType == BindingType::Element) {
@@ -4366,6 +4369,8 @@ void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs)
             target.pattern->bindValue(generator, result.get());
         }
     }
+
+    generator.restoreTDZStack(preservedTDZStack);
 }
 
 void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const