Source/JavaScriptCore: Strict mode does not work in non-trivial nested functions.
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Sep 2011 22:59:18 +0000 (22:59 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Sep 2011 22:59:18 +0000 (22:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=68740

Reviewed by Oliver Hunt.

Function-info caching does not preserve all state that it should.

* parser/JSParser.cpp:
(JSC::JSParser::Scope::saveFunctionInfo):
(JSC::JSParser::Scope::restoreFunctionInfo):
(JSC::JSParser::parseFunctionInfo):
* parser/SourceProviderCacheItem.h:

LayoutTests: gh@apple.com>

Strict mode does not work in non-trivial nested functions.
https://bugs.webkit.org/show_bug.cgi?id=68740

Reviewed by Oliver Hunt.

Function-info caching does not preserve all state that it should.

* fast/js/nested-functions-expected.txt: Added.
* fast/js/nested-functions.html: Added.
* fast/js/script-tests/nested-functions.js: Added.
(runTests.test1):
(runTests.test2):
(runTests.test3):
(runTests):

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

LayoutTests/ChangeLog
LayoutTests/fast/js/nested-functions-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/nested-functions.html [new file with mode: 0644]
LayoutTests/fast/js/script-tests/nested-functions.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/parser/JSParser.cpp
Source/JavaScriptCore/parser/SourceProviderCacheItem.h

index eaa8070..353abea 100644 (file)
@@ -1,3 +1,20 @@
+gh@apple.com>
+
+        Strict mode does not work in non-trivial nested functions.
+        https://bugs.webkit.org/show_bug.cgi?id=68740
+
+        Reviewed by Oliver Hunt.
+
+        Function-info caching does not preserve all state that it should.
+
+        * fast/js/nested-functions-expected.txt: Added.
+        * fast/js/nested-functions.html: Added.
+        * fast/js/script-tests/nested-functions.js: Added.
+        (runTests.test1):
+        (runTests.test2):
+        (runTests.test3):
+        (runTests):
+
 2011-09-23  Dan Bernstein  <mitz@apple.com>
 
         <rdar://problem/10178576> REGRESSION (r95391): Crash in -[WebCascadeList objectAtIndex:] when a font-family list contains missing fonts
diff --git a/LayoutTests/fast/js/nested-functions-expected.txt b/LayoutTests/fast/js/nested-functions-expected.txt
new file mode 100644 (file)
index 0000000..fcfe189
--- /dev/null
@@ -0,0 +1,13 @@
+This test ensures that properties of nested function code are not lost (due to cached function info).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS passed1 is true
+PASS passed2 is true
+PASS passed3 is true
+PASS passed4 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/nested-functions.html b/LayoutTests/fast/js/nested-functions.html
new file mode 100644 (file)
index 0000000..b4add49
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/nested-functions.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/script-tests/nested-functions.js b/LayoutTests/fast/js/script-tests/nested-functions.js
new file mode 100644 (file)
index 0000000..91e5376
--- /dev/null
@@ -0,0 +1,36 @@
+description(
+"This test ensures that properties of nested function code are not lost (due to cached function info)."
+);
+
+var passed1 = false;
+var passed2 = false;
+var passed3 = false;
+var passed4 = false;
+
+// Test cases deliberately nested!
+function runTests() {
+    // Formating of these functions is significant for regression
+    // testing; functions with small bodies are not cached!
+    function test1() { return this; }
+    function test2() { "use strict"; return this; }
+    function test3() {
+        return this ? "OKAY" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
+    }
+    function test4() {
+        "use strict";
+        return !this ? "OKAY" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
+    }
+
+    passed1 = test1() === this;
+    passed2 = test2() === undefined;
+    passed3 = test3() === "OKAY";
+    passed4 = test4() === "OKAY";
+};
+
+runTests();
+shouldBeTrue("passed1");
+shouldBeTrue("passed2");
+shouldBeTrue("passed3");
+shouldBeTrue("passed4");
+
+successfullyParsed = true;
index 77fe7c7..3a7282e 100644 (file)
@@ -1,3 +1,18 @@
+2011-09-23  Gavin Barraclough  <barraclough@apple.com>
+
+        Strict mode does not work in non-trivial nested functions.
+        https://bugs.webkit.org/show_bug.cgi?id=68740
+
+        Reviewed by Oliver Hunt.
+
+        Function-info caching does not preserve all state that it should.
+
+        * parser/JSParser.cpp:
+        (JSC::JSParser::Scope::saveFunctionInfo):
+        (JSC::JSParser::Scope::restoreFunctionInfo):
+        (JSC::JSParser::parseFunctionInfo):
+        * parser/SourceProviderCacheItem.h:
+
 2011-09-23  Filip Pizlo  <fpizlo@apple.com>
 
         ValueToDouble handling in prediction propagation should be ASSERT_NOT_REACHED
index 20f22a5..f445259 100644 (file)
@@ -752,6 +752,8 @@ private:
         {
             ASSERT(m_isFunction);
             info->usesEval = m_usesEval;
+            info->strictMode = m_strictMode;
+            info->needsFullActivation = m_needsFullActivation;
             copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables);
             copyCapturedVariablesToVector(m_usedVariables, info->usedVariables);
         }
@@ -760,6 +762,8 @@ private:
         {
             ASSERT(m_isFunction);
             m_usesEval = info->usesEval;
+            m_strictMode = info->strictMode;
+            m_needsFullActivation = info->needsFullActivation;
             unsigned size = info->usedVariables.size();
             for (unsigned i = 0; i < size; ++i)
                 m_usedVariables.add(info->usedVariables[i]);
@@ -1608,9 +1612,11 @@ template <JSParser::FunctionRequirements requirements, bool nameIsInContainingSc
     openBracePos = m_token.m_data.intValue;
     bodyStartLine = tokenLine();
 
+    // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
     if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) {
-        // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
-        body = context.createFunctionBody(strictMode());
+        // If we're in a strict context, the cached function info must say it was strict too.
+        ASSERT(!strictMode() || cachedInfo->strictMode);
+        body = context.createFunctionBody(cachedInfo->strictMode);
 
         functionScope->restoreFunctionInfo(cachedInfo);
         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
index b9ab225..b433e6a 100644 (file)
@@ -59,6 +59,8 @@ public:
     int closeBraceLine;
     int closeBracePos;
     bool usesEval;
+    bool strictMode;
+    bool needsFullActivation;
     Vector<RefPtr<StringImpl> > usedVariables;
     Vector<RefPtr<StringImpl> > writtenVariables;
 };