Changeset 107498 in webkit
- Timestamp:
- Feb 11, 2012 6:47:50 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r107496 r107498 1 2012-02-10 Gavin Barraclough <barraclough@apple.com> 2 3 Move special __proto__ property to Object.prototype 4 https://bugs.webkit.org/show_bug.cgi?id=78409 5 6 Reviewed by Oliver Hunt. 7 8 Re-implement this as a regular accessor property. This has three key benefits: 9 1) It makes it possible for objects to be given properties named __proto__. 10 2) Object.prototype.__proto__ can be deleted, preventing object prototypes from being changed. 11 3) This largely removes the magic used the implement __proto__, it can just be made a regular accessor property. 12 13 * fast/js/Object-getOwnPropertyNames-expected.txt: 14 * fast/js/cyclic-prototypes-expected.txt: 15 * fast/js/parser-syntax-check-expected.txt: 16 * fast/js/preventExtensions-expected.txt: 17 * fast/js/prototypes-expected.txt: 18 - Update results 19 * fast/js/script-tests/Object-getOwnPropertyNames.js: 20 - __proto__ is now a property of Object Prototype. 21 * fast/js/script-tests/cyclic-prototypes.js: 22 - setting an object's prototype to null removes __proto__ setter, future usage won't set prototype. 23 * fast/js/script-tests/parser-syntax-check.js: 24 - Allow functions named __proto__ 25 * fast/js/script-tests/preventExtensions.js: 26 - Setting __proto__ should not throw. 27 * fast/js/script-tests/prototypes.js: 28 - Objects may contained own properties named __proto__, add new test cases. 29 1 30 2012-02-11 Filip Pizlo <fpizlo@apple.com> 2 31 -
trunk/LayoutTests/fast/js/Object-getOwnPropertyNames-expected.txt
r95867 r107498 42 42 PASS getSortedOwnPropertyNames(encodeURIComponent) is ['length', 'name'] 43 43 PASS getSortedOwnPropertyNames(Object) is ['create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getPrototypeOf', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal'] 44 PASS getSortedOwnPropertyNames(Object.prototype) is ['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', ' constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']44 PASS getSortedOwnPropertyNames(Object.prototype) is ['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf'] 45 45 PASS getSortedOwnPropertyNames(Function) is ['length', 'name', 'prototype'] 46 46 PASS getSortedOwnPropertyNames(Function.prototype) is ['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString'] -
trunk/LayoutTests/fast/js/cyclic-prototypes-expected.txt
r21336 r107498 4 4 5 5 6 PASS o1.__proto__ = o3 threw exception Error: cyclic __proto__ value. 6 PASS o1.__proto__ = o3; threw exception Error: cyclic __proto__ value. 7 PASS ({}).hasOwnProperty.call(o1, '__proto__') is false 8 PASS ({}).hasOwnProperty.call(o1, '__proto__') is true 9 PASS Object.getPrototypeOf(o1) is null 7 10 PASS successfullyParsed is true 8 11 -
trunk/LayoutTests/fast/js/parser-syntax-check-expected.txt
r106297 r107498 542 542 PASS Invalid: "for(var a,b '" 543 543 PASS Invalid: "function f() { for(var a,b ' }" 544 PASS Invalid:"function __proto__(){}"545 PASS Invalid:"function f() { function __proto__(){} }"546 PASS Invalid:"(function __proto__(){})"547 PASS Invalid:"function f() { (function __proto__(){}) }"548 PASS Invalid:"'use strict'; function __proto__(){}"549 PASS Invalid:"function f() { 'use strict'; function __proto__(){} }"550 PASS Invalid:"'use strict'; (function __proto__(){})"551 PASS Invalid:"function f() { 'use strict'; (function __proto__(){}) }"544 PASS Valid: "function __proto__(){}" 545 PASS Valid: "function f() { function __proto__(){} }" 546 PASS Valid: "(function __proto__(){})" 547 PASS Valid: "function f() { (function __proto__(){}) }" 548 PASS Valid: "'use strict'; function __proto__(){}" 549 PASS Valid: "function f() { 'use strict'; function __proto__(){} }" 550 PASS Valid: "'use strict'; (function __proto__(){})" 551 PASS Valid: "function f() { 'use strict'; (function __proto__(){}) }" 552 552 PASS Valid: "if (0) $foo; " 553 553 PASS Valid: "function f() { if (0) $foo; }" -
trunk/LayoutTests/fast/js/preventExtensions-expected.txt
r93048 r107498 13 13 PASS Object.preventExtensions(Math.sin) is Math.sin 14 14 PASS var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" }; o.newProp; is undefined. 15 PASS "use strict"; var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" }; threw exception TypeError: Attempted to assign to readonly property..15 PASS "use strict"; var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" }; o.newProp; is undefined. 16 16 PASS Object.preventExtensions(Math); Math.sqrt(4) is 2 17 17 PASS successfullyParsed is true -
trunk/LayoutTests/fast/js/prototypes-expected.txt
r98998 r107498 54 54 PASS Object.__proto__.isPrototypeOf(Number) is true 55 55 PASS Object.__proto__.isPrototypeOf(String) is true 56 PASS var wasSet = false; var o = { }; o.__defineGetter__("__proto__", function() { wasSet = true }); o.__proto__; wasSet; is false57 PASS var wasSet = false; var o = { }; o.__defineSetter__("__proto__", function() { wasSet = true }); o.__proto__ = {}; wasSet; is false58 PASS var wasSet = false; var o = { }; Object.defineProperty(o, "__proto__", { "get": function() { wasSet = true } }); o.__proto__; wasSet; is false56 PASS var wasSet = false; var o = { }; o.__defineGetter__("__proto__", function() { wasSet = true }); o.__proto__; wasSet; is true 57 PASS var wasSet = false; var o = { }; o.__defineSetter__("__proto__", function() { wasSet = true }); o.__proto__ = {}; wasSet; is true 58 PASS var wasSet = false; var o = { }; Object.defineProperty(o, "__proto__", { "get": function() { wasSet = true } }); o.__proto__; wasSet; is true 59 59 PASS var wasSet = false; var o = { }; Object.defineProperty(o, "__proto__", { "__proto__": function(x) { wasSet = true } }); o.__proto__ = {}; wasSet; is false 60 PASS var o = {}; o.__proto__ = { x:true }; o.x is true 61 PASS var o = {}; o.__proto__ = { x:true }; o.hasOwnProperty('__proto__') is false 62 PASS var o = {}; o.__proto__ = { x:true }; o.x is undefined. 63 PASS var o = {}; o.__proto__ = { x:true }; o.hasOwnProperty('__proto__') is true 60 64 PASS successfullyParsed is true 61 65 -
trunk/LayoutTests/fast/js/script-tests/Object-getOwnPropertyNames.js
r98407 r107498 50 50 // Built-in ECMA objects 51 51 "Object": "['create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getPrototypeOf', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal']", 52 "Object.prototype": "['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', ' constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']",52 "Object.prototype": "['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']", 53 53 "Function": "['length', 'name', 'prototype']", 54 54 "Function.prototype": "['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']", -
trunk/LayoutTests/fast/js/script-tests/cyclic-prototypes.js
r98407 r107498 7 7 o3.__proto__ = o2; 8 8 9 o1.__proto__ = null; // just for sanity's sake 9 // Try to create a cyclical prototype chain. 10 shouldThrow("o1.__proto__ = o3;"); 10 11 11 shouldThrow("o1.__proto__ = o3"); 12 // This changes behaviour, since __proto__ is an accessor on Object.prototype. 13 o1.__proto__ = null; 14 15 shouldBeFalse("({}).hasOwnProperty.call(o1, '__proto__')"); 16 o1.__proto__ = o3; 17 shouldBeTrue("({}).hasOwnProperty.call(o1, '__proto__')"); 18 shouldBe("Object.getPrototypeOf(o1)", "null"); -
trunk/LayoutTests/fast/js/script-tests/parser-syntax-check.js
r106297 r107498 348 348 invalid("for(var a,b '"); 349 349 350 invalid("function __proto__(){}")351 invalid("(function __proto__(){})")352 invalid("'use strict'; function __proto__(){}")353 invalid("'use strict'; (function __proto__(){})")350 valid("function __proto__(){}") 351 valid("(function __proto__(){})") 352 valid("'use strict'; function __proto__(){}") 353 valid("'use strict'; (function __proto__(){})") 354 354 355 355 valid("if (0) $foo; ") -
trunk/LayoutTests/fast/js/script-tests/preventExtensions.js
r98407 r107498 70 70 71 71 shouldBeUndefined('var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" }; o.newProp;'); 72 should Throw('"use strict"; var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" };');72 shouldBeUndefined('"use strict"; var o = {}; Object.preventExtensions(o); o.__proto__ = { newProp: "Should not see this" }; o.newProp;'); 73 73 74 74 // check that we can still access static properties on an object after calling preventExtensions. -
trunk/LayoutTests/fast/js/script-tests/prototypes.js
r98998 r107498 56 56 shouldBeTrue("Object.__proto__.isPrototypeOf(String)"); 57 57 58 shouldBe False("var wasSet = false; var o = { }; o.__defineGetter__(\"__proto__\", function() { wasSet = true }); o.__proto__; wasSet;");59 shouldBe False("var wasSet = false; var o = { }; o.__defineSetter__(\"__proto__\", function() { wasSet = true }); o.__proto__ = {}; wasSet;");60 shouldBe False("var wasSet = false; var o = { }; Object.defineProperty(o, \"__proto__\", { \"get\": function() { wasSet = true } }); o.__proto__; wasSet;");58 shouldBeTrue("var wasSet = false; var o = { }; o.__defineGetter__(\"__proto__\", function() { wasSet = true }); o.__proto__; wasSet;"); 59 shouldBeTrue("var wasSet = false; var o = { }; o.__defineSetter__(\"__proto__\", function() { wasSet = true }); o.__proto__ = {}; wasSet;"); 60 shouldBeTrue("var wasSet = false; var o = { }; Object.defineProperty(o, \"__proto__\", { \"get\": function() { wasSet = true } }); o.__proto__; wasSet;"); 61 61 shouldBeFalse("var wasSet = false; var o = { }; Object.defineProperty(o, \"__proto__\", { \"__proto__\": function(x) { wasSet = true } }); o.__proto__ = {}; wasSet;"); 62 63 // Deleting Object.prototype.__proto__ removes the ability to set the object's prototype. 64 shouldBeTrue("var o = {}; o.__proto__ = { x:true }; o.x"); 65 shouldBeFalse("var o = {}; o.__proto__ = { x:true }; o.hasOwnProperty('__proto__')"); 66 delete Object.prototype.__proto__; 67 shouldBeUndefined("var o = {}; o.__proto__ = { x:true }; o.x"); 68 shouldBeTrue("var o = {}; o.__proto__ = { x:true }; o.hasOwnProperty('__proto__')"); -
trunk/Source/JavaScriptCore/ChangeLog
r107496 r107498 1 2012-02-11 Gavin Barraclough <barraclough@apple.com> 2 3 Move special __proto__ property to Object.prototype 4 https://bugs.webkit.org/show_bug.cgi?id=78409 5 6 Reviewed by Oliver Hunt. 7 8 Re-implement this as a regular accessor property. This has three key benefits: 9 1) It makes it possible for objects to be given properties named __proto__. 10 2) Object.prototype.__proto__ can be deleted, preventing object prototypes from being changed. 11 3) This largely removes the magic used the implement __proto__, it can just be made a regular accessor property. 12 13 * parser/Parser.cpp: 14 (JSC::::parseFunctionInfo): 15 - No need to prohibit functions named __proto__. 16 * runtime/JSGlobalObject.cpp: 17 (JSC::JSGlobalObject::reset): 18 - Add __proto__ accessor to Object.prototype. 19 * runtime/JSGlobalObjectFunctions.cpp: 20 (JSC::globalFuncProtoGetter): 21 (JSC::globalFuncProtoSetter): 22 - Definition of the __proto__ accessor functions. 23 * runtime/JSGlobalObjectFunctions.h: 24 - Declaration of the __proto__ accessor functions. 25 * runtime/JSObject.cpp: 26 (JSC::JSObject::put): 27 - Remove the special handling for __proto__, there is still a check to allow for a fast guard for accessors excluding __proto__. 28 (JSC::JSObject::putDirectAccessor): 29 - Track on the structure whether an object contains accessors other than one for __proto__. 30 (JSC::JSObject::defineOwnProperty): 31 - No need to prohibit definition of own properties named __proto__. 32 * runtime/JSObject.h: 33 (JSC::JSObject::inlineGetOwnPropertySlot): 34 - Remove the special handling for __proto__. 35 (JSC::JSValue::get): 36 - Remove the special handling for __proto__. 37 * runtime/JSString.cpp: 38 (JSC::JSString::getOwnPropertySlot): 39 - Remove the special handling for __proto__. 40 * runtime/JSValue.h: 41 (JSValue): 42 - Made synthesizePrototype public (this may be needed by the __proto__ getter). 43 * runtime/ObjectConstructor.cpp: 44 (JSC::objectConstructorGetPrototypeOf): 45 - Perform the security check & call prototype() directly. 46 * runtime/Structure.cpp: 47 (JSC::Structure::Structure): 48 - Added 'ExcludingProto' variant of the 'hasGetterSetterProperties' state. 49 * runtime/Structure.h: 50 (JSC::Structure::hasGetterSetterPropertiesExcludingProto): 51 (JSC::Structure::setHasGetterSetterProperties): 52 (Structure): 53 - Added 'ExcludingProto' variant of the 'hasGetterSetterProperties' state. 54 1 55 2012-02-11 Filip Pizlo <fpizlo@apple.com> 2 56 -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r107338 r107498 775 775 if (match(IDENT)) { 776 776 name = m_token.m_data.ident; 777 failIfTrueWithMessage(*name == m_globalData->propertyNames->underscoreProto, "Cannot name a function __proto__");778 777 next(); 779 778 if (!nameIsInContainingScope) -
trunk/Source/JavaScriptCore/runtime/ClassInfo.h
r106783 r107498 90 90 typedef bool (*GetOwnPropertyDescriptorFunctionPtr)(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); 91 91 GetOwnPropertyDescriptorFunctionPtr getOwnPropertyDescriptor; 92 93 typedef bool (*AllowsAccessFromFunctionPtr)(JSObject*, ExecState*); 94 AllowsAccessFromFunctionPtr allowsAccessFrom; 92 95 }; 93 96 … … 131 134 &ClassName::defineOwnProperty, \ 132 135 &ClassName::getOwnPropertyDescriptor, \ 136 &ClassName::allowsAccessFrom, \ 133 137 }, \ 134 138 sizeof(ClassName), \ -
trunk/Source/JavaScriptCore/runtime/JSCell.cpp
r106783 r107498 192 192 } 193 193 194 bool JSCell::allowsAccessFrom(JSObject*, ExecState*) 195 { 196 ASSERT_NOT_REACHED(); 197 return false; 198 } 199 194 200 bool JSCell::defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool) 195 201 { -
trunk/Source/JavaScriptCore/runtime/JSCell.h
r107445 r107498 162 162 static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); 163 163 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); 164 static bool allowsAccessFrom(JSObject*, ExecState*); 164 165 165 166 private: -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r106783 r107498 206 206 m_applyFunction.set(exec->globalData(), this, applyFunction); 207 207 m_objectPrototype.set(exec->globalData(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->globalData(), this, jsNull()))); 208 GetterSetter* protoAccessor = GetterSetter::create(exec); 209 protoAccessor->setGetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoGetter)); 210 protoAccessor->setSetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoSetter)); 211 m_objectPrototype->putDirectAccessor(exec->globalData(), exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum); 208 212 m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get()); 209 213 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r105698 r107498 715 715 } 716 716 717 EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec) 718 { 719 if (!exec->thisValue().isObject()) 720 return JSValue::encode(exec->thisValue().synthesizePrototype(exec)); 721 722 JSObject* thisObject = asObject(exec->thisValue()); 723 if (!thisObject->methodTable()->allowsAccessFrom(thisObject, exec)) 724 return JSValue::encode(jsUndefined()); 725 726 return JSValue::encode(thisObject->prototype()); 727 } 728 729 EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec) 730 { 731 JSValue value = exec->argument(0); 732 733 // Setting __proto__ of a primitive should have no effect. 734 if (!exec->thisValue().isObject()) 735 return JSValue::encode(jsUndefined()); 736 737 JSObject* thisObject = asObject(exec->thisValue()); 738 if (!thisObject->methodTable()->allowsAccessFrom(thisObject, exec)) 739 return JSValue::encode(jsUndefined()); 740 741 // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla. 742 if (!value.isObject() && !value.isNull()) 743 return JSValue::encode(jsUndefined()); 744 745 if (!thisObject->isExtensible()) 746 return JSValue::encode(jsUndefined()); 747 748 if (!thisObject->setPrototypeWithCycleCheck(exec->globalData(), value)) 749 throwError(exec, createError(exec, "cyclic __proto__ value")); 750 751 return JSValue::encode(jsUndefined()); 752 } 753 717 754 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
r99436 r107498 49 49 EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*); 50 50 EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState*); 51 EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*); 52 EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*); 51 53 52 54 static const double mantissaOverflowLowerBound = 9007199254740992.0; -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r107445 r107498 133 133 JSGlobalData& globalData = exec->globalData(); 134 134 135 if (propertyName == exec->propertyNames().underscoreProto) {136 // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.137 if (!value.isObject() && !value.isNull())138 return;139 140 if (!thisObject->isExtensible()) {141 if (slot.isStrictMode())142 throwTypeError(exec, StrictModeReadonlyPropertyWriteError);143 return;144 }145 146 if (!thisObject->setPrototypeWithCycleCheck(globalData, value))147 throwError(exec, createError(exec, "cyclic __proto__ value"));148 return;149 }150 151 135 // Check if there are any setters or getters in the prototype chain 152 136 JSValue prototype; 153 for (JSObject* obj = thisObject; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) { 154 prototype = obj->prototype(); 155 if (prototype.isNull()) { 156 if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode()) 157 throwTypeError(exec, StrictModeReadonlyPropertyWriteError); 158 return; 159 } 160 } 161 137 if (propertyName != exec->propertyNames().underscoreProto) { 138 for (JSObject* obj = thisObject; !obj->structure()->hasGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) { 139 prototype = obj->prototype(); 140 if (prototype.isNull()) { 141 if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode()) 142 throwTypeError(exec, StrictModeReadonlyPropertyWriteError); 143 return; 144 } 145 } 146 } 147 162 148 unsigned attributes; 163 149 JSCell* specificValue; … … 216 202 } 217 203 204 bool JSObject::allowsAccessFrom(JSObject*, ExecState*) 205 { 206 return true; 207 } 208 218 209 void JSObject::putDirectAccessor(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) 219 210 { 220 211 ASSERT(value.isGetterSetter() && (attributes & Accessor)); 221 ASSERT(propertyName != globalData.propertyNames->underscoreProto);222 212 223 213 PutPropertySlot slot; … … 230 220 setStructure(globalData, Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes)); 231 221 232 structure()->setHasGetterSetterProperties( true);222 structure()->setHasGetterSetterProperties(propertyName == globalData.propertyNames->underscoreProto); 233 223 } 234 224 … … 630 620 bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException) 631 621 { 632 // __proto__ is magic; we don't currently support setting it as a regular property.633 // Silent filter out calls to set __proto__ at an early stage; pretend all is okay.634 if (propertyName == exec->propertyNames().underscoreProto)635 return true;636 637 622 // If we have a new property we can just put it on normally 638 623 PropertyDescriptor current; -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r107445 r107498 105 105 JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); 106 106 JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); 107 JS_EXPORT_PRIVATE static bool allowsAccessFrom(JSObject*, ExecState*); 107 108 108 109 JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); … … 548 549 else 549 550 slot.setValue(this, location->get(), offsetForLocation(location)); 550 return true;551 }552 553 // non-standard Netscape extension554 if (propertyName == exec->propertyNames().underscoreProto) {555 slot.setValue(prototype());556 551 return true; 557 552 } … … 804 799 if (UNLIKELY(!isCell())) { 805 800 JSObject* prototype = synthesizePrototype(exec); 806 if (propertyName == exec->propertyNames().underscoreProto)807 return prototype;808 801 if (!prototype->getPropertySlot(exec, propertyName, slot)) 809 802 return jsUndefined(); -
trunk/Source/JavaScriptCore/runtime/JSString.cpp
r105698 r107498 254 254 if (thisObject->getStringPropertySlot(exec, propertyName, slot)) 255 255 return true; 256 if (propertyName == exec->propertyNames().underscoreProto) {257 slot.setValue(exec->lexicalGlobalObject()->stringPrototype());258 return true;259 }260 256 slot.setBase(thisObject); 261 257 JSObject* object; -
trunk/Source/JavaScriptCore/runtime/JSValue.h
r106590 r107498 235 235 char* description(); 236 236 237 JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const; 238 237 239 private: 238 240 template <class T> JSValue(WriteBarrierBase<T>); … … 247 249 JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const; 248 250 249 JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;250 251 JSObject* synthesizeObject(ExecState*) const; 251 252 -
trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
r105698 r107498 139 139 if (!exec->argument(0).isObject()) 140 140 return throwVMError(exec, createTypeError(exec, "Requested prototype of a value that is not an object.")); 141 142 // This uses JSValue::get() instead of directly accessing the prototype from the object 143 // (using JSObject::prototype()) in order to allow objects to override the behavior, such 144 // as returning jsUndefined() for cross-origin access. 145 return JSValue::encode(exec->argument(0).get(exec, exec->propertyNames().underscoreProto)); 141 JSObject* object = asObject(exec->argument(0)); 142 143 if (!object->methodTable()->allowsAccessFrom(object, exec)) 144 return JSValue::encode(jsUndefined()); 145 146 return JSValue::encode(object->prototype()); 146 147 } 147 148 -
trunk/Source/JavaScriptCore/runtime/Structure.cpp
r104871 r107498 168 168 , m_isPinnedPropertyTable(false) 169 169 , m_hasGetterSetterProperties(false) 170 , m_hasGetterSetterPropertiesExcludingProto(false) 170 171 , m_hasNonEnumerableProperties(false) 171 172 , m_attributesInPrevious(0) … … 189 190 , m_isPinnedPropertyTable(false) 190 191 , m_hasGetterSetterProperties(false) 192 , m_hasGetterSetterPropertiesExcludingProto(false) 191 193 , m_hasNonEnumerableProperties(false) 192 194 , m_attributesInPrevious(0) … … 208 210 , m_isPinnedPropertyTable(false) 209 211 , m_hasGetterSetterProperties(previous->m_hasGetterSetterProperties) 212 , m_hasGetterSetterPropertiesExcludingProto(previous->m_hasGetterSetterPropertiesExcludingProto) 210 213 , m_hasNonEnumerableProperties(previous->m_hasNonEnumerableProperties) 211 214 , m_attributesInPrevious(0) -
trunk/Source/JavaScriptCore/runtime/Structure.h
r104900 r107498 146 146 147 147 bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } 148 void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; } 148 bool hasGetterSetterPropertiesExcludingProto() const { return m_hasGetterSetterPropertiesExcludingProto; } 149 void setHasGetterSetterProperties(bool isProto) 150 { 151 m_hasGetterSetterProperties = true; 152 if (!isProto) 153 m_hasGetterSetterPropertiesExcludingProto = true; 154 } 149 155 150 156 bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; } … … 283 289 bool m_isPinnedPropertyTable : 1; 284 290 bool m_hasGetterSetterProperties : 1; 291 bool m_hasGetterSetterPropertiesExcludingProto : 1; 285 292 bool m_hasNonEnumerableProperties : 1; 286 293 unsigned m_attributesInPrevious : 7; -
trunk/Source/WebCore/ChangeLog
r107497 r107498 1 2012-02-11 Gavin Barraclough <barraclough@apple.com> 2 3 Move special __proto__ property to Object.prototype 4 https://bugs.webkit.org/show_bug.cgi?id=78409 5 6 Reviewed by Oliver Hunt. 7 8 Re-implement this as a regular accessor property. This has three key benefits: 9 1) It makes it possible for objects to be given properties named __proto__. 10 2) Object.prototype.__proto__ can be deleted, preventing object prototypes from being changed. 11 3) This largely removes the magic used the implement __proto__, it can just be made a regular accessor property. 12 13 * bindings/js/JSDOMWindowBase.cpp: 14 (WebCore::JSDOMWindowBase::allowsAccessFrom): 15 (WebCore): 16 - expose allowsAccessFrom check to JSC. 17 * bindings/js/JSDOMWindowBase.h: 18 (JSDOMWindowBase): 19 - expose allowsAccessFrom check to JSC. 20 1 21 2012-02-11 Benjamin Poulain <benjamin@webkit.org> 2 22 -
trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
r103083 r107498 93 93 } 94 94 95 bool JSDOMWindowBase::allowsAccessFrom(JSObject* thisObject, ExecState* exec) 96 { 97 return static_cast<JSDOMWindowBase*>(thisObject)->allowsAccessFrom(exec); 98 } 99 95 100 bool JSDOMWindowBase::supportsProfiling(const JSGlobalObject* object) 96 101 { -
trunk/Source/WebCore/bindings/js/JSDOMWindowBase.h
r103083 r107498 64 64 static bool supportsRichSourceInfo(const JSC::JSGlobalObject*); 65 65 static bool shouldInterruptScript(const JSC::JSGlobalObject*); 66 66 static bool allowsAccessFrom(JSC::JSObject*, JSC::ExecState*); 67 67 68 bool allowsAccessFrom(JSC::ExecState*) const; 68 69 bool allowsAccessFromNoErrorMessage(JSC::ExecState*) const;
Note: See TracChangeset
for help on using the changeset viewer.