bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) { descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].get(), None); } else descriptor.setDescriptor(d->extraArguments[i - d->numParameters].get(), None); return true; } if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { descriptor.setDescriptor(jsNumber(d->numArguments), DontEnum); return true; } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { if (!d->isStrictMode) { descriptor.setDescriptor(d->callee.get(), DontEnum); return true; } createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && d->isStrictMode) createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool AJFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (isHostFunction()) return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (propertyName == exec->propertyNames().prototype) { PropertySlot slot; getOwnPropertySlot(exec, propertyName, slot); return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); } if (propertyName == exec->propertyNames().arguments) { descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().caller) { descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); return true; } return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(exec, length()), DontDelete | DontEnum); return true; } bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex) { if (i >= m_storage->m_length) return false; if (i < m_vectorLength) { JSValue& value = m_storage->m_vector[i]; if (value) { descriptor.setDescriptor(value, 0); return true; } } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) { if (i >= MIN_SPARSE_ARRAY_INDEX) { SparseArrayValueMap::iterator it = map->find(i); if (it != map->end()) { descriptor.setDescriptor(it->second, 0); return true; } } } } return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool JSNPObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (!m_npObject) { throwInvalidAccessError(exec); return false; } NPIdentifier npIdentifier = npIdentifierFromIdentifier(propertyName); // First, check if the NPObject has a property with this name. if (m_npObject->_class->hasProperty && m_npObject->_class->hasProperty(m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(this, propertyGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } // Second, check if the NPObject has a method with this name. if (m_npObject->_class->hasMethod && m_npObject->_class->hasMethod(m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(this, methodGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } return false; }
EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec) { // 1. If Type(O) is not Object throw a TypeError exception. JSValue obj = exec->argument(0); if (!obj.isObject()) return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.isFrozen can only be called on Objects."))); JSObject* object = asObject(obj); if (isJSFinalObject(object)) return JSValue::encode(jsBoolean(object->isFrozen(exec->vm()))); // 2. For each named own property name P of O, PropertyNameArray properties(exec); object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties); PropertyNameArray::const_iterator end = properties.end(); for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) { // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P. PropertyDescriptor desc; if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc)) continue; // b. If IsDataDescriptor(desc) is true then // i. If desc.[[Writable]] is true, return false. c. If desc.[[Configurable]] is true, then return false. if ((desc.isDataDescriptor() && desc.writable()) || desc.configurable()) return JSValue::encode(jsBoolean(false)); } // 3. If the [[Extensible]] internal property of O is false, then return true. // 4. Otherwise, return false. return JSValue::encode(jsBoolean(!object->isExtensible())); }
bool JSNPObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSNPObject* thisObject = jsCast<JSNPObject*>(object); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); if (!thisObject->m_npObject) { throwInvalidAccessError(exec); return false; } NPIdentifier npIdentifier = npIdentifierFromIdentifier(propertyName); // Calling NPClass::invoke will call into plug-in code, and there's no telling what the plug-in can do. // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until // the call has finished. NPRuntimeObjectMap::PluginProtector protector(thisObject->m_objectMap); // First, check if the NPObject has a property with this name. if (thisObject->m_npObject->_class->hasProperty && thisObject->m_npObject->_class->hasProperty(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, propertyGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } // Second, check if the NPObject has a method with this name. if (thisObject->m_npObject->_class->hasMethod && thisObject->m_npObject->_class->hasMethod(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, methodGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } return false; }
// https://tc39.github.io/ecma262/#sec-reflect.defineproperty EncodedJSValue JSC_HOST_CALL reflectObjectDefineProperty(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSValue target = exec->argument(0); if (!target.isObject()) return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.defineProperty requires the first argument be an object"))); auto propertyName = exec->argument(1).toPropertyKey(exec); RETURN_IF_EXCEPTION(scope, encodedJSValue()); PropertyDescriptor descriptor; bool success = toPropertyDescriptor(exec, exec->argument(2), descriptor); ASSERT(!scope.exception() == success); if (UNLIKELY(!success)) return encodedJSValue(); ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor())); ASSERT(!scope.exception()); // Reflect.defineProperty should not throw an error when the defineOwnProperty operation fails. bool shouldThrow = false; JSObject* targetObject = asObject(target); scope.release(); return JSValue::encode(jsBoolean(targetObject->methodTable(vm)->defineOwnProperty(targetObject, exec, propertyName, descriptor, shouldThrow))); }
EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec) { if (!exec->argument(0).isObject()) return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested property descriptor of a value that is not an object."))); String propertyName = exec->argument(1).toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsNull()); JSObject* object = asObject(exec->argument(0)); PropertyDescriptor descriptor; if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, Identifier(exec, propertyName), descriptor)) return JSValue::encode(jsUndefined()); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSObject* description = constructEmptyObject(exec); if (!descriptor.isAccessorDescriptor()) { description->putDirect(exec->vm(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0); description->putDirect(exec->vm(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0); } else { ASSERT(descriptor.getter()); ASSERT(descriptor.setter()); description->putDirect(exec->vm(), exec->propertyNames().get, descriptor.getter(), 0); description->putDirect(exec->vm(), exec->propertyNames().set, descriptor.setter(), 0); } description->putDirect(exec->vm(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0); description->putDirect(exec->vm(), exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0); return JSValue::encode(description); }
bool JSNamedNodeMap::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { ASSERT_GC_OBJECT_INHERITS(this, &s_info); JSValue proto = prototype(); if (proto.isObject() && static_cast<JSObject*>(asObject(proto))->hasProperty(exec, propertyName)) return false; const HashEntry* entry = JSNamedNodeMapTable.entry(exec, propertyName); if (entry) { PropertySlot slot; slot.setCustom(this, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } bool ok; unsigned index = propertyName.toUInt32(ok); if (ok && index < static_cast<NamedNodeMap*>(impl())->length()) { PropertySlot slot; slot.setCustomIndex(this, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } if (canGetItemsForName(exec, static_cast<NamedNodeMap*>(impl()), propertyName)) { PropertySlot slot; slot.setCustom(this, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSNamedNodeMap, Base>(exec, &JSNamedNodeMapTable, this, propertyName, descriptor); }
bool Arguments::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { Arguments* thisObject = jsCast<Arguments*>(object); unsigned i = propertyName.asIndex(); if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { ASSERT(i < PropertyName::NotAnIndex); descriptor.setDescriptor(thisObject->argument(i).get(), None); return true; } if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->d->overrodeLength)) { descriptor.setDescriptor(jsNumber(thisObject->d->numArguments), DontEnum); return true; } if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->d->overrodeCallee)) { if (!thisObject->d->isStrictMode) { descriptor.setDescriptor(thisObject->d->callee.get(), DontEnum); return true; } thisObject->createStrictModeCalleeIfNecessary(exec); } if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const { PropertyDescriptor descriptor; if (!const_cast<JSObject*>(this)->getOwnPropertyDescriptor(exec, propertyName, descriptor)) return false; return descriptor.enumerable(); }
void BaseEntity::SerializeProperties(IPropertyContainer *container, SerializableNodeObject *parent) { int count = container->GetNumProperties(); auto props = container->GetProperties(); SerializableNodeArray* nPropContainer = new SerializableNodeArray("properties"); for (int i = 0; i < count; ++i) { auto p = props[i]; PropertyDescriptor* desc = p->GetDescriptor(); if (desc->CanSerialize) { auto propObject = new SerializableNodeObject(); desc->Serialize(propObject); propObject->AddChild(new SerializableProperty("Value", p->GetString().c_str())); nPropContainer->AddChild(propObject); } } parent->AddChild(nPropContainer); }
bool JSTestEventTarget::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSTestEventTarget* thisObject = jsCast<JSTestEventTarget*>(object); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); const HashEntry* entry = JSTestEventTargetTable.entry(exec, propertyName); if (entry) { PropertySlot slot(thisObject); slot.setCustom(thisObject, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } unsigned index = propertyName.asIndex(); if (index != PropertyName::NotAnIndex && index < static_cast<TestEventTarget*>(thisObject->impl())->length()) { PropertySlot slot(thisObject); slot.setCustomIndex(thisObject, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } if (canGetItemsForName(exec, static_cast<TestEventTarget*>(thisObject->impl()), propertyName)) { PropertySlot slot(thisObject); slot.setCustom(thisObject, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSTestEventTarget, Base>(exec, &JSTestEventTargetTable, thisObject, propertyName, descriptor); }
EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec) { JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSValue set = exec->argument(1); CallData callData; if (getCallData(set, callData) == CallTypeNone) return throwVMError(exec, createTypeError(exec, ASCIILiteral("invalid setter usage"))); auto propertyName = exec->argument(0).toPropertyKey(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); PropertyDescriptor descriptor; descriptor.setSetter(set); descriptor.setEnumerable(true); descriptor.setConfigurable(true); bool shouldThrow = false; thisObject->methodTable(exec->vm())->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); return JSValue::encode(jsUndefined()); }
bool JSNPObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSNPObject* thisObject = jsCast<JSNPObject*>(object); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); if (!thisObject->m_npObject) { throwInvalidAccessError(exec); return false; } NPIdentifier npIdentifier = npIdentifierFromIdentifier(propertyName); // First, check if the NPObject has a property with this name. if (thisObject->m_npObject->_class->hasProperty && thisObject->m_npObject->_class->hasProperty(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, propertyGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } // Second, check if the NPObject has a method with this name. if (thisObject->m_npObject->_class->hasMethod && thisObject->m_npObject->_class->hasMethod(thisObject->m_npObject, npIdentifier)) { PropertySlot slot; slot.setCustom(thisObject, methodGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } return false; }
bool JSCSSStyleDeclaration::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { ASSERT_GC_OBJECT_INHERITS(this, &s_info); const HashEntry* entry = JSCSSStyleDeclarationTable.entry(exec, propertyName); if (entry) { PropertySlot slot; slot.setCustom(this, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } bool ok; unsigned index = propertyName.toUInt32(ok); if (ok && index < static_cast<CSSStyleDeclaration*>(impl())->length()) { PropertySlot slot; slot.setCustomIndex(this, index, indexGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } if (canGetItemsForName(exec, static_cast<CSSStyleDeclaration*>(impl()), propertyName)) { PropertySlot slot; slot.setCustom(this, nameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); return true; } return getStaticValueDescriptor<JSCSSStyleDeclaration, Base>(exec, &JSCSSStyleDeclarationTable, this, propertyName, descriptor); }
void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) { if (d->overrodeCallee) return; d->overrodeCallee = true; PropertyDescriptor descriptor; descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor); methodTable()->defineOwnProperty(this, exec, exec->propertyNames().callee, descriptor, false); }
static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties) { PropertyNameArray propertyNames(exec); asObject(properties)->methodTable()->getOwnPropertyNames(asObject(properties), exec, propertyNames, ExcludeDontEnumProperties); size_t numProperties = propertyNames.size(); Vector<PropertyDescriptor> descriptors; MarkedArgumentBuffer markBuffer; for (size_t i = 0; i < numProperties; i++) { PropertySlot slot; JSValue prop = properties->get(exec, propertyNames[i]); if (exec->hadException()) return jsNull(); PropertyDescriptor descriptor; if (!toPropertyDescriptor(exec, prop, descriptor)) return jsNull(); descriptors.append(descriptor); // Ensure we mark all the values that we're accumulating if (descriptor.isDataDescriptor() && descriptor.value()) markBuffer.append(descriptor.value()); if (descriptor.isAccessorDescriptor()) { if (descriptor.getter()) markBuffer.append(descriptor.getter()); if (descriptor.setter()) markBuffer.append(descriptor.setter()); } } for (size_t i = 0; i < numProperties; i++) { object->methodTable()->defineOwnProperty(object, exec, propertyNames[i], descriptors[i], true); if (exec->hadException()) return jsNull(); } return object; }
void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) { if (d->overrodeCallee) return; d->overrodeCallee = true; PropertyDescriptor descriptor; JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function"); descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); defineOwnProperty(exec, exec->propertyNames().callee, descriptor, false); }
void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) { if (m_overrodeCaller) return; VM& vm = exec->vm(); m_overrodeCaller = true; PropertyDescriptor descriptor; descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(vm), DontEnum | DontDelete | Accessor); methodTable(exec->vm())->defineOwnProperty(this, exec, vm.propertyNames->caller, descriptor, false); }
bool JSFunction::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { JSFunction* thisObject = jsCast<JSFunction*>(object); if (thisObject->isHostFunction()) return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); if (propertyName == exec->propertyNames().prototype) { PropertySlot slot; thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot); return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); } if (propertyName == exec->propertyNames().arguments) { if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); if (!result) { thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); ASSERT(result); } return result; } descriptor.setDescriptor(exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(thisObject->jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().name) { descriptor.setDescriptor(thisObject->jsExecutable()->nameValue(), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().caller) { if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); if (!result) { thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); ASSERT(result); } return result; } descriptor.setDescriptor(exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete); return true; } return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
void ReferencePrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) { Base::finishCreation(vm); this->putDirectNativeFunction(vm, globalObject, vm.propertyNames->toString, 0, referenceProtoFuncToString, NoIntrinsic, DontEnum); PropertyDescriptor descriptor; descriptor.setEnumerable(true); descriptor.setGetter(JSFunction::create(vm, globalObject, 0, WTF::emptyString(), &referenceProtoFuncGetValue)); descriptor.setSetter(JSFunction::create(vm, globalObject, 1, WTF::emptyString(), &referenceProtoFuncSetValue)); Base::defineOwnProperty(this, globalObject->globalExec(), vm.propertyNames->value, descriptor, false); }
EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec) { JSObject* thisObject = exec->hostThisValue().toObject(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); PropertyDescriptor descriptor; if (thisObject->getPropertyDescriptor(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), descriptor) && descriptor.setterPresent()) return JSValue::encode(descriptor.setter()); return JSValue::encode(jsUndefined()); }
bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool shouldThrow) { Arguments* thisObject = jsCast<Arguments*>(object); unsigned i = propertyName.asIndex(); if (i < thisObject->d->numArguments) { ASSERT(i < PropertyName::NotAnIndex); // If the property is not yet present on the object, and is not yet marked as deleted, then add it now. PropertySlot slot; if ((!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i]) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) object->putDirect(exec->globalData(), propertyName, thisObject->argument(i).get(), 0); if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow)) return false; if (!thisObject->d->deletedArguments) { thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]); memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments); } // From ES 5.1, 10.6 Arguments Object // 5. If the value of isMapped is not undefined, then if (!thisObject->d->deletedArguments[i]) { // a. If IsAccessorDescriptor(Desc) is true, then if (descriptor.isAccessorDescriptor()) { // i. Call the [[Delete]] internal method of map passing P, and false as the arguments. thisObject->d->deletedArguments[i] = true; } else { // b. Else // i. If Desc.[[Value]] is present, then // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments. if (descriptor.value()) thisObject->argument(i).set(exec->globalData(), thisObject, descriptor.value()); // ii. If Desc.[[Writable]] is present and its value is false, then // 1. Call the [[Delete]] internal method of map passing P and false as arguments. if (descriptor.writablePresent() && !descriptor.writable()) thisObject->d->deletedArguments[i] = true; } } return true; } if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) { thisObject->putDirect(exec->globalData(), propertyName, jsNumber(thisObject->d->numArguments), DontEnum); thisObject->d->overrodeLength = true; } else if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { thisObject->putDirect(exec->globalData(), propertyName, thisObject->d->callee.get(), DontEnum); thisObject->d->overrodeCallee = true; } else if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); }
bool RuntimeObject::getOwnPropertyDescriptor(JSObject* object, ExecState *exec, PropertyName propertyName, PropertyDescriptor& descriptor) { RuntimeObject* thisObject = jsCast<RuntimeObject*>(object); if (!thisObject->m_instance) { throwInvalidAccessError(exec); return false; } RefPtr<Instance> instance = thisObject->m_instance; instance->begin(); Class *aClass = instance->getClass(); if (aClass) { // See if the instance has a field with the specified name. Field *aField = aClass->fieldNamed(propertyName, instance.get()); if (aField) { PropertySlot slot; slot.setCustom(thisObject, fieldGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } else { // Now check if a method with specified name exists, if so return a function object for // that method. MethodList methodList = aClass->methodsNamed(propertyName, instance.get()); if (methodList.size() > 0) { PropertySlot slot; slot.setCustom(thisObject, methodGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } } // Try a fallback object. if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) { PropertySlot slot; slot.setCustom(thisObject, fallbackObjectGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); return true; } } instance->end(); return instance->getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
bool JSString::getStringPropertyDescriptor(ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) { if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(length()), DontEnum | DontDelete | ReadOnly); return true; } std::optional<uint32_t> index = parseIndex(propertyName); if (index && index.value() < length()) { descriptor.setDescriptor(getIndex(exec, index.value()), DontDelete | ReadOnly); return true; } return false; }
static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue) { if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) { target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter)); return true; } attributes &= ~ReadOnly; if (descriptor.getter() && descriptor.getter().isObject()) target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes); if (exec->hadException()) return false; if (descriptor.setter() && descriptor.setter().isObject()) target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes); return !exec->hadException(); }
bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) { Arguments* thisObject = jsCast<Arguments*>(object); unsigned i = propertyName.asIndex(); if (i < thisObject->m_numArguments) { RELEASE_ASSERT(i < PropertyName::NotAnIndex); // If the property is not yet present on the object, and is not yet marked as deleted, then add it now. PropertySlot slot(thisObject); if (!thisObject->isDeletedArgument(i) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) { JSValue value = thisObject->tryGetArgument(i); ASSERT(value); object->putDirectMayBeIndex(exec, propertyName, value); } if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow)) return false; // From ES 5.1, 10.6 Arguments Object // 5. If the value of isMapped is not undefined, then if (thisObject->isArgument(i)) { // a. If IsAccessorDescriptor(Desc) is true, then if (descriptor.isAccessorDescriptor()) { // i. Call the [[Delete]] internal method of map passing P, and false as the arguments. thisObject->tryDeleteArgument(exec->vm(), i); } else { // b. Else // i. If Desc.[[Value]] is present, then // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments. if (descriptor.value()) thisObject->trySetArgument(exec->vm(), i, descriptor.value()); // ii. If Desc.[[Writable]] is present and its value is false, then // 1. Call the [[Delete]] internal method of map passing P and false as arguments. if (descriptor.writablePresent() && !descriptor.writable()) thisObject->tryDeleteArgument(exec->vm(), i); } } return true; } if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { thisObject->putDirect(exec->vm(), propertyName, jsNumber(thisObject->m_numArguments), DontEnum); thisObject->m_overrodeLength = true; } else if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { thisObject->putDirect(exec->vm(), propertyName, thisObject->m_callee.get(), DontEnum); thisObject->m_overrodeCallee = true; } else if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); }
EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec) { if (!exec->argument(0).isObject()) return throwVMError(exec, createTypeError(exec, ASCIILiteral("Properties can only be defined on Objects."))); JSObject* O = asObject(exec->argument(0)); String propertyName = exec->argument(1).toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsNull()); PropertyDescriptor descriptor; if (!toPropertyDescriptor(exec, exec->argument(2), descriptor)) return JSValue::encode(jsNull()); ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor())); ASSERT(!exec->hadException()); O->methodTable()->defineOwnProperty(O, exec, Identifier(exec, propertyName), descriptor, true); return JSValue::encode(O); }
bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(exec, m_value.size()), DontEnum | DontDelete | ReadOnly); return true; } bool isStrictUInt32; unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) { descriptor.setDescriptor(jsSingleCharacterSubstring(exec, m_value, i), DontDelete | ReadOnly); return true; } return false; }