mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
* Implement Array.from * Disable part of ES6-shim due to wrong implementation Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
178 lines
9.8 KiB
C++
178 lines
9.8 KiB
C++
/*
|
|
* Copyright (c) 2018-present Samsung Electronics Co., Ltd
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include "Escargot.h"
|
|
#include "GlobalObject.h"
|
|
#include "Context.h"
|
|
#include "VMInstance.h"
|
|
#include "WeakMapObject.h"
|
|
#include "IteratorObject.h"
|
|
#include "ToStringRecursionPreventer.h"
|
|
|
|
namespace Escargot {
|
|
|
|
Value builtinWeakMapConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression)
|
|
{
|
|
if (!isNewExpression) {
|
|
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_GlobalObject_ConstructorRequiresNew);
|
|
}
|
|
|
|
// Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", « [[MapData]] »).
|
|
// Set map's [[MapData]] internal slot to a new empty List.
|
|
WeakMapObject* map = thisValue.asObject()->asWeakMapObject();
|
|
// If iterable is not present, let iterable be undefined.
|
|
Value iterable;
|
|
if (argc >= 1) {
|
|
iterable = argv[0];
|
|
}
|
|
// If iterable is either undefined or null, let iter be undefined.
|
|
Value adder;
|
|
Object* iter = nullptr;
|
|
if (iterable.isUndefinedOrNull()) {
|
|
iterable = Value();
|
|
} else {
|
|
// Else,
|
|
// 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()) {
|
|
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_Call_NotFunction);
|
|
}
|
|
// Let iter be ? GetIterator(iterable).
|
|
iterable = iterable.toObject(state);
|
|
iter = iterable.asObject()->iterator(state);
|
|
if (iter == nullptr) {
|
|
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "object is not iterable");
|
|
}
|
|
}
|
|
// If iter is undefined, return map.
|
|
if (!iter) {
|
|
return map;
|
|
}
|
|
|
|
// Repeat
|
|
while (true) {
|
|
// Let next be ? IteratorStep(iter).
|
|
auto next = iter->iteratorNext(state);
|
|
// If next is false(done is true), return map.
|
|
if (next.second) {
|
|
return map;
|
|
}
|
|
// Let nextItem be ? IteratorValue(next).
|
|
Value nextItem = next.first;
|
|
|
|
// If Type(nextItem) is not Object, then
|
|
if (!nextItem.isObject()) {
|
|
// Let error be Completion{[[Type]]: throw, [[Value]]: a newly created TypeError object, [[Target]]: empty}.
|
|
// Return ? IteratorClose(iter, error).
|
|
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Iterator value a is not an entry object");
|
|
}
|
|
|
|
// Let k be Get(nextItem, "0").
|
|
// If k is an abrupt completion, return ? IteratorClose(iter, k).
|
|
Value k = nextItem.asObject()->getIndexedProperty(state, Value(0)).value(state, nextItem);
|
|
// Let v be Get(nextItem, "1").
|
|
// If v is an abrupt completion, return ? IteratorClose(iter, v).
|
|
Value v = nextItem.asObject()->getIndexedProperty(state, Value(1)).value(state, nextItem);
|
|
|
|
// 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);
|
|
}
|
|
return map;
|
|
}
|
|
|
|
#define RESOLVE_THIS_BINDING_TO_MAP(NAME, OBJ, BUILT_IN_METHOD) \
|
|
if (!thisValue.isObject() || !thisValue.asObject()->isWeakMapObject()) { \
|
|
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), errorMessage_GlobalObject_CalledOnIncompatibleReceiver); \
|
|
} \
|
|
WeakMapObject* NAME = thisValue.asObject()->asWeakMapObject();
|
|
|
|
static Value builtinWeakMapDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression)
|
|
{
|
|
RESOLVE_THIS_BINDING_TO_MAP(M, WeakMap, stringDelete);
|
|
if (!argv[0].isObject()) {
|
|
return Value(false);
|
|
}
|
|
|
|
return Value(M->deleteOperation(state, argv[0].asObject()));
|
|
}
|
|
|
|
static Value builtinWeakMapGet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression)
|
|
{
|
|
RESOLVE_THIS_BINDING_TO_MAP(M, WeakMap, get);
|
|
if (!argv[0].isObject()) {
|
|
return Value();
|
|
}
|
|
|
|
return M->get(state, argv[0].asObject());
|
|
}
|
|
|
|
static Value builtinWeakMapHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression)
|
|
{
|
|
RESOLVE_THIS_BINDING_TO_MAP(M, WeakMap, has);
|
|
if (!argv[0].isObject()) {
|
|
return Value(false);
|
|
}
|
|
|
|
return Value(M->has(state, argv[0].asObject()));
|
|
}
|
|
|
|
static Value builtinWeakMapSet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression)
|
|
{
|
|
RESOLVE_THIS_BINDING_TO_MAP(M, WeakMap, set);
|
|
if (!argv[0].isObject()) {
|
|
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Invalid value used as weak map key");
|
|
}
|
|
|
|
M->set(state, argv[0].asObject(), argv[1]);
|
|
return M;
|
|
}
|
|
|
|
void GlobalObject::installWeakMap(ExecutionState& state)
|
|
{
|
|
m_weakMap = new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakMap, builtinWeakMapConstructor, 0, [](ExecutionState& state, CodeBlock* codeBlock, size_t argc, Value* argv) -> Object* {
|
|
return new WeakMapObject(state);
|
|
}),
|
|
FunctionObject::__ForBuiltin__);
|
|
m_weakMap->markThisObjectDontNeedStructureTransitionTable(state);
|
|
m_weakMap->setPrototype(state, m_functionPrototype);
|
|
m_weakMapPrototype = m_objectPrototype;
|
|
m_weakMapPrototype = new WeakMapObject(state);
|
|
m_weakMapPrototype->markThisObjectDontNeedStructureTransitionTable(state);
|
|
m_weakMapPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
|
|
|
m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
|
|
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinWeakMapDelete, 1, nullptr, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
|
|
|
m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().get),
|
|
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get, builtinWeakMapGet, 1, nullptr, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
|
|
|
m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
|
|
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinWeakMapHas, 1, nullptr, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
|
|
|
m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().set),
|
|
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set, builtinWeakMapSet, 2, nullptr, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
|
|
|
m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
|
|
ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakMap.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
|
|
|
|
m_weakMap->setFunctionPrototype(state, m_weakMapPrototype);
|
|
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakMap),
|
|
ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
|
}
|
|
}
|