Пример #1
0
bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
{
    JSFunction* thisObject = jsCast<JSFunction*>(object);
    if (thisObject->isHostFunction())
        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);

    if (propertyName == exec->propertyNames().prototype) {
        // Make sure prototype has been reified, such that it can only be overwritten
        // following the rules set out in ECMA-262 8.12.9.
        PropertySlot slot;
        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
    } else if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) {
        if (!object->isExtensible()) {
            if (throwException)
                throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
            return false;
        }
        if (descriptor.configurablePresent() && descriptor.configurable()) {
            if (throwException)
                throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
            return false;
        }
        if (descriptor.enumerablePresent() && descriptor.enumerable()) {
            if (throwException)
                throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
            return false;
        }
        if (descriptor.isAccessorDescriptor()) {
            if (throwException)
                throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
            return false;
        }
        if (descriptor.writablePresent() && descriptor.writable()) {
            if (throwException)
                throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
            return false;
        }
        if (!descriptor.value())
            return true;
        if (propertyName == exec->propertyNames().arguments && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject)))
            return true;
        if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount())))
            return true;
        if (propertyName == exec->propertyNames().caller && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject)))
            return true;
        if (throwException)
            throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
        return false;
    }

    return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
Пример #2
0
bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
{
    if (propertyName == exec->propertyNames().lastIndex) {
        RegExpObject* regExp = asRegExpObject(object);
        if (descriptor.configurablePresent() && descriptor.configurable())
            return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property.");
        if (descriptor.enumerablePresent() && descriptor.enumerable())
            return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property.");
        if (descriptor.isAccessorDescriptor())
            return reject(exec, shouldThrow, "Attempting to change access mechanism for an unconfigurable property.");
        if (!regExp->m_lastIndexIsWritable) {
            if (descriptor.writablePresent() && descriptor.writable())
                return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property.");
            if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
                return reject(exec, shouldThrow, "Attempting to change value of a readonly property.");
            return true;
        }
        if (descriptor.writablePresent() && !descriptor.writable())
            regExp->m_lastIndexIsWritable = false;
        if (descriptor.value())
            regExp->setLastIndex(exec, descriptor.value(), false);
        return true;
    }

    return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
}
Пример #3
0
bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (propertyName == vm.propertyNames->lastIndex) {
        RegExpObject* regExp = asRegExpObject(object);
        if (descriptor.configurablePresent() && descriptor.configurable())
            return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
        if (descriptor.enumerablePresent() && descriptor.enumerable())
            return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
        if (descriptor.isAccessorDescriptor())
            return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
        if (!regExp->m_lastIndexIsWritable) {
            if (descriptor.writablePresent() && descriptor.writable())
                return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
            if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
                return typeError(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyChangeError));
            return true;
        }
        if (descriptor.value()) {
            regExp->setLastIndex(exec, descriptor.value(), false);
            RETURN_IF_EXCEPTION(scope, false);
        }
        if (descriptor.writablePresent() && !descriptor.writable())
            regExp->m_lastIndexIsWritable = false;
        return true;
    }

    scope.release();
    return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
}
bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
{
    if (other.m_value.isEmpty() != m_value.isEmpty()
        || other.m_getter.isEmpty() != m_getter.isEmpty()
        || other.m_setter.isEmpty() != m_setter.isEmpty())
        return false;
    return (!m_value || sameValue(exec, other.m_value, m_value))
        && (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter))
        && (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter))
        && attributesEqual(other);
}
Пример #5
0
bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool throwException)
{
    StringObject* thisObject = jsCast<StringObject*>(object);

    if (propertyName == exec->propertyNames().length) {
        if (!object->isExtensible()) {
            if (throwException)
                throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to define property on object that is not extensible.")));
            return false;
        }
        if (descriptor.configurablePresent() && descriptor.configurable()) {
            if (throwException)
                throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to configurable attribute of unconfigurable property.")));
            return false;
        }
        if (descriptor.enumerablePresent() && descriptor.enumerable()) {
            if (throwException)
                throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
            return false;
        }
        if (descriptor.isAccessorDescriptor()) {
            if (throwException)
                throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
            return false;
        }
        if (descriptor.writablePresent() && descriptor.writable()) {
            if (throwException)
                throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
            return false;
        }
        if (!descriptor.value())
            return true;
        if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length())))
            return true;
        if (throwException)
            throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
        return false;
    }

    return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
Пример #6
0
EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState* exec)
{
    // -- Promise.resolve(x) --
    JSValue x = exec->argument(0);

    // 1. Let 'C' be the this value.
    JSValue C = exec->thisValue();

    // 2. If IsPromise(x) is true,
    JSPromise* promise = jsDynamicCast<JSPromise*>(x);
    if (promise) {
        // i. Let 'constructor' be the value of x's [[PromiseConstructor]] internal slot.
        JSValue constructor = promise->constructor();
        // ii. If SameValue(constructor, C) is true, return x.
        if (sameValue(exec, constructor, C))
            return JSValue::encode(x);
    }

    // 3. Let 'deferred' be the result of calling GetDeferred(C).
    JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);

    // 4. ReturnIfAbrupt(deferred).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);

    // 5. Let 'resolveResult' be the result of calling the [[Call]] internal method
    //    of deferred.[[Resolve]] with undefined as thisArgument and a List containing x
    //    as argumentsList.
    performDeferredResolve(exec, deferred, x);

    // 6. ReturnIfAbrupt(resolveResult).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    // 7. Return deferred.[[Promise]].
    return JSValue::encode(deferred->promise());
}
Пример #7
0
bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool throwException)
{
    JSFunction* thisObject = jsCast<JSFunction*>(object);
    if (thisObject->isHostFunction())
        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);

    if (propertyName == exec->propertyNames().prototype) {
        // Make sure prototype has been reified, such that it can only be overwritten
        // following the rules set out in ECMA-262 8.12.9.
        PropertySlot slot;
        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
        thisObject->m_allocationProfile.clear();
        thisObject->m_allocationProfileWatchpoint.notifyWrite();
        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
    }

    bool valueCheck;
    if (propertyName == exec->propertyNames().arguments) {
        if (thisObject->jsExecutable()->isStrictMode()) {
            if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
                thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
            return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
        }
        valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject));
    } else if (propertyName == exec->propertyNames().caller) {
        if (thisObject->jsExecutable()->isStrictMode()) {
            if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
                thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
            return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
        }
        valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject));
    } else if (propertyName == exec->propertyNames().length)
        valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()));
    else if (propertyName == exec->propertyNames().name)
        valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), thisObject->jsExecutable()->nameValue());
    else
        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
     
    if (descriptor.configurablePresent() && descriptor.configurable()) {
        if (throwException)
            throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to configurable attribute of unconfigurable property.")));
        return false;
    }
    if (descriptor.enumerablePresent() && descriptor.enumerable()) {
        if (throwException)
            throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
        return false;
    }
    if (descriptor.isAccessorDescriptor()) {
        if (throwException)
            throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
        return false;
    }
    if (descriptor.writablePresent() && descriptor.writable()) {
        if (throwException)
            throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
        return false;
    }
    if (!valueCheck) {
        if (throwException)
            throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
        return false;
    }
    return true;
}
static EncodedJSValue JSC_HOST_CALL promiseResolutionHandlerFunction(ExecState* exec)
{
    JSValue x = exec->argument(0);
    VM& vm = exec->vm();
    JSObject* F = exec->callee();

    // 1. Let 'promise' be the value of F's [[Promise]] internal slot
    JSPromise* promise = jsCast<JSPromise*>(F->get(exec, vm.propertyNames->promisePrivateName));

    // 2. Let 'fulfillmentHandler' be the value of F's [[FulfillmentHandler]] internal slot.
    JSValue fulfillmentHandler = F->get(exec, vm.propertyNames->fulfillmentHandlerPrivateName);
    
    // 3. Let 'rejectionHandler' be the value of F's [[RejectionHandler]] internal slot.
    JSValue rejectionHandler = F->get(exec, vm.propertyNames->rejectionHandlerPrivateName);
    
    // 4. If SameValue(x, promise) is true,
    if (sameValue(exec, x, promise)) {
        // i. Let 'selfResolutionError' be a newly-created TypeError object.
        JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
        // ii. Return the result of calling the [[Call]] internal method of rejectionHandler with
        //     undefined as thisArgument and a List containing selfResolutionError as argumentsList.
        CallData rejectCallData;
        CallType rejectCallType = getCallData(rejectionHandler, rejectCallData);
        ASSERT(rejectCallType != CallTypeNone);

        MarkedArgumentBuffer rejectArguments;
        rejectArguments.append(selfResolutionError);

        return JSValue::encode(call(exec, rejectionHandler, rejectCallType, rejectCallData, jsUndefined(), rejectArguments));
    }

    // 5. Let 'C' be the value of promise's [[PromiseConstructor]] internal slot.
    JSValue C = promise->constructor();

    // 6. Let 'deferred' be the result of calling GetDeferred(C)
    JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);

    // 7. ReturnIfAbrupt(deferred).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);

    // 8. Let 'updateResult' be the result of calling UpdateDeferredFromPotentialThenable(x, deferred).
    ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, x, deferred);

    // 9. ReturnIfAbrupt(updateResult).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    // 10. If 'updateResult' is not "not a thenable", return the result of calling
    //     Invoke(deferred.[[Promise]], "then", (fulfillmentHandler, rejectionHandler)).
    // NOTE: Invoke does not seem to be defined anywhere, so I am guessing here.
    if (updateResult != NotAThenable) {
        JSObject* deferredPromise = deferred->promise();
    
        JSValue thenValue = deferredPromise->get(exec, exec->vm().propertyNames->then);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        CallData thenCallData;
        CallType thenCallType = getCallData(thenValue, thenCallData);
        if (thenCallType == CallTypeNone)
            return JSValue::encode(throwTypeError(exec));

        MarkedArgumentBuffer arguments;
        arguments.append(fulfillmentHandler);
        arguments.append(rejectionHandler);

        return JSValue::encode(call(exec, thenValue, thenCallType, thenCallData, deferredPromise, arguments));
    }
    
    // 11. Return the result of calling the [[Call]] internal method of fulfillmentHandler
    //     with undefined as thisArgument and a List containing x as argumentsList.
    CallData fulfillmentHandlerCallData;
    CallType fulfillmentHandlerCallType = getCallData(fulfillmentHandler, fulfillmentHandlerCallData);
    ASSERT(fulfillmentHandlerCallType != CallTypeNone);
    
    MarkedArgumentBuffer fulfillmentHandlerArguments;
    fulfillmentHandlerArguments.append(x);

    return JSValue::encode(call(exec, fulfillmentHandler, fulfillmentHandlerCallType, fulfillmentHandlerCallData, jsUndefined(), fulfillmentHandlerArguments));
}