Changeset 109177 in webkit
- Timestamp:
- Feb 28, 2012 5:39:15 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r109176 r109177 1 2012-02-28 Gavin Barraclough <barraclough@apple.com> 2 3 [[Get]]/[[Put]] for primitives should not wrap on strict accessor call 4 https://bugs.webkit.org/show_bug.cgi?id=79588 5 6 Reviewed by Oliver Hunt. 7 8 In the case of [[Get]], this is a pretty trivial bug - just don't wrap 9 primitives at the point you call a getter. 10 11 For setters, this is a little more involved, since we have already wrapped 12 the value up in a synthesized object. Stop doing so. There is also a further 13 subtely, that in strict mode all attempts to create a new data property on 14 the object should throw. 15 16 * fast/js/mozilla/strict/15.5.5.1-expected.txt: 17 * fast/js/primitive-property-access-edge-cases-expected.txt: 18 * fast/js/read-modify-eval-expected.txt: 19 * fast/js/script-tests/primitive-property-access-edge-cases.js: 20 * fast/js/script-tests/read-modify-eval.js: 21 - Added new test cases & updated test results. 22 1 23 2012-02-28 Daniel Cheng <dcheng@chromium.org> 2 24 -
trunk/LayoutTests/fast/js/mozilla/strict/15.5.5.1-expected.txt
r78731 r109177 5 5 PASS var s = str(); delete s.length is false 6 6 PASS true === true 7 FAIL 'use strict'; "foo".length = 1 should throw an instance of TypeError 7 PASS 'use strict'; "foo".length = 1 threw exception of type TypeError. 8 8 PASS "foo".length = 1 is 1 9 9 PASS true === true -
trunk/LayoutTests/fast/js/primitive-property-access-edge-cases-expected.txt
r39374 r109177 4 4 5 5 6 PASS checkGet(1, Number) is true 7 PASS checkGet('hello', String) is true 8 PASS checkGet(true, Boolean) is true 9 PASS checkSet(1, Number) is true 10 PASS checkSet('hello', String) is true 11 PASS checkSet(true, Boolean) is true 12 PASS checkGetStrict(1, Number) is true 13 PASS checkGetStrict('hello', String) is true 14 PASS checkGetStrict(true, Boolean) is true 15 PASS checkSetStrict(1, Number) is true 16 PASS checkSetStrict('hello', String) is true 17 PASS checkSetStrict(true, Boolean) is true 18 PASS checkRead(1, Number) is true 19 PASS checkRead('hello', String) is true 20 PASS checkRead(true, Boolean) is true 21 PASS checkWrite(1, Number) is true 22 PASS checkWrite('hello', String) is true 23 PASS checkWrite(true, Boolean) is true 24 PASS checkReadStrict(1, Number) is true 25 PASS checkReadStrict('hello', String) is true 26 PASS checkReadStrict(true, Boolean) is true 27 PASS checkWriteStrict(1, Number) threw exception TypeError: Attempted to assign to readonly property.. 28 PASS checkWriteStrict('hello', String) threw exception TypeError: Attempted to assign to readonly property.. 29 PASS checkWriteStrict(true, Boolean) threw exception TypeError: Attempted to assign to readonly property.. 6 30 PASS didNotCrash is true 7 31 PASS successfullyParsed is true -
trunk/LayoutTests/fast/js/read-modify-eval-expected.txt
r91164 r109177 20 20 PASS postDecTest(); is true 21 21 PASS primitiveThisTest.call(1); is true 22 PASS strictThisTest.call(1); is true22 PASS strictThisTest.call(1); threw exception TypeError: Attempted to assign to readonly property.. 23 23 PASS successfullyParsed is true 24 24 -
trunk/LayoutTests/fast/js/script-tests/primitive-property-access-edge-cases.js
r98407 r109177 38 38 })(); 39 39 40 41 var checkOkay; 42 43 function checkGet(x, constructor) 44 { 45 checkOkay = false; 46 Object.defineProperty(constructor.prototype, "foo", { get: function() { checkOkay = typeof this === 'object'; }, configurable: true }); 47 x.foo; 48 delete constructor.prototype.foo; 49 return checkOkay; 50 } 51 52 function checkSet(x, constructor) 53 { 54 checkOkay = false; 55 Object.defineProperty(constructor.prototype, "foo", { set: function() { checkOkay = typeof this === 'object'; }, configurable: true }); 56 x.foo = null; 57 delete constructor.prototype.foo; 58 return checkOkay; 59 } 60 61 function checkGetStrict(x, constructor) 62 { 63 checkOkay = false; 64 Object.defineProperty(constructor.prototype, "foo", { get: function() { "use strict"; checkOkay = typeof this !== 'object'; }, configurable: true }); 65 x.foo; 66 delete constructor.prototype.foo; 67 return checkOkay; 68 } 69 70 function checkSetStrict(x, constructor) 71 { 72 checkOkay = false; 73 Object.defineProperty(constructor.prototype, "foo", { set: function() { "use strict"; checkOkay = typeof this !== 'object'; }, configurable: true }); 74 x.foo = null; 75 delete constructor.prototype.foo; 76 return checkOkay; 77 } 78 79 shouldBeTrue("checkGet(1, Number)"); 80 shouldBeTrue("checkGet('hello', String)"); 81 shouldBeTrue("checkGet(true, Boolean)"); 82 shouldBeTrue("checkSet(1, Number)"); 83 shouldBeTrue("checkSet('hello', String)"); 84 shouldBeTrue("checkSet(true, Boolean)"); 85 shouldBeTrue("checkGetStrict(1, Number)"); 86 shouldBeTrue("checkGetStrict('hello', String)"); 87 shouldBeTrue("checkGetStrict(true, Boolean)"); 88 shouldBeTrue("checkSetStrict(1, Number)"); 89 shouldBeTrue("checkSetStrict('hello', String)"); 90 shouldBeTrue("checkSetStrict(true, Boolean)"); 91 92 function checkRead(x, constructor) 93 { 94 return x.foo === undefined; 95 } 96 97 function checkWrite(x, constructor) 98 { 99 x.foo = null; 100 return x.foo === undefined; 101 } 102 103 function checkReadStrict(x, constructor) 104 { 105 "use strict"; 106 return x.foo === undefined; 107 } 108 109 function checkWriteStrict(x, constructor) 110 { 111 "use strict"; 112 x.foo = null; 113 return x.foo === undefined; 114 } 115 116 shouldBeTrue("checkRead(1, Number)"); 117 shouldBeTrue("checkRead('hello', String)"); 118 shouldBeTrue("checkRead(true, Boolean)"); 119 shouldBeTrue("checkWrite(1, Number)"); 120 shouldBeTrue("checkWrite('hello', String)"); 121 shouldBeTrue("checkWrite(true, Boolean)"); 122 shouldBeTrue("checkReadStrict(1, Number)"); 123 shouldBeTrue("checkReadStrict('hello', String)"); 124 shouldBeTrue("checkReadStrict(true, Boolean)"); 125 shouldThrow("checkWriteStrict(1, Number)"); 126 shouldThrow("checkWriteStrict('hello', String)"); 127 shouldThrow("checkWriteStrict(true, Boolean)"); 128 40 129 shouldBeTrue("didNotCrash"); -
trunk/LayoutTests/fast/js/script-tests/read-modify-eval.js
r98407 r109177 120 120 // In a strict mode function primitive this values are not converted, so 121 121 // the property access in the first eval is writing a value to a temporary 122 // object , and should not be observed by the second eval.122 // object. This throws, per section 8.7.2. 123 123 "use strict"; 124 124 eval('this.value = "Seekrit message";'); … … 144 144 145 145 shouldBeTrue('primitiveThisTest.call(1);'); 146 should BeTrue('strictThisTest.call(1);');146 shouldThrow('strictThisTest.call(1);'); -
trunk/Source/JavaScriptCore/ChangeLog
r109174 r109177 1 2012-02-28 Gavin Barraclough <barraclough@apple.com> 2 3 [[Get]]/[[Put]] for primitives should not wrap on strict accessor call 4 https://bugs.webkit.org/show_bug.cgi?id=79588 5 6 Reviewed by Oliver Hunt. 7 8 In the case of [[Get]], this is a pretty trivial bug - just don't wrap 9 primitives at the point you call a getter. 10 11 For setters, this is a little more involved, since we have already wrapped 12 the value up in a synthesized object. Stop doing so. There is also a further 13 subtely, that in strict mode all attempts to create a new data property on 14 the object should throw. 15 16 * runtime/JSCell.cpp: 17 (JSC::JSCell::put): 18 - [[Put]] to a string primitive should use JSValue::putToPrimitive. 19 * runtime/JSObject.cpp: 20 (JSC::JSObject::put): 21 - Remove static function called in one place. 22 * runtime/JSObject.h: 23 (JSC::JSValue::put): 24 - [[Put]] to a non-cell JSValue should use JSValue::putToPrimitive. 25 * runtime/JSValue.cpp: 26 (JSC::JSValue::synthesizePrototype): 27 - Add support for synthesizing the prototype of strings. 28 (JSC::JSValue::putToPrimitive): 29 - Added, implements [[Put]] for primitive bases, per 8.7.2. 30 * runtime/JSValue.h: 31 (JSValue): 32 - Add declaration for JSValue::putToPrimitive. 33 * runtime/PropertySlot.cpp: 34 (JSC::PropertySlot::functionGetter): 35 - Don't call ToObject on primitive this values. 36 1 37 2012-02-28 Mark Hahnenberg <mhahnenberg@apple.com> 2 38 -
trunk/Source/JavaScriptCore/runtime/JSCell.cpp
r107544 r109177 98 98 void JSCell::put(JSCell* cell, ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) 99 99 { 100 if (cell->isString()) { 101 JSValue(cell).putToPrimitive(exec, identifier, value, slot); 102 return; 103 } 100 104 JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject()); 101 105 thisObject->methodTable()->put(thisObject, exec, identifier, value, slot); -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r108427 r109177 120 120 } 121 121 122 static void throwSetterError(ExecState* exec)123 {124 throwError(exec, createTypeError(exec, "setting a property that has only a getter"));125 }126 127 122 // ECMA 8.6.2.2 128 123 void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) … … 162 157 if (!setterFunc) { 163 158 if (slot.isStrictMode()) 164 throw SetterError(exec);159 throwError(exec, createTypeError(exec, "setting a property that has only a getter")); 165 160 return; 166 161 } -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r108444 r109177 835 835 { 836 836 if (UNLIKELY(!isCell())) { 837 JSObject* thisObject = synthesizeObject(exec); 838 thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); 837 putToPrimitive(exec, propertyName, value, slot); 839 838 return; 840 839 } -
trunk/Source/JavaScriptCore/runtime/JSValue.cpp
r108444 r109177 28 28 #include "Error.h" 29 29 #include "ExceptionHelpers.h" 30 #include "GetterSetter.h" 30 31 #include "JSGlobalObject.h" 31 32 #include "JSFunction.h" … … 106 107 JSObject* JSValue::synthesizePrototype(ExecState* exec) const 107 108 { 108 ASSERT(!isCell()); 109 if (isCell()) { 110 ASSERT(isString()); 111 return exec->lexicalGlobalObject()->stringPrototype(); 112 } 113 109 114 if (isNumber()) 110 115 return exec->lexicalGlobalObject()->numberPrototype(); … … 115 120 throwError(exec, createNotAnObjectError(exec, *this)); 116 121 return JSNotAnObject::create(exec); 122 } 123 124 // ECMA 8.7.2 125 void JSValue::putToPrimitive(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) 126 { 127 JSGlobalData& globalData = exec->globalData(); 128 129 // Check if there are any setters or getters in the prototype chain 130 JSObject* obj = synthesizePrototype(exec); 131 JSValue prototype; 132 if (propertyName != exec->propertyNames().underscoreProto) { 133 for (; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) { 134 prototype = obj->prototype(); 135 if (prototype.isNull()) { 136 if (slot.isStrictMode()) 137 throwTypeError(exec, StrictModeReadonlyPropertyWriteError); 138 return; 139 } 140 } 141 } 142 143 for (; ; obj = asObject(prototype)) { 144 unsigned attributes; 145 JSCell* specificValue; 146 size_t offset = obj->structure()->get(globalData, propertyName, attributes, specificValue); 147 if (offset != WTF::notFound) { 148 if (attributes & ReadOnly) { 149 if (slot.isStrictMode()) 150 throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError)); 151 return; 152 } 153 154 JSValue gs = obj->getDirectOffset(offset); 155 if (gs.isGetterSetter()) { 156 JSObject* setterFunc = asGetterSetter(gs)->setter(); 157 if (!setterFunc) { 158 if (slot.isStrictMode()) 159 throwError(exec, createTypeError(exec, "setting a property that has only a getter")); 160 return; 161 } 162 163 CallData callData; 164 CallType callType = setterFunc->methodTable()->getCallData(setterFunc, callData); 165 MarkedArgumentBuffer args; 166 args.append(value); 167 168 // If this is WebCore's global object then we need to substitute the shell. 169 call(exec, setterFunc, callType, callData, *this, args); 170 return; 171 } 172 173 // If there's an existing property on the object or one of its 174 // prototypes it should be replaced, so break here. 175 break; 176 } 177 178 prototype = obj->prototype(); 179 if (prototype.isNull()) 180 break; 181 } 182 183 if (slot.isStrictMode()) 184 throwTypeError(exec, StrictModeReadonlyPropertyWriteError); 185 return; 117 186 } 118 187 -
trunk/Source/JavaScriptCore/runtime/JSValue.h
r108444 r109177 222 222 JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const; 223 223 void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); 224 void putToPrimitive(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); 224 225 void put(ExecState*, unsigned propertyName, JSValue); 225 226 -
trunk/Source/JavaScriptCore/runtime/PropertySlot.cpp
r97097 r109177 35 35 CallData callData; 36 36 CallType callType = m_data.getterFunc->methodTable()->getCallData(m_data.getterFunc, callData); 37 38 // Only objects can have accessor properties. 39 // If the base is WebCore's global object then we need to substitute the shell. 40 ASSERT(m_slotBase.isObject()); 41 return call(exec, m_data.getterFunc, callType, callData, m_thisValue.toThisObject(exec), exec->emptyList()); 37 return call(exec, m_data.getterFunc, callType, callData, m_thisValue.isObject() ? m_thisValue.toThisObject(exec) : m_thisValue, exec->emptyList()); 42 38 } 43 39
Note: See TracChangeset
for help on using the changeset viewer.