Changeset 197136 in webkit for trunk/Source/JavaScriptCore/runtime
- Timestamp:
- Feb 25, 2016, 2:58:23 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore/runtime
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r196999 r197136 422 422 } 423 423 } 424 } 425 if (obj->type() == ProxyObjectType) { 426 ProxyObject* proxy = jsCast<ProxyObject*>(obj); 427 proxy->ProxyObject::put(proxy, exec, propertyName, value, slot); 428 return; 424 429 } 425 430 JSValue prototype = obj->prototype(); … … 1917 1922 } 1918 1923 } 1924 1925 if (current->type() == ProxyObjectType) { 1926 ProxyObject* proxy = jsCast<ProxyObject*>(current); 1927 proxy->putByIndexCommon(exec, thisValue, i, value, shouldThrow); 1928 return true; 1929 } 1919 1930 1920 1931 JSValue prototypeValue = current->prototype(); -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r196849 r197136 856 856 template<PutMode> 857 857 bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&); 858 bool canPerformFastPutInline(ExecState* exec, VM&, PropertyName); 858 859 859 860 JS_EXPORT_PRIVATE NEVER_INLINE void putInlineSlow(ExecState*, PropertyName, JSValue, PutPropertySlot&); -
trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h
r194175 r197136 31 31 namespace JSC { 32 32 33 ALWAYS_INLINE bool JSObject::canPerformFastPutInline(ExecState* exec, VM& vm, PropertyName propertyName) 34 { 35 if (UNLIKELY(propertyName == exec->propertyNames().underscoreProto)) 36 return false; 37 38 // Check if there are any setters or getters in the prototype chain 39 JSValue prototype; 40 JSObject* obj = this; 41 while (true) { 42 if (obj->structure(vm)->hasReadOnlyOrGetterSetterPropertiesExcludingProto() || obj->type() == ProxyObjectType) 43 return false; 44 45 prototype = obj->prototype(); 46 if (prototype.isNull()) 47 return true; 48 49 obj = asObject(prototype); 50 } 51 52 ASSERT_NOT_REACHED(); 53 } 54 33 55 // ECMA 8.6.2.2 34 56 ALWAYS_INLINE void JSObject::putInline(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) … … 45 67 return; 46 68 } 47 48 // Check if there are any setters or getters in the prototype chain49 JSValue prototype;50 if (propertyName != exec->propertyNames().underscoreProto) {51 for (JSObject* obj = thisObject; !obj->structure(vm)->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {52 prototype = obj->prototype();53 if (prototype.isNull()) {54 ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName));55 if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot)56 && slot.isStrictMode())57 throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));58 return;59 }60 }61 }62 69 63 thisObject->putInlineSlow(exec, propertyName, value, slot); 70 if (thisObject->canPerformFastPutInline(exec, vm, propertyName)) { 71 ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName)); 72 if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) 73 && slot.isStrictMode()) 74 throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError)); 75 } else 76 thisObject->putInlineSlow(exec, propertyName, value, slot); 64 77 } 65 78 -
trunk/Source/JavaScriptCore/runtime/JSType.h
r189279 r197136 79 79 ClosureObjectType, 80 80 81 LastJSCObjectType = ClosureObjectType, 81 ProxyObjectType, 82 83 LastJSCObjectType = ProxyObjectType, 82 84 }; 83 85 -
trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp
r197042 r197136 301 301 } 302 302 303 template <typename PerformDefaultPutFunction> 304 void ProxyObject::performPut(ExecState* exec, JSValue putValue, JSValue thisValue, PropertyName propertyName, PerformDefaultPutFunction performDefaultPutFunction) 305 { 306 VM& vm = exec->vm(); 307 JSValue handlerValue = this->handler(); 308 if (handlerValue.isNull()) { 309 throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object.")); 310 return; 311 } 312 313 JSObject* handler = jsCast<JSObject*>(handlerValue); 314 CallData callData; 315 CallType callType; 316 JSValue setMethod = handler->getMethod(exec, callData, callType, vm.propertyNames->set, ASCIILiteral("'set' property of a Proxy's handler should be callable.")); 317 if (exec->hadException()) 318 return; 319 JSObject* target = this->target(); 320 if (setMethod.isUndefined()) { 321 performDefaultPutFunction(); 322 return; 323 } 324 325 MarkedArgumentBuffer arguments; 326 arguments.append(target); 327 arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid()))); 328 arguments.append(putValue); 329 arguments.append(thisValue); 330 JSValue trapResult = call(exec, setMethod, callType, callData, handler, arguments); 331 if (exec->hadException()) 332 return; 333 bool trapResultAsBool = trapResult.toBoolean(exec); 334 if (exec->hadException()) 335 return; 336 if (!trapResultAsBool) 337 return; 338 339 PropertyDescriptor descriptor; 340 if (target->getOwnPropertyDescriptor(exec, propertyName, descriptor)) { 341 if (descriptor.isDataDescriptor() && !descriptor.configurable() && !descriptor.writable()) { 342 if (!sameValue(exec, descriptor.value(), putValue)) { 343 throwVMTypeError(exec, ASCIILiteral("Proxy handler's 'set' on a non-configurable and non-writable property on 'target' should either return false or be the same value already on the 'target'.")); 344 return; 345 } 346 } else if (descriptor.isAccessorDescriptor() && !descriptor.configurable() && descriptor.setter().isUndefined()) { 347 throwVMTypeError(exec, ASCIILiteral("Proxy handler's 'set' method on a non-configurable accessor property without a setter should return false.")); 348 return; 349 } 350 } 351 } 352 353 void ProxyObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) 354 { 355 VM& vm = exec->vm(); 356 ProxyObject* thisObject = jsCast<ProxyObject*>(cell); 357 auto performDefaultPut = [&] () { 358 JSObject* target = jsCast<JSObject*>(thisObject->target()); 359 target->methodTable(vm)->put(target, exec, propertyName, value, slot); 360 }; 361 thisObject->performPut(exec, value, slot.thisValue(), propertyName, performDefaultPut); 362 } 363 364 void ProxyObject::putByIndexCommon(ExecState* exec, JSValue thisValue, unsigned propertyName, JSValue putValue, bool shouldThrow) 365 { 366 VM& vm = exec->vm(); 367 Identifier ident = Identifier::from(exec, propertyName); 368 if (exec->hadException()) 369 return; 370 auto performDefaultPut = [&] () { 371 JSObject* target = this->target(); 372 bool isStrictMode = shouldThrow; 373 PutPropertySlot slot(thisValue, isStrictMode); // We must preserve the "this" target of the putByIndex. 374 target->methodTable(vm)->put(target, exec, ident.impl(), putValue, slot); 375 }; 376 performPut(exec, putValue, thisValue, ident.impl(), performDefaultPut); 377 } 378 379 void ProxyObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) 380 { 381 ProxyObject* thisObject = jsCast<ProxyObject*>(cell); 382 thisObject->putByIndexCommon(exec, thisObject, propertyName, value, shouldThrow); 383 } 384 303 385 static EncodedJSValue JSC_HOST_CALL performProxyCall(ExecState* exec) 304 386 { … … 346 428 } 347 429 348 void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor)349 {350 ProxyObject* thisObject = jsCast<ProxyObject*>(cell);351 ASSERT_GC_OBJECT_INHERITS(thisObject, info());352 Base::visitChildren(thisObject, visitor);353 354 visitor.append(&thisObject->m_target);355 visitor.append(&thisObject->m_handler);356 }357 358 430 static EncodedJSValue JSC_HOST_CALL performProxyConstruct(ExecState* exec) 359 431 { … … 477 549 } 478 550 551 void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor) 552 { 553 ProxyObject* thisObject = jsCast<ProxyObject*>(cell); 554 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 555 Base::visitChildren(thisObject, visitor); 556 557 visitor.append(&thisObject->m_target); 558 visitor.append(&thisObject->m_handler); 559 } 560 479 561 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/ProxyObject.h
r197042 r197136 36 36 typedef JSNonFinalObject Base; 37 37 38 const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | TypeOfShouldCallGetCallData ;38 const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | TypeOfShouldCallGetCallData | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero; 39 39 40 40 static ProxyObject* create(ExecState* exec, Structure* structure, JSValue target, JSValue handler) … … 48 48 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 49 49 { 50 return Structure::create(vm, globalObject, prototype, TypeInfo( ObjectType, StructureFlags), info());50 return Structure::create(vm, globalObject, prototype, TypeInfo(ProxyObjectType, StructureFlags), info(), NonArray | MayHaveIndexedAccessors); 51 51 } 52 52 … … 55 55 JSObject* target() { return m_target.get(); } 56 56 JSValue handler() { return m_handler.get(); } 57 58 static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); 59 static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); 60 void putByIndexCommon(ExecState*, JSValue thisValue, unsigned propertyName, JSValue putValue, bool shouldThrow); 57 61 58 62 private: … … 73 77 template <typename DefaultDeleteFunction> 74 78 bool performDelete(ExecState*, PropertyName, DefaultDeleteFunction); 79 template <typename PerformDefaultPutFunction> 80 void performPut(ExecState*, JSValue putValue, JSValue thisValue, PropertyName, PerformDefaultPutFunction); 75 81 76 82 WriteBarrier<JSObject> m_target;
Note:
See TracChangeset
for help on using the changeset viewer.