2017-08-12 16:48:01 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
|
|
|
|
* Copyright (C) 2003, 2007-2008, 2011, 2016 Apple Inc. All rights reserved.
|
|
|
|
* Copyright (C) 2003 Peter Kelly (pmk@post.com)
|
|
|
|
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
|
|
* USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "ArrayConstructor.h"
|
|
|
|
|
|
|
|
#include "ArrayPrototype.h"
|
|
|
|
#include "JSCInlines.h"
|
2022-10-23 02:55:20 +00:00
|
|
|
#include "ProxyObject.h"
|
2017-08-12 16:48:01 +00:00
|
|
|
|
|
|
|
#include "ArrayConstructor.lut.h"
|
|
|
|
|
|
|
|
namespace JSC {
|
|
|
|
|
|
|
|
STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ArrayConstructor);
|
|
|
|
|
2018-01-03 05:16:05 +00:00
|
|
|
const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_info, &arrayConstructorTable, nullptr, CREATE_METHOD_TABLE(ArrayConstructor) };
|
2017-08-12 16:48:01 +00:00
|
|
|
|
|
|
|
/* Source for ArrayConstructor.lut.h
|
|
|
|
@begin arrayConstructorTable
|
|
|
|
of JSBuiltin DontEnum|Function 0
|
|
|
|
from JSBuiltin DontEnum|Function 0
|
|
|
|
@end
|
|
|
|
*/
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
static JSC_DECLARE_HOST_FUNCTION(callArrayConstructor);
|
|
|
|
static JSC_DECLARE_HOST_FUNCTION(constructWithArrayConstructor);
|
2020-08-29 13:27:11 +00:00
|
|
|
|
2017-08-12 16:48:01 +00:00
|
|
|
ArrayConstructor::ArrayConstructor(VM& vm, Structure* structure)
|
2020-08-29 13:27:11 +00:00
|
|
|
: InternalFunction(vm, structure, callArrayConstructor, constructWithArrayConstructor)
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArrayConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayPrototype* arrayPrototype, GetterSetter* speciesSymbol)
|
|
|
|
{
|
2022-10-23 02:55:20 +00:00
|
|
|
Base::finishCreation(vm, 1, vm.propertyNames->Array.string(), PropertyAdditionMode::WithoutStructureTransition);
|
2020-08-29 13:27:11 +00:00
|
|
|
putDirectWithoutTransition(vm, vm.propertyNames->prototype, arrayPrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
|
|
|
|
putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->speciesSymbol, speciesSymbol, PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
|
|
|
|
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isArray, arrayConstructorIsArrayCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------ Functions ---------------------------
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
JSArray* constructArrayWithSizeQuirk(JSGlobalObject* globalObject, ArrayAllocationProfile* profile, JSValue length, JSValue newTarget)
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
2022-10-23 02:55:20 +00:00
|
|
|
VM& vm = globalObject->vm();
|
2017-08-12 16:48:01 +00:00
|
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
2020-08-29 13:27:11 +00:00
|
|
|
if (!length.isNumber())
|
2022-10-23 02:55:20 +00:00
|
|
|
RELEASE_AND_RETURN(scope, constructArrayNegativeIndexed(globalObject, profile, &length, 1, newTarget));
|
2017-08-12 16:48:01 +00:00
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
uint32_t n = length.toUInt32(globalObject);
|
|
|
|
if (n != length.toNumber(globalObject)) {
|
|
|
|
throwException(globalObject, scope, createRangeError(globalObject, "Array size is not a small enough positive integer."_s));
|
2020-08-29 13:27:11 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2022-10-23 02:55:20 +00:00
|
|
|
RELEASE_AND_RETURN(scope, constructEmptyArray(globalObject, profile, n, newTarget));
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
static inline JSArray* constructArrayWithSizeQuirk(JSGlobalObject* globalObject, const ArgList& args, JSValue newTarget)
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
|
|
|
// a single numeric argument denotes the array size (!)
|
|
|
|
if (args.size() == 1)
|
2022-10-23 02:55:20 +00:00
|
|
|
return constructArrayWithSizeQuirk(globalObject, nullptr, args.at(0), newTarget);
|
2017-08-12 16:48:01 +00:00
|
|
|
|
|
|
|
// otherwise the array is constructed with the arguments in it
|
2022-10-23 02:55:20 +00:00
|
|
|
return constructArray(globalObject, static_cast<ArrayAllocationProfile*>(nullptr), args, newTarget);
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
JSC_DEFINE_HOST_FUNCTION(constructWithArrayConstructor, (JSGlobalObject* globalObject, CallFrame* callFrame))
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
2022-10-23 02:55:20 +00:00
|
|
|
ArgList args(callFrame);
|
|
|
|
return JSValue::encode(constructArrayWithSizeQuirk(globalObject, args, callFrame->newTarget()));
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
JSC_DEFINE_HOST_FUNCTION(callArrayConstructor, (JSGlobalObject* globalObject, CallFrame* callFrame))
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
2022-10-23 02:55:20 +00:00
|
|
|
ArgList args(callFrame);
|
|
|
|
return JSValue::encode(constructArrayWithSizeQuirk(globalObject, args, JSValue()));
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
static ALWAYS_INLINE bool isArraySlowInline(JSGlobalObject* globalObject, ProxyObject* proxy)
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
2022-10-23 02:55:20 +00:00
|
|
|
VM& vm = globalObject->vm();
|
2017-08-12 16:48:01 +00:00
|
|
|
auto scope = DECLARE_THROW_SCOPE(vm);
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
if (proxy->isRevoked()) {
|
2022-10-23 02:55:20 +00:00
|
|
|
throwTypeError(globalObject, scope, "Array.isArray cannot be called on a Proxy that has been revoked"_s);
|
2017-08-12 16:48:01 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
JSObject* argument = proxy->target();
|
|
|
|
|
|
|
|
if (argument->type() == ArrayType || argument->type() == DerivedArrayType)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (argument->type() != ProxyObjectType)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
proxy = jsCast<ProxyObject*>(argument);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
bool isArraySlow(JSGlobalObject* globalObject, ProxyObject* argument)
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
2022-10-23 02:55:20 +00:00
|
|
|
return isArraySlowInline(globalObject, argument);
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ES6 7.2.2
|
|
|
|
// https://tc39.github.io/ecma262/#sec-isarray
|
2022-10-23 02:55:20 +00:00
|
|
|
JSC_DEFINE_HOST_FUNCTION(arrayConstructorPrivateFuncIsArraySlow, (JSGlobalObject* globalObject, CallFrame* callFrame))
|
2017-08-12 16:48:01 +00:00
|
|
|
{
|
2022-10-23 02:55:20 +00:00
|
|
|
ASSERT_UNUSED(globalObject, jsDynamicCast<ProxyObject*>(globalObject->vm(), callFrame->argument(0)));
|
|
|
|
return JSValue::encode(jsBoolean(isArraySlowInline(globalObject, jsCast<ProxyObject*>(callFrame->uncheckedArgument(0)))));
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace JSC
|