Changeset 109824 in webkit


Ignore:
Timestamp:
Mar 5, 2012 5:18:42 PM (12 years ago)
Author:
barraclough@apple.com
Message:

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

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

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.
Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r109820 r109824  
     12012-03-05  Gavin Barraclough  <barraclough@apple.com>
     2
     3        putByIndex should throw in strict mode
     4        https://bugs.webkit.org/show_bug.cgi?id=80335
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * fast/js/primitive-property-access-edge-cases-expected.txt:
     9        * fast/js/script-tests/primitive-property-access-edge-cases.js:
     10        (checkNumericGet.Object.defineProperty):
     11        (checkNumericSet.Object.defineProperty):
     12        (checkNumericGetStrict.Object.defineProperty):
     13        (checkNumericSetStrict.Object.defineProperty):
     14        (checkNumericRead):
     15        (checkNumericWrite):
     16        (checkNumericReadStrict):
     17        (checkNumericWriteStrict):
     18            - Added test cases.
     19
    1202012-03-05  Stephen Chenney  <schenney@chromium.org>
    221
  • trunk/LayoutTests/fast/js/primitive-property-access-edge-cases-expected.txt

    r109177 r109824  
    2828PASS checkWriteStrict('hello', String) threw exception TypeError: Attempted to assign to readonly property..
    2929PASS checkWriteStrict(true, Boolean) threw exception TypeError: Attempted to assign to readonly property..
     30PASS checkNumericGet(1, Number) is true
     31PASS checkNumericGet('hello', String) is true
     32PASS checkNumericGet(true, Boolean) is true
     33PASS checkNumericSet(1, Number) is true
     34PASS checkNumericSet('hello', String) is true
     35PASS checkNumericSet(true, Boolean) is true
     36PASS checkNumericGetStrict(1, Number) is true
     37PASS checkNumericGetStrict('hello', String) is true
     38PASS checkNumericGetStrict(true, Boolean) is true
     39PASS checkNumericSetStrict(1, Number) is true
     40PASS checkNumericSetStrict(true, Boolean) is true
     41PASS checkNumericRead(1, Number) is true
     42PASS checkNumericRead('hello', String) is true
     43PASS checkNumericRead(true, Boolean) is true
     44PASS checkNumericWrite(1, Number) is true
     45PASS checkNumericWrite('hello', String) is true
     46PASS checkNumericWrite(true, Boolean) is true
     47PASS checkNumericReadStrict(1, Number) is true
     48PASS checkNumericReadStrict('hello', String) is true
     49PASS checkNumericReadStrict(true, Boolean) is true
     50PASS checkNumericWriteStrict(1, Number) threw exception TypeError: Attempted to assign to readonly property..
     51PASS checkNumericWriteStrict(true, Boolean) threw exception TypeError: Attempted to assign to readonly property..
    3052PASS didNotCrash is true
    3153PASS successfullyParsed is true
  • trunk/LayoutTests/fast/js/script-tests/primitive-property-access-edge-cases.js

    r109177 r109824  
    127127shouldThrow("checkWriteStrict(true, Boolean)");
    128128
     129function checkNumericGet(x, constructor)
     130{
     131    checkOkay = false;
     132    Object.defineProperty(constructor.prototype, 42, { get: function() { checkOkay = typeof this === 'object'; }, configurable: true });
     133    x[42];
     134    delete constructor.prototype[42];
     135    return checkOkay;
     136}
     137
     138function checkNumericSet(x, constructor)
     139{
     140    checkOkay = false;
     141    Object.defineProperty(constructor.prototype, 42, { set: function() { checkOkay = typeof this === 'object'; }, configurable: true });
     142    x[42] = null;
     143    delete constructor.prototype[42];
     144    return checkOkay;
     145}
     146
     147function checkNumericGetStrict(x, constructor)
     148{
     149    checkOkay = false;
     150    Object.defineProperty(constructor.prototype, 42, { get: function() { "use strict"; checkOkay = typeof this !== 'object'; }, configurable: true });
     151    x[42];
     152    delete constructor.prototype[42];
     153    return checkOkay;
     154}
     155
     156function checkNumericSetStrict(x, constructor)
     157{
     158    checkOkay = false;
     159    Object.defineProperty(constructor.prototype, 42, { set: function() { "use strict"; checkOkay = typeof this !== 'object'; }, configurable: true });
     160    x[42] = null;
     161    delete constructor.prototype[42];
     162    return checkOkay;
     163}
     164
     165shouldBeTrue("checkNumericGet(1, Number)");
     166shouldBeTrue("checkNumericGet('hello', String)");
     167shouldBeTrue("checkNumericGet(true, Boolean)");
     168shouldBeTrue("checkNumericSet(1, Number)");
     169shouldBeTrue("checkNumericSet('hello', String)");
     170shouldBeTrue("checkNumericSet(true, Boolean)");
     171shouldBeTrue("checkNumericGetStrict(1, Number)");
     172shouldBeTrue("checkNumericGetStrict('hello', String)");
     173shouldBeTrue("checkNumericGetStrict(true, Boolean)");
     174shouldBeTrue("checkNumericSetStrict(1, Number)");
     175//shouldBeTrue("checkNumericSetStrict('hello', String)"); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=80335
     176shouldBeTrue("checkNumericSetStrict(true, Boolean)");
     177
     178function checkNumericRead(x, constructor)
     179{
     180    return x[42] === undefined;
     181}
     182
     183function checkNumericWrite(x, constructor)
     184{
     185    x[42] = null;
     186    return x[42] === undefined;
     187}
     188
     189function checkNumericReadStrict(x, constructor)
     190{
     191    "use strict";
     192    return x[42] === undefined;
     193}
     194
     195function checkNumericWriteStrict(x, constructor)
     196{
     197    "use strict";
     198    x[42] = null;
     199    return x[42] === undefined;
     200}
     201
     202shouldBeTrue("checkNumericRead(1, Number)");
     203shouldBeTrue("checkNumericRead('hello', String)");
     204shouldBeTrue("checkNumericRead(true, Boolean)");
     205shouldBeTrue("checkNumericWrite(1, Number)");
     206shouldBeTrue("checkNumericWrite('hello', String)");
     207shouldBeTrue("checkNumericWrite(true, Boolean)");
     208shouldBeTrue("checkNumericReadStrict(1, Number)");
     209shouldBeTrue("checkNumericReadStrict('hello', String)");
     210shouldBeTrue("checkNumericReadStrict(true, Boolean)");
     211shouldThrow("checkNumericWriteStrict(1, Number)");
     212//shouldThrow("checkNumericWriteStrict('hello', String)"); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=80335
     213shouldThrow("checkNumericWriteStrict(true, Boolean)");
     214
    129215shouldBeTrue("didNotCrash");
  • trunk/Source/JavaScriptCore/ChangeLog

    r109804 r109824  
     12012-03-05  Gavin Barraclough  <barraclough@apple.com>
     2
     3        putByIndex should throw in strict mode
     4        https://bugs.webkit.org/show_bug.cgi?id=80335
     5
     6        Reviewed by Filip Pizlo.
     7
     8        We'll need to pass an additional parameter.
     9
     10        Part 1 - rename JSValue::put() for integer indices to JSValue::putByIndex()
     11        to match the method in the MethodTable, make this take a parameter indicating
     12        whether the put should throw. This fixes the cases where the base of the put
     13        is a primitive.
     14
     15        * dfg/DFGOperations.cpp:
     16        (DFG):
     17        (JSC::DFG::putByVal):
     18        (JSC::DFG::operationPutByValInternal):
     19        * interpreter/Interpreter.cpp:
     20        (JSC::Interpreter::execute):
     21        (JSC::Interpreter::privateExecute):
     22        * jit/JITStubs.cpp:
     23        (JSC::DEFINE_STUB_FUNCTION):
     24        * llint/LLIntSlowPaths.cpp:
     25        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     26        * runtime/JSObject.h:
     27        (JSC::JSValue::putByIndex):
     28        * runtime/JSValue.cpp:
     29        (JSC):
     30        * runtime/JSValue.h:
     31        (JSValue):
     32
    1332012-03-05  Sam Weinig  <sam@webkit.org>
    234
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r109172 r109824  
    147147namespace JSC { namespace DFG {
    148148
     149template<bool strict>
    149150static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
    150151{
     
    176177    }
    177178
    178     baseValue.put(exec, index, value);
     179    baseValue.putByIndex(exec, index, value, strict);
    179180}
    180181
     
    190191
    191192    if (LIKELY(property.isUInt32())) {
    192         putByVal(exec, baseValue, property.asUInt32(), value);
     193        putByVal<strict>(exec, baseValue, property.asUInt32(), value);
    193194        return;
    194195    }
     
    198199        uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
    199200        if (propertyAsDouble == propertyAsUInt32) {
    200             putByVal(exec, baseValue, propertyAsUInt32, value);
     201            putByVal<strict>(exec, baseValue, propertyAsUInt32, value);
    201202            return;
    202203        }
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r109627 r109824  
    11591159            }
    11601160            case JSONPPathEntryTypeLookup: {
    1161                 baseObject.put(callFrame, JSONPPath.last().m_pathIndex, JSONPValue);
     1161                baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
    11621162                if (callFrame->hadException())
    11631163                    return jsUndefined();
     
    37913791                    jsByteArray->setIndex(i, jsValue.asDouble());
    37923792                else
    3793                     baseValue.put(callFrame, i, jsValue);
     3793                    baseValue.putByIndex(callFrame, i, jsValue, codeBlock->isStrictMode());
    37943794            } else
    3795                 baseValue.put(callFrame, i, callFrame->r(value).jsValue());
     3795                baseValue.putByIndex(callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode());
    37963796        } else {
    37973797            Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
     
    38563856        int value = vPC[3].u.operand;
    38573857
    3858         callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
     3858        JSValue arrayValue = callFrame->r(base).jsValue();
     3859        ASSERT(isJSArray(arrayValue));
     3860        asArray(arrayValue)->putDirectIndex(callFrame, property, callFrame->r(value).jsValue(), false);
    38593861
    38603862        vPC += OPCODE_LENGTH(op_put_by_index);
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r109705 r109824  
    25692569            }
    25702570
    2571             baseValue.put(callFrame, i, value);
     2571            baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
    25722572        } else
    2573             baseValue.put(callFrame, i, value);
     2573            baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
    25742574    } else {
    25752575        Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
     
    26122612        if (!isJSByteArray(baseValue))
    26132613            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
    2614         baseValue.put(callFrame, i, value);
     2614        baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
    26152615    } else {
    26162616        Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
     
    34033403    unsigned property = stackFrame.args[1].int32();
    34043404
    3405     stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue());
     3405    JSValue arrayValue = stackFrame.args[0].jsValue();
     3406    ASSERT(isJSArray(arrayValue));
     3407    asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue(), false);
    34063408}
    34073409
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r109705 r109824  
    10601060            }
    10611061        }
    1062         baseValue.put(exec, i, value);
     1062        baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode());
    10631063        LLINT_END();
    10641064    }
     
    11001100{
    11011101    LLINT_BEGIN();
    1102     LLINT_OP_C(1).jsValue().put(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
     1102    JSValue arrayValue = LLINT_OP_C(1).jsValue();
     1103    ASSERT(isJSArray(arrayValue));
     1104    asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue(), false);
    11031105    LLINT_END();
    11041106}
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r109177 r109824  
    841841}
    842842
    843 inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
     843inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
    844844{
    845845    if (UNLIKELY(!isCell())) {
    846         JSObject* thisObject = synthesizeObject(exec);
    847         thisObject->methodTable()->putByIndex(thisObject, exec, propertyName, value);
     846        PutPropertySlot slot(shouldThrow);
     847        putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot);
    848848        return;
    849849    }
  • trunk/Source/JavaScriptCore/runtime/JSValue.cpp

    r109177 r109824  
    9090    ASSERT(isUndefinedOrNull());
    9191    return exec->globalThisValue();
    92 }
    93 
    94 JSObject* JSValue::synthesizeObject(ExecState* exec) const
    95 {
    96     ASSERT(!isCell());
    97     if (isNumber())
    98         return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
    99     if (isBoolean())
    100         return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
    101 
    102     ASSERT(isUndefinedOrNull());
    103     throwError(exec, createNotAnObjectError(exec, *this));
    104     return JSNotAnObject::create(exec);
    10592}
    10693
  • trunk/Source/JavaScriptCore/runtime/JSValue.h

    r109177 r109824  
    223223        void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    224224        void putToPrimitive(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    225         void put(ExecState*, unsigned propertyName, JSValue);
     225        void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
    226226
    227227        JSObject* toThisObject(ExecState*) const;
     
    253253        JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
    254254        JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
    255 
    256         JSObject* synthesizeObject(ExecState*) const;
    257255
    258256#if USE(JSVALUE32_64)
Note: See TracChangeset for help on using the changeset viewer.