Title: [109824] trunk
Revision
109824
Author
barraclo...@apple.com
Date
2012-03-05 17:18:42 -0800 (Mon, 05 Mar 2012)

Log Message

putByIndex should throw in strict mode
https://bugs.webkit.org/show_bug.cgi?id=80335

Reviewed by Filip Pizlo.

Source/_javascript_Core: 

We'll need to pass an additional parameter.

Part 1 - rename JSValue::put() for integer indices to JSValue::putByIndex()
to match the method in the MethodTable, make this take a parameter indicating
whether the put should throw. This fixes the cases where the base of the put
is a primitive.

* dfg/DFGOperations.cpp:
(DFG):
(JSC::DFG::putByVal):
(JSC::DFG::operationPutByValInternal):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::privateExecute):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSObject.h:
(JSC::JSValue::putByIndex):
* runtime/JSValue.cpp:
(JSC):
* runtime/JSValue.h:
(JSValue):

LayoutTests: 

* fast/js/primitive-property-access-edge-cases-expected.txt:
* fast/js/script-tests/primitive-property-access-edge-cases.js:
(checkNumericGet.Object.defineProperty):
(checkNumericSet.Object.defineProperty):
(checkNumericGetStrict.Object.defineProperty):
(checkNumericSetStrict.Object.defineProperty):
(checkNumericRead):
(checkNumericWrite):
(checkNumericReadStrict):
(checkNumericWriteStrict):
    - Added test cases.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (109823 => 109824)


--- trunk/LayoutTests/ChangeLog	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/LayoutTests/ChangeLog	2012-03-06 01:18:42 UTC (rev 109824)
@@ -1,3 +1,22 @@
+2012-03-05  Gavin Barraclough  <barraclo...@apple.com>
+
+        putByIndex should throw in strict mode
+        https://bugs.webkit.org/show_bug.cgi?id=80335
+
+        Reviewed by Filip Pizlo.
+
+        * fast/js/primitive-property-access-edge-cases-expected.txt:
+        * fast/js/script-tests/primitive-property-access-edge-cases.js:
+        (checkNumericGet.Object.defineProperty):
+        (checkNumericSet.Object.defineProperty):
+        (checkNumericGetStrict.Object.defineProperty):
+        (checkNumericSetStrict.Object.defineProperty):
+        (checkNumericRead):
+        (checkNumericWrite):
+        (checkNumericReadStrict):
+        (checkNumericWriteStrict):
+            - Added test cases.
+
 2012-03-05  Stephen Chenney  <schen...@chromium.org>
 
         [Chromium] SVG Composite of Offset crashes

Modified: trunk/LayoutTests/fast/js/primitive-property-access-edge-cases-expected.txt (109823 => 109824)


--- trunk/LayoutTests/fast/js/primitive-property-access-edge-cases-expected.txt	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/LayoutTests/fast/js/primitive-property-access-edge-cases-expected.txt	2012-03-06 01:18:42 UTC (rev 109824)
@@ -27,6 +27,28 @@
 PASS checkWriteStrict(1, Number) threw exception TypeError: Attempted to assign to readonly property..
 PASS checkWriteStrict('hello', String) threw exception TypeError: Attempted to assign to readonly property..
 PASS checkWriteStrict(true, Boolean) threw exception TypeError: Attempted to assign to readonly property..
+PASS checkNumericGet(1, Number) is true
+PASS checkNumericGet('hello', String) is true
+PASS checkNumericGet(true, Boolean) is true
+PASS checkNumericSet(1, Number) is true
+PASS checkNumericSet('hello', String) is true
+PASS checkNumericSet(true, Boolean) is true
+PASS checkNumericGetStrict(1, Number) is true
+PASS checkNumericGetStrict('hello', String) is true
+PASS checkNumericGetStrict(true, Boolean) is true
+PASS checkNumericSetStrict(1, Number) is true
+PASS checkNumericSetStrict(true, Boolean) is true
+PASS checkNumericRead(1, Number) is true
+PASS checkNumericRead('hello', String) is true
+PASS checkNumericRead(true, Boolean) is true
+PASS checkNumericWrite(1, Number) is true
+PASS checkNumericWrite('hello', String) is true
+PASS checkNumericWrite(true, Boolean) is true
+PASS checkNumericReadStrict(1, Number) is true
+PASS checkNumericReadStrict('hello', String) is true
+PASS checkNumericReadStrict(true, Boolean) is true
+PASS checkNumericWriteStrict(1, Number) threw exception TypeError: Attempted to assign to readonly property..
+PASS checkNumericWriteStrict(true, Boolean) threw exception TypeError: Attempted to assign to readonly property..
 PASS didNotCrash is true
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/js/script-tests/primitive-property-access-edge-cases.js (109823 => 109824)


--- trunk/LayoutTests/fast/js/script-tests/primitive-property-access-edge-cases.js	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/LayoutTests/fast/js/script-tests/primitive-property-access-edge-cases.js	2012-03-06 01:18:42 UTC (rev 109824)
@@ -126,4 +126,90 @@
 shouldThrow("checkWriteStrict('hello', String)");
 shouldThrow("checkWriteStrict(true, Boolean)");
 
+function checkNumericGet(x, constructor)
+{
+    checkOkay = false;
+    Object.defineProperty(constructor.prototype, 42, { get: function() { checkOkay = typeof this === 'object'; }, configurable: true });
+    x[42];
+    delete constructor.prototype[42];
+    return checkOkay;
+}
+
+function checkNumericSet(x, constructor)
+{
+    checkOkay = false;
+    Object.defineProperty(constructor.prototype, 42, { set: function() { checkOkay = typeof this === 'object'; }, configurable: true });
+    x[42] = null;
+    delete constructor.prototype[42];
+    return checkOkay;
+}
+
+function checkNumericGetStrict(x, constructor)
+{
+    checkOkay = false;
+    Object.defineProperty(constructor.prototype, 42, { get: function() { "use strict"; checkOkay = typeof this !== 'object'; }, configurable: true });
+    x[42];
+    delete constructor.prototype[42];
+    return checkOkay;
+}
+
+function checkNumericSetStrict(x, constructor)
+{
+    checkOkay = false;
+    Object.defineProperty(constructor.prototype, 42, { set: function() { "use strict"; checkOkay = typeof this !== 'object'; }, configurable: true });
+    x[42] = null;
+    delete constructor.prototype[42];
+    return checkOkay;
+}
+
+shouldBeTrue("checkNumericGet(1, Number)");
+shouldBeTrue("checkNumericGet('hello', String)");
+shouldBeTrue("checkNumericGet(true, Boolean)");
+shouldBeTrue("checkNumericSet(1, Number)");
+shouldBeTrue("checkNumericSet('hello', String)");
+shouldBeTrue("checkNumericSet(true, Boolean)");
+shouldBeTrue("checkNumericGetStrict(1, Number)");
+shouldBeTrue("checkNumericGetStrict('hello', String)");
+shouldBeTrue("checkNumericGetStrict(true, Boolean)");
+shouldBeTrue("checkNumericSetStrict(1, Number)");
+//shouldBeTrue("checkNumericSetStrict('hello', String)"); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=80335
+shouldBeTrue("checkNumericSetStrict(true, Boolean)");
+
+function checkNumericRead(x, constructor)
+{
+    return x[42] === undefined;
+}
+
+function checkNumericWrite(x, constructor)
+{
+    x[42] = null;
+    return x[42] === undefined;
+}
+
+function checkNumericReadStrict(x, constructor)
+{
+    "use strict";
+    return x[42] === undefined;
+}
+
+function checkNumericWriteStrict(x, constructor)
+{
+    "use strict";
+    x[42] = null;
+    return x[42] === undefined;
+}
+
+shouldBeTrue("checkNumericRead(1, Number)");
+shouldBeTrue("checkNumericRead('hello', String)");
+shouldBeTrue("checkNumericRead(true, Boolean)");
+shouldBeTrue("checkNumericWrite(1, Number)");
+shouldBeTrue("checkNumericWrite('hello', String)");
+shouldBeTrue("checkNumericWrite(true, Boolean)");
+shouldBeTrue("checkNumericReadStrict(1, Number)");
+shouldBeTrue("checkNumericReadStrict('hello', String)");
+shouldBeTrue("checkNumericReadStrict(true, Boolean)");
+shouldThrow("checkNumericWriteStrict(1, Number)");
+//shouldThrow("checkNumericWriteStrict('hello', String)"); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=80335
+shouldThrow("checkNumericWriteStrict(true, Boolean)");
+
 shouldBeTrue("didNotCrash");

Modified: trunk/Source/_javascript_Core/ChangeLog (109823 => 109824)


--- trunk/Source/_javascript_Core/ChangeLog	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-03-06 01:18:42 UTC (rev 109824)
@@ -1,3 +1,35 @@
+2012-03-05  Gavin Barraclough  <barraclo...@apple.com>
+
+        putByIndex should throw in strict mode
+        https://bugs.webkit.org/show_bug.cgi?id=80335
+
+        Reviewed by Filip Pizlo.
+
+        We'll need to pass an additional parameter.
+
+        Part 1 - rename JSValue::put() for integer indices to JSValue::putByIndex()
+        to match the method in the MethodTable, make this take a parameter indicating
+        whether the put should throw. This fixes the cases where the base of the put
+        is a primitive.
+
+        * dfg/DFGOperations.cpp:
+        (DFG):
+        (JSC::DFG::putByVal):
+        (JSC::DFG::operationPutByValInternal):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::privateExecute):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/JSObject.h:
+        (JSC::JSValue::putByIndex):
+        * runtime/JSValue.cpp:
+        (JSC):
+        * runtime/JSValue.h:
+        (JSValue):
+
 2012-03-05  Sam Weinig  <s...@webkit.org>
 
         Add support for hosting layers in the window server in WebKit2

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (109823 => 109824)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2012-03-06 01:18:42 UTC (rev 109824)
@@ -146,6 +146,7 @@
 
 namespace JSC { namespace DFG {
 
+template<bool strict>
 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
 {
     JSGlobalData* globalData = &exec->globalData();
@@ -175,7 +176,7 @@
         }
     }
 
-    baseValue.put(exec, index, value);
+    baseValue.putByIndex(exec, index, value, strict);
 }
 
 template<bool strict>
@@ -189,7 +190,7 @@
     JSValue value = JSValue::decode(encodedValue);
 
     if (LIKELY(property.isUInt32())) {
-        putByVal(exec, baseValue, property.asUInt32(), value);
+        putByVal<strict>(exec, baseValue, property.asUInt32(), value);
         return;
     }
 
@@ -197,7 +198,7 @@
         double propertyAsDouble = property.asDouble();
         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
         if (propertyAsDouble == propertyAsUInt32) {
-            putByVal(exec, baseValue, propertyAsUInt32, value);
+            putByVal<strict>(exec, baseValue, propertyAsUInt32, value);
             return;
         }
     }

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (109823 => 109824)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2012-03-06 01:18:42 UTC (rev 109824)
@@ -1158,7 +1158,7 @@
                 break;
             }
             case JSONPPathEntryTypeLookup: {
-                baseObject.put(callFrame, JSONPPath.last().m_pathIndex, JSONPValue);
+                baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
                 if (callFrame->hadException())
                     return jsUndefined();
                 break;
@@ -3790,9 +3790,9 @@
                 else if (jsValue.isDouble())
                     jsByteArray->setIndex(i, jsValue.asDouble());
                 else
-                    baseValue.put(callFrame, i, jsValue);
+                    baseValue.putByIndex(callFrame, i, jsValue, codeBlock->isStrictMode());
             } else
-                baseValue.put(callFrame, i, callFrame->r(value).jsValue());
+                baseValue.putByIndex(callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode());
         } else {
             Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
@@ -3855,7 +3855,9 @@
         unsigned property = vPC[2].u.operand;
         int value = vPC[3].u.operand;
 
-        callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
+        JSValue arrayValue = callFrame->r(base).jsValue();
+        ASSERT(isJSArray(arrayValue));
+        asArray(arrayValue)->putDirectIndex(callFrame, property, callFrame->r(value).jsValue(), false);
 
         vPC += OPCODE_LENGTH(op_put_by_index);
         NEXT_INSTRUCTION();

Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (109823 => 109824)


--- trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-03-06 01:18:42 UTC (rev 109824)
@@ -2568,9 +2568,9 @@
                 }
             }
 
-            baseValue.put(callFrame, i, value);
+            baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
         } else
-            baseValue.put(callFrame, i, value);
+            baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
     } else {
         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
@@ -2611,7 +2611,7 @@
 
         if (!isJSByteArray(baseValue))
             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
-        baseValue.put(callFrame, i, value);
+        baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
     } else {
         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
@@ -3402,7 +3402,9 @@
     CallFrame* callFrame = stackFrame.callFrame;
     unsigned property = stackFrame.args[1].int32();
 
-    stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue());
+    JSValue arrayValue = stackFrame.args[0].jsValue();
+    ASSERT(isJSArray(arrayValue));
+    asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue(), false);
 }
 
 DEFINE_STUB_FUNCTION(void*, op_switch_imm)

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (109823 => 109824)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2012-03-06 01:18:42 UTC (rev 109824)
@@ -1059,7 +1059,7 @@
                 LLINT_END();
             }
         }
-        baseValue.put(exec, i, value);
+        baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode());
         LLINT_END();
     }
     
@@ -1099,7 +1099,9 @@
 LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
 {
     LLINT_BEGIN();
-    LLINT_OP_C(1).jsValue().put(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
+    JSValue arrayValue = LLINT_OP_C(1).jsValue();
+    ASSERT(isJSArray(arrayValue));
+    asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue(), false);
     LLINT_END();
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (109823 => 109824)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2012-03-06 01:18:42 UTC (rev 109824)
@@ -840,11 +840,11 @@
     asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
 }
 
-inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
+inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
 {
     if (UNLIKELY(!isCell())) {
-        JSObject* thisObject = synthesizeObject(exec);
-        thisObject->methodTable()->putByIndex(thisObject, exec, propertyName, value);
+        PutPropertySlot slot(shouldThrow);
+        putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot);
         return;
     }
     asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value);

Modified: trunk/Source/_javascript_Core/runtime/JSValue.cpp (109823 => 109824)


--- trunk/Source/_javascript_Core/runtime/JSValue.cpp	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/runtime/JSValue.cpp	2012-03-06 01:18:42 UTC (rev 109824)
@@ -91,19 +91,6 @@
     return exec->globalThisValue();
 }
 
-JSObject* JSValue::synthesizeObject(ExecState* exec) const
-{
-    ASSERT(!isCell());
-    if (isNumber())
-        return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
-    if (isBoolean())
-        return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
-
-    ASSERT(isUndefinedOrNull());
-    throwError(exec, createNotAnObjectError(exec, *this));
-    return JSNotAnObject::create(exec);
-}
-
 JSObject* JSValue::synthesizePrototype(ExecState* exec) const
 {
     if (isCell()) {

Modified: trunk/Source/_javascript_Core/runtime/JSValue.h (109823 => 109824)


--- trunk/Source/_javascript_Core/runtime/JSValue.h	2012-03-06 01:18:12 UTC (rev 109823)
+++ trunk/Source/_javascript_Core/runtime/JSValue.h	2012-03-06 01:18:42 UTC (rev 109824)
@@ -222,7 +222,7 @@
         JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
         void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         void putToPrimitive(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        void put(ExecState*, unsigned propertyName, JSValue);
+        void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
 
         JSObject* toThisObject(ExecState*) const;
 
@@ -253,8 +253,6 @@
         JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
         JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
 
-        JSObject* synthesizeObject(ExecState*) const;
-
 #if USE(JSVALUE32_64)
         /*
          * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to