Title: [163328] trunk
Revision
163328
Author
[email protected]
Date
2014-02-03 14:43:28 -0800 (Mon, 03 Feb 2014)

Log Message

Deconstructed parameters aren't being placed in the correct scope
https://bugs.webkit.org/show_bug.cgi?id=128126

Reviewed by Antti Koivisto.

Source/_javascript_Core:

Make sure we declare the bound parameter names as variables when
we reparse.  In the BytecodeGenerator we now also directly ensure
that bound parameters are placed in the symbol table of the function
we're currently compiling.  We then delay binding until just before
we start codegen for the body of the function so that we can ensure
the function has completely initialised all scope details.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
* bytecompiler/BytecodeGenerator.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::createBindingPattern):

LayoutTests:

Added tests for correct behaviour.

* js/deconstructing-parameters-should-be-locals-expected.txt: Added.
* js/deconstructing-parameters-should-be-locals.html: Added.
* js/script-tests/deconstructing-parameters-should-be-locals.js: Added.
(description.value.string_appeared_here.readDeconstructedParameter):
(overwriteDeconstructedParameter):
(readCapturedDeconstructedParameter):
(overwriteCapturedDeconstructedParameter):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (163327 => 163328)


--- trunk/LayoutTests/ChangeLog	2014-02-03 22:39:38 UTC (rev 163327)
+++ trunk/LayoutTests/ChangeLog	2014-02-03 22:43:28 UTC (rev 163328)
@@ -1,3 +1,20 @@
+2014-02-03  Oliver Hunt  <[email protected]>
+
+        Deconstructed parameters aren't being placed in the correct scope
+        https://bugs.webkit.org/show_bug.cgi?id=128126
+
+        Reviewed by Antti Koivisto.
+
+        Added tests for correct behaviour.
+
+        * js/deconstructing-parameters-should-be-locals-expected.txt: Added.
+        * js/deconstructing-parameters-should-be-locals.html: Added.
+        * js/script-tests/deconstructing-parameters-should-be-locals.js: Added.
+        (description.value.string_appeared_here.readDeconstructedParameter):
+        (overwriteDeconstructedParameter):
+        (readCapturedDeconstructedParameter):
+        (overwriteCapturedDeconstructedParameter):
+
 2014-01-31  Geoffrey Garen  <[email protected]>
 
         Simplified name scope creation for function expressions

Added: trunk/LayoutTests/js/deconstructing-parameters-should-be-locals-expected.txt (0 => 163328)


--- trunk/LayoutTests/js/deconstructing-parameters-should-be-locals-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/deconstructing-parameters-should-be-locals-expected.txt	2014-02-03 22:43:28 UTC (rev 163328)
@@ -0,0 +1,14 @@
+This tests to ensure that ddeconstructing parameters behave like regular locals
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS readDeconstructedParameter(['inner']) is 'inner'
+PASS overwriteDeconstructedParameter(['unused']); value; is 'outer'
+PASS readCapturedDeconstructedParameter(['inner']) is 'inner'
+PASS overwriteCapturedDeconstructedParameter(['unused']); is 'innermost'
+PASS value is 'outer'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/deconstructing-parameters-should-be-locals.html (0 => 163328)


--- trunk/LayoutTests/js/deconstructing-parameters-should-be-locals.html	                        (rev 0)
+++ trunk/LayoutTests/js/deconstructing-parameters-should-be-locals.html	2014-02-03 22:43:28 UTC (rev 163328)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/script-tests/deconstructing-parameters-should-be-locals.js (0 => 163328)


--- trunk/LayoutTests/js/script-tests/deconstructing-parameters-should-be-locals.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/deconstructing-parameters-should-be-locals.js	2014-02-03 22:43:28 UTC (rev 163328)
@@ -0,0 +1,35 @@
+description("This tests to ensure that ddeconstructing parameters behave like regular locals")
+
+var value="outer"
+function readDeconstructedParameter([value]) {
+    return value;
+}
+
+function overwriteDeconstructedParameter([value]) {
+	value = "inner"
+}
+
+function readCapturedDeconstructedParameter([value]) {
+	return (function () {
+	    return value;
+	})()
+}
+
+function overwriteCapturedDeconstructedParameter([value]) {
+	(function () {
+	    value = "innermost";
+	})()
+	return value
+}
+
+shouldBe("readDeconstructedParameter(['inner'])", "'inner'")
+overwriteDeconstructedParameter(['inner'])
+
+shouldBe("overwriteDeconstructedParameter(['unused']); value;", "'outer'")
+
+shouldBe("readCapturedDeconstructedParameter(['inner'])", "'inner'")
+overwriteDeconstructedParameter(['inner'])
+
+shouldBe("overwriteCapturedDeconstructedParameter(['unused']);", "'innermost'")
+shouldBe("value", "'outer'")
+

Modified: trunk/Source/_javascript_Core/ChangeLog (163327 => 163328)


--- trunk/Source/_javascript_Core/ChangeLog	2014-02-03 22:39:38 UTC (rev 163327)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-02-03 22:43:28 UTC (rev 163328)
@@ -1,3 +1,25 @@
+2014-02-03  Oliver Hunt  <[email protected]>
+
+        Deconstructed parameters aren't being placed in the correct scope
+        https://bugs.webkit.org/show_bug.cgi?id=128126
+
+        Reviewed by Antti Koivisto.
+
+        Make sure we declare the bound parameter names as variables when
+        we reparse.  In the BytecodeGenerator we now also directly ensure
+        that bound parameters are placed in the symbol table of the function
+        we're currently compiling.  We then delay binding until just before
+        we start codegen for the body of the function so that we can ensure
+        the function has completely initialised all scope details.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::generate):
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * bytecompiler/BytecodeGenerator.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::Parser):
+        (JSC::Parser<LexerType>::createBindingPattern):
+
 2014-02-03  Alexey Proskuryakov  <[email protected]>
 
         Update JS whitespace definition for changes in Unicode 6.3

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (163327 => 163328)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2014-02-03 22:39:38 UTC (rev 163327)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2014-02-03 22:43:28 UTC (rev 163328)
@@ -63,6 +63,10 @@
     SamplingRegion samplingRegion("Bytecode Generation");
     
     m_codeBlock->setThisRegister(m_thisRegister.virtualRegister());
+    for (size_t i = 0; i < m_deconstructedParameters.size(); i++) {
+        auto& entry = m_deconstructedParameters[i];
+        entry.second->bindValue(*this, entry.first.get());
+    }
 
     m_scopeNode->emitBytecode(*this);
 
@@ -298,10 +302,16 @@
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     const DeclarationStacks::VarStack& varStack = functionBody->varStack();
+    IdentifierSet test;
 
     // Captured variables and functions go first so that activations don't have
     // to step over the non-captured locals to mark them.
     if (functionBody->hasCapturedVariables()) {
+        for (size_t i = 0; i < boundParameterProperties.size(); i++) {
+            const Identifier& ident = boundParameterProperties[i];
+            if (functionBody->captures(ident))
+                addVar(ident, IsVariable, IsWatchable);
+        }
         for (size_t i = 0; i < functionStack.size(); ++i) {
             FunctionBodyNode* function = functionStack[i];
             const Identifier& ident = function->ident();
@@ -338,6 +348,11 @@
         }
     }
     m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
+    for (size_t i = 0; i < boundParameterProperties.size(); i++) {
+        const Identifier& ident = boundParameterProperties[i];
+        if (!functionBody->captures(ident))
+            addVar(ident, IsVariable, IsWatchable);
+    }
     for (size_t i = 0; i < varStack.size(); ++i) {
         const Identifier& ident = varStack[i].first;
         if (!functionBody->captures(ident))
@@ -356,7 +371,6 @@
     int nextParameterIndex = CallFrame::thisArgumentOffset();
     m_thisRegister.setIndex(nextParameterIndex++);
     m_codeBlock->addParameter();
-    Vector<std::pair<RegisterID*, const DeconstructionPatternNode*>> deconstructedParameters;
     for (size_t i = 0; i < parameters.size(); ++i, ++nextParameterIndex) {
         int index = nextParameterIndex;
         auto pattern = parameters.at(i);
@@ -364,7 +378,7 @@
             m_codeBlock->addParameter();
             RegisterID& parameter = registerFor(index);
             parameter.setIndex(index);
-            deconstructedParameters.append(std::make_pair(&parameter, pattern));
+            m_deconstructedParameters.append(std::make_pair(&parameter, pattern));
             continue;
         }
         auto simpleParameter = static_cast<const BindingNode*>(pattern);
@@ -389,10 +403,6 @@
         instructions().append(kill(&m_thisRegister));
         instructions().append(0);
     }
-    for (size_t i = 0; i < deconstructedParameters.size(); i++) {
-        auto& entry = deconstructedParameters[i];
-        entry.second->bindValue(*this, entry.first);
-    }
 }
 
 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (163327 => 163328)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2014-02-03 22:39:38 UTC (rev 163327)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2014-02-03 22:43:28 UTC (rev 163328)
@@ -644,6 +644,7 @@
         Vector<SwitchInfo> m_switchContextStack;
         Vector<ForInContext> m_forInContextStack;
         Vector<TryContext> m_tryContextStack;
+        Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
         
         Vector<TryRange> m_tryRanges;
         SegmentedVector<TryData, 8> m_tryData;

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (163327 => 163328)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2014-02-03 22:39:38 UTC (rev 163327)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2014-02-03 22:43:28 UTC (rev 163328)
@@ -219,12 +219,26 @@
     if (strictness == JSParseStrict)
         scope->setStrictMode();
     if (parameters) {
+        bool hadBindingParameters = false;
         for (unsigned i = 0; i < parameters->size(); i++) {
             auto parameter = parameters->at(i);
-            if (!parameter->isBindingNode())
+            if (!parameter->isBindingNode()) {
+                hadBindingParameters = true;
                 continue;
+            }
             scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty());
         }
+        if (hadBindingParameters) {
+            Vector<Identifier> boundParameterNames;
+            for (unsigned i = 0; i < parameters->size(); i++) {
+                auto parameter = parameters->at(i);
+                if (parameter->isBindingNode())
+                    continue;
+                parameter->collectBoundIdentifiers(boundParameterNames);
+            }
+            for (auto boundParameterName : boundParameterNames)
+                scope->declareVariable(&boundParameterName);
+        }
     }
     if (!name.isNull())
         scope->declareCallee(&name);
@@ -498,7 +512,8 @@
             }
         }
         if (kind != DeconstructToExpressions)
-            context.addVar(&name, kind == DeconstructToParameters ? 0 : DeclarationStacks::HasInitializer);
+            context.addVar(&name, DeclarationStacks::HasInitializer);
+
     } else {
         if (kind == DeconstructToVariables) {
             failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to