зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 645be0c7780a (bug 1069666) for breaking non-unified build at js/src/builtin/WeakMapObject-inl.h:19. r=backout on a CLOSED TREE
This commit is contained in:
Родитель
e93cfe86b2
Коммит
5b70ed6728
|
@ -73,6 +73,9 @@
|
|||
// to be resolved eagerly.
|
||||
#define BOUND_FUN_LENGTH_SLOT 1
|
||||
|
||||
// Stores the private WeakMap slot used for WeakSets
|
||||
#define WEAKSET_MAP_SLOT 0
|
||||
|
||||
#define ITERATOR_SLOT_TARGET 0
|
||||
// Used for collection iterators.
|
||||
#define ITERATOR_SLOT_RANGE 1
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef builtin_WeakMapObject_inl_h
|
||||
#define builtin_WeakMapObject_inl_h
|
||||
|
||||
#include "builtin/WeakMapObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
static bool
|
||||
TryPreserveReflector(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
if (obj->getClass()->isWrappedNative() ||
|
||||
obj->getClass()->isDOMClass() ||
|
||||
(obj->is<ProxyObject>() &&
|
||||
obj->as<ProxyObject>().handler()->family() == GetDOMProxyHandlerFamily()))
|
||||
{
|
||||
MOZ_ASSERT(cx->runtime()->preserveWrapperCallback);
|
||||
if (!cx->runtime()->preserveWrapperCallback(cx, obj)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_WEAKMAP_KEY);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
WeakCollectionPutEntryInternal(JSContext* cx, Handle<WeakCollectionObject*> obj,
|
||||
HandleObject key, HandleValue value)
|
||||
{
|
||||
ObjectValueMap* map = obj->getMap();
|
||||
if (!map) {
|
||||
auto newMap = cx->make_unique<ObjectValueMap>(cx, obj.get());
|
||||
if (!newMap)
|
||||
return false;
|
||||
if (!newMap->init()) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
map = newMap.release();
|
||||
obj->setPrivate(map);
|
||||
}
|
||||
|
||||
// Preserve wrapped native keys to prevent wrapper optimization.
|
||||
if (!TryPreserveReflector(cx, key))
|
||||
return false;
|
||||
|
||||
if (JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp()) {
|
||||
RootedObject delegate(cx, op(key));
|
||||
if (delegate && !TryPreserveReflector(cx, delegate))
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(key->compartment() == obj->compartment());
|
||||
MOZ_ASSERT_IF(value.isObject(), value.toObject().compartment() == obj->compartment());
|
||||
if (!map->put(key, value)) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* builtin_WeakMapObject_inl_h */
|
|
@ -4,7 +4,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "builtin/WeakMapObject-inl.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
|
@ -44,8 +44,8 @@ WeakMap_has_impl(JSContext* cx, const CallArgs& args)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
WeakMap_has(JSContext* cx, unsigned argc, Value* vp)
|
||||
bool
|
||||
js::WeakMap_has(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsWeakMap, WeakMap_has_impl>(cx, args);
|
||||
|
@ -103,13 +103,66 @@ WeakMap_delete_impl(JSContext* cx, const CallArgs& args)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
WeakMap_delete(JSContext* cx, unsigned argc, Value* vp)
|
||||
bool
|
||||
js::WeakMap_delete(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsWeakMap, WeakMap_delete_impl>(cx, args);
|
||||
}
|
||||
|
||||
static bool
|
||||
TryPreserveReflector(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
if (obj->getClass()->isWrappedNative() ||
|
||||
obj->getClass()->isDOMClass() ||
|
||||
(obj->is<ProxyObject>() &&
|
||||
obj->as<ProxyObject>().handler()->family() == GetDOMProxyHandlerFamily()))
|
||||
{
|
||||
MOZ_ASSERT(cx->runtime()->preserveWrapperCallback);
|
||||
if (!cx->runtime()->preserveWrapperCallback(cx, obj)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_WEAKMAP_KEY);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
SetWeakMapEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
|
||||
HandleObject key, HandleValue value)
|
||||
{
|
||||
ObjectValueMap* map = mapObj->getMap();
|
||||
if (!map) {
|
||||
auto newMap = cx->make_unique<ObjectValueMap>(cx, mapObj.get());
|
||||
if (!newMap)
|
||||
return false;
|
||||
if (!newMap->init()) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
map = newMap.release();
|
||||
mapObj->setPrivate(map);
|
||||
}
|
||||
|
||||
// Preserve wrapped native keys to prevent wrapper optimization.
|
||||
if (!TryPreserveReflector(cx, key))
|
||||
return false;
|
||||
|
||||
if (JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp()) {
|
||||
RootedObject delegate(cx, op(key));
|
||||
if (delegate && !TryPreserveReflector(cx, delegate))
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(key->compartment() == mapObj->compartment());
|
||||
MOZ_ASSERT_IF(value.isObject(), value.toObject().compartment() == mapObj->compartment());
|
||||
if (!map->put(key, value)) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WeakMap_set_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
|
@ -121,9 +174,10 @@ WeakMap_set_impl(JSContext* cx, const CallArgs& args)
|
|||
}
|
||||
|
||||
RootedObject key(cx, &args[0].toObject());
|
||||
Rooted<WeakMapObject*> map(cx, &args.thisv().toObject().as<WeakMapObject>());
|
||||
Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
|
||||
Rooted<WeakMapObject*> map(cx, &thisObj->as<WeakMapObject>());
|
||||
|
||||
if (!WeakCollectionPutEntryInternal(cx, map, key, args.get(1)))
|
||||
if (!SetWeakMapEntryInternal(cx, map, key, args.get(1)))
|
||||
return false;
|
||||
args.rval().set(args.thisv());
|
||||
return true;
|
||||
|
@ -136,14 +190,20 @@ js::WeakMap_set(JSContext* cx, unsigned argc, Value* vp)
|
|||
return CallNonGenericMethod<IsWeakMap, WeakMap_set_impl>(cx, args);
|
||||
}
|
||||
|
||||
bool
|
||||
WeakCollectionObject::nondeterministicGetKeys(JSContext* cx, Handle<WeakCollectionObject*> obj,
|
||||
MutableHandleObject ret)
|
||||
JS_FRIEND_API(bool)
|
||||
JS_NondeterministicGetWeakMapKeys(JSContext* cx, HandleObject objArg, MutableHandleObject ret)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
obj = UncheckedUnwrap(obj);
|
||||
if (!obj || !obj->is<WeakMapObject>()) {
|
||||
ret.set(nullptr);
|
||||
return true;
|
||||
}
|
||||
RootedObject arr(cx, NewDenseEmptyArray(cx));
|
||||
if (!arr)
|
||||
return false;
|
||||
if (ObjectValueMap* map = obj->getMap()) {
|
||||
ObjectValueMap* map = obj->as<WeakMapObject>().getMap();
|
||||
if (map) {
|
||||
// Prevent GC from mutating the weakmap while iterating.
|
||||
AutoSuppressGC suppress(cx);
|
||||
for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) {
|
||||
|
@ -159,29 +219,18 @@ WeakCollectionObject::nondeterministicGetKeys(JSContext* cx, Handle<WeakCollecti
|
|||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
JS_NondeterministicGetWeakMapKeys(JSContext* cx, HandleObject objArg, MutableHandleObject ret)
|
||||
{
|
||||
RootedObject obj(cx, UncheckedUnwrap(objArg));
|
||||
if (!obj || !obj->is<WeakMapObject>()) {
|
||||
ret.set(nullptr);
|
||||
return true;
|
||||
}
|
||||
return WeakCollectionObject::nondeterministicGetKeys(cx, obj.as<WeakCollectionObject>(), ret);
|
||||
}
|
||||
|
||||
static void
|
||||
WeakCollection_trace(JSTracer* trc, JSObject* obj)
|
||||
WeakMap_trace(JSTracer* trc, JSObject* obj)
|
||||
{
|
||||
if (ObjectValueMap* map = obj->as<WeakCollectionObject>().getMap())
|
||||
if (ObjectValueMap* map = obj->as<WeakMapObject>().getMap())
|
||||
map->trace(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
WeakCollection_finalize(FreeOp* fop, JSObject* obj)
|
||||
WeakMap_finalize(FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(fop->maybeOnHelperThread());
|
||||
if (ObjectValueMap* map = obj->as<WeakCollectionObject>().getMap()) {
|
||||
if (ObjectValueMap* map = obj->as<WeakMapObject>().getMap()) {
|
||||
#ifdef DEBUG
|
||||
map->~ObjectValueMap();
|
||||
memset(static_cast<void*>(map), 0xdc, sizeof(*map));
|
||||
|
@ -229,8 +278,8 @@ JS::SetWeakMapEntry(JSContext* cx, HandleObject mapObj, HandleObject key,
|
|||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, key, val);
|
||||
Handle<WeakMapObject*> rootedMap = mapObj.as<WeakMapObject>();
|
||||
return WeakCollectionPutEntryInternal(cx, rootedMap, key, val);
|
||||
Rooted<WeakMapObject*> rootedMap(cx, &mapObj->as<WeakMapObject>());
|
||||
return SetWeakMapEntryInternal(cx, rootedMap, key, val);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -264,18 +313,18 @@ WeakMap_construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
const ClassOps WeakCollectionObject::classOps_ = {
|
||||
static const ClassOps WeakMapObjectClassOps = {
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* newEnumerate */
|
||||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
WeakCollection_finalize,
|
||||
WeakMap_finalize,
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
WeakCollection_trace
|
||||
WeakMap_trace
|
||||
};
|
||||
|
||||
const Class WeakMapObject::class_ = {
|
||||
|
@ -283,7 +332,7 @@ const Class WeakMapObject::class_ = {
|
|||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap) |
|
||||
JSCLASS_BACKGROUND_FINALIZE,
|
||||
&WeakCollectionObject::classOps_
|
||||
&WeakMapObjectClassOps
|
||||
};
|
||||
|
||||
static const JSFunctionSpec weak_map_methods[] = {
|
||||
|
|
|
@ -12,40 +12,14 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
// Abstract base class for WeakMapObject and WeakSetObject.
|
||||
class WeakCollectionObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
ObjectValueMap* getMap() { return static_cast<ObjectValueMap*>(getPrivate()); }
|
||||
|
||||
static MOZ_MUST_USE bool nondeterministicGetKeys(JSContext* cx,
|
||||
Handle<WeakCollectionObject*> obj,
|
||||
MutableHandleObject ret);
|
||||
|
||||
protected:
|
||||
static const ClassOps classOps_;
|
||||
};
|
||||
|
||||
class WeakMapObject : public WeakCollectionObject
|
||||
class WeakMapObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
ObjectValueMap* getMap() { return static_cast<ObjectValueMap*>(getPrivate()); }
|
||||
};
|
||||
|
||||
// WeakMap methods exposed so they can be installed in the self-hosting global.
|
||||
|
||||
extern bool
|
||||
WeakMap_get(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
WeakMap_set(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern JSObject*
|
||||
InitBareWeakMapCtor(JSContext* cx, HandleObject obj);
|
||||
|
||||
extern JSObject*
|
||||
InitWeakMapClass(JSContext* cx, HandleObject obj);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* builtin_WeakMapObject_h */
|
||||
|
|
|
@ -18,3 +18,66 @@ function WeakSetConstructorInit(iterable) {
|
|||
for (var nextValue of allowContentIter(iterable))
|
||||
callContentFunction(adder, set, nextValue);
|
||||
}
|
||||
|
||||
// 23.4.3.1
|
||||
function WeakSet_add(value) {
|
||||
// Steps 1-3.
|
||||
var S = this;
|
||||
if (!IsObject(S) || !IsWeakSet(S))
|
||||
return callFunction(CallWeakSetMethodIfWrapped, this, value, "WeakSet_add");
|
||||
|
||||
// Step 4.,6.
|
||||
let entries = UnsafeGetReservedSlot(this, WEAKSET_MAP_SLOT);
|
||||
if (!entries)
|
||||
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "add", typeof S);
|
||||
|
||||
// Step 5.
|
||||
if (!IsObject(value))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_NAME, "WeakSet value", ToSource(value));
|
||||
|
||||
// Steps 7-8.
|
||||
callFunction(std_WeakMap_set, entries, value, true);
|
||||
|
||||
// Step 8.
|
||||
return S;
|
||||
}
|
||||
|
||||
// 23.4.3.3
|
||||
function WeakSet_delete(value) {
|
||||
// Steps 1-3.
|
||||
var S = this;
|
||||
if (!IsObject(S) || !IsWeakSet(S))
|
||||
return callFunction(CallWeakSetMethodIfWrapped, this, value, "WeakSet_delete");
|
||||
|
||||
// Step 4.,6.
|
||||
let entries = UnsafeGetReservedSlot(this, WEAKSET_MAP_SLOT);
|
||||
if (!entries)
|
||||
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "delete", typeof S);
|
||||
|
||||
// Step 5.
|
||||
if (!IsObject(value))
|
||||
return false;
|
||||
|
||||
// Steps 7-8.
|
||||
return callFunction(std_WeakMap_delete, entries, value);
|
||||
}
|
||||
|
||||
// 23.4.3.4
|
||||
function WeakSet_has(value) {
|
||||
// Steps 1-3.
|
||||
var S = this;
|
||||
if (!IsObject(S) || !IsWeakSet(S))
|
||||
return callFunction(CallWeakSetMethodIfWrapped, this, value, "WeakSet_has");
|
||||
|
||||
// Step 4-5.
|
||||
let entries = UnsafeGetReservedSlot(this, WEAKSET_MAP_SLOT);
|
||||
if (!entries)
|
||||
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "has", typeof S);
|
||||
|
||||
// Step 6.
|
||||
if (!IsObject(value))
|
||||
return false;
|
||||
|
||||
// Steps 7-8.
|
||||
return callFunction(std_WeakMap_has, entries, value);
|
||||
}
|
||||
|
|
|
@ -11,132 +11,22 @@
|
|||
#include "jsiter.h"
|
||||
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "builtin/WeakMapObject-inl.h"
|
||||
#include "vm/Interpreter-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
IsWeakSet(HandleValue v)
|
||||
{
|
||||
return v.isObject() && v.toObject().is<WeakSetObject>();
|
||||
}
|
||||
|
||||
// ES2018 draft rev 7a2d3f053ecc2336fc19f377c55d52d78b11b296
|
||||
// 23.4.3.1 WeakSet.prototype.add ( value )
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WeakSet_add_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsWeakSet(args.thisv()));
|
||||
|
||||
// Step 4.
|
||||
if (!args.get(0).isObject()) {
|
||||
ReportNotObjectWithName(cx, "WeakSet value", args.get(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 5-7.
|
||||
RootedObject value(cx, &args[0].toObject());
|
||||
Rooted<WeakSetObject*> map(cx, &args.thisv().toObject().as<WeakSetObject>());
|
||||
if (!WeakCollectionPutEntryInternal(cx, map, value, TrueHandleValue))
|
||||
return false;
|
||||
|
||||
// Steps 6.a.i, 8.
|
||||
args.rval().set(args.thisv());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
WeakSet_add(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
// Steps 1-3.
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsWeakSet, WeakSet_add_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES2018 draft rev 7a2d3f053ecc2336fc19f377c55d52d78b11b296
|
||||
// 23.4.3.3 WeakSet.prototype.delete ( value )
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WeakSet_delete_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsWeakSet(args.thisv()));
|
||||
|
||||
// Step 4.
|
||||
if (!args.get(0).isObject()) {
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 5-6.
|
||||
if (ObjectValueMap* map = args.thisv().toObject().as<WeakSetObject>().getMap()) {
|
||||
JSObject* value = &args[0].toObject();
|
||||
if (ObjectValueMap::Ptr ptr = map->lookup(value)) {
|
||||
map->remove(ptr);
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7.
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
WeakSet_delete(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
// Steps 1-3.
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsWeakSet, WeakSet_delete_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES2018 draft rev 7a2d3f053ecc2336fc19f377c55d52d78b11b296
|
||||
// 23.4.3.4 WeakSet.prototype.has ( value )
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WeakSet_has_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsWeakSet(args.thisv()));
|
||||
|
||||
// Step 5.
|
||||
if (!args.get(0).isObject()) {
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Steps 4, 6.
|
||||
if (ObjectValueMap* map = args.thisv().toObject().as<WeakSetObject>().getMap()) {
|
||||
JSObject* value = &args[0].toObject();
|
||||
if (map->has(value)) {
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7.
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
WeakSet_has(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
// Steps 1-3.
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsWeakSet, WeakSet_has_impl>(cx, args);
|
||||
}
|
||||
|
||||
const Class WeakSetObject::class_ = {
|
||||
"WeakSet",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_WeakSet) |
|
||||
JSCLASS_BACKGROUND_FINALIZE,
|
||||
&WeakCollectionObject::classOps_
|
||||
JSCLASS_HAS_RESERVED_SLOTS(WeakSetObject::RESERVED_SLOTS)
|
||||
};
|
||||
|
||||
const JSPropertySpec WeakSetObject::properties[] = {
|
||||
|
@ -144,9 +34,9 @@ const JSPropertySpec WeakSetObject::properties[] = {
|
|||
};
|
||||
|
||||
const JSFunctionSpec WeakSetObject::methods[] = {
|
||||
JS_FN("add", WeakSet_add, 1, 0),
|
||||
JS_FN("delete", WeakSet_delete, 1, 0),
|
||||
JS_FN("has", WeakSet_has, 1, 0),
|
||||
JS_SELF_HOSTED_FN("add", "WeakSet_add", 1, 0),
|
||||
JS_SELF_HOSTED_FN("delete", "WeakSet_delete", 1, 0),
|
||||
JS_SELF_HOSTED_FN("has", "WeakSet_has", 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -174,13 +64,23 @@ WeakSetObject::initClass(JSContext* cx, HandleObject obj)
|
|||
WeakSetObject*
|
||||
WeakSetObject::create(JSContext* cx, HandleObject proto /* = nullptr */)
|
||||
{
|
||||
return NewObjectWithClassProto<WeakSetObject>(cx, proto);
|
||||
RootedObject map(cx, NewBuiltinClassInstance<WeakMapObject>(cx));
|
||||
if (!map)
|
||||
return nullptr;
|
||||
|
||||
WeakSetObject* obj = NewObjectWithClassProto<WeakSetObject>(cx, proto);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
obj->setReservedSlot(WEAKSET_MAP_SLOT, ObjectValue(*map));
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
WeakSetObject::isBuiltinAdd(HandleValue add, JSContext* cx)
|
||||
{
|
||||
return IsNativeFunction(add, WeakSet_add);
|
||||
JSFunction* addFn;
|
||||
return IsFunctionObject(add, &addFn) && IsSelfHostedFunctionWithName(addFn, cx->names().WeakSet_add);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -209,6 +109,8 @@ WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (optimized) {
|
||||
RootedValue keyVal(cx);
|
||||
RootedObject keyObject(cx);
|
||||
RootedValue placeholder(cx, BooleanValue(true));
|
||||
RootedObject map(cx, &obj->getReservedSlot(WEAKSET_MAP_SLOT).toObject());
|
||||
RootedArrayObject array(cx, &iterable.toObject().as<ArrayObject>());
|
||||
for (uint32_t index = 0; index < array->getDenseInitializedLength(); ++index) {
|
||||
keyVal.set(array->getDenseElement(index));
|
||||
|
@ -220,7 +122,7 @@ WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
keyObject = &keyVal.toObject();
|
||||
if (!WeakCollectionPutEntryInternal(cx, obj, keyObject, TrueHandleValue))
|
||||
if (!SetWeakMapEntry(cx, map, keyObject, placeholder))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -247,10 +149,17 @@ js::InitWeakSetClass(JSContext* cx, HandleObject obj)
|
|||
JS_FRIEND_API(bool)
|
||||
JS_NondeterministicGetWeakSetKeys(JSContext* cx, HandleObject objArg, MutableHandleObject ret)
|
||||
{
|
||||
RootedObject obj(cx, UncheckedUnwrap(objArg));
|
||||
RootedObject obj(cx, objArg);
|
||||
obj = UncheckedUnwrap(obj);
|
||||
if (!obj || !obj->is<WeakSetObject>()) {
|
||||
ret.set(nullptr);
|
||||
return true;
|
||||
}
|
||||
return WeakCollectionObject::nondeterministicGetKeys(cx, obj.as<WeakCollectionObject>(), ret);
|
||||
|
||||
Rooted<WeakSetObject*> weakset(cx, &obj->as<WeakSetObject>());
|
||||
if (!weakset)
|
||||
return false;
|
||||
|
||||
RootedObject map(cx, &weakset->getReservedSlot(WEAKSET_MAP_SLOT).toObject());
|
||||
return JS_NondeterministicGetWeakMapKeys(cx, map, ret);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
#ifndef builtin_WeakSetObject_h
|
||||
#define builtin_WeakSetObject_h
|
||||
|
||||
#include "builtin/WeakMapObject.h"
|
||||
#include "vm/NativeObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class WeakSetObject : public WeakCollectionObject
|
||||
class WeakSetObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 1;
|
||||
|
||||
static JSObject* initClass(JSContext* cx, HandleObject obj);
|
||||
static const Class class_;
|
||||
|
||||
|
@ -32,11 +34,4 @@ InitWeakSetClass(JSContext* cx, HandleObject obj);
|
|||
|
||||
} // namespace js
|
||||
|
||||
template<>
|
||||
inline bool
|
||||
JSObject::is<js::WeakCollectionObject>() const
|
||||
{
|
||||
return is<js::WeakMapObject>() || is<js::WeakSetObject>();
|
||||
}
|
||||
|
||||
#endif /* builtin_WeakSetObject_h */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
load(libdir + "asserts.js");
|
||||
|
||||
assertTypeErrorMessage(() => Set.prototype.forEach.call({}), "forEach method called on incompatible Object");
|
||||
assertTypeErrorMessage(() => newGlobal().Set.prototype.forEach.call({}), "forEach method called on incompatible Object");
|
||||
assertTypeErrorMessage(() => Set.prototype.forEach.call(15), "forEach method called on incompatible number");
|
||||
assertTypeErrorMessage(() => WeakSet.prototype.add.call({}), "add method called on incompatible Object");
|
||||
assertTypeErrorMessage(() => newGlobal().WeakSet.prototype.add.call({}), "add method called on incompatible Object");
|
||||
assertTypeErrorMessage(() => WeakSet.prototype.add.call(15), "add method called on incompatible number");
|
||||
|
||||
assertTypeErrorMessage(() => Int8Array.prototype.find.call({}), "find method called on incompatible Object");
|
||||
assertTypeErrorMessage(() => newGlobal().Int8Array.prototype.find.call({}), "find method called on incompatible Object");
|
||||
|
|
|
@ -364,6 +364,26 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
|
|||
}
|
||||
};
|
||||
|
||||
/* WeakMap methods exposed so they can be installed in the self-hosting global. */
|
||||
|
||||
extern JSObject*
|
||||
InitBareWeakMapCtor(JSContext* cx, js::HandleObject obj);
|
||||
|
||||
extern bool
|
||||
WeakMap_has(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
WeakMap_get(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
WeakMap_set(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
WeakMap_delete(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern JSObject*
|
||||
InitWeakMapClass(JSContext* cx, HandleObject obj);
|
||||
|
||||
|
||||
class ObjectValueMap : public WeakMap<HeapPtr<JSObject*>, HeapPtr<Value>,
|
||||
MovableCellHasher<HeapPtr<JSObject*>>>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "jsmath.h"
|
||||
#include "json.h"
|
||||
#include "jsprototypes.h"
|
||||
#include "jsweakmap.h"
|
||||
|
||||
#include "builtin/AtomicsObject.h"
|
||||
#include "builtin/DataViewObject.h"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "jshashutil.h"
|
||||
#include "jsiter.h"
|
||||
#include "jsstr.h"
|
||||
#include "jsweakmap.h"
|
||||
#include "jswrapper.h"
|
||||
#include "selfhosted.out.h"
|
||||
|
||||
|
@ -34,7 +35,7 @@
|
|||
#include "builtin/SIMD.h"
|
||||
#include "builtin/Stream.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
#include "builtin/WeakSetObject.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Policy.h"
|
||||
#include "jit/AtomicOperations.h"
|
||||
|
@ -2323,8 +2324,10 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
|
||||
JS_FN("std_TypedArray_buffer", js::TypedArray_bufferGetter, 1,0),
|
||||
|
||||
JS_FN("std_WeakMap_get", WeakMap_get, 1,0),
|
||||
JS_FN("std_WeakMap_has", WeakMap_has, 1,0),
|
||||
JS_FN("std_WeakMap_get", WeakMap_get, 2,0),
|
||||
JS_FN("std_WeakMap_set", WeakMap_set, 2,0),
|
||||
JS_FN("std_WeakMap_delete", WeakMap_delete, 1,0),
|
||||
|
||||
JS_FN("std_SIMD_Int8x16_extractLane", simd_int8x16_extractLane, 2,0),
|
||||
JS_FN("std_SIMD_Int16x8_extractLane", simd_int16x8_extractLane, 2,0),
|
||||
|
@ -2530,6 +2533,10 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
IntrinsicIsSetObject),
|
||||
JS_FN("CallSetMethodIfWrapped", CallNonGenericSelfhostedMethod<Is<SetObject>>, 2, 0),
|
||||
|
||||
JS_FN("IsWeakSet", intrinsic_IsInstanceOfBuiltin<WeakSetObject>, 1,0),
|
||||
JS_FN("CallWeakSetMethodIfWrapped",
|
||||
CallNonGenericSelfhostedMethod<Is<WeakSetObject>>, 2, 0),
|
||||
|
||||
JS_FN("IsReadableStreamBYOBRequest",
|
||||
intrinsic_IsInstanceOfBuiltin<ReadableStreamBYOBRequest>, 1, 0),
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче