escargot/src/runtime/GlobalObjectBuiltinWeakMap.cpp
김승현/Tizen Platform Lab(SR)/Engineer/삼성전자 e66f512b32 Implement ES6 Symbol.hasInstance, iterator, toStringTag, toPrimitive and built-ins (#46)
* Implement Array.from
* Disable part of ES6-shim due to wrong implementation

Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
2018-01-19 15:20:27 +09:00

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)));
}
}