mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 697479 - Implement Map and Set builtins for JS. r=jimb.
This commit is contained in:
parent
ee1591d990
commit
94bdef7f4f
@ -171,6 +171,7 @@ CPPSRCS = \
|
||||
SemanticAnalysis.cpp \
|
||||
TokenStream.cpp \
|
||||
LifoAlloc.cpp \
|
||||
MapObject.cpp \
|
||||
MemoryMetrics.cpp \
|
||||
RegExpObject.cpp \
|
||||
RegExpStatics.cpp \
|
||||
|
407
js/src/builtin/MapObject.cpp
Normal file
407
js/src/builtin/MapObject.cpp
Normal file
@ -0,0 +1,407 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Orendorff <jorendorff@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "builtin/MapObject.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsgcmark.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/Stack.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
static JSObject *
|
||||
InitClass(JSContext *cx, GlobalObject *global, Class *clasp, JSProtoKey key, Native construct,
|
||||
JSFunctionSpec *methods)
|
||||
{
|
||||
JSObject *proto = global->createBlankPrototype(cx, clasp);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
proto->setPrivate(NULL);
|
||||
|
||||
JSAtom *atom = cx->runtime->atomState.classAtoms[key];
|
||||
JSFunction *ctor = global->createConstructor(cx, construct, clasp, atom, 0);
|
||||
if (!ctor ||
|
||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!DefinePropertiesAndBrand(cx, proto, NULL, methods) ||
|
||||
!DefineConstructorAndPrototype(cx, global, key, ctor, proto))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
||||
/*** HashableValue *******************************************************************************/
|
||||
|
||||
bool
|
||||
HashableValue::setValue(JSContext *cx, const Value &v)
|
||||
{
|
||||
if (v.isString() && v.toString()->isRope()) {
|
||||
/* Flatten this rope so that equals() is infallible. */
|
||||
JSString *str = v.toString()->ensureLinear(cx);
|
||||
if (!str)
|
||||
return false;
|
||||
value = StringValue(str);
|
||||
} else if (v.isDouble()) {
|
||||
jsdouble d = v.toDouble();
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(d, &i)) {
|
||||
/* Normalize int32-valued doubles to int32 for faster hashing and testing. */
|
||||
value = Int32Value(i);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
/* All NaN values are the same. The bit-pattern must reflect this. */
|
||||
jsval_layout a, b;
|
||||
a.asDouble = d;
|
||||
b.asDouble = JS_CANONICALIZE_NAN(d);
|
||||
JS_ASSERT(a.asBits == b.asBits);
|
||||
#endif
|
||||
value = v;
|
||||
}
|
||||
} else {
|
||||
value = v;
|
||||
}
|
||||
|
||||
JS_ASSERT(value.isUndefined() || value.isNull() || value.isBoolean() ||
|
||||
value.isNumber() || value.isString() || value.isObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
HashNumber
|
||||
HashableValue::hash() const
|
||||
{
|
||||
/*
|
||||
* HashableValue::setValue normalizes values so that the SameValue relation
|
||||
* on HashableValues is the same as the == relationship on
|
||||
* value.data.asBits, except for strings.
|
||||
*/
|
||||
if (value.isString()) {
|
||||
JSLinearString &s = value.toString()->asLinear();
|
||||
return HashChars(s.chars(), s.length());
|
||||
}
|
||||
|
||||
/* Having dispensed with strings, we can just hash asBits. */
|
||||
uint64_t u = value.asRawBits();
|
||||
return HashNumber((u >> 3) ^ (u >> (32 + 3)) ^ (u << (32 - 3)));
|
||||
}
|
||||
|
||||
bool
|
||||
HashableValue::equals(const HashableValue &other) const
|
||||
{
|
||||
/* Two HashableValues are equal if they have equal bits or they're equal strings. */
|
||||
bool b = (value.asRawBits() == other.value.asRawBits()) ||
|
||||
(value.isString() &&
|
||||
other.value.isString() &&
|
||||
EqualStrings(&value.toString()->asLinear(),
|
||||
&other.value.toString()->asLinear()));
|
||||
|
||||
#ifdef DEBUG
|
||||
JSBool same;
|
||||
JS_ASSERT(SameValue(NULL, value, other.value, &same));
|
||||
JS_ASSERT(same == b);
|
||||
#endif
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/*** Map *****************************************************************************************/
|
||||
|
||||
Class MapObject::class_ = {
|
||||
"Map",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Map),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
finalize,
|
||||
NULL, /* reserved0 */
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
mark
|
||||
};
|
||||
|
||||
JSFunctionSpec MapObject::methods[] = {
|
||||
JS_FN("get", get, 1, 0),
|
||||
JS_FN("has", has, 1, 0),
|
||||
JS_FN("set", set, 2, 0),
|
||||
JS_FN("delete", delete_, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
JSObject *
|
||||
MapObject::initClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return InitClass(cx, &obj->asGlobal(), &class_, JSProto_Map, construct, methods);
|
||||
}
|
||||
|
||||
void
|
||||
MapObject::mark(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
MapObject *mapobj = static_cast<MapObject *>(obj);
|
||||
if (ValueMap *map = mapobj->getData()) {
|
||||
for (ValueMap::Range r = map->all(); !r.empty(); r.popFront()) {
|
||||
gc::MarkValue(trc, r.front().key, "key");
|
||||
gc::MarkValue(trc, r.front().value, "value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MapObject::finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
MapObject *mapobj = static_cast<MapObject *>(obj);
|
||||
if (ValueMap *map = mapobj->getData())
|
||||
cx->delete_(map);
|
||||
}
|
||||
|
||||
JSBool
|
||||
MapObject::construct(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &class_);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
ValueMap *map = cx->new_<ValueMap>(cx->runtime);
|
||||
if (!map || !map->init())
|
||||
return false;
|
||||
obj->setPrivate(map);
|
||||
|
||||
CallArgsFromVp(argc, vp).rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define UNPACK_THIS(T, native, cx, argc, vp, args, data) \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
if (!args.thisv().isObject() || \
|
||||
!args.thisv().toObject().hasClass(&T::class_)) \
|
||||
{ \
|
||||
return js::HandleNonGenericMethodClassMismatch(cx, args, native, \
|
||||
&T::class_); \
|
||||
} \
|
||||
if (!args.thisv().toObject().getPrivate()) { \
|
||||
ReportIncompatibleMethod(cx, args, &T::class_); \
|
||||
return false; \
|
||||
} \
|
||||
T::Data &data = *static_cast<T &>(args.thisv().toObject()).getData(); \
|
||||
(void) data
|
||||
|
||||
#define THIS_MAP(native, cx, argc, vp, args, map) \
|
||||
UNPACK_THIS(MapObject, native, cx, argc, vp, args, map)
|
||||
|
||||
#define ARG0_KEY(cx, args, key) \
|
||||
HashableValue key; \
|
||||
if (args.length() > 0 && !key.setValue(cx, args[0])) \
|
||||
return false
|
||||
|
||||
JSBool
|
||||
MapObject::get(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_MAP(get, cx, argc, vp, args, map);
|
||||
ARG0_KEY(cx, args, key);
|
||||
|
||||
if (ValueMap::Ptr p = map.lookup(key))
|
||||
args.rval() = p->value;
|
||||
else
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
MapObject::has(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_MAP(has, cx, argc, vp, args, map);
|
||||
ARG0_KEY(cx, args, key);
|
||||
args.rval().setBoolean(map.lookup(key));
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
MapObject::set(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_MAP(set, cx, argc, vp, args, map);
|
||||
ARG0_KEY(cx, args, key);
|
||||
map.put(key, args.length() > 1 ? args[1] : UndefinedValue());
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
MapObject::delete_(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_MAP(delete_, cx, argc, vp, args, map);
|
||||
ARG0_KEY(cx, args, key);
|
||||
ValueMap::Ptr p = map.lookup(key);
|
||||
bool found = p.found();
|
||||
if (found)
|
||||
map.remove(p);
|
||||
args.rval().setBoolean(found);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_InitMapClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return MapObject::initClass(cx, obj);
|
||||
}
|
||||
|
||||
|
||||
/*** Set *****************************************************************************************/
|
||||
|
||||
Class SetObject::class_ = {
|
||||
"Set",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Set),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
finalize,
|
||||
NULL, /* reserved0 */
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* construct */
|
||||
NULL, /* xdrObject */
|
||||
NULL, /* hasInstance */
|
||||
mark
|
||||
};
|
||||
|
||||
JSFunctionSpec SetObject::methods[] = {
|
||||
JS_FN("has", has, 1, 0),
|
||||
JS_FN("add", add, 1, 0),
|
||||
JS_FN("delete", delete_, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
JSObject *
|
||||
SetObject::initClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return InitClass(cx, &obj->asGlobal(), &class_, JSProto_Set, construct, methods);
|
||||
}
|
||||
|
||||
void
|
||||
SetObject::mark(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
SetObject *setobj = static_cast<SetObject *>(obj);
|
||||
if (ValueSet *set = setobj->getData()) {
|
||||
for (ValueSet::Range r = set->all(); !r.empty(); r.popFront())
|
||||
gc::MarkValue(trc, r.front(), "key");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SetObject::finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
SetObject *setobj = static_cast<SetObject *>(obj);
|
||||
if (ValueSet *set = setobj->getData())
|
||||
cx->delete_(set);
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetObject::construct(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &class_);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
ValueSet *set = cx->new_<ValueSet>(cx->runtime);
|
||||
if (!set || !set->init())
|
||||
return false;
|
||||
obj->setPrivate(set);
|
||||
|
||||
CallArgsFromVp(argc, vp).rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define THIS_SET(native, cx, argc, vp, args, set) \
|
||||
UNPACK_THIS(SetObject, native, cx, argc, vp, args, set)
|
||||
|
||||
JSBool
|
||||
SetObject::has(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_SET(has, cx, argc, vp, args, set);
|
||||
ARG0_KEY(cx, args, key);
|
||||
args.rval().setBoolean(set.has(key));
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetObject::add(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_SET(add, cx, argc, vp, args, set);
|
||||
ARG0_KEY(cx, args, key);
|
||||
if (!set.put(key))
|
||||
return false;
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetObject::delete_(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_SET(delete_, cx, argc, vp, args, set);
|
||||
ARG0_KEY(cx, args, key);
|
||||
ValueSet::Ptr p = set.lookup(key);
|
||||
bool found = p.found();
|
||||
if (found)
|
||||
set.remove(p);
|
||||
args.rval().setBoolean(found);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_InitSetClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return SetObject::initClass(cx, obj);
|
||||
}
|
122
js/src/builtin/MapObject.h
Normal file
122
js/src/builtin/MapObject.h
Normal file
@ -0,0 +1,122 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Orendorff <jorendorff@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MapObject_h__
|
||||
#define MapObject_h__
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "js/HashTable.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Comparing two ropes for equality can fail. The js::HashTable template
|
||||
* requires infallible hash() and match() operations. Therefore we require
|
||||
* all values to be converted to hashable form before being used as a key
|
||||
* in a Map or Set object.
|
||||
*
|
||||
* All values except ropes are hashable as-is.
|
||||
*/
|
||||
class HashableValue {
|
||||
HeapValue value;
|
||||
|
||||
public:
|
||||
struct Hasher {
|
||||
typedef HashableValue Lookup;
|
||||
static HashNumber hash(const Lookup &v) { return v.hash(); }
|
||||
static bool match(const HashableValue &k, const Lookup &l) { return k.equals(l); }
|
||||
};
|
||||
|
||||
HashableValue() : value(UndefinedValue()) {}
|
||||
|
||||
operator const HeapValue &() const { return value; }
|
||||
bool setValue(JSContext *cx, const Value &v);
|
||||
HashNumber hash() const;
|
||||
bool equals(const HashableValue &other) const;
|
||||
};
|
||||
|
||||
typedef HashMap<HashableValue, HeapValue, HashableValue::Hasher, RuntimeAllocPolicy> ValueMap;
|
||||
typedef HashSet<HashableValue, HashableValue::Hasher, RuntimeAllocPolicy> ValueSet;
|
||||
|
||||
class MapObject : public JSObject {
|
||||
public:
|
||||
static JSObject *initClass(JSContext *cx, JSObject *obj);
|
||||
static Class class_;
|
||||
private:
|
||||
typedef ValueMap Data;
|
||||
static JSFunctionSpec methods[];
|
||||
ValueMap *getData() { return static_cast<ValueMap *>(getPrivate()); }
|
||||
static void mark(JSTracer *trc, JSObject *obj);
|
||||
static void finalize(JSContext *cx, JSObject *obj);
|
||||
static JSBool construct(JSContext *cx, uintN argc, Value *vp);
|
||||
static JSBool get(JSContext *cx, uintN argc, Value *vp);
|
||||
static JSBool has(JSContext *cx, uintN argc, Value *vp);
|
||||
static JSBool set(JSContext *cx, uintN argc, Value *vp);
|
||||
static JSBool delete_(JSContext *cx, uintN argc, Value *vp);
|
||||
};
|
||||
|
||||
class SetObject : public JSObject {
|
||||
public:
|
||||
static JSObject *initClass(JSContext *cx, JSObject *obj);
|
||||
static Class class_;
|
||||
private:
|
||||
typedef ValueSet Data;
|
||||
static JSFunctionSpec methods[];
|
||||
ValueSet *getData() { return static_cast<ValueSet *>(getPrivate()); }
|
||||
static void mark(JSTracer *trc, JSObject *obj);
|
||||
static void finalize(JSContext *cx, JSObject *obj);
|
||||
static JSBool construct(JSContext *cx, uintN argc, Value *vp);
|
||||
static JSBool has(JSContext *cx, uintN argc, Value *vp);
|
||||
static JSBool add(JSContext *cx, uintN argc, Value *vp);
|
||||
static JSBool delete_(JSContext *cx, uintN argc, Value *vp);
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern JSObject *
|
||||
js_InitMapClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSObject *
|
||||
js_InitSetClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
#endif /* MapObject_h__ */
|
@ -321,27 +321,32 @@ class HeapValue
|
||||
const Value &get() const { return value; }
|
||||
operator const Value &() const { return value; }
|
||||
|
||||
bool isMarkable() const { return value.isMarkable(); }
|
||||
bool isMagic(JSWhyMagic why) const { return value.isMagic(why); }
|
||||
bool isUndefined() const { return value.isUndefined(); }
|
||||
bool isObject() const { return value.isObject(); }
|
||||
bool isGCThing() const { return value.isGCThing(); }
|
||||
bool isNull() const { return value.isNull(); }
|
||||
bool isBoolean() const { return value.isBoolean(); }
|
||||
bool isTrue() const { return value.isTrue(); }
|
||||
bool isFalse() const { return value.isFalse(); }
|
||||
bool isNumber() const { return value.isNumber(); }
|
||||
bool isInt32() const { return value.isInt32(); }
|
||||
bool isNull() const { return value.isNull(); }
|
||||
bool isString() const { return value.isString(); }
|
||||
bool isObject() const { return value.isObject(); }
|
||||
bool isMagic(JSWhyMagic why) const { return value.isMagic(why); }
|
||||
bool isGCThing() const { return value.isGCThing(); }
|
||||
bool isMarkable() const { return value.isMarkable(); }
|
||||
|
||||
bool toBoolean() const { return value.toBoolean(); }
|
||||
double toNumber() const { return value.toNumber(); }
|
||||
int32_t toInt32() const { return value.toInt32(); }
|
||||
double toDouble() const { return value.toDouble(); }
|
||||
JSString *toString() const { return value.toString(); }
|
||||
JSObject &toObject() const { return value.toObject(); }
|
||||
JSObject *toObjectOrNull() const { return value.toObjectOrNull(); }
|
||||
void *toGCThing() const { return value.toGCThing(); }
|
||||
double toDouble() const { return value.toDouble(); }
|
||||
int32_t toInt32() const { return value.toInt32(); }
|
||||
JSString *toString() const { return value.toString(); }
|
||||
bool toBoolean() const { return value.toBoolean(); }
|
||||
double toNumber() const { return value.toNumber(); }
|
||||
|
||||
JSGCTraceKind gcKind() const { return value.gcKind(); }
|
||||
|
||||
uint64_t asRawBits() const { return value.asRawBits(); }
|
||||
|
||||
#ifdef DEBUG
|
||||
JSWhyMagic whyMagic() const { return value.whyMagic(); }
|
||||
#endif
|
||||
|
@ -82,6 +82,13 @@ test("new WeakMap()", function(w) WeakMap.prototype.has.call(w, {}));
|
||||
test("new WeakMap()", function(w) WeakMap.prototype.get.call(w, {}));
|
||||
test("new WeakMap()", function(w) WeakMap.prototype.delete.call(w, {}));
|
||||
test("new WeakMap()", function(w) WeakMap.prototype.set.call(w, {}));
|
||||
test("new Map()", function(w) Map.prototype.has.call(w, {}));
|
||||
test("new Map()", function(w) Map.prototype.get.call(w, {}));
|
||||
test("new Map()", function(w) Map.prototype.delete.call(w, {}));
|
||||
test("new Map()", function(w) Map.prototype.set.call(w, {}));
|
||||
test("new Set()", function(w) Set.prototype.has.call(w, {}));
|
||||
test("new Set()", function(w) Set.prototype.add.call(w, {}));
|
||||
test("new Set()", function(w) Set.prototype.delete.call(w, {}));
|
||||
|
||||
test("new Int8Array(1)", function(a) Int8Array.prototype.subarray.call(a).toString());
|
||||
test("new Uint8Array(1)", function(a) Uint8Array.prototype.subarray.call(a).toString());
|
||||
|
18
js/src/jit-test/tests/collections/Map-delete.js
Normal file
18
js/src/jit-test/tests/collections/Map-delete.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Map.prototype.delete works whether the key is present or not.
|
||||
|
||||
var m = new Map;
|
||||
var key = {};
|
||||
|
||||
// when the map is new
|
||||
assertEq(m.delete(key), false);
|
||||
assertEq(m.has(key), false);
|
||||
|
||||
// when the key is present
|
||||
assertEq(m.set(key, 'x'), undefined);
|
||||
assertEq(m.delete(key), true);
|
||||
assertEq(m.has(key), false);
|
||||
assertEq(m.get(key), undefined);
|
||||
|
||||
// when the key has already been deleted
|
||||
assertEq(m.delete(key), false);
|
||||
assertEq(m.has(key), false);
|
16
js/src/jit-test/tests/collections/Map-gc-1.js
Normal file
16
js/src/jit-test/tests/collections/Map-gc-1.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Check marking through the keys of a Map.
|
||||
|
||||
load(libdir + "referencesVia.js");
|
||||
|
||||
var m = new Map;
|
||||
for (var i = 0; i < 20; i++) {
|
||||
var n = new Map;
|
||||
n.set(m, i);
|
||||
assertEq(referencesVia(n, 'key', m), true);
|
||||
m = n;
|
||||
}
|
||||
|
||||
gc();
|
||||
gc();
|
||||
|
||||
// TODO: walk the chain using for-of to make sure everything is still there
|
14
js/src/jit-test/tests/collections/Map-gc-2.js
Normal file
14
js/src/jit-test/tests/collections/Map-gc-2.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Check marking through the values of a Map.
|
||||
|
||||
load(libdir + "referencesVia.js");
|
||||
|
||||
var m = new Map;
|
||||
for (var i = 0; i < 20; i++) {
|
||||
var n = new Map;
|
||||
n.set(i, m);
|
||||
assertEq(referencesVia(n, 'value', m), true);
|
||||
m = n;
|
||||
}
|
||||
|
||||
gc();
|
||||
gc();
|
41
js/src/jit-test/tests/collections/Map-get.js
Normal file
41
js/src/jit-test/tests/collections/Map-get.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Map.prototype.get and .has basically work
|
||||
var m = new Map;
|
||||
|
||||
function rope() {
|
||||
var s = "s";
|
||||
for (var i = 0; i < 16; i++)
|
||||
s += s;
|
||||
return s;
|
||||
}
|
||||
|
||||
var keys = [undefined, null, true, false,
|
||||
0, 1, 65535, 65536, 2147483647, 2147483648, 4294967295, 4294967296,
|
||||
-1, -65536, -2147483648,
|
||||
0.5, Math.sqrt(81), Math.PI,
|
||||
Number.MAX_VALUE, -Number.MAX_VALUE, Number.MIN_VALUE, -Number.MIN_VALUE,
|
||||
-0, NaN, Infinity, -Infinity,
|
||||
"", "\0", "a", "ab", "abcdefg", rope(),
|
||||
{}, [], /a*b/, Object.prototype, Object];
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
// without being set
|
||||
var key = keys[i];
|
||||
assertEq(m.has(key), false);
|
||||
assertEq(m.get(key), undefined);
|
||||
|
||||
// after being set
|
||||
var v = {};
|
||||
assertEq(m.set(key, v), undefined);
|
||||
assertEq(m.has(key), true);
|
||||
assertEq(m.get(key), v);
|
||||
|
||||
// after being deleted
|
||||
assertEq(m.delete(key), true);
|
||||
assertEq(m.has(key), false);
|
||||
assertEq(m.get(key), undefined);
|
||||
|
||||
m.set(key, v);
|
||||
}
|
||||
|
||||
for (var i = 0; i < keys.length; i++)
|
||||
assertEq(m.has(keys[i]), true);
|
8
js/src/jit-test/tests/collections/Map-scale.js
Normal file
8
js/src/jit-test/tests/collections/Map-scale.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Maps can hold at least 64K values.
|
||||
|
||||
var N = 1 << 16;
|
||||
var m = new Map;
|
||||
for (var i = 0; i < N; i++)
|
||||
assertEq(m.set(i, i), undefined);
|
||||
for (var i = 0; i < N; i++)
|
||||
assertEq(m.get(i), i);
|
15
js/src/jit-test/tests/collections/Map-set-undefined.js
Normal file
15
js/src/jit-test/tests/collections/Map-set-undefined.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Setting a Map key to undefined, or a missing argument, isn't the same as deleting it.
|
||||
|
||||
var m = new Map;
|
||||
m.set(42, undefined);
|
||||
assertEq(m.has(42), true);
|
||||
assertEq(m.get(42), undefined);
|
||||
|
||||
m.set(42, "wrong");
|
||||
m.set(42);
|
||||
assertEq(m.has(42), true);
|
||||
assertEq(m.get(42), undefined);
|
||||
|
||||
m.set();
|
||||
assertEq(m.has(undefined), true);
|
||||
assertEq(m.get(undefined), undefined);
|
33
js/src/jit-test/tests/collections/Map-surfaces-1.js
Normal file
33
js/src/jit-test/tests/collections/Map-surfaces-1.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Map surfaces
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(this, "Map");
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.writable, true);
|
||||
|
||||
assertEq(typeof Map, 'function');
|
||||
assertEq(Object.keys(Map).length, 0);
|
||||
assertEq(Map.length, 0);
|
||||
assertEq(Map.name, "Map");
|
||||
|
||||
assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype);
|
||||
assertEq(Object.prototype.toString.call(Map.prototype), "[object Map]");
|
||||
assertEq(Object.prototype.toString.call(new Map), "[object Map]");
|
||||
assertEq(Object.prototype.toString.call(Map()), "[object Map]");
|
||||
assertEq(Object.keys(Map.prototype).join(), "");
|
||||
assertEq(Map.prototype.constructor, Map);
|
||||
|
||||
function checkMethod(name, arity) {
|
||||
var desc = Object.getOwnPropertyDescriptor(Map.prototype, name);
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.writable, true);
|
||||
assertEq(typeof desc.value, 'function');
|
||||
assertEq(desc.value.name, name);
|
||||
assertEq(desc.value.length, arity);
|
||||
}
|
||||
|
||||
checkMethod("get", 1);
|
||||
checkMethod("has", 1);
|
||||
checkMethod("set", 2);
|
||||
checkMethod("delete", 1);
|
23
js/src/jit-test/tests/collections/Map-surfaces-2.js
Normal file
23
js/src/jit-test/tests/collections/Map-surfaces-2.js
Normal file
@ -0,0 +1,23 @@
|
||||
// Map methods throw when passed a this-value that isn't a Map.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
function testcase(obj, fn) {
|
||||
assertEq(typeof fn, "function");
|
||||
var args = Array.slice(arguments, 2);
|
||||
assertThrowsInstanceOf(function () { fn.apply(obj, args); }, TypeError);
|
||||
}
|
||||
|
||||
function test(obj) {
|
||||
testcase(obj, Map.prototype.get, "x");
|
||||
testcase(obj, Map.prototype.has, "x");
|
||||
testcase(obj, Map.prototype.set, "x", 1);
|
||||
testcase(obj, Map.prototype.delete, "x");
|
||||
}
|
||||
|
||||
test(Map.prototype);
|
||||
test(Object.create(new Map));
|
||||
test(new Set());
|
||||
test({});
|
||||
test(null);
|
||||
test(undefined);
|
14
js/src/jit-test/tests/collections/Map-surfaces-3.js
Normal file
14
js/src/jit-test/tests/collections/Map-surfaces-3.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Map methods work when arguments are omitted.
|
||||
|
||||
var m = new Map;
|
||||
assertEq(m.has(), false);
|
||||
assertEq(m.get(), undefined);
|
||||
assertEq(m.delete(), false);
|
||||
assertEq(m.has(), false);
|
||||
assertEq(m.get(), undefined);
|
||||
assertEq(m.set(), undefined);
|
||||
assertEq(m.has(), true);
|
||||
assertEq(m.get(), undefined);
|
||||
assertEq(m.delete(), true);
|
||||
assertEq(m.has(), false);
|
||||
assertEq(m.get(), undefined);
|
16
js/src/jit-test/tests/collections/Set-gc-1.js
Normal file
16
js/src/jit-test/tests/collections/Set-gc-1.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Check marking through the elements of a Set.
|
||||
|
||||
load(libdir + "referencesVia.js");
|
||||
|
||||
var s = new Set;
|
||||
for (var i = 0; i < 20; i++) {
|
||||
var t = new Set;
|
||||
t.add(s);
|
||||
assertEq(referencesVia(t, 'key', s), true);
|
||||
s = t;
|
||||
}
|
||||
|
||||
gc();
|
||||
gc();
|
||||
|
||||
// TODO: walk the chain and make sure it's still intact
|
8
js/src/jit-test/tests/collections/Set-scale.js
Normal file
8
js/src/jit-test/tests/collections/Set-scale.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Sets can hold at least 64K values.
|
||||
|
||||
var N = 1 << 16;
|
||||
var s = new Set;
|
||||
for (var i = 0; i < N; i++)
|
||||
assertEq(s.add(i), undefined);
|
||||
for (var i = 0; i < N; i++)
|
||||
assertEq(s.has(i), true);
|
32
js/src/jit-test/tests/collections/Set-surfaces-1.js
Normal file
32
js/src/jit-test/tests/collections/Set-surfaces-1.js
Normal file
@ -0,0 +1,32 @@
|
||||
// Set surfaces
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(this, "Set");
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.writable, true);
|
||||
|
||||
assertEq(typeof Set, 'function');
|
||||
assertEq(Object.keys(Set).length, 0);
|
||||
assertEq(Set.length, 0);
|
||||
assertEq(Set.name, "Set");
|
||||
|
||||
assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype);
|
||||
assertEq(Object.prototype.toString.call(Set.prototype), "[object Set]");
|
||||
assertEq(Object.prototype.toString.call(new Set), "[object Set]");
|
||||
assertEq(Object.prototype.toString.call(Set()), "[object Set]");
|
||||
assertEq(Object.keys(Set.prototype).join(), "");
|
||||
assertEq(Set.prototype.constructor, Set);
|
||||
|
||||
function checkMethod(name, arity) {
|
||||
var desc = Object.getOwnPropertyDescriptor(Set.prototype, name);
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.writable, true);
|
||||
assertEq(typeof desc.value, 'function');
|
||||
assertEq(desc.value.name, name);
|
||||
assertEq(desc.value.length, arity);
|
||||
}
|
||||
|
||||
checkMethod("has", 1);
|
||||
checkMethod("add", 1);
|
||||
checkMethod("delete", 1);
|
22
js/src/jit-test/tests/collections/Set-surfaces-2.js
Normal file
22
js/src/jit-test/tests/collections/Set-surfaces-2.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Set methods throw when passed a this-value that isn't a Set.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
function testcase(obj, fn) {
|
||||
assertEq(typeof fn, "function");
|
||||
var args = Array.slice(arguments, 2);
|
||||
assertThrowsInstanceOf(function () { fn.apply(obj, args); }, TypeError);
|
||||
}
|
||||
|
||||
function test(obj) {
|
||||
testcase(obj, Set.prototype.has, 12);
|
||||
testcase(obj, Set.prototype.add, 12);
|
||||
testcase(obj, Set.prototype.delete, 12);
|
||||
}
|
||||
|
||||
test(Set.prototype);
|
||||
test(Object.create(new Set));
|
||||
test(new Map());
|
||||
test({});
|
||||
test(null);
|
||||
test(undefined);
|
10
js/src/jit-test/tests/collections/Set-surfaces-3.js
Normal file
10
js/src/jit-test/tests/collections/Set-surfaces-3.js
Normal file
@ -0,0 +1,10 @@
|
||||
// Set methods work when arguments are omitted.
|
||||
|
||||
var s = new Set;
|
||||
assertEq(s.has(), false);
|
||||
assertEq(s.delete(), false);
|
||||
assertEq(s.has(), false);
|
||||
assertEq(s.add(), undefined);
|
||||
assertEq(s.has(), true);
|
||||
assertEq(s.delete(), true);
|
||||
assertEq(s.has(), false);
|
25
js/src/jit-test/tests/collections/for-in.js
Normal file
25
js/src/jit-test/tests/collections/for-in.js
Normal file
@ -0,0 +1,25 @@
|
||||
// for-in loops on Maps and Sets enumerate properties.
|
||||
|
||||
var test = function test(obj) {
|
||||
assertEq(Object.keys(obj).length, 0);
|
||||
|
||||
var i = 0, v;
|
||||
for (v in obj)
|
||||
i++;
|
||||
assertEq(i, 0);
|
||||
|
||||
obj.ownProp = 1;
|
||||
assertEq(Object.keys(obj).join(), "ownProp");
|
||||
|
||||
for (v in obj)
|
||||
i++;
|
||||
assertEq(i, 1);
|
||||
assertEq(v, "ownProp");
|
||||
|
||||
delete obj.ownProp;
|
||||
};
|
||||
|
||||
test(Map.prototype);
|
||||
test(new Map);
|
||||
test(Set.prototype);
|
||||
test(new Set);
|
37
js/src/jit-test/tests/collections/key-equality-0.js
Normal file
37
js/src/jit-test/tests/collections/key-equality-0.js
Normal file
@ -0,0 +1,37 @@
|
||||
// -0 is a distinct key from +0.
|
||||
|
||||
var s = new Set;
|
||||
s.add(-0);
|
||||
assertEq(s.has(0), false);
|
||||
assertEq(s.has(-0), true);
|
||||
|
||||
assertEq(s.delete(0), false);
|
||||
assertEq(s.has(-0), true);
|
||||
|
||||
s.add(0);
|
||||
assertEq(s.delete(-0), true);
|
||||
assertEq(s.has(0), true);
|
||||
assertEq(s.has(-0), false);
|
||||
|
||||
var m = new Map;
|
||||
m.set(-0, 'x');
|
||||
assertEq(m.has(0), false);
|
||||
assertEq(m.get(0), undefined);
|
||||
assertEq(m.has(-0), true);
|
||||
assertEq(m.get(-0), 'x');
|
||||
|
||||
assertEq(m.delete(0), false);
|
||||
assertEq(m.has(-0), true);
|
||||
assertEq(m.get(-0), 'x');
|
||||
|
||||
m.set(0, 'y');
|
||||
assertEq(m.has(0), true);
|
||||
assertEq(m.get(0), 'y');
|
||||
assertEq(m.has(-0), true);
|
||||
assertEq(m.get(-0), 'x');
|
||||
|
||||
assertEq(m.delete(-0), true);
|
||||
assertEq(m.has(0), true);
|
||||
assertEq(m.get(0), 'y');
|
||||
assertEq(m.has(-0), false);
|
||||
assertEq(m.get(-0), undefined);
|
28
js/src/jit-test/tests/collections/key-equality-1.js
Normal file
28
js/src/jit-test/tests/collections/key-equality-1.js
Normal file
@ -0,0 +1,28 @@
|
||||
// Different representations of the same number or string are treated as the same Map key.
|
||||
|
||||
var m = new Map;
|
||||
var test = function test(a, b) {
|
||||
m.set(a, 'secret');
|
||||
assertEq(m.get(b), 'secret');
|
||||
m.set(b, 'password');
|
||||
assertEq(m.get(a), 'password');
|
||||
|
||||
assertEq(a, b);
|
||||
};
|
||||
|
||||
// Float and integer representations of the same number are the same key.
|
||||
test(9, Math.sqrt(81));
|
||||
|
||||
// Ordinary strings and ropes are the same key.
|
||||
var a = Array(1001).join('x');
|
||||
var b = Array(501).join('x') + Array(501).join('x');
|
||||
test(a, b);
|
||||
|
||||
// Two structurally different ropes with the same characters are the same key.
|
||||
a = "";
|
||||
b = "";
|
||||
for (var i = 0; i < 10; i++) {
|
||||
a = Array(501).join('x') + a;
|
||||
b = b + Array(501).join('x');
|
||||
}
|
||||
test(a, b);
|
11
js/src/jit-test/tests/collections/key-equality-2.js
Normal file
11
js/src/jit-test/tests/collections/key-equality-2.js
Normal file
@ -0,0 +1,11 @@
|
||||
// Number keys are distinct from string keys that would name the same property.
|
||||
|
||||
var s = new Set;
|
||||
|
||||
s.add(17);
|
||||
assertEq(s.has("17"), false);
|
||||
assertEq(s.has(17), true);
|
||||
s.add("17");
|
||||
assertEq(s.delete(17), true);
|
||||
assertEq(s.has("17"), true);
|
||||
assertEq(s.has(17), false);
|
15
js/src/jit-test/tests/collections/key-equality-NaN.js
Normal file
15
js/src/jit-test/tests/collections/key-equality-NaN.js
Normal file
@ -0,0 +1,15 @@
|
||||
// NaN is equal to itself for the purpose of key lookups.
|
||||
|
||||
var m = new Map;
|
||||
m.set(NaN, "ok");
|
||||
assertEq(m.has(NaN), true);
|
||||
assertEq(m.get(NaN), "ok");
|
||||
assertEq(m.delete(NaN), true);
|
||||
assertEq(m.has(NaN), false);
|
||||
assertEq(m.get(NaN), undefined);
|
||||
|
||||
var s = new Set;
|
||||
s.add(NaN);
|
||||
assertEq(s.has(NaN), true);
|
||||
assertEq(s.delete(NaN), true);
|
||||
assertEq(s.has(NaN), false);
|
@ -83,6 +83,7 @@
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/RegExp.h"
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
@ -1789,6 +1790,8 @@ static JSStdName standard_class_atoms[] = {
|
||||
{js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
|
||||
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::slowClass},
|
||||
{js_InitWeakMapClass, EAGER_CLASS_ATOM(WeakMap), &js::WeakMapClass},
|
||||
{js_InitMapClass, EAGER_CLASS_ATOM(Map), &js::MapObject::class_},
|
||||
{js_InitSetClass, EAGER_CLASS_ATOM(Set), &js::SetObject::class_},
|
||||
{NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -566,6 +566,11 @@ class Value
|
||||
return data.s.payload.u32;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
uint64_t asRawBits() const {
|
||||
return data.asBits;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
JSValueType extractNonDoubleType() const {
|
||||
return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include "jswatchpoint.h"
|
||||
#include "jswrapper.h"
|
||||
|
||||
#include "builtin/MapObject.h"
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
#include "frontend/Parser.h"
|
||||
@ -6550,7 +6551,9 @@ js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (thisv.isObject()) {
|
||||
JS_ASSERT(thisv.toObject().getClass() != clasp);
|
||||
JS_ASSERT(thisv.toObject().getClass() != clasp ||
|
||||
!thisv.toObject().getProto() ||
|
||||
thisv.toObject().getProto()->getClass() != clasp);
|
||||
} else if (thisv.isString()) {
|
||||
JS_ASSERT(clasp != &StringClass);
|
||||
} else if (thisv.isNumber()) {
|
||||
|
@ -92,6 +92,8 @@ JS_PROTO(Uint8ClampedArray, 33, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Proxy, 34, js_InitProxyClass)
|
||||
JS_PROTO(AnyName, 35, js_InitNullClass)
|
||||
JS_PROTO(WeakMap, 36, js_InitWeakMapClass)
|
||||
JS_PROTO(Map, 37, js_InitMapClass)
|
||||
JS_PROTO(Set, 38, js_InitSetClass)
|
||||
|
||||
#undef XML_INIT
|
||||
#undef NAMESPACE_INIT
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "json.h"
|
||||
#include "jsweakmap.h"
|
||||
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/RegExp.h"
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
#include "vm/GlobalObject-inl.h"
|
||||
@ -321,7 +322,9 @@ GlobalObject::initStandardClasses(JSContext *cx)
|
||||
#endif
|
||||
js_InitDateClass(cx, this) &&
|
||||
js_InitWeakMapClass(cx, this) &&
|
||||
js_InitProxyClass(cx, this);
|
||||
js_InitProxyClass(cx, this) &&
|
||||
js_InitMapClass(cx, this) &&
|
||||
js_InitSetClass(cx, this);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user