From df62ef652ac1c97eed5bdf7ed6ea1fac92d885da Mon Sep 17 00:00:00 2001 From: HyukWoo Park Date: Thu, 13 Jun 2019 11:14:12 +0900 Subject: [PATCH] Update isCallable check function according to call operation * isFunction is replaced with isCallable check function * call operations in Promise / TypedArray are fixed Signed-off-by: HyukWoo Park --- src/api/EscargotPublic.cpp | 7 +- src/api/EscargotPublic.h | 1 + src/interpreter/ByteCodeInterpreter.cpp | 22 +++-- src/runtime/BoundFunctionObject.cpp | 4 +- src/runtime/BoundFunctionObject.h | 7 +- src/runtime/FunctionObject.cpp | 2 +- src/runtime/FunctionObject.h | 44 ++------- src/runtime/GlobalObject.cpp | 8 +- src/runtime/GlobalObjectBuiltinArray.cpp | 66 ++++++------- src/runtime/GlobalObjectBuiltinDate.cpp | 2 +- src/runtime/GlobalObjectBuiltinFunction.cpp | 7 +- src/runtime/GlobalObjectBuiltinIntl.cpp | 4 +- src/runtime/GlobalObjectBuiltinJSON.cpp | 6 +- src/runtime/GlobalObjectBuiltinMap.cpp | 8 +- src/runtime/GlobalObjectBuiltinNumber.cpp | 4 +- src/runtime/GlobalObjectBuiltinObject.cpp | 4 +- src/runtime/GlobalObjectBuiltinPromise.cpp | 48 +++++----- src/runtime/GlobalObjectBuiltinReflect.cpp | 4 +- src/runtime/GlobalObjectBuiltinRegExp.cpp | 6 +- src/runtime/GlobalObjectBuiltinSet.cpp | 8 +- src/runtime/GlobalObjectBuiltinString.cpp | 10 +- src/runtime/GlobalObjectBuiltinTypedArray.cpp | 96 +++++++++---------- src/runtime/GlobalObjectBuiltinWeakMap.cpp | 4 +- src/runtime/GlobalObjectBuiltinWeakSet.cpp | 4 +- src/runtime/GlobalRegExpFunctionObject.cpp | 14 +-- src/runtime/IteratorOperations.cpp | 8 +- src/runtime/Job.cpp | 19 ++-- src/runtime/Job.h | 4 +- src/runtime/Object.cpp | 50 +++++++--- src/runtime/Object.h | 21 ++-- src/runtime/PromiseObject.cpp | 17 ++-- src/runtime/PromiseObject.h | 14 +-- src/runtime/ProxyObject.cpp | 28 +++--- src/runtime/ProxyObject.h | 7 +- src/runtime/Value.cpp | 6 +- src/shell/Shell.cpp | 2 +- test/regression-tests/issue-288.js | 16 ++++ test/regression-tests/xfail/issue-287.js | 16 ++++ 38 files changed, 316 insertions(+), 282 deletions(-) create mode 100644 test/regression-tests/issue-288.js create mode 100644 test/regression-tests/xfail/issue-287.js diff --git a/src/api/EscargotPublic.cpp b/src/api/EscargotPublic.cpp index f45fa87ce..ea6a8ed70 100644 --- a/src/api/EscargotPublic.cpp +++ b/src/api/EscargotPublic.cpp @@ -1292,7 +1292,7 @@ ValueRef* FunctionObjectRef::call(ExecutionStateRef* state, ValueRef* receiver, for (size_t i = 0; i < argc; i++) { newArgv[i] = toImpl(argv[i]); } - return toRef(o->call(*toImpl(state), toImpl(receiver), argc, newArgv)); + return toRef(Object::call(*toImpl(state), o, toImpl(receiver), argc, newArgv)); } static void markEvalToCodeblock(InterpretedCodeBlock* cb) @@ -1622,6 +1622,11 @@ bool ValueRef::isFunction() const return Value(SmallValue::fromPayload(this)).isFunction(); } +bool ValueRef::isCallable() const +{ + return Value(SmallValue::fromPayload(this)).isCallable(); +} + bool ValueRef::toBoolean(ExecutionStateRef* es) { ExecutionState* esi = toImpl(es); diff --git a/src/api/EscargotPublic.h b/src/api/EscargotPublic.h index 73a62f38a..3e4ee9d89 100644 --- a/src/api/EscargotPublic.h +++ b/src/api/EscargotPublic.h @@ -352,6 +352,7 @@ class EXPORT ValueRef { bool isString() const; bool isObject() const; bool isFunction() const; + bool isCallable() const; bool isUndefinedOrNull() const { return isUndefined() || isNull(); diff --git a/src/interpreter/ByteCodeInterpreter.cpp b/src/interpreter/ByteCodeInterpreter.cpp index b94b5091d..7a9aa3ebe 100644 --- a/src/interpreter/ByteCodeInterpreter.cpp +++ b/src/interpreter/ByteCodeInterpreter.cpp @@ -558,7 +558,7 @@ Value ByteCodeInterpreter::interpret(ExecutionState& state, ByteCodeBlock* byteC { CallFunction* code = (CallFunction*)programCounter; const Value& callee = registerFile[code->m_calleeIndex]; - registerFile[code->m_resultIndex] = FunctionObject::call(state, callee, Value(), code->m_argumentCount, ®isterFile[code->m_argumentsStartIndex]); + registerFile[code->m_resultIndex] = Object::call(state, callee, Value(), code->m_argumentCount, ®isterFile[code->m_argumentsStartIndex]); ADD_PROGRAM_COUNTER(CallFunction); NEXT_INSTRUCTION(); } @@ -569,7 +569,7 @@ Value ByteCodeInterpreter::interpret(ExecutionState& state, ByteCodeBlock* byteC CallFunctionWithReceiver* code = (CallFunctionWithReceiver*)programCounter; const Value& callee = registerFile[code->m_calleeIndex]; const Value& receiver = registerFile[code->m_receiverIndex]; - registerFile[code->m_resultIndex] = FunctionObject::call(state, callee, receiver, code->m_argumentCount, ®isterFile[code->m_argumentsStartIndex]); + registerFile[code->m_resultIndex] = Object::call(state, callee, receiver, code->m_argumentCount, ®isterFile[code->m_argumentsStartIndex]); ADD_PROGRAM_COUNTER(CallFunctionWithReceiver); NEXT_INSTRUCTION(); } @@ -1268,7 +1268,7 @@ Value ByteCodeInterpreter::interpret(ExecutionState& state, ByteCodeBlock* byteC const Value& receiver = code->m_receiverIndex == REGISTER_LIMIT ? Value() : registerFile[code->m_receiverIndex]; ValueVector spreadArgs; spreadFunctionArguments(state, ®isterFile[code->m_argumentsStartIndex], code->m_argumentCount, spreadArgs); - registerFile[code->m_resultIndex] = FunctionObject::call(state, callee, receiver, spreadArgs.size(), spreadArgs.data()); + registerFile[code->m_resultIndex] = Object::call(state, callee, receiver, spreadArgs.size(), spreadArgs.data()); ADD_PROGRAM_COUNTER(CallFunctionWithSpreadElement); NEXT_INSTRUCTION(); } @@ -1500,7 +1500,7 @@ NEVER_INLINE Object* ByteCodeInterpreter::newOperation(ExecutionState& state, co if (callee.isConstructor() == false) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_Not_Constructor); } - return FunctionObject::construct(state, callee, argc, argv); + return Object::construct(state, callee, argc, argv); } // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-instanceofoperator @@ -1517,7 +1517,7 @@ NEVER_INLINE Value ByteCodeInterpreter::instanceOfOperation(ExecutionState& stat if (!instOfHandler.isUndefined()) { // Return ToBoolean(Call(instOfHandler, C, «O»)). Value arg[1] = { left }; - return Value(FunctionObject::call(state, instOfHandler, right, 1, arg).toBoolean(state)); + return Value(Object::call(state, instOfHandler, right, 1, arg).toBoolean(state)); } #endif // If IsCallable(C) is false, throw a TypeError exception. @@ -2193,7 +2193,7 @@ NEVER_INLINE void ByteCodeInterpreter::evalOperation(ExecutionState& state, Call thisValue = env->record()->asObjectEnvironmentRecord()->bindingObject(); } } - registerFile[code->m_resultIndex] = FunctionObject::call(state, eval, thisValue, argc, argv); + registerFile[code->m_resultIndex] = Object::call(state, eval, thisValue, argc, argv); } } @@ -2396,9 +2396,9 @@ NEVER_INLINE Value ByteCodeInterpreter::callFunctionInWithScope(ExecutionState& if (code->m_hasSpreadElement) { ValueVector spreadArgs; spreadFunctionArguments(state, argv, code->m_argumentCount, spreadArgs); - return FunctionObject::call(state, callee, receiverObj, spreadArgs.size(), spreadArgs.data()); + return Object::call(state, callee, receiverObj, spreadArgs.size(), spreadArgs.data()); } - return FunctionObject::call(state, callee, receiverObj, code->m_argumentCount, argv); + return Object::call(state, callee, receiverObj, code->m_argumentCount, argv); } void ByteCodeInterpreter::spreadFunctionArguments(ExecutionState& state, const Value* argv, const size_t argc, ValueVector& argVector) @@ -2458,7 +2458,7 @@ Value ByteCodeInterpreter::yieldDelegateOperation(ExecutionState& state, Value* return nextValue; } - Value innerResult = FunctionObject::call(state, ret, iterator, 1, &nextValue); + Value innerResult = Object::call(state, ret, iterator, 1, &nextValue); if (innerResult.isObject() == false) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "IteratorResult is not an object"); @@ -2479,7 +2479,7 @@ Value ByteCodeInterpreter::yieldDelegateOperation(ExecutionState& state, Value* if (throwMethod.isUndefined() == false) { Value innerResult; - innerResult = FunctionObject::call(state, throwMethod, iterator, 1, &nextValue); + innerResult = Object::call(state, throwMethod, iterator, 1, &nextValue); if (innerResult.isObject() == false) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "IteratorResult is not an object"); } @@ -2559,6 +2559,7 @@ NEVER_INLINE void ByteCodeInterpreter::declareFunctionDeclarations(ExecutionStat NEVER_INLINE void ByteCodeInterpreter::defineObjectGetter(ExecutionState& state, ObjectDefineGetter* code, Value* registerFile) { + // FIXME: FunctionObject FunctionObject* fn = registerFile[code->m_objectPropertyValueRegisterIndex].asFunction(); String* pName = registerFile[code->m_objectPropertyNameRegisterIndex].toString(state); StringBuilder builder; @@ -2574,6 +2575,7 @@ NEVER_INLINE void ByteCodeInterpreter::defineObjectGetter(ExecutionState& state, NEVER_INLINE void ByteCodeInterpreter::defineObjectSetter(ExecutionState& state, ObjectDefineSetter* code, Value* registerFile) { + // FIXME: FunctionObject FunctionObject* fn = registerFile[code->m_objectPropertyValueRegisterIndex].asFunction(); String* pName = registerFile[code->m_objectPropertyNameRegisterIndex].toString(state); StringBuilder builder; diff --git a/src/runtime/BoundFunctionObject.cpp b/src/runtime/BoundFunctionObject.cpp index 4ac3d1dff..d5bd5b8f5 100644 --- a/src/runtime/BoundFunctionObject.cpp +++ b/src/runtime/BoundFunctionObject.cpp @@ -73,7 +73,7 @@ Value BoundFunctionObject::call(ExecutionState& state, const Value& thisValue, c } // Return Call(target, boundThis, args). - return FunctionObject::call(state, m_boundTargetFunction, m_boundThis, mergedArgc, mergedArgv); + return Object::call(state, m_boundTargetFunction, m_boundThis, mergedArgc, mergedArgv); } // https://www.ecma-international.org/ecma-262/6.0/#sec-bound-function-exotic-objects-construct-argumentslist-newtarget @@ -95,6 +95,6 @@ Object* BoundFunctionObject::construct(ExecutionState& state, const size_t calle Value newConstructTarget = (Value(this) == Value(newTarget)) ? Value(m_boundTargetFunction) : newTarget; // Return Construct(target, args, newTarget). - return FunctionObject::construct(state, m_boundTargetFunction, mergedArgc, mergedArgv, newConstructTarget); + return Object::construct(state, m_boundTargetFunction, mergedArgc, mergedArgv, newConstructTarget); } } diff --git a/src/runtime/BoundFunctionObject.h b/src/runtime/BoundFunctionObject.h index 84e924bba..ede25f91c 100644 --- a/src/runtime/BoundFunctionObject.h +++ b/src/runtime/BoundFunctionObject.h @@ -46,10 +46,6 @@ class BoundFunctionObject : public Object { return Value(m_boundTargetFunction).isConstructor(); } - virtual Value call(ExecutionState& state, const Value& thisValue, const size_t calledArgc, Value* calledArgv) override; - - virtual Object* construct(ExecutionState& state, const size_t calledArgc, Value* calledArgv, const Value& newTarget) override; - Value targetFunction() { return m_boundTargetFunction; @@ -62,6 +58,9 @@ class BoundFunctionObject : public Object { } private: + virtual Value call(ExecutionState& state, const Value& thisValue, const size_t calledArgc, Value* calledArgv) override; + virtual Object* construct(ExecutionState& state, const size_t calledArgc, Value* calledArgv, const Value& newTarget) override; + SmallValue m_boundTargetFunction; SmallValue m_boundThis; SmallValueVector m_boundArguments; diff --git a/src/runtime/FunctionObject.cpp b/src/runtime/FunctionObject.cpp index e13392458..b6fafc85b 100644 --- a/src/runtime/FunctionObject.cpp +++ b/src/runtime/FunctionObject.cpp @@ -282,7 +282,7 @@ Value FunctionObject::processCall(ExecutionState& state, const Value& receiverSr } if (UNLIKELY(isSuperCall == true && isBuiltin() == true && isNewExpression == false)) { - Value returnValue = FunctionObject::construct(state, this, argc, argv); + Value returnValue = Object::construct(state, this, argc, argv); returnValue.asObject()->setPrototype(state, receiverSrc.toObject(state)->getPrototype(state)); return returnValue; } diff --git a/src/runtime/FunctionObject.h b/src/runtime/FunctionObject.h index a29bbac7b..366ba4c66 100644 --- a/src/runtime/FunctionObject.h +++ b/src/runtime/FunctionObject.h @@ -163,40 +163,6 @@ class FunctionObject : public Object { return FunctionKind::Normal; } - // https://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist - virtual Value call(ExecutionState& state, const Value& thisValue, const size_t argc, NULLABLE Value* argv) override - { - return processCall(state, thisValue, argc, argv, false); - } - - virtual Object* construct(ExecutionState& state, const size_t argc, NULLABLE Value* argv, const Value& newTarget) override; - - // https://www.ecma-international.org/ecma-262/6.0/#sec-call - ALWAYS_INLINE static Value call(ExecutionState& state, const Value& callee, const Value& thisValue, const size_t argc, NULLABLE Value* argv) - { - // If IsCallable(F) is false, throw a TypeError exception. - if (callee.isCallable() == false) { - ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_NOT_Callable); - } - // Return F.[[Call]](V, argumentsList). - return callee.asObject()->call(state, thisValue, argc, argv); - } - - // https://www.ecma-international.org/ecma-262/6.0/#sec-construct - ALWAYS_INLINE static Object* construct(ExecutionState& state, const Value& constructor, const size_t argc, NULLABLE Value* argv, Value newTarget = Value(Value::EmptyValue)) - { - // If newTarget was not passed, let newTarget be F. - if (newTarget.isEmpty() == true) { - newTarget = constructor; - } - // Assert: IsConstructor (F) is true. - ASSERT(constructor.isConstructor() == true); - // Assert: IsConstructor (newTarget) is true. - ASSERT(newTarget.isConstructor() == true); - // Return F.[[Construct]](argumentsList, newTarget). - return constructor.asObject()->construct(state, argc, argv, newTarget); - } - // http://www.ecma-international.org/ecma-262/5.1/#sec-8.6.2 virtual const char* internalClassProperty() override { @@ -209,6 +175,16 @@ class FunctionObject : public Object { } private: + friend class Object; + friend class ObjectGetResult; + // https://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + virtual Value call(ExecutionState& state, const Value& thisValue, const size_t argc, NULLABLE Value* argv) override + { + return processCall(state, thisValue, argc, argv, false); + } + + virtual Object* construct(ExecutionState& state, const size_t argc, NULLABLE Value* argv, const Value& newTarget) override; + LexicalEnvironment* outerEnvironment() { return m_outerEnvironment; diff --git a/src/runtime/GlobalObject.cpp b/src/runtime/GlobalObject.cpp index 1793f811a..bef109f2f 100644 --- a/src/runtime/GlobalObject.cpp +++ b/src/runtime/GlobalObject.cpp @@ -885,11 +885,11 @@ static Value builtinDefineGetter(ExecutionState& state, Value thisValue, size_t // Let O be ? ToObject(this value). Object* O = thisValue.toObject(state); // If IsCallable(getter) is false, throw a TypeError exception. - if (!argv[1].isFunction()) { + if (!argv[1].isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, String::emptyString, true, state.context()->staticStrings().__defineGetter__.string(), errorMessage_GlobalObject_CallbackNotCallable); } // Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true, [[Configurable]]: true}. - ObjectPropertyDescriptor desc(JSGetterSetter(argv[1].asFunction(), Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)); + ObjectPropertyDescriptor desc(JSGetterSetter(argv[1].asObject(), Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)); // Let key be ? ToPropertyKey(P). ObjectPropertyName key(state, argv[0]); @@ -910,11 +910,11 @@ static Value builtinDefineSetter(ExecutionState& state, Value thisValue, size_t // Let O be ? ToObject(this value). Object* O = thisValue.toObject(state); // If IsCallable(getter) is false, throw a TypeError exception. - if (!argv[1].isFunction()) { + if (!argv[1].isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, String::emptyString, true, state.context()->staticStrings().__defineSetter__.string(), errorMessage_GlobalObject_CallbackNotCallable); } // Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true, [[Configurable]]: true}. - ObjectPropertyDescriptor desc(JSGetterSetter(Value(Value::EmptyValue), argv[1].asFunction()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)); + ObjectPropertyDescriptor desc(JSGetterSetter(Value(Value::EmptyValue), argv[1].asObject()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)); // Let key be ? ToPropertyKey(P). ObjectPropertyName key(state, argv[0]); diff --git a/src/runtime/GlobalObjectBuiltinArray.cpp b/src/runtime/GlobalObjectBuiltinArray.cpp index d5306efc0..55eedc699 100644 --- a/src/runtime/GlobalObjectBuiltinArray.cpp +++ b/src/runtime/GlobalObjectBuiltinArray.cpp @@ -115,7 +115,7 @@ static Value arraySpeciesCreate(ExecutionState& state, Object* originalArray, co } // Return Construct(C, <>). Value argv[1] = { Value(length) }; - return FunctionObject::construct(state, C, 1, argv); + return Object::construct(state, C, 1, argv); } static Value builtinArrayIsArray(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) @@ -148,7 +148,7 @@ static Value builtinArrayFrom(ExecutionState& state, Value thisValue, size_t arg bool mapping = false; if (!mapfn.isUndefined()) { // If IsCallable(mapfn) is false, throw a TypeError exception. - if (!mapfn.isFunction()) { + if (!mapfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "argument map function should be undefined or function"); } // If thisArg was supplied, let T be thisArg; else let T be undefined. @@ -166,7 +166,7 @@ static Value builtinArrayFrom(ExecutionState& state, Value thisValue, size_t arg // If IsConstructor(C) is true, then if (C.isConstructor() == true) { // Let A be ? Construct(C). - A = FunctionObject::construct(state, C, 0, nullptr); + A = Object::construct(state, C, 0, nullptr); } else { // Let A be ArrayCreate(0). A = new ArrayObject(state); @@ -203,7 +203,7 @@ static Value builtinArrayFrom(ExecutionState& state, Value thisValue, size_t arg // If mappedValue is an abrupt completion, return ? IteratorClose(iterator, mappedValue). // Let mappedValue be mappedValue.[[Value]]. Value argv[] = { nextValue, Value(k) }; - mappedValue = mapfn.asFunction()->call(state, T, 2, argv); + mappedValue = Object::call(state, mapfn, T, 2, argv); } else { mappedValue = nextValue; } @@ -223,7 +223,7 @@ static Value builtinArrayFrom(ExecutionState& state, Value thisValue, size_t arg if (C.isConstructor() == true) { // Let A be ? Construct(C, « len »). Value vlen(len); - A = FunctionObject::construct(state, C, 1, &vlen); + A = Object::construct(state, C, 1, &vlen); } else { // Else, // Let A be ? ArrayCreate(len). @@ -243,7 +243,7 @@ static Value builtinArrayFrom(ExecutionState& state, Value thisValue, size_t arg if (mapping) { // Let mappedValue be ? Call(mapfn, T, « kValue, k »). Value argv[] = { kValue, Value(k) }; - mappedValue = mapfn.asFunction()->call(state, T, 2, argv); + mappedValue = Object::call(state, mapfn, T, 2, argv); } else { // Else, let mappedValue be kValue. mappedValue = kValue; @@ -268,7 +268,7 @@ static Value builtinArrayOf(ExecutionState& state, Value thisValue, size_t argc, Object* A; if (C.isConstructor() == true) { Value arg[1] = { Value(len) }; - A = FunctionObject::construct(state, C, 1, arg); + A = Object::construct(state, C, 1, arg); } else { A = new ArrayObject(state, static_cast(len)); } @@ -403,7 +403,7 @@ static Value builtinArraySort(ExecutionState& state, Value thisValue, size_t arg { RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, sort); Value cmpfn = argv[0]; - if (!cmpfn.isUndefined() && !cmpfn.isFunction()) { + if (!cmpfn.isUndefined() && !cmpfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().sort.string(), errorMessage_GlobalObject_FirstArgumentNotCallable); } bool defaultSort = (argc == 0) || cmpfn.isUndefined(); @@ -423,7 +423,7 @@ static Value builtinArraySort(ExecutionState& state, Value thisValue, size_t arg String* valb = b.toString(state); return *vala < *valb; } else { - Value ret = FunctionObject::call(state, cmpfn, Value(), 2, arg); + Value ret = Object::call(state, cmpfn, Value(), 2, arg); return (ret.toNumber(state) < 0); } }); return thisObject; @@ -624,10 +624,10 @@ static Value builtinArrayToString(ExecutionState& state, Value thisValue, size_t { RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, toString); Value toString = thisObject->get(state, state.context()->staticStrings().join).value(state, thisObject); - if (!toString.isFunction()) { + if (!toString.isCallable()) { toString = state.context()->globalObject()->objectPrototypeToString(); } - return FunctionObject::call(state, toString, thisObject, 0, nullptr); + return Object::call(state, toString, thisObject, 0, nullptr); } static Value builtinArrayConcat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) @@ -735,7 +735,7 @@ static Value builtinArrayForEach(ExecutionState& state, Value thisValue, size_t uint32_t len = thisObject->length(state); Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().forEach.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -752,7 +752,7 @@ static Value builtinArrayForEach(ExecutionState& state, Value thisValue, size_t if (res.hasValue()) { Value kValue = res.value(state, thisObject); Value args[3] = { kValue, Pk, thisObject }; - callbackfn.asFunction()->call(state, T, 3, args); + Object::call(state, callbackfn, T, 3, args); k++; } else { double result; @@ -900,7 +900,7 @@ static Value builtinArrayEvery(ExecutionState& state, Value thisValue, size_t ar // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().every.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -926,7 +926,7 @@ static Value builtinArrayEvery(ExecutionState& state, Value thisValue, size_t ar Value kValue = O->get(state, ObjectPropertyName(state, pk)).value(state, O); // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O. Value args[] = { kValue, Value(k), O }; - Value testResult = callbackfn.asFunction()->call(state, T, 3, args); + Value testResult = Object::call(state, callbackfn, T, 3, args); if (!testResult.toBoolean(state)) { return Value(false); @@ -988,7 +988,7 @@ static Value builtinArrayFilter(ExecutionState& state, Value thisValue, size_t a // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().every.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1026,7 +1026,7 @@ static Value builtinArrayFilter(ExecutionState& state, Value thisValue, size_t a // Let selected be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O. Value v[] = { kValue, Value(k), O }; - Value selected = callbackfn.asFunction()->call(state, T, 3, v); + Value selected = Object::call(state, callbackfn, T, 3, v); // If ToBoolean(selected) is true, then if (selected.toBoolean(state)) { @@ -1060,7 +1060,7 @@ static Value builtinArrayMap(ExecutionState& state, Value thisValue, size_t argc // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().every.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1096,7 +1096,7 @@ static Value builtinArrayMap(ExecutionState& state, Value thisValue, size_t argc Value kValue = kPresent.value(state, O); // Let mappedValue be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O. Value v[] = { kValue, Value(k), O }; - Value mappedValue = callbackfn.asFunction()->call(state, T, 3, v); + Value mappedValue = Object::call(state, callbackfn, T, 3, v); // Let status be CreateDataPropertyOrThrow (A, Pk, mappedValue). A->defineOwnPropertyThrowsException(state, Pk, ObjectPropertyDescriptor(mappedValue, ObjectPropertyDescriptor::AllPresent)); k++; @@ -1123,7 +1123,7 @@ static Value builtinArraySome(ExecutionState& state, Value thisValue, size_t arg // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().some.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1148,7 +1148,7 @@ static Value builtinArraySome(ExecutionState& state, Value thisValue, size_t arg Value kValue = kPresent.value(state, O); // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O. Value argv[] = { kValue, Value(k), O }; - Value testResult = callbackfn.asFunction()->call(state, T, 3, argv); + Value testResult = Object::call(state, callbackfn, T, 3, argv); // If ToBoolean(testResult) is true, return true. if (testResult.toBoolean(state)) { return Value(true); @@ -1249,11 +1249,11 @@ static Value builtinArrayToLocaleString(ExecutionState& state, Value thisValue, // Let func be the result of calling the [[Get]] internal method of elementObj with argument "toLocaleString". Value func = elementObj->get(state, state.context()->staticStrings().toLocaleString).value(state, elementObj); // If IsCallable(func) is false, throw a TypeError exception. - if (!func.isFunction()) { + if (!func.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().toLocaleString.string(), errorMessage_GlobalObject_ToLocaleStringNotCallable); } // Let R be the result of calling the [[Call]] internal method of func providing elementObj as the this value and an empty arguments list. - R = func.asFunction()->call(state, elementObj, 0, nullptr); + R = Object::call(state, func, elementObj, 0, nullptr); } // Let k be 1. @@ -1280,11 +1280,11 @@ static Value builtinArrayToLocaleString(ExecutionState& state, Value thisValue, // Let func be the result of calling the [[Get]] internal method of elementObj with argument "toLocaleString". Value func = elementObj->get(state, state.context()->staticStrings().toLocaleString).value(state, elementObj); // If IsCallable(func) is false, throw a TypeError exception. - if (!func.isFunction()) { + if (!func.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().toLocaleString.string(), errorMessage_GlobalObject_ToLocaleStringNotCallable); } // Let R be the result of calling the [[Call]] internal method of func providing elementObj as the this value and an empty arguments list. - R = func.asFunction()->call(state, elementObj, 0, nullptr); + R = Object::call(state, func, elementObj, 0, nullptr); } // Let R be a String value produced by concatenating S and R. StringBuilder builder2; @@ -1309,7 +1309,7 @@ static Value builtinArrayReduce(ExecutionState& state, Value thisValue, size_t a initialValue = argv[1]; } - if (!callbackfn.isFunction()) // 4 + if (!callbackfn.isCallable()) // 4 ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduce.string(), errorMessage_GlobalObject_CallbackNotCallable); if (len == 0 && (initialValue.isUndefined() || initialValue.isEmpty())) // 5 @@ -1338,7 +1338,7 @@ static Value builtinArrayReduce(ExecutionState& state, Value thisValue, size_t a Value kValue = O->get(state, ObjectPropertyName(state, Pk)).value(state, O); // 9.c.i const int fnargc = 4; Value fnargs[] = { accumulator, kValue, Value(k), O }; - accumulator = FunctionObject::call(state, callbackfn, Value(), fnargc, fnargs); + accumulator = Object::call(state, callbackfn, Value(), fnargc, fnargs); k++; } else { double result; @@ -1360,7 +1360,7 @@ static Value builtinArrayReduceRight(ExecutionState& state, Value thisValue, siz // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduceRight.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1422,7 +1422,7 @@ static Value builtinArrayReduceRight(ExecutionState& state, Value thisValue, siz // Let accumulator be the result of calling the [[Call]] internal method of callbackfn with undefined as the this value and argument list containing accumulator, kValue, k, and O. Value v[] = { accumulator, kValue, Value(k), O }; - accumulator = callbackfn.asFunction()->call(state, Value(), 4, v); + accumulator = Object::call(state, callbackfn, Value(), 4, v); } // Decrease k by 1. @@ -1645,7 +1645,7 @@ static Value builtinArrayFind(ExecutionState& state, Value thisValue, size_t arg // Let len be ? ToLength(? Get(O, "length")). double len = O->lengthES6(state); // If IsCallable(predicate) is false, throw a TypeError exception. - if (!argv[0].isFunction()) { + if (!argv[0].isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().find.string(), errorMessage_GlobalObject_CallbackNotCallable); } Value T; @@ -1662,7 +1662,7 @@ static Value builtinArrayFind(ExecutionState& state, Value thisValue, size_t arg Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O); // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). Value v[] = { kValue, Value(k), O }; - bool testResult = argv[0].asFunction()->call(state, T, 3, v).toBoolean(state); + bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state); // If testResult is true, return kValue. if (testResult) { return kValue; @@ -1682,7 +1682,7 @@ static Value builtinArrayFindIndex(ExecutionState& state, Value thisValue, size_ // Let len be ? ToLength(? Get(O, "length")). double len = O->lengthES6(state); // If IsCallable(predicate) is false, throw a TypeError exception. - if (!argv[0].isFunction()) { + if (!argv[0].isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().findIndex.string(), errorMessage_GlobalObject_CallbackNotCallable); } Value T; @@ -1699,7 +1699,7 @@ static Value builtinArrayFindIndex(ExecutionState& state, Value thisValue, size_ Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O); // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). Value v[] = { kValue, Value(k), O }; - bool testResult = argv[0].asFunction()->call(state, T, 3, v).toBoolean(state); + bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state); // If testResult is true, return k. if (testResult) { return Value(k); diff --git a/src/runtime/GlobalObjectBuiltinDate.cpp b/src/runtime/GlobalObjectBuiltinDate.cpp index d4d3d5e06..90c03b986 100644 --- a/src/runtime/GlobalObjectBuiltinDate.cpp +++ b/src/runtime/GlobalObjectBuiltinDate.cpp @@ -274,7 +274,7 @@ static Value builtinDateToJSON(ExecutionState& state, Value thisValue, size_t ar } Value isoFunc = thisObject->get(state, ObjectPropertyName(state.context()->staticStrings().toISOString)).value(state, thisObject); - return FunctionObject::call(state, isoFunc, thisObject, 0, nullptr); + return Object::call(state, isoFunc, thisObject, 0, nullptr); } #define DECLARE_STATIC_DATE_GETTER(Name, unused1, unused2, unused3) \ diff --git a/src/runtime/GlobalObjectBuiltinFunction.cpp b/src/runtime/GlobalObjectBuiltinFunction.cpp index 42de5146e..b32e1a69d 100644 --- a/src/runtime/GlobalObjectBuiltinFunction.cpp +++ b/src/runtime/GlobalObjectBuiltinFunction.cpp @@ -122,6 +122,7 @@ static Value builtinFunctionConstructor(ExecutionState& state, Value thisValue, // https://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.tostring static Value builtinFunctionToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) { + // FIXME: If Type(func) is Object and is either a built-in function object or has an [[ECMAScriptCode]] internal slot, then if (thisValue.isFunction() == true) { FunctionObject* fn = thisValue.asFunction(); StringBuilder builder; @@ -167,7 +168,6 @@ static Value builtinFunctionApply(ExecutionState& state, Value thisValue, size_t if (thisValue.isCallable() == false) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().apply.string(), errorMessage_GlobalObject_ThisNotFunctionObject); } - FunctionObject* thisVal = thisValue.asFunction(); Value thisArg = argv[0]; Value argArray = argv[1]; size_t arrlen = 0; @@ -190,7 +190,7 @@ static Value builtinFunctionApply(ExecutionState& state, Value thisValue, size_t ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().apply.string(), errorMessage_GlobalObject_SecondArgumentNotObject); } - return FunctionObject::call(state, thisVal, thisArg, arrlen, arguments); + return Object::call(state, thisValue, thisArg, arrlen, arguments); } static Value builtinFunctionCall(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) @@ -198,7 +198,6 @@ static Value builtinFunctionCall(ExecutionState& state, Value thisValue, size_t if (thisValue.isCallable() == false) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().apply.string(), errorMessage_GlobalObject_ThisNotFunctionObject); } - FunctionObject* thisVal = thisValue.asFunction(); Value thisArg = argv[0]; size_t arrlen = argc > 0 ? argc - 1 : 0; Value* arguments = ALLOCA(sizeof(Value) * arrlen, Value, state); @@ -206,7 +205,7 @@ static Value builtinFunctionCall(ExecutionState& state, Value thisValue, size_t arguments[i] = argv[i + 1]; } - return FunctionObject::call(state, thisVal, thisArg, arrlen, arguments); + return Object::call(state, thisValue, thisArg, arrlen, arguments); } // https://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.bind diff --git a/src/runtime/GlobalObjectBuiltinIntl.cpp b/src/runtime/GlobalObjectBuiltinIntl.cpp index 4aa9129ac..3c8129e71 100644 --- a/src/runtime/GlobalObjectBuiltinIntl.cpp +++ b/src/runtime/GlobalObjectBuiltinIntl.cpp @@ -485,7 +485,7 @@ static ValueVector canonicalizeLocaleList(ExecutionState& state, Value locales) // Let locales be a new array created as if // by the expression new Array(locales) where Array is the standard built-in constructor with that name and locales is the value of locales. Value callArg[] = { locales }; - locales = FunctionObject::construct(state, state.context()->globalObject()->array(), 1, callArg); + locales = Object::construct(state, state.context()->globalObject()->array(), 1, callArg); } // Let O be ToObject(locales). Object* O = locales.toObject(state); @@ -1372,7 +1372,7 @@ static Value toDateTimeOptions(ExecutionState& state, Value options, Value requi // Let create be the standard built-in function object defined in ES5, 15.2.3.5. // Let options be the result of calling the [[Call]] internal method of create with undefined as the this value // and an argument list containing the single item options. - options = state.context()->globalObject()->objectCreate()->call(state, Value(), 1, &options); + options = Object::call(state, state.context()->globalObject()->objectCreate(), Value(), 1, &options); // Let needDefaults be true. bool needDefaults = true; diff --git a/src/runtime/GlobalObjectBuiltinJSON.cpp b/src/runtime/GlobalObjectBuiltinJSON.cpp index 05d26c32a..f9e1d7367 100644 --- a/src/runtime/GlobalObjectBuiltinJSON.cpp +++ b/src/runtime/GlobalObjectBuiltinJSON.cpp @@ -268,7 +268,7 @@ static Value builtinJSONParse(ExecutionState& state, Value thisValue, size_t arg } } Value arguments[] = { name.toPlainValue(state), val }; - return FunctionObject::call(state, reviver, holder, 2, arguments); + return Object::call(state, reviver, holder, 2, arguments); }; return Walk(root, ObjectPropertyName(state, String::emptyString)); } @@ -378,13 +378,13 @@ static Value builtinJSONStringify(ExecutionState& state, Value thisValue, size_t Value toJson = valObj->get(state, ObjectPropertyName(state, strings->toJSON)).value(state, valObj); if (toJson.isCallable()) { Value arguments[] = { key.toPlainValue(state) }; - value = FunctionObject::call(state, toJson, value, 1, arguments); + value = Object::call(state, toJson, value, 1, arguments); } } if (replacerFunc.isUndefined() == false) { Value arguments[] = { key.toPlainValue(state), value }; - value = FunctionObject::call(state, replacerFunc, holder, 2, arguments); + value = Object::call(state, replacerFunc, holder, 2, arguments); } if (value.isObject()) { diff --git a/src/runtime/GlobalObjectBuiltinMap.cpp b/src/runtime/GlobalObjectBuiltinMap.cpp index c088c4fb5..dd757baf7 100644 --- a/src/runtime/GlobalObjectBuiltinMap.cpp +++ b/src/runtime/GlobalObjectBuiltinMap.cpp @@ -49,7 +49,7 @@ Value builtinMapConstructor(ExecutionState& state, Value thisValue, size_t argc, // Let adder be ? Get(map, "set"). adder = map->Object::get(state, ObjectPropertyName(state.context()->staticStrings().set)).value(state, map); // If IsCallable(adder) is false, throw a TypeError exception. - if (!adder.isFunction()) { + if (!adder.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_NOT_Callable); } // Let iter be ? GetIterator(iterable). @@ -88,7 +88,7 @@ Value builtinMapConstructor(ExecutionState& state, Value thisValue, size_t argc, // Let status be Call(adder, map, « k.[[Value]], v.[[Value]] »). Value argv[2] = { k, v }; // TODO If status is an abrupt completion, return ? IteratorClose(iter, status). - adder.asFunction()->call(state, map, 2, argv); + Object::call(state, adder, map, 2, argv); } return map; } @@ -140,7 +140,7 @@ static Value builtinMapForEach(ExecutionState& state, Value thisValue, size_t ar Value callbackfn = argv[0]; // If IsCallable(callbackfn) is false, throw a TypeError exception. - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Map.string(), true, state.context()->staticStrings().forEach.string(), errorMessage_GlobalObject_CallbackNotCallable); } // If thisArg was supplied, let T be thisArg; else let T be undefined. @@ -156,7 +156,7 @@ static Value builtinMapForEach(ExecutionState& state, Value thisValue, size_t ar if (!entries[i].first.isEmpty()) { // Perform ? Call(callbackfn, T, « e.[[Value]], e.[[Key]], M »). Value argv[3] = { Value(entries[i].second), Value(entries[i].first), Value(M) }; - callbackfn.asFunction()->call(state, T, 3, argv); + Object::call(state, callbackfn, T, 3, argv); } } diff --git a/src/runtime/GlobalObjectBuiltinNumber.cpp b/src/runtime/GlobalObjectBuiltinNumber.cpp index 3dbdfd704..8915e3a67 100644 --- a/src/runtime/GlobalObjectBuiltinNumber.cpp +++ b/src/runtime/GlobalObjectBuiltinNumber.cpp @@ -273,9 +273,9 @@ static Value builtinNumberToLocaleString(ExecutionState& state, Value thisValue, ObjectGetResult toStrFuncGetResult = thisObject->get(state, ObjectPropertyName(state.context()->staticStrings().toString)); if (toStrFuncGetResult.hasValue()) { Value toStrFunc = toStrFuncGetResult.value(state, thisObject); - if (toStrFunc.isFunction()) { + if (toStrFunc.isCallable()) { // toLocaleString() ignores the first argument, unlike toString() - return FunctionObject::call(state, toStrFunc, thisObject, 0, argv); + return Object::call(state, toStrFunc, thisObject, 0, argv); } } ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toLocaleString.string(), errorMessage_GlobalObject_ToLocaleStringNotCallable); diff --git a/src/runtime/GlobalObjectBuiltinObject.cpp b/src/runtime/GlobalObjectBuiltinObject.cpp index f34a58adc..829947e6f 100644 --- a/src/runtime/GlobalObjectBuiltinObject.cpp +++ b/src/runtime/GlobalObjectBuiltinObject.cpp @@ -223,11 +223,11 @@ static Value builtinObjectToLocaleString(ExecutionState& state, Value thisValue, Value toString = O->get(state, ObjectPropertyName(state.context()->staticStrings().toString)).value(state, O); // If IsCallable(toString) is false, throw a TypeError exception. - if (!toString.isFunction()) + if (!toString.isCallable()) ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), true, state.context()->staticStrings().toLocaleString.string(), errorMessage_GlobalObject_ToLocaleStringNotCallable); // Return the result of calling the [[Call]] internal method of toString passing O as the this value and no arguments. - return FunctionObject::call(state, toString, Value(O), 0, nullptr); + return Object::call(state, toString, Value(O), 0, nullptr); } static Value builtinObjectGetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) diff --git a/src/runtime/GlobalObjectBuiltinPromise.cpp b/src/runtime/GlobalObjectBuiltinPromise.cpp index 55b0033b0..e1de9d050 100644 --- a/src/runtime/GlobalObjectBuiltinPromise.cpp +++ b/src/runtime/GlobalObjectBuiltinPromise.cpp @@ -35,7 +35,7 @@ static SandBox::SandBoxResult tryCallMethodAndCatchError(ExecutionState& state, SandBox sb(state.context()); return sb.run([&]() -> Value { Value callee = receiver.toObject(state)->get(state, name).value(state, receiver); - return FunctionObject::call(state, callee, receiver, argumentCount, arguments); + return Object::call(state, callee, receiver, argumentCount, arguments); }); } @@ -47,7 +47,7 @@ static Value builtinPromiseConstructor(ExecutionState& state, Value thisValue, s Value executor; if (isNewExpression) { executor = argv[0]; - if (!executor.isFunction()) + if (!executor.isCallable()) ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, String::emptyString, "%s: Promise executor is not a function object"); promise = thisValue.toObject(state)->asPromiseObject(); } else { @@ -60,12 +60,12 @@ static Value builtinPromiseConstructor(ExecutionState& state, Value thisValue, s SandBox sb(state.context()); auto res = sb.run([&]() -> Value { Value arguments[] = { capability.m_resolveFunction, capability.m_rejectFunction }; - FunctionObject::call(state, executor, Value(), 2, arguments); + Object::call(state, executor, Value(), 2, arguments); return Value(); }); if (!res.error.isEmpty()) { Value arguments[] = { res.error }; - return FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + return Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); } return promise; } @@ -89,7 +89,7 @@ static Value builtinPromiseAll(ExecutionState& state, Value thisValue, size_t ar if (!iterableValue.isIterable()) { Value arguments[] = { new TypeErrorObject(state, String::emptyString) }; - FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); } else { Object* iterable = iterableValue.toObject(state); bool done = false; @@ -103,7 +103,7 @@ static Value builtinPromiseAll(ExecutionState& state, Value thisValue, size_t ar if (!iterable->isArrayObject()) { Value arguments[] = { new TypeErrorObject(state, new ASCIIString("Second argument is not an array")) }; - FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); return capability.m_promise; } @@ -180,7 +180,7 @@ static Value builtinPromiseAll(ExecutionState& state, Value thisValue, size_t ar SandBox sb(state.context()); auto res = sb.run([&]() -> Value { Value arguments[] = { values }; - FunctionObject::call(state, capability.m_resolveFunction, Value(), 1, arguments); + Object::call(state, capability.m_resolveFunction, Value(), 1, arguments); return Value(); }); if (!res.error.isEmpty()) { @@ -192,7 +192,7 @@ static Value builtinPromiseAll(ExecutionState& state, Value thisValue, size_t ar // If result is an abrupt completion && If iteratorRecord.[[done]] is false if (!error.isEmpty() && !done) { Value arguments[] = { error }; - FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); } } return capability.m_promise; @@ -216,7 +216,7 @@ static Value builtinPromiseRace(ExecutionState& state, Value thisValue, size_t a if (!iterableValue.isIterable()) { Value arguments[] = { new TypeErrorObject(state, String::emptyString) }; - FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); } else { Object* iterable = iterableValue.toObject(state); bool done = false; @@ -228,7 +228,7 @@ static Value builtinPromiseRace(ExecutionState& state, Value thisValue, size_t a if (!iterable->isArrayObject()) { Value arguments[] = { new TypeErrorObject(state, new ASCIIString("Second argument is not an array")) }; - FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); return capability.m_promise; } @@ -274,7 +274,7 @@ static Value builtinPromiseRace(ExecutionState& state, Value thisValue, size_t a // If result is an abrupt completion && If iteratorRecord.[[done]] is false if (!error.isEmpty() && !done) { Value arguments[] = { error }; - FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); } } return capability.m_promise; @@ -287,7 +287,7 @@ static Value builtinPromiseReject(ExecutionState& state, Value thisValue, size_t PromiseReaction::Capability capability = PromiseObject::newPromiseCapability(state, thisObject); Value arguments[] = { argv[0] }; - FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, arguments); + Object::call(state, capability.m_rejectFunction, Value(), 1, arguments); return capability.m_promise; } @@ -302,7 +302,7 @@ static Value builtinPromiseResolve(ExecutionState& state, Value thisValue, size_ PromiseReaction::Capability capability = PromiseObject::newPromiseCapability(state, thisObject); Value arguments[] = { x }; - FunctionObject::call(state, capability.m_resolveFunction, Value(), 1, arguments); + Object::call(state, capability.m_resolveFunction, Value(), 1, arguments); return capability.m_promise; } @@ -313,7 +313,7 @@ static Value builtinPromiseCatch(ExecutionState& state, Value thisValue, size_t Value onRejected = argv[0]; Value then = thisObject->get(state, strings->then).value(state, thisObject); Value arguments[] = { Value(), onRejected }; - return FunctionObject::call(state, then, thisObject, 2, arguments); + return Object::call(state, then, thisObject, 2, arguments); } @@ -327,8 +327,8 @@ static Value builtinPromiseThen(ExecutionState& state, Value thisValue, size_t a Value onFulfilledValue = argv[0]; Value onRejectedValue = argv[1]; - FunctionObject* onFulfilled = onFulfilledValue.isFunction() ? onFulfilledValue.asFunction() : (FunctionObject*)(1); - FunctionObject* onRejected = onRejectedValue.isFunction() ? onRejectedValue.asFunction() : (FunctionObject*)(2); + Object* onFulfilled = onFulfilledValue.isCallable() ? onFulfilledValue.asObject() : (Object*)(1); + Object* onRejected = onRejectedValue.isCallable() ? onRejectedValue.asObject() : (Object*)(2); // Let C be SpeciesConstructor(promise, %Promise%) Value C = promise->speciesConstructor(state, state.context()->globalObject()->promise()); @@ -361,7 +361,7 @@ static Value builtinPromiseThen(ExecutionState& state, Value thisValue, size_t a Value getCapabilitiesExecutorFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) { auto strings = &state.context()->staticStrings(); - FunctionObject* executor = state.resolveCallee(); + Object* executor = state.resolveCallee(); executor->deleteOwnProperty(state, strings->name); Object* executorInternalSlot = executor->ensureInternalSlot(state); if (!executorInternalSlot->getOwnProperty(state, strings->resolve).value(state, executorInternalSlot).isUndefined() @@ -381,7 +381,7 @@ Value getCapabilitiesExecutorFunction(ExecutionState& state, Value thisValue, si Value promiseResolveFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) { auto strings = &state.context()->staticStrings(); - FunctionObject* callee = state.resolveCallee(); + Object* callee = state.resolveCallee(); Object* alreadyResolved = PromiseObject::resolvingFunctionAlreadyResolved(state, callee); Object* internalSlot = callee->internalSlot(); PromiseObject* promise = internalSlot->getOwnProperty(state, strings->Promise).value(state, internalSlot).asObject()->asPromiseObject(); @@ -411,8 +411,8 @@ Value promiseResolveFunction(ExecutionState& state, Value thisValue, size_t argc } Value then = res.result; - if (then.isFunction()) { - state.context()->jobQueue()->enqueueJob(state, new PromiseResolveThenableJob(state.context(), promise, resolution, then.asFunction())); + if (then.isCallable()) { + state.context()->jobQueue()->enqueueJob(state, new PromiseResolveThenableJob(state.context(), promise, resolution, then.asObject())); } else { promise->fulfillPromise(state, resolution); return Value(); @@ -425,7 +425,7 @@ Value promiseResolveFunction(ExecutionState& state, Value thisValue, size_t argc Value promiseRejectFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) { auto strings = &state.context()->staticStrings(); - FunctionObject* callee = state.resolveCallee(); + Object* callee = state.resolveCallee(); Object* alreadyResolved = PromiseObject::resolvingFunctionAlreadyResolved(state, callee); Object* internalSlot = callee->internalSlot(); PromiseObject* promise = internalSlot->getOwnProperty(state, strings->Promise).value(state, internalSlot).asObject()->asPromiseObject(); @@ -441,7 +441,7 @@ Value promiseRejectFunction(ExecutionState& state, Value thisValue, size_t argc, Value promiseAllResolveElementFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) { auto strings = &state.context()->staticStrings(); - FunctionObject* callee = state.resolveCallee(); + Object* callee = state.resolveCallee(); Value x = argv[0]; Object* internalSlot = callee->internalSlot(); @@ -452,7 +452,7 @@ Value promiseAllResolveElementFunction(ExecutionState& state, Value thisValue, s uint32_t index = internalSlot->getOwnProperty(state, strings->index).value(state, internalSlot).asUInt32(); ArrayObject* values = internalSlot->getOwnProperty(state, strings->values).value(state, internalSlot).asObject()->asArrayObject(); - FunctionObject* resolveFunction = internalSlot->getOwnProperty(state, strings->resolve).value(state, internalSlot).asFunction(); + Object* resolveFunction = internalSlot->getOwnProperty(state, strings->resolve).value(state, internalSlot).asObject(); Object* remainingElementsCount = internalSlot->getOwnProperty(state, strings->remainingElements).value(state, internalSlot).asObject(); values->setThrowsException(state, ObjectPropertyName(state, Value(index)), x, values); @@ -460,7 +460,7 @@ Value promiseAllResolveElementFunction(ExecutionState& state, Value thisValue, s remainingElementsCount->setThrowsException(state, strings->value, Value(remainingElements - 1), remainingElementsCount); if (remainingElements == 1) { Value arguments[] = { values }; - FunctionObject::call(state, resolveFunction, Value(), 1, arguments); + Object::call(state, resolveFunction, Value(), 1, arguments); } return Value(); } diff --git a/src/runtime/GlobalObjectBuiltinReflect.cpp b/src/runtime/GlobalObjectBuiltinReflect.cpp index 00c373ec0..1fbe11df2 100644 --- a/src/runtime/GlobalObjectBuiltinReflect.cpp +++ b/src/runtime/GlobalObjectBuiltinReflect.cpp @@ -59,7 +59,7 @@ static Value builtinReflectApply(ExecutionState& state, Value thisValue, size_t // TODO 4. Perform PrepareForTailCall(). // 5. Return Call(target, thisArgument, args). - return FunctionObject::call(state, target, thisArgument, arglen, args); + return Object::call(state, target, thisArgument, arglen, args); } // https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.construct @@ -99,7 +99,7 @@ static Value builtinReflectConstruct(ExecutionState& state, Value thisValue, siz // FIXME Construct (F, [argumentsList], [newTarget]) // 6. Return Construct(target, args, newTarget). - return FunctionObject::construct(state, target, arglen, args); + return Object::construct(state, target, arglen, args); } // https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.defineproperty diff --git a/src/runtime/GlobalObjectBuiltinRegExp.cpp b/src/runtime/GlobalObjectBuiltinRegExp.cpp index f55454ce9..6558ede24 100644 --- a/src/runtime/GlobalObjectBuiltinRegExp.cpp +++ b/src/runtime/GlobalObjectBuiltinRegExp.cpp @@ -243,7 +243,7 @@ static Value builtinRegExpSplit(ExecutionState& state, Value thisValue, size_t a // Let splitter be Construct(C, <>). Value params[2] = { rx->asRegExpObject(state)->source(), newFlags }; - RegExpObject* splitter = FunctionObject::construct(state, C, 2, params)->asRegExpObject(state); + RegExpObject* splitter = Object::construct(state, C, 2, params)->asRegExpObject(state); // Let A be ArrayCreate(0). ArrayObject* A = new ArrayObject(state); @@ -269,7 +269,7 @@ static Value builtinRegExpSplit(ExecutionState& state, Value thisValue, size_t a Value execFunction = Object::getMethod(state, splitter, ObjectPropertyName(state.context()->staticStrings().exec)); // Let z be RegExpExec(splitter, S). Value arg[1] = { S }; - z = FunctionObject::call(state, execFunction, splitter, 1, arg); + z = Object::call(state, execFunction, splitter, 1, arg); // If z is not null, return A. if (!z.isNull()) { return A; @@ -289,7 +289,7 @@ static Value builtinRegExpSplit(ExecutionState& state, Value thisValue, size_t a // Let z be RegExpExec(splitter, S). Value execFunction = Object::getMethod(state, splitter, ObjectPropertyName(state.context()->staticStrings().exec)); Value arg[1] = { S }; - z = FunctionObject::call(state, execFunction, splitter, 1, arg); + z = Object::call(state, execFunction, splitter, 1, arg); // If z is null, let q be AdvanceStringIndex(S, q, unicodeMatching). if (z.isNull()) { q = S->advanceStringIndex(q, unicodeMatching); diff --git a/src/runtime/GlobalObjectBuiltinSet.cpp b/src/runtime/GlobalObjectBuiltinSet.cpp index 5886a60f8..15b76e0dd 100644 --- a/src/runtime/GlobalObjectBuiltinSet.cpp +++ b/src/runtime/GlobalObjectBuiltinSet.cpp @@ -51,7 +51,7 @@ Value builtinSetConstructor(ExecutionState& state, Value thisValue, size_t argc, // Let adder be ? Get(set, "add"). adder = set->Object::get(state, ObjectPropertyName(state.context()->staticStrings().add)).value(state, set); // If IsCallable(adder) is false, throw a TypeError exception. - if (!adder.isFunction()) { + if (!adder.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_NOT_Callable); } // Let iter be ? GetIterator(iterable). @@ -76,7 +76,7 @@ Value builtinSetConstructor(ExecutionState& state, Value thisValue, size_t argc, // Let status be Call(adder, set, « nextValue.[[Value]] »). // TODO If status is an abrupt completion, return ? IteratorClose(iter, status). Value argv[1] = { nextValue }; - adder.asFunction()->call(state, set, 1, argv); + Object::call(state, adder, set, 1, argv); } return set; } @@ -122,7 +122,7 @@ static Value builtinSetForEach(ExecutionState& state, Value thisValue, size_t ar Value callbackfn = argv[0]; // If IsCallable(callbackfn) is false, throw a TypeError exception. - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Set.string(), true, state.context()->staticStrings().forEach.string(), errorMessage_GlobalObject_CallbackNotCallable); } // If thisArg was supplied, let T be thisArg; else let T be undefined. @@ -140,7 +140,7 @@ static Value builtinSetForEach(ExecutionState& state, Value thisValue, size_t ar // If e.[[Key]] is not empty, then // Perform ? Call(callbackfn, T, « e, e, S »). Value argv[3] = { Value(e), Value(e), Value(S) }; - callbackfn.asFunction()->call(state, T, 3, argv); + Object::call(state, callbackfn, T, 3, argv); } } diff --git a/src/runtime/GlobalObjectBuiltinString.cpp b/src/runtime/GlobalObjectBuiltinString.cpp index d63c1ea7f..4a88fbaba 100644 --- a/src/runtime/GlobalObjectBuiltinString.cpp +++ b/src/runtime/GlobalObjectBuiltinString.cpp @@ -311,7 +311,7 @@ static Value builtinStringReplace(ExecutionState& state, Value thisValue, size_t Value searchValue = argv[0]; Value replaceValue = argv[1]; String* replaceString = nullptr; - bool replaceValueIsFunction = replaceValue.isFunction(); + bool replaceValueIsFunction = replaceValue.isCallable(); RegexMatchResult result; if (searchValue.isPointerValue() == true && searchValue.asPointerValue()->isRegExpObject(state) == true) { @@ -375,7 +375,7 @@ static Value builtinStringReplace(ExecutionState& state, Value thisValue, size_t arguments[subLen] = Value((int)result.m_matchResults[i][0].m_start); arguments[subLen + 1] = string; // 21.1.3.14 (11) it should be called with this as undefined - String* res = FunctionObject::call(state, callee, Value(), subLen + 2, arguments).toString(state); + String* res = Object::call(state, callee, Value(), subLen + 2, arguments).toString(state); builer.appendSubString(res, 0, res->length()); if (i < matchCount - 1) { @@ -485,13 +485,13 @@ static Value builtinStringSearch(ExecutionState& state, Value thisValue, size_t if (!searcher.isUndefined()) { Value parameter[1] = { obj }; - return FunctionObject::call(state, searcher, regexp, 1, parameter); + return Object::call(state, searcher, regexp, 1, parameter); } } rx = new RegExpObject(state, regexp.isUndefined() ? String::emptyString : regexp.toString(state), String::emptyString); Value func = rx->getMethod(state, rx, ObjectPropertyName(state, state.context()->vmInstance()->globalSymbols().search)); Value parameter[1] = { Value(string) }; - return func.asObject()->asFunctionObject()->call(state, rx, 1, parameter); + return Object::call(state, func, rx, 1, parameter); #else if (regexp.isPointerValue() == true && regexp.asPointerValue()->isRegExpObject(state) == true) { // If Type(regexp) is Object and the value of the [[Class]] internal property of regexp is "RegExp", then let rx be regexp; @@ -530,7 +530,7 @@ static Value builtinStringSplit(ExecutionState& state, Value thisValue, size_t a if (!splitter.isUndefined()) { // Return Call(splitter, separator, <>). Value params[2] = { obj, limit }; - return FunctionObject::call(state, splitter, separator, 2, params); + return Object::call(state, splitter, separator, 2, params); } } // If limit is undefined, let lim = 2^53 - 1, else let lim = ToLength(limit). diff --git a/src/runtime/GlobalObjectBuiltinTypedArray.cpp b/src/runtime/GlobalObjectBuiltinTypedArray.cpp index 1758e4376..596b5d88a 100644 --- a/src/runtime/GlobalObjectBuiltinTypedArray.cpp +++ b/src/runtime/GlobalObjectBuiltinTypedArray.cpp @@ -58,6 +58,7 @@ static Value builtinArrayBufferByteLengthGetter(ExecutionState& state, Value thi RELEASE_ASSERT_NOT_REACHED(); } +// https://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer.prototype.slice static Value builtinArrayBufferByteSlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression) { Object* thisObject = thisValue.toObject(state); @@ -73,30 +74,21 @@ static Value builtinArrayBufferByteSlice(ExecutionState& state, Value thisValue, double relativeEnd = end.isUndefined() ? len : end.toInteger(state); unsigned final_ = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, len); unsigned newLen = std::max((int)final_ - (int)first, 0); - ArrayBufferObject* newObject; - Value constructor = thisObject->get(state, state.context()->staticStrings().constructor).value(state, thisObject); - if (constructor.isUndefined()) { - newObject = new ArrayBufferObject(state); - newObject->allocateBuffer(newLen); - } else { - if (!constructor.isFunction()) - ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: constructor of ArrayBuffer is not a function"); - Value arguments[] = { Value(newLen) }; - Value newValue = FunctionObject::construct(state, constructor, 1, arguments); - - if (!newValue.isObject() || !newValue.asObject()->isArrayBufferObject()) { - ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer"); - } - newObject = newValue.asObject()->asArrayBufferObject(); + Value constructor = thisObject->speciesConstructor(state, state.context()->globalObject()->arrayBuffer()); + Value arguments[] = { Value(newLen) }; + Value newValue = Object::construct(state, constructor, 1, arguments); + if (!newValue.isObject() || !newValue.asObject()->isArrayBufferObject()) { + ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer"); } + ArrayBufferObject* newObject = newValue.asObject()->asArrayBufferObject(); if (newObject->isDetachedBuffer()) // 18 ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer"); if (newObject == obj) // 19 ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer"); if (newObject->bytelength() < newLen) // 20 ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer"); - if (newObject->isDetachedBuffer()) // 22 + if (obj->isDetachedBuffer()) // 22 ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer"); newObject->fillData(obj->data() + first, newLen); @@ -162,7 +154,7 @@ static Value TypedArrayFrom(ExecutionState& state, const Value& constructor, con // FIXME Let targetObj be AllocateTypedArray(C, len). Value arg[1] = { Value(len) }; - Value targetObj = FunctionObject::construct(state, C, 1, arg); + Value targetObj = Object::construct(state, C, 1, arg); // Let k be 0. size_t k = 0; @@ -176,7 +168,7 @@ static Value TypedArrayFrom(ExecutionState& state, const Value& constructor, con if (mapping) { // Let mappedValue be Call(mapfn, T, «kValue, k»). Value args[2] = { kValue, Value(k) }; - mappedValue = FunctionObject::call(state, mapfn, T, 2, args); + mappedValue = Object::call(state, mapfn, T, 2, args); } // Let setStatus be Set(targetObj, Pk, mappedValue, true). targetObj.asObject()->setIndexedPropertyThrowsException(state, Value(k), mappedValue); @@ -194,7 +186,7 @@ static Value TypedArrayFrom(ExecutionState& state, const Value& constructor, con // FIXME Let targetObj be AllocateTypedArray(C, len). Value arg[1] = { Value(len) }; - Value targetObj = FunctionObject::construct(state, C, 1, arg); + Value targetObj = Object::construct(state, C, 1, arg); // Let k be 0. size_t k = 0; @@ -208,7 +200,7 @@ static Value TypedArrayFrom(ExecutionState& state, const Value& constructor, con if (mapping) { // Let mappedValue be Call(mapfn, T, «kValue, k»). Value args[2] = { kValue, Value(k) }; - mappedValue = FunctionObject::call(state, mapfn, T, 2, args); + mappedValue = Object::call(state, mapfn, T, 2, args); } // Let setStatus be Set(targetObj, Pk, mappedValue, true). targetObj.asObject()->setIndexedPropertyThrowsException(state, Value(k), mappedValue); @@ -306,7 +298,7 @@ static Value builtinTypedArrayOf(ExecutionState& state, Value thisValue, size_t // FIXME AllocateTypedArray(C, len) Value arg[1] = { Value(len) }; - Value newObj = FunctionObject::construct(state, C, 1, arg); + Value newObj = Object::construct(state, C, 1, arg); size_t k = 0; while (k < len) { @@ -445,7 +437,7 @@ Value builtinTypedArrayConstructor(ExecutionState& state, Value thisValue, size_ Value bufferConstructor = srcData->speciesConstructor(state, state.context()->globalObject()->arrayBuffer()); // FIXME Let data be AllocateArrayBuffer(bufferConstructor, byteLength). Value arg[1] = { Value(byteLength) }; - data = FunctionObject::construct(state, bufferConstructor, 1, arg)->asArrayBufferObject(); + data = Object::construct(state, bufferConstructor, 1, arg)->asArrayBufferObject(); // Let srcByteIndex be srcByteOffset. unsigned srcByteIndex = srcByteOffset; @@ -793,7 +785,7 @@ static Value builtinTypedArraySome(ExecutionState& state, Value thisValue, size_ // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().some.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -815,7 +807,7 @@ static Value builtinTypedArraySome(ExecutionState& state, Value thisValue, size_ Value kValue = kResult.value(state, O); // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O. Value args[] = { kValue, Value(k), O }; - Value testResult = FunctionObject::call(state, callbackfn, T, 3, args); + Value testResult = Object::call(state, callbackfn, T, 3, args); // If ToBoolean(testResult) is true, return true. if (testResult.toBoolean(state)) { @@ -840,7 +832,7 @@ static Value builtinTypedArraySort(ExecutionState& state, Value thisValue, size_ double len = O->asArrayBufferView()->arraylength(); Value cmpfn = argv[0]; - if (!cmpfn.isUndefined() && !cmpfn.isFunction()) { + if (!cmpfn.isUndefined() && !cmpfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().sort.string(), errorMessage_GlobalObject_FirstArgumentNotCallable); } bool defaultSort = (argc == 0) || cmpfn.isUndefined(); @@ -850,7 +842,7 @@ static Value builtinTypedArraySort(ExecutionState& state, Value thisValue, size_ ASSERT(x.isNumber() && y.isNumber()); if (!defaultSort) { Value args[] = { x, y }; - Value v = FunctionObject::call(state, cmpfn, Value(), 2, args); + Value v = Object::call(state, cmpfn, Value(), 2, args); if (buffer->isDetachedBuffer()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().sort.string(), errorMessage_GlobalObject_DetachedBuffer); } @@ -904,7 +896,7 @@ static Value builtinTypedArraySubArray(ExecutionState& state, Value thisValue, s // Let argumentsList be «buffer, beginByteOffset, newLength». Value args[3] = { buffer, Value(beginByteOffset), Value(newLength) }; // Return Construct(constructor, argumentsList). - return FunctionObject::construct(state, constructor, 3, args); + return Object::construct(state, constructor, 3, args); } static Value builtinTypedArrayEvery(ExecutionState& state, Value thisValue, size_t argc, NULLABLE Value* argv, bool isNewExpression) @@ -921,7 +913,7 @@ static Value builtinTypedArrayEvery(ExecutionState& state, Value thisValue, size // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().every.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -941,7 +933,7 @@ static Value builtinTypedArrayEvery(ExecutionState& state, Value thisValue, size Value kValue = value.value(state, O); // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O. Value args[] = { kValue, Value(k), O }; - Value testResult = FunctionObject::call(state, callbackfn, T, 3, args); + Value testResult = Object::call(state, callbackfn, T, 3, args); if (!testResult.toBoolean(state)) { return Value(false); @@ -1004,7 +996,7 @@ static Value builtinTypedArrayFilter(ExecutionState& state, Value thisValue, siz // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().filter.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1029,7 +1021,7 @@ static Value builtinTypedArrayFilter(ExecutionState& state, Value thisValue, siz while (k < len) { Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O); Value args[] = { kValue, Value(k), O }; - bool selected = FunctionObject::call(state, callbackfn, T, 3, args).toBoolean(state); + bool selected = Object::call(state, callbackfn, T, 3, args).toBoolean(state); if (selected) { kept.push_back(kValue); captured++; @@ -1039,7 +1031,7 @@ static Value builtinTypedArrayFilter(ExecutionState& state, Value thisValue, siz // FIXME Let A be AllocateTypedArray(C, captured). Value arg[1] = { Value(captured) }; - Value A = FunctionObject::construct(state, C, 1, arg); + Value A = Object::construct(state, C, 1, arg); // Let n be 0. size_t n = 0; @@ -1068,7 +1060,7 @@ static Value builtinTypedArrayFind(ExecutionState& state, Value thisValue, size_ // If IsCallable(predicate) is false, throw a TypeError exception. Value predicate = argv[0]; - if (!predicate.isFunction()) { + if (!predicate.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().find.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1087,7 +1079,7 @@ static Value builtinTypedArrayFind(ExecutionState& state, Value thisValue, size_ kValue = O->getIndexedProperty(state, Value(k)).value(state, O); // Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)). Value args[] = { kValue, Value(k), O }; - bool testResult = FunctionObject::call(state, predicate, T, 3, args).toBoolean(state); + bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state); // If testResult is true, return kValue. if (testResult) { return kValue; @@ -1113,7 +1105,7 @@ static Value builtinTypedArrayFindIndex(ExecutionState& state, Value thisValue, // If IsCallable(predicate) is false, throw a TypeError exception. Value predicate = argv[0]; - if (!predicate.isFunction()) { + if (!predicate.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().findIndex.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1132,7 +1124,7 @@ static Value builtinTypedArrayFindIndex(ExecutionState& state, Value thisValue, Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O); // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). Value args[] = { kValue, Value(k), O }; - bool testResult = FunctionObject::call(state, predicate, T, 3, args).toBoolean(state); + bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state); // If testResult is true, return k. if (testResult) { return Value(k); @@ -1157,7 +1149,7 @@ static Value builtinTypedArrayForEach(ExecutionState& state, Value thisValue, si double len = O->asArrayBufferView()->arraylength(); Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().forEach.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1175,7 +1167,7 @@ static Value builtinTypedArrayForEach(ExecutionState& state, Value thisValue, si RELEASE_ASSERT(res.hasValue()); Value kValue = res.value(state, O); Value args[] = { kValue, Value(k), O }; - FunctionObject::call(state, callbackfn, T, 3, args); + Object::call(state, callbackfn, T, 3, args); k++; } // Return undefined. @@ -1243,7 +1235,7 @@ static Value builtinTypedArrayMap(ExecutionState& state, Value thisValue, size_t // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().map.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1260,7 +1252,7 @@ static Value builtinTypedArrayMap(ExecutionState& state, Value thisValue, size_t // FIXME Let A be AllocateTypedArray(C, len). Value arg[1] = { Value(len) }; - Value A = FunctionObject::construct(state, C, 1, arg); + Value A = Object::construct(state, C, 1, arg); // Let k be 0. size_t k = 0; @@ -1268,7 +1260,7 @@ static Value builtinTypedArrayMap(ExecutionState& state, Value thisValue, size_t while (k < len) { Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O); Value args[] = { kValue, Value(k), O }; - Value mappedValue = FunctionObject::call(state, callbackfn, T, 3, args); + Value mappedValue = Object::call(state, callbackfn, T, 3, args); A.asObject()->setIndexedPropertyThrowsException(state, Value(k), mappedValue); k++; } @@ -1289,7 +1281,7 @@ static Value builtinTypedArrayReduce(ExecutionState& state, Value thisValue, siz double len = O->asArrayBufferView()->arraylength(); Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduce.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1312,7 +1304,7 @@ static Value builtinTypedArrayReduce(ExecutionState& state, Value thisValue, siz RELEASE_ASSERT(res.hasValue()); Value kValue = res.value(state, O); Value args[] = { accumulator, kValue, Value(k), O }; - accumulator = FunctionObject::call(state, callbackfn, Value(), 4, args); + accumulator = Object::call(state, callbackfn, Value(), 4, args); k++; } return accumulator; @@ -1332,7 +1324,7 @@ static Value builtinTypedArrayReduceRight(ExecutionState& state, Value thisValue // If IsCallable(callbackfn) is false, throw a TypeError exception. Value callbackfn = argv[0]; - if (!callbackfn.isFunction()) { + if (!callbackfn.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduceRight.string(), errorMessage_GlobalObject_CallbackNotCallable); } @@ -1364,7 +1356,7 @@ static Value builtinTypedArrayReduceRight(ExecutionState& state, Value thisValue RELEASE_ASSERT(res.hasValue()); Value kValue = res.value(state, O); Value args[] = { accumulator, kValue, Value(k), O }; - accumulator = FunctionObject::call(state, callbackfn, Value(), 4, args); + accumulator = Object::call(state, callbackfn, Value(), 4, args); k--; } // Return accumulator. @@ -1432,7 +1424,7 @@ static Value builtinTypedArraySlice(ExecutionState& state, Value thisValue, size Value C = O->speciesConstructor(state, defaultConstructor); // FIXME Let A be AllocateTypedArray(C, count). Value arg[1] = { Value(count) }; - Value A = FunctionObject::construct(state, C, 1, arg); + Value A = Object::construct(state, C, 1, arg); // If SameValue(srcType, targetType) is false, then if (O->asArrayBufferView()->typedArrayType() != A.asObject()->asArrayBufferView()->typedArrayType()) { @@ -1505,11 +1497,11 @@ static Value builtinTypedArrayToLocaleString(ExecutionState& state, Value thisVa // Let func be the result of calling the [[Get]] internal method of elementObj with argument "toLocaleString". Value func = elementObj->get(state, state.context()->staticStrings().toLocaleString).value(state, elementObj); // If IsCallable(func) is false, throw a TypeError exception. - if (!func.isFunction()) { + if (!func.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().toLocaleString.string(), errorMessage_GlobalObject_ToLocaleStringNotCallable); } // Let R be the result of calling the [[Call]] internal method of func providing elementObj as the this value and an empty arguments list. - R = FunctionObject::call(state, func, elementObj, 0, nullptr); + R = Object::call(state, func, elementObj, 0, nullptr); // Let k be 1. int64_t k = 1; @@ -1532,11 +1524,11 @@ static Value builtinTypedArrayToLocaleString(ExecutionState& state, Value thisVa // Let func be the result of calling the [[Get]] internal method of elementObj with argument "toLocaleString". Value func = elementObj->get(state, state.context()->staticStrings().toLocaleString).value(state, elementObj); // If IsCallable(func) is false, throw a TypeError exception. - if (!func.isFunction()) { + if (!func.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().toLocaleString.string(), errorMessage_GlobalObject_ToLocaleStringNotCallable); } // Let R be the result of calling the [[Call]] internal method of func providing elementObj as the this value and an empty arguments list. - R = FunctionObject::call(state, func, elementObj, 0, nullptr); + R = Object::call(state, func, elementObj, 0, nullptr); // Let R be a String value produced by concatenating S and R. StringBuilder builder2; @@ -1556,10 +1548,10 @@ static Value builtinTypedArrayToString(ExecutionState& state, Value thisValue, s validateTypedArray(state, O, state.context()->staticStrings().toString.string()); Value toString = O->get(state, state.context()->staticStrings().join).value(state, O); - if (!toString.isFunction()) { + if (!toString.isCallable()) { toString = state.context()->globalObject()->objectPrototypeToString(); } - return FunctionObject::call(state, toString, O, 0, nullptr); + return Object::call(state, toString, O, 0, nullptr); } template diff --git a/src/runtime/GlobalObjectBuiltinWeakMap.cpp b/src/runtime/GlobalObjectBuiltinWeakMap.cpp index 8e31e1794..e9e67c3aa 100644 --- a/src/runtime/GlobalObjectBuiltinWeakMap.cpp +++ b/src/runtime/GlobalObjectBuiltinWeakMap.cpp @@ -50,7 +50,7 @@ Value builtinWeakMapConstructor(ExecutionState& state, Value thisValue, size_t a // Let adder be ? Get(map, "set"). adder = map->Object::get(state, ObjectPropertyName(state.context()->staticStrings().set)).value(state, map); // If IsCallable(adder) is false, throw a TypeError exception. - if (adder.isFunction() == false) { + if (!adder.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_NOT_Callable); } // Let iter be ? GetIterator(iterable). @@ -89,7 +89,7 @@ Value builtinWeakMapConstructor(ExecutionState& state, Value thisValue, size_t a // Let status be Call(adder, map, « k.[[Value]], v.[[Value]] »). Value argv[2] = { k, v }; // TODO If status is an abrupt completion, return ? IteratorClose(iter, status). - adder.asFunction()->call(state, map, 2, argv); + Object::call(state, adder, map, 2, argv); } return map; } diff --git a/src/runtime/GlobalObjectBuiltinWeakSet.cpp b/src/runtime/GlobalObjectBuiltinWeakSet.cpp index 970c60512..558987ec1 100644 --- a/src/runtime/GlobalObjectBuiltinWeakSet.cpp +++ b/src/runtime/GlobalObjectBuiltinWeakSet.cpp @@ -52,7 +52,7 @@ Value builtinWeakSetConstructor(ExecutionState& state, Value thisValue, size_t a // Let adder be ? Get(set, "add"). adder = set->Object::get(state, ObjectPropertyName(state.context()->staticStrings().add)).value(state, set); // If IsCallable(adder) is false, throw a TypeError exception. - if (adder.isFunction() == false) { + if (!adder.isCallable()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_NOT_Callable); } // Let iter be ? GetIterator(iterable). @@ -77,7 +77,7 @@ Value builtinWeakSetConstructor(ExecutionState& state, Value thisValue, size_t a // Let status be Call(adder, set, « nextValue.[[Value]] »). // TODO If status is an abrupt completion, return ? IteratorClose(iter, status). Value argv[1] = { nextValue }; - adder.asFunction()->call(state, set, 1, argv); + Object::call(state, adder, set, 1, argv); } return set; } diff --git a/src/runtime/GlobalRegExpFunctionObject.cpp b/src/runtime/GlobalRegExpFunctionObject.cpp index 1a32993c6..961d7243a 100644 --- a/src/runtime/GlobalRegExpFunctionObject.cpp +++ b/src/runtime/GlobalRegExpFunctionObject.cpp @@ -83,8 +83,8 @@ void GlobalRegExpFunctionObject::initInternalProperties(ExecutionState& state) JSGetterSetter gs( new FunctionObject(state, NativeFunctionInfo(strings.get, GlobalRegExpFunctionObjectBuiltinFunctions::builtinGlobalRegExpFunctionObjectInputGetter, 0, nullptr, NativeFunctionInfo::Strict)), new FunctionObject(state, NativeFunctionInfo(strings.set, GlobalRegExpFunctionObjectBuiltinFunctions::builtinGlobalRegExpFunctionObjectInputSetter, 1, nullptr, NativeFunctionInfo::Strict))); - gs.getter().asFunction()->setInternalSlot(state.context()->globalObject()); - gs.setter().asFunction()->setInternalSlot(state.context()->globalObject()); + gs.getter().asObject()->setInternalSlot(state.context()->globalObject()); + gs.setter().asObject()->setInternalSlot(state.context()->globalObject()); ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::EnumerablePresent); defineOwnProperty(state, ObjectPropertyName(strings.input), desc); ObjectPropertyDescriptor desc2(gs, ObjectPropertyDescriptor::NotPresent); @@ -95,7 +95,7 @@ void GlobalRegExpFunctionObject::initInternalProperties(ExecutionState& state) JSGetterSetter gs( new FunctionObject(state, NativeFunctionInfo(strings.get, GlobalRegExpFunctionObjectBuiltinFunctions::builtinGlobalRegExpFunctionObjectLastMatchGetter, 0, nullptr, NativeFunctionInfo::Strict)), Value()); - gs.getter().asFunction()->setInternalSlot(state.context()->globalObject()); + gs.getter().asObject()->setInternalSlot(state.context()->globalObject()); ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::EnumerablePresent); defineOwnProperty(state, ObjectPropertyName(strings.lastMatch), desc); ObjectPropertyDescriptor desc2(gs, ObjectPropertyDescriptor::NotPresent); @@ -106,7 +106,7 @@ void GlobalRegExpFunctionObject::initInternalProperties(ExecutionState& state) JSGetterSetter gs( new FunctionObject(state, NativeFunctionInfo(strings.get, GlobalRegExpFunctionObjectBuiltinFunctions::builtinGlobalRegExpFunctionObjectLastParenGetter, 0, nullptr, NativeFunctionInfo::Strict)), Value()); - gs.getter().asFunction()->setInternalSlot(state.context()->globalObject()); + gs.getter().asObject()->setInternalSlot(state.context()->globalObject()); ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::EnumerablePresent); defineOwnProperty(state, ObjectPropertyName(strings.lastParen), desc); ObjectPropertyDescriptor desc2(gs, ObjectPropertyDescriptor::NotPresent); @@ -117,7 +117,7 @@ void GlobalRegExpFunctionObject::initInternalProperties(ExecutionState& state) JSGetterSetter gs( new FunctionObject(state, NativeFunctionInfo(strings.get, GlobalRegExpFunctionObjectBuiltinFunctions::builtinGlobalRegExpFunctionObjectLeftContextGetter, 0, nullptr, NativeFunctionInfo::Strict)), Value()); - gs.getter().asFunction()->setInternalSlot(state.context()->globalObject()); + gs.getter().asObject()->setInternalSlot(state.context()->globalObject()); ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::EnumerablePresent); defineOwnProperty(state, ObjectPropertyName(strings.leftContext), desc); ObjectPropertyDescriptor desc2(gs, ObjectPropertyDescriptor::NotPresent); @@ -128,7 +128,7 @@ void GlobalRegExpFunctionObject::initInternalProperties(ExecutionState& state) JSGetterSetter gs( new FunctionObject(state, NativeFunctionInfo(strings.get, GlobalRegExpFunctionObjectBuiltinFunctions::builtinGlobalRegExpFunctionObjectRightContextGetter, 0, nullptr, NativeFunctionInfo::Strict)), Value()); - gs.getter().asFunction()->setInternalSlot(state.context()->globalObject()); + gs.getter().asObject()->setInternalSlot(state.context()->globalObject()); ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::EnumerablePresent); defineOwnProperty(state, ObjectPropertyName(strings.rightContext), desc); ObjectPropertyDescriptor desc2(gs, ObjectPropertyDescriptor::NotPresent); @@ -140,7 +140,7 @@ void GlobalRegExpFunctionObject::initInternalProperties(ExecutionState& state) JSGetterSetter gs( \ new FunctionObject(state, NativeFunctionInfo(strings.get, GlobalRegExpFunctionObjectBuiltinFunctions::builtinGlobalRegExpFunctionObjectDollar##number##Getter, 0, nullptr, NativeFunctionInfo::Strict)), \ Value()); \ - gs.getter().asFunction()->setInternalSlot(state.context()->globalObject()); \ + gs.getter().asObject()->setInternalSlot(state.context()->globalObject()); \ ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::EnumerablePresent); \ defineOwnProperty(state, ObjectPropertyName(strings.$##number), desc); \ } diff --git a/src/runtime/IteratorOperations.cpp b/src/runtime/IteratorOperations.cpp index 3a883b180..4e8ac2932 100644 --- a/src/runtime/IteratorOperations.cpp +++ b/src/runtime/IteratorOperations.cpp @@ -35,7 +35,7 @@ Value getIterator(ExecutionState& state, const Value& obj, const Value& method) func = Object::getMethod(state, obj, ObjectPropertyName(state, state.context()->vmInstance()->globalSymbols().iterator)); } - Value iterator = FunctionObject::call(state, func, obj, 0, nullptr); + Value iterator = Object::call(state, func, obj, 0, nullptr); if (!iterator.isObject()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "result is not an object"); } @@ -51,10 +51,10 @@ Value iteratorNext(ExecutionState& state, const Value& iterator, const Value& va Value result; if (value.isEmpty()) { - result = FunctionObject::call(state, func, iterator, 0, nullptr); + result = Object::call(state, func, iterator, 0, nullptr); } else { Value argumentList[] = { value }; - result = FunctionObject::call(state, func, iterator, 1, argumentList); + result = Object::call(state, func, iterator, 1, argumentList); } if (!result.isObject()) { @@ -100,7 +100,7 @@ void iteratorClose(ExecutionState& state, const Value& iterator) ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "return function is undefined"); } - Value innerResult = FunctionObject::call(state, returnFunction, iterator, 0, nullptr); + Value innerResult = Object::call(state, returnFunction, iterator, 0, nullptr); if (!innerResult.isObject()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "result is not an object"); } diff --git a/src/runtime/Job.cpp b/src/runtime/Job.cpp index c904b6af7..af20e468c 100644 --- a/src/runtime/Job.cpp +++ b/src/runtime/Job.cpp @@ -22,7 +22,6 @@ #include "Escargot.h" #include "Job.h" #include "Context.h" -#include "FunctionObject.h" #include "SandBox.h" namespace Escargot { @@ -33,27 +32,27 @@ SandBox::SandBoxResult PromiseReactionJob::run() ExecutionState state(relatedContext()); return sandbox.run([&]() -> Value { /* 25.4.2.1.4 Handler is "Identity" case */ - if (m_reaction.m_handler == (FunctionObject*)1) { + if (m_reaction.m_handler == (Object*)1) { Value value[] = { m_argument }; - return FunctionObject::call(state, m_reaction.m_capability.m_resolveFunction, Value(), 1, value); + return Object::call(state, m_reaction.m_capability.m_resolveFunction, Value(), 1, value); } /* 25.4.2.1.5 Handler is "Thrower" case */ - if (m_reaction.m_handler == (FunctionObject*)2) { + if (m_reaction.m_handler == (Object*)2) { Value value[] = { m_argument }; - return FunctionObject::call(state, m_reaction.m_capability.m_rejectFunction, Value(), 1, value); + return Object::call(state, m_reaction.m_capability.m_rejectFunction, Value(), 1, value); } SandBox sb(state.context()); auto res = sb.run([&]() -> Value { Value arguments[] = { m_argument }; - Value res = FunctionObject::call(state, m_reaction.m_handler, Value(), 1, arguments); + Value res = Object::call(state, m_reaction.m_handler, Value(), 1, arguments); Value value[] = { res }; - return FunctionObject::call(state, m_reaction.m_capability.m_resolveFunction, Value(), 1, value); + return Object::call(state, m_reaction.m_capability.m_resolveFunction, Value(), 1, value); }); if (!res.error.isEmpty()) { Value reason[] = { res.error }; - return FunctionObject::call(state, m_reaction.m_capability.m_rejectFunction, Value(), 1, reason); + return Object::call(state, m_reaction.m_capability.m_rejectFunction, Value(), 1, reason); } return res.result; }); @@ -70,7 +69,7 @@ SandBox::SandBoxResult PromiseResolveThenableJob::run() SandBox sb(state.context()); auto res = sb.run([&]() -> Value { Value arguments[] = { capability.m_resolveFunction, capability.m_rejectFunction }; - Value thenCallResult = FunctionObject::call(state, m_then, m_thenable, 2, arguments); + Value thenCallResult = Object::call(state, m_then, m_thenable, 2, arguments); Value value[] = { thenCallResult }; return Value(); }); @@ -81,7 +80,7 @@ SandBox::SandBoxResult PromiseResolveThenableJob::run() alreadyResolved->setThrowsException(state, strings->value, Value(true), alreadyResolved); Value reason[] = { res.error }; - return FunctionObject::call(state, capability.m_rejectFunction, Value(), 1, reason); + return Object::call(state, capability.m_rejectFunction, Value(), 1, reason); } return Value(); }); diff --git a/src/runtime/Job.h b/src/runtime/Job.h index 1a0535c1e..e62084a4d 100644 --- a/src/runtime/Job.h +++ b/src/runtime/Job.h @@ -85,7 +85,7 @@ class PromiseReactionJob : public Job { class PromiseResolveThenableJob : public Job { public: - PromiseResolveThenableJob(Context* relatedContext, PromiseObject* promise, Object* thenable, FunctionObject* then) + PromiseResolveThenableJob(Context* relatedContext, PromiseObject* promise, Object* thenable, Object* then) : Job(JobType::PromiseResolveThenableJob, relatedContext) , m_promise(promise) , m_thenable(thenable) @@ -98,7 +98,7 @@ class PromiseResolveThenableJob : public Job { private: PromiseObject* m_promise; Object* m_thenable; - FunctionObject* m_then; + Object* m_then; }; diff --git a/src/runtime/Object.cpp b/src/runtime/Object.cpp index 6074c6600..41d1ae3b1 100644 --- a/src/runtime/Object.cpp +++ b/src/runtime/Object.cpp @@ -113,11 +113,11 @@ void* ObjectRareData::operator new(size_t size) Value ObjectGetResult::valueSlowCase(ExecutionState& state, const Value& receiver) const { #ifdef ESCARGOT_32 - if (m_jsGetterSetter->getter().isFunction()) { + if (m_jsGetterSetter->getter().isCallable()) { #else - if (m_jsGetterSetter->hasGetter() && m_jsGetterSetter->getter().isFunction()) { + if (m_jsGetterSetter->hasGetter() && m_jsGetterSetter->getter().isCallable()) { #endif - return m_jsGetterSetter->getter().asFunction()->call(state, receiver, 0, nullptr); + return Object::call(state, m_jsGetterSetter->getter(), receiver, 0, nullptr); } return Value(); } @@ -191,7 +191,7 @@ ObjectPropertyDescriptor::ObjectPropertyDescriptor(ExecutionState& state, Object desc = obj->get(state, ObjectPropertyName(strings->get)); if (desc.hasValue()) { Value getter = desc.value(state, obj); - if (!getter.isFunction() && !getter.isUndefined()) { + if (!getter.isCallable() && !getter.isUndefined()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Getter must be a function or undefined"); } else { m_isDataProperty = false; @@ -202,7 +202,7 @@ ObjectPropertyDescriptor::ObjectPropertyDescriptor(ExecutionState& state, Object desc = obj->get(state, ObjectPropertyName(strings->set)); if (desc.hasValue()) { Value setter = desc.value(state, obj); - if (!setter.isFunction() && !setter.isUndefined()) { + if (!setter.isCallable() && !setter.isUndefined()) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Setter must be a function or undefined"); } else { if (m_isDataProperty) { @@ -823,7 +823,7 @@ bool Object::set(ExecutionState& state, const ObjectPropertyName& propertyName, } // 9. Let setterResult be Call(setter, Receiver, «V»). Value argv[] = { v }; - FunctionObject::call(state, setter, receiver, 1, argv); + Object::call(state, setter, receiver, 1, argv); return true; } @@ -845,6 +845,32 @@ Value Object::getMethod(ExecutionState& state, const Value& object, const Object return func; } +// https://www.ecma-international.org/ecma-262/6.0/#sec-call +Value Object::call(ExecutionState& state, const Value& callee, const Value& thisValue, const size_t argc, NULLABLE Value* argv) +{ + // If IsCallable(F) is false, throw a TypeError exception. + if (callee.isCallable() == false) { + ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_NOT_Callable); + } + // Return F.[[Call]](V, argumentsList). + return callee.asObject()->call(state, thisValue, argc, argv); +} + +// https://www.ecma-international.org/ecma-262/6.0/#sec-construct +Object* Object::construct(ExecutionState& state, const Value& constructor, const size_t argc, NULLABLE Value* argv, Value newTarget) +{ + // If newTarget was not passed, let newTarget be F. + if (newTarget.isEmpty() == true) { + newTarget = constructor; + } + // Assert: IsConstructor (F) is true. + ASSERT(constructor.isConstructor() == true); + // Assert: IsConstructor (newTarget) is true. + ASSERT(newTarget.isConstructor() == true); + // Return F.[[Construct]](argumentsList, newTarget). + return constructor.asObject()->construct(state, argc, argv, newTarget); +} + // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinaryhasinstance bool Object::hasInstance(ExecutionState& state, const Value& C, Value O) { @@ -1071,11 +1097,11 @@ Value Object::getOwnPropertyUtilForObjectAccCase(ExecutionState& state, size_t i Value v = m_values[idx]; auto gs = v.asPointerValue()->asJSGetterSetter(); #ifdef ESCARGOT_32 - if (gs->getter().isFunction()) { + if (gs->getter().isCallable()) { #else - if (gs->hasGetter() && gs->getter().isFunction()) { + if (gs->hasGetter() && gs->getter().isCallable()) { #endif - return gs->getter().asFunction()->call(state, receiver, 0, nullptr); + return Object::call(state, gs->getter(), receiver, 0, nullptr); } return Value(); } @@ -1085,12 +1111,12 @@ bool Object::setOwnPropertyUtilForObjectAccCase(ExecutionState& state, size_t id Value v = m_values[idx]; auto gs = v.asPointerValue()->asJSGetterSetter(); #ifdef ESCARGOT_32 - if (gs->setter().isFunction()) { + if (gs->setter().isCallable()) { #else - if (gs->hasSetter() && gs->setter().isFunction()) { + if (gs->hasSetter() && gs->setter().isCallable()) { #endif Value arg = newValue; - gs->setter().asFunction()->call(state, receiver, 1, &arg); + Object::call(state, gs->setter(), receiver, 1, &arg); return true; } return false; diff --git a/src/runtime/Object.h b/src/runtime/Object.h index 2e75d7059..aa6dcfd06 100644 --- a/src/runtime/Object.h +++ b/src/runtime/Object.h @@ -587,15 +587,6 @@ class Object : public PointerValue { bool isConcatSpreadable(ExecutionState& state); - virtual Value call(ExecutionState& state, const Value& thisValue, const size_t argc, NULLABLE Value* argv) - { - RELEASE_ASSERT_NOT_REACHED(); - } - virtual Object* construct(ExecutionState& state, const size_t argc, NULLABLE Value* argv, const Value& newTarget) - { - RELEASE_ASSERT_NOT_REACHED(); - } - // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-isextensiblie #if ESCARGOT_ENABLE_PROXY_REFLECT virtual bool isExtensible(ExecutionState&) @@ -801,6 +792,8 @@ class Object : public PointerValue { } static Value getMethod(ExecutionState& state, const Value& object, const ObjectPropertyName& propertyName); + static Value call(ExecutionState& state, const Value& callee, const Value& thisValue, const size_t argc, NULLABLE Value* argv); + static Object* construct(ExecutionState& state, const Value& constructor, const size_t argc, NULLABLE Value* argv, Value newTarget = Value(Value::EmptyValue)); static bool hasInstance(ExecutionState& state, const Value& C, const Value O); static void throwCannotDefineError(ExecutionState& state, const PropertyName& P); @@ -922,6 +915,16 @@ class Object : public PointerValue { void markAsPrototypeObject(ExecutionState& state); void deleteOwnProperty(ExecutionState& state, size_t idx); + +private: + virtual Value call(ExecutionState& state, const Value& thisValue, const size_t argc, NULLABLE Value* argv) + { + RELEASE_ASSERT_NOT_REACHED(); + } + virtual Object* construct(ExecutionState& state, const size_t argc, NULLABLE Value* argv, const Value& newTarget) + { + RELEASE_ASSERT_NOT_REACHED(); + } }; } diff --git a/src/runtime/PromiseObject.cpp b/src/runtime/PromiseObject.cpp index f49154711..64ecc7957 100644 --- a/src/runtime/PromiseObject.cpp +++ b/src/runtime/PromiseObject.cpp @@ -54,8 +54,8 @@ PromiseReaction::Capability PromiseObject::createResolvingFunctions(ExecutionSta { const StaticStrings* strings = &state.context()->staticStrings(); - FunctionObject* resolveFunction = new FunctionObject(state, NativeFunctionInfo(strings->Empty, promiseResolveFunction, 1, nullptr, NativeFunctionInfo::Strict)); - FunctionObject* rejectFunction = new FunctionObject(state, NativeFunctionInfo(strings->Empty, promiseRejectFunction, 1, nullptr, NativeFunctionInfo::Strict)); + Object* resolveFunction = new FunctionObject(state, NativeFunctionInfo(strings->Empty, promiseResolveFunction, 1, nullptr, NativeFunctionInfo::Strict)); + Object* rejectFunction = new FunctionObject(state, NativeFunctionInfo(strings->Empty, promiseRejectFunction, 1, nullptr, NativeFunctionInfo::Strict)); resolveFunction->deleteOwnProperty(state, strings->name); rejectFunction->deleteOwnProperty(state, strings->name); @@ -83,26 +83,27 @@ PromiseReaction::Capability PromiseObject::newPromiseCapability(ExecutionState& { const StaticStrings* strings = &state.context()->staticStrings(); - if (!constructor->isFunctionObject()) + if (!constructor->isConstructor()) state.throwException(new TypeErrorObject(state, new ASCIIString("Constructor is not a function object"))); - FunctionObject* executor = new FunctionObject(state, NativeFunctionInfo(strings->Empty, getCapabilitiesExecutorFunction, 2, nullptr, NativeFunctionInfo::Strict)); + // FIXME: Let executor be a new built-in function object as defined in GetCapabilitiesExecutor Functions (25.4.1.5.1). + Object* executor = new FunctionObject(state, NativeFunctionInfo(strings->Empty, getCapabilitiesExecutorFunction, 2, nullptr, NativeFunctionInfo::Strict)); Object* internalSlot = executor->ensureInternalSlot(state); Value arguments[] = { executor }; - Value promise = FunctionObject::construct(state, constructor, 1, arguments); + Value promise = Object::construct(state, constructor, 1, arguments); ASSERT(internalSlot == executor->internalSlot()); Value resolveFunction = internalSlot->get(state, strings->resolve).value(state, internalSlot); Value rejectFunction = internalSlot->get(state, strings->reject).value(state, internalSlot); - if (!resolveFunction.isFunction() || !rejectFunction.isFunction()) + if (!resolveFunction.isCallable() || !rejectFunction.isCallable()) state.throwException(new TypeErrorObject(state, new ASCIIString("Promise resolve or reject function is not callable"))); - return PromiseReaction::Capability(promise, resolveFunction.asFunction(), rejectFunction.asFunction()); + return PromiseReaction::Capability(promise, resolveFunction.asObject(), rejectFunction.asObject()); } -Object* PromiseObject::resolvingFunctionAlreadyResolved(ExecutionState& state, FunctionObject* callee) +Object* PromiseObject::resolvingFunctionAlreadyResolved(ExecutionState& state, Object* callee) { const StaticStrings* strings = &state.context()->staticStrings(); Object* internalSlot = callee->internalSlot(); diff --git a/src/runtime/PromiseObject.h b/src/runtime/PromiseObject.h index fb06f4cf3..fcc5c258c 100644 --- a/src/runtime/PromiseObject.h +++ b/src/runtime/PromiseObject.h @@ -37,7 +37,7 @@ struct PromiseReaction { { } - Capability(Value promise, FunctionObject* resolveFunction, FunctionObject* rejectFunction) + Capability(Value promise, Object* resolveFunction, Object* rejectFunction) : m_promise(promise) , m_resolveFunction(resolveFunction) , m_rejectFunction(rejectFunction) @@ -52,8 +52,8 @@ struct PromiseReaction { } Value m_promise; - FunctionObject* m_resolveFunction; - FunctionObject* m_rejectFunction; + Object* m_resolveFunction; + Object* m_rejectFunction; }; PromiseReaction() @@ -62,7 +62,7 @@ struct PromiseReaction { { } - PromiseReaction(FunctionObject* handler, const Capability& capability) + PromiseReaction(Object* handler, const Capability& capability) : m_capability(capability) , m_handler(handler) { @@ -70,7 +70,7 @@ struct PromiseReaction { Capability m_capability; - FunctionObject* m_handler; + Object* m_handler; }; class PromiseObject : public Object { @@ -100,7 +100,7 @@ class PromiseObject : public Object { typedef Vector > Reactions; void triggerPromiseReactions(ExecutionState& state, Reactions& reactions); - void appendReaction(FunctionObject* onFulfilled, FunctionObject* onRejected, PromiseReaction::Capability& capability) + void appendReaction(Object* onFulfilled, Object* onRejected, PromiseReaction::Capability& capability) { m_fulfillReactions.push_back(PromiseReaction(onFulfilled, capability)); m_rejectReactions.push_back(PromiseReaction(onRejected, capability)); @@ -109,7 +109,7 @@ class PromiseObject : public Object { PromiseReaction::Capability createResolvingFunctions(ExecutionState& state); static PromiseReaction::Capability newPromiseCapability(ExecutionState& state, Object* constructor); - static Object* resolvingFunctionAlreadyResolved(ExecutionState& state, FunctionObject* callee); + static Object* resolvingFunctionAlreadyResolved(ExecutionState& state, Object* callee); PromiseState state() { return m_state; } Value promiseResult() diff --git a/src/runtime/ProxyObject.cpp b/src/runtime/ProxyObject.cpp index ecfbd9ec2..7a20eac2d 100644 --- a/src/runtime/ProxyObject.cpp +++ b/src/runtime/ProxyObject.cpp @@ -148,7 +148,7 @@ bool ProxyObject::defineOwnProperty(ExecutionState& state, const ObjectPropertyN // 11. ReturnIfAbrupt(booleanTrapResult). bool booleanTrapResult; Value arguments[] = { target, P.toPlainValue(state), Value(ObjectPropertyDescriptor::fromObjectPropertyDescriptor(state, desc)) }; - booleanTrapResult = FunctionObject::call(state, trap, handler, 3, arguments).toBoolean(state); + booleanTrapResult = Object::call(state, trap, handler, 3, arguments).toBoolean(state); // 12. If booleanTrapResult is false, return false. if (!booleanTrapResult) { @@ -223,7 +223,7 @@ bool ProxyObject::deleteOwnProperty(ExecutionState& state, const ObjectPropertyN // 10. ReturnIfAbrupt(booleanTrapResult). bool booleanTrapResult; Value arguments[] = { target, P.toPlainValue(state) }; - booleanTrapResult = FunctionObject::call(state, trap, handler, 2, arguments).toBoolean(state); + booleanTrapResult = Object::call(state, trap, handler, 2, arguments).toBoolean(state); // 11. If booleanTrapResult is false, return false. if (!booleanTrapResult) { @@ -280,7 +280,7 @@ ObjectGetResult ProxyObject::getOwnProperty(ExecutionState& state, const ObjectP // 10. ReturnIfAbrupt(trapResultObj). Value trapResultObj; Value arguments[] = { target, P.toPlainValue(state) }; - trapResultObj = FunctionObject::call(state, trap, handler, 2, arguments); + trapResultObj = Object::call(state, trap, handler, 2, arguments); // 11. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception. if (!trapResultObj.isObject() && !trapResultObj.isUndefined()) { @@ -374,7 +374,7 @@ bool ProxyObject::preventExtensions(ExecutionState& state) // 9. ReturnIfAbrupt(booleanTrapResult). bool booleanTrapResult; Value arguments[] = { target }; - booleanTrapResult = FunctionObject::call(state, trap, handler, 1, arguments).toBoolean(state); + booleanTrapResult = Object::call(state, trap, handler, 1, arguments).toBoolean(state); // 10. If booleanTrapResult is true, then if (booleanTrapResult) { @@ -425,7 +425,7 @@ bool ProxyObject::hasProperty(ExecutionState& state, const ObjectPropertyName& p // 10. ReturnIfAbrupt(booleanTrapResult). bool booleanTrapResult; Value arguments[] = { target, propertyName.toPlainValue(state) }; - booleanTrapResult = FunctionObject::call(state, trap, handler, 2, arguments).toBoolean(state); + booleanTrapResult = Object::call(state, trap, handler, 2, arguments).toBoolean(state); // 11. If booleanTrapResult is false, then if (!booleanTrapResult) { @@ -485,7 +485,7 @@ bool ProxyObject::isExtensible(ExecutionState& state) // 9. ReturnIfAbrupt(booleanTrapResult). bool booleanTrapResult; Value arguments[] = { target }; - booleanTrapResult = FunctionObject::call(state, trap, handler, 1, arguments).toBoolean(state); + booleanTrapResult = Object::call(state, trap, handler, 1, arguments).toBoolean(state); // 10. Let targetResult be target.[[IsExtensible]](). bool targetResult = target.asObject()->isExtensible(state); @@ -536,7 +536,7 @@ bool ProxyObject::setPrototype(ExecutionState& state, const Value& value) // 10. ReturnIfAbrupt(booleanTrapResult). bool booleanTrapResult; Value arguments[] = { target, value }; - booleanTrapResult = FunctionObject::call(state, trap, handler, 2, arguments).toBoolean(state); + booleanTrapResult = Object::call(state, trap, handler, 2, arguments).toBoolean(state); if (!booleanTrapResult) { ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Proxy.string(), false, String::emptyString, "%s: Proxy setPrototypeOf could not set the prototype."); return false; @@ -611,7 +611,7 @@ Value ProxyObject::getPrototype(ExecutionState& state) // 9. ReturnIfAbrupt(handlerProto). Value handlerProto; Value arguments[] = { target }; - handlerProto = FunctionObject::call(state, trap, handler, 1, arguments); + handlerProto = Object::call(state, trap, handler, 1, arguments); // 10. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception. if (!handlerProto.isObject() && !handlerProto.isNull()) { @@ -674,7 +674,7 @@ ObjectGetResult ProxyObject::get(ExecutionState& state, const ObjectPropertyName // 10. ReturnIfAbrupt(trapResult). Value trapResult; Value arguments[] = { target, propertyName.toPlainValue(state), Value(this) }; - trapResult = FunctionObject::call(state, trap, handler, 3, arguments); + trapResult = Object::call(state, trap, handler, 3, arguments); // 11. Let targetDesc be target.[[GetOwnProperty]](P). ObjectGetResult targetDesc = target.asObject()->getOwnProperty(state, propertyName); @@ -737,7 +737,7 @@ bool ProxyObject::set(ExecutionState& state, const ObjectPropertyName& propertyN // 10. ReturnIfAbrupt(booleanTrapResult). bool booleanTrapResult; Value arguments[] = { target, propertyName.toPlainValue(state), v, receiver }; - booleanTrapResult = FunctionObject::call(state, trap, handler, 4, arguments).toBoolean(state); + booleanTrapResult = Object::call(state, trap, handler, 4, arguments).toBoolean(state); // 11. If booleanTrapResult is false, return false. if (!booleanTrapResult) { @@ -798,7 +798,7 @@ Value ProxyObject::call(ExecutionState& state, const Value& receiver, const size // 7. If trap is undefined, then // a. Return Call(target, thisArgument, argumentsList). if (trap.isUndefined()) { - return FunctionObject::call(state, target, receiver, argc, argv); + return Object::call(state, target, receiver, argc, argv); } // 8. Let argArray be CreateArrayFromList(argumentsList). @@ -809,7 +809,7 @@ Value ProxyObject::call(ExecutionState& state, const Value& receiver, const size // 9. Return Call(trap, handler, «target, thisArgument, argArray»). Value arguments[] = { target, receiver, Value(argArray) }; - return FunctionObject::call(state, trap, handler, 3, arguments); + return Object::call(state, trap, handler, 3, arguments); } // https://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget @@ -841,7 +841,7 @@ Object* ProxyObject::construct(ExecutionState& state, const size_t argc, NULLABL // b. Return Construct(target, argumentsList, newTarget). if (trap.isUndefined() == true) { ASSERT(target.isConstructor() == true); - return FunctionObject::construct(state, target, argc, argv, newTarget); + return Object::construct(state, target, argc, argv, newTarget); } // 8. Let argArray be CreateArrayFromList(argumentsList). @@ -852,7 +852,7 @@ Object* ProxyObject::construct(ExecutionState& state, const size_t argc, NULLABL // 9. Let newObj be Call(trap, handler, «target, argArray, newTarget »). Value arguments[] = { target, Value(argArray), newTarget }; - Value newObj = FunctionObject::call(state, trap, handler, 3, arguments); + Value newObj = Object::call(state, trap, handler, 3, arguments); // 11. If Type(newObj) is not Object, throw a TypeError exception. if (!newObj.isObject()) { diff --git a/src/runtime/ProxyObject.h b/src/runtime/ProxyObject.h index d6299b866..86145f222 100644 --- a/src/runtime/ProxyObject.h +++ b/src/runtime/ProxyObject.h @@ -109,10 +109,6 @@ class ProxyObject : public Object { virtual bool isExtensible(ExecutionState&) override; - virtual Value call(ExecutionState& state, const Value& receiver, const size_t argc, Value* argv) override; - - virtual Object* construct(ExecutionState& state, const size_t argc, Value* argv, const Value& newTarget) override; - void setTarget(Object* target) { m_target = target; @@ -137,6 +133,9 @@ class ProxyObject : public Object { void* operator new[](size_t size) = delete; private: + virtual Value call(ExecutionState& state, const Value& receiver, const size_t argc, Value* argv) override; + virtual Object* construct(ExecutionState& state, const size_t argc, Value* argv, const Value& newTarget) override; + bool m_isCallable : 1; bool m_isConstructible : 1; diff --git a/src/runtime/Value.cpp b/src/runtime/Value.cpp index c5d88ee86..b9bb6140f 100644 --- a/src/runtime/Value.cpp +++ b/src/runtime/Value.cpp @@ -199,14 +199,14 @@ Value Value::ordinaryToPrimitive(ExecutionState& state, PrimitiveTypeHint prefer // If Type(result) is not Object, return result. Value method1 = input->get(state, ObjectPropertyName(methodName1)).value(state, input); if (method1.isCallable()) { - Value result = FunctionObject::call(state, method1, input, 0, nullptr); + Value result = Object::call(state, method1, input, 0, nullptr); if (!result.isObject()) { return result; } } Value method2 = input->get(state, ObjectPropertyName(methodName2)).value(state, input); if (method2.isCallable()) { - Value result = FunctionObject::call(state, method2, input, 0, nullptr); + Value result = Object::call(state, method2, input, 0, nullptr); if (!result.isObject()) { return result; } @@ -237,7 +237,7 @@ Value Value::toPrimitiveSlowCase(ExecutionState& state, PrimitiveTypeHint prefer hint = strings.stringDefault.string(); } // Let result be Call(exoticToPrim, input, «hint»). - Value result = FunctionObject::call(state, exoticToPrim, input, 1, &hint); + Value result = Object::call(state, exoticToPrim, input, 1, &hint); // If Type(result) is not Object, return result. if (!result.isObject()) { return result; diff --git a/src/shell/Shell.cpp b/src/shell/Shell.cpp index 4fc791419..dbab57825 100644 --- a/src/shell/Shell.cpp +++ b/src/shell/Shell.cpp @@ -127,7 +127,7 @@ int main(int argc, char* argv[]) if (fp) { runShell = false; Escargot::Value arg(Escargot::String::fromUTF8(argv[i], strlen(argv[i]))); - Escargot::String* src = Escargot::FunctionObject::call(stateForInit, fnRead, Escargot::Value(), 1, &arg).asString(); + Escargot::String* src = Escargot::Object::call(stateForInit, fnRead, Escargot::Value(), 1, &arg).asString(); if (!eval(context, src, Escargot::String::fromUTF8(argv[i], strlen(argv[i])), false)) return 3; diff --git a/test/regression-tests/issue-288.js b/test/regression-tests/issue-288.js new file mode 100644 index 000000000..3b1e1fa69 --- /dev/null +++ b/test/regression-tests/issue-288.js @@ -0,0 +1,16 @@ +/* Copyright 2019-present Samsung Electronics Co., Ltd. and other contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +EvalError.bind( ).call( ) diff --git a/test/regression-tests/xfail/issue-287.js b/test/regression-tests/xfail/issue-287.js new file mode 100644 index 000000000..c1c851640 --- /dev/null +++ b/test/regression-tests/xfail/issue-287.js @@ -0,0 +1,16 @@ +/* Copyright 2019-present Samsung Electronics Co., Ltd. and other contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +if (Promise.reject.call (Function.prototype));