Bug 1067459 - Only install a small subset of the standard builtins in the self-hosting global. r=jorendorff

This commit is contained in:
Till Schneidereit 2014-09-16 10:01:09 -04:00
parent 5184091514
commit 276cd0a709
24 changed files with 323 additions and 169 deletions

View File

@ -2055,17 +2055,12 @@ js_InitIntlClass(JSContext *cx, HandleObject obj)
if (!JS_DefineFunctions(cx, Intl, intl_static_methods))
return nullptr;
// Skip initialization of the Intl constructors during initialization of the
// self-hosting global as we may get here before self-hosted code is compiled,
// and no core code refers to the Intl classes.
if (!cx->runtime()->isSelfHostingGlobal(cx->global())) {
if (!InitCollatorClass(cx, Intl, global))
return nullptr;
if (!InitNumberFormatClass(cx, Intl, global))
return nullptr;
if (!InitDateTimeFormatClass(cx, Intl, global))
return nullptr;
}
if (!InitCollatorClass(cx, Intl, global))
return nullptr;
if (!InitNumberFormatClass(cx, Intl, global))
return nullptr;
if (!InitDateTimeFormatClass(cx, Intl, global))
return nullptr;
global->setConstructor(JSProto_Intl, ObjectValue(*Intl));

View File

@ -1274,7 +1274,7 @@ function InitializeCollator(collator, locales, options) {
// Step 13, unrolled.
var numericValue = GetOption(options, "numeric", "boolean", undefined, undefined);
if (numericValue !== undefined)
numericValue = callFunction(std_Boolean_toString, numericValue);
numericValue = numericValue ? 'true' : 'false';
opt.kn = numericValue;
var caseFirstValue = GetOption(options, "caseFirst", "string", ["upper", "lower", "false"], undefined);

View File

@ -849,6 +849,7 @@ class MapIteratorObject : public JSObject
static const JSFunctionSpec methods[];
static MapIteratorObject *create(JSContext *cx, HandleObject mapobj, ValueMap *data,
MapObject::IteratorKind kind);
static bool next(JSContext *cx, unsigned argc, Value *vp);
static void finalize(FreeOp *fop, JSObject *obj);
private:
@ -856,7 +857,6 @@ class MapIteratorObject : public JSObject
inline ValueMap::Range *range();
inline MapObject::IteratorKind kind() const;
static bool next_impl(JSContext *cx, CallArgs args);
static bool next(JSContext *cx, unsigned argc, Value *vp);
};
} /* anonymous namespace */
@ -1157,7 +1157,8 @@ WriteBarrierPost(JSRuntime *rt, ValueSet *set, const Value &key)
}
bool
MapObject::entries(JSContext *cx, HandleObject obj, JS::AutoValueVector *entries)
MapObject::getKeysAndValuesInterleaved(JSContext *cx, HandleObject obj,
JS::AutoValueVector *entries)
{
ValueMap *map = obj->as<MapObject>().getData();
if (!map)
@ -1497,6 +1498,7 @@ class SetIteratorObject : public JSObject
static const JSFunctionSpec methods[];
static SetIteratorObject *create(JSContext *cx, HandleObject setobj, ValueSet *data,
SetObject::IteratorKind kind);
static bool next(JSContext *cx, unsigned argc, Value *vp);
static void finalize(FreeOp *fop, JSObject *obj);
private:
@ -1504,7 +1506,6 @@ class SetIteratorObject : public JSObject
inline ValueSet::Range *range();
inline SetObject::IteratorKind kind() const;
static bool next_impl(JSContext *cx, CallArgs args);
static bool next(JSContext *cx, unsigned argc, Value *vp);
};
} /* anonymous namespace */
@ -1966,3 +1967,15 @@ js_InitSetClass(JSContext *cx, HandleObject obj)
{
return SetObject::initClass(cx, obj);
}
const JSFunctionSpec selfhosting_collection_iterator_methods[] = {
JS_FN("std_Map_iterator_next", MapIteratorObject::next, 0, 0),
JS_FN("std_Set_iterator_next", SetIteratorObject::next, 0, 0),
JS_FS_END
};
bool
js::InitSelfHostingCollectionIteratorFunctions(JSContext *cx, HandleObject obj)
{
return JS_DefineFunctions(cx, obj, selfhosting_collection_iterator_methods);
}

View File

@ -92,9 +92,11 @@ class MapObject : public JSObject {
static JSObject *initClass(JSContext *cx, JSObject *obj);
static const Class class_;
// Entries is every key followed by value.
static bool entries(JSContext *cx, HandleObject obj, JS::AutoValueVector *entries);
static bool getKeysAndValuesInterleaved(JSContext *cx, HandleObject obj,
JS::AutoValueVector *entries);
static bool entries(JSContext *cx, unsigned argc, Value *vp);
static bool set(JSContext *cx, HandleObject obj, HandleValue key, HandleValue value);
static bool has(JSContext *cx, unsigned argc, Value *vp);
static MapObject* create(JSContext *cx);
private:
@ -115,7 +117,6 @@ class MapObject : public JSObject {
static bool get_impl(JSContext *cx, CallArgs args);
static bool get(JSContext *cx, unsigned argc, Value *vp);
static bool has_impl(JSContext *cx, CallArgs args);
static bool has(JSContext *cx, unsigned argc, Value *vp);
static bool set_impl(JSContext *cx, CallArgs args);
static bool set(JSContext *cx, unsigned argc, Value *vp);
static bool delete_impl(JSContext *cx, CallArgs args);
@ -125,7 +126,6 @@ class MapObject : public JSObject {
static bool values_impl(JSContext *cx, CallArgs args);
static bool values(JSContext *cx, unsigned argc, Value *vp);
static bool entries_impl(JSContext *cx, CallArgs args);
static bool entries(JSContext *cx, unsigned argc, Value *vp);
static bool clear_impl(JSContext *cx, CallArgs args);
static bool clear(JSContext *cx, unsigned argc, Value *vp);
};
@ -137,7 +137,9 @@ class SetObject : public JSObject {
static const Class class_;
static bool keys(JSContext *cx, HandleObject obj, JS::AutoValueVector *keys);
static bool values(JSContext *cx, unsigned argc, Value *vp);
static bool add(JSContext *cx, HandleObject obj, HandleValue key);
static bool has(JSContext *cx, unsigned argc, Value *vp);
static SetObject* create(JSContext *cx);
private:
@ -156,19 +158,20 @@ class SetObject : public JSObject {
static bool size_impl(JSContext *cx, CallArgs args);
static bool size(JSContext *cx, unsigned argc, Value *vp);
static bool has_impl(JSContext *cx, CallArgs args);
static bool has(JSContext *cx, unsigned argc, Value *vp);
static bool add_impl(JSContext *cx, CallArgs args);
static bool add(JSContext *cx, unsigned argc, Value *vp);
static bool delete_impl(JSContext *cx, CallArgs args);
static bool delete_(JSContext *cx, unsigned argc, Value *vp);
static bool values_impl(JSContext *cx, CallArgs args);
static bool values(JSContext *cx, unsigned argc, Value *vp);
static bool entries_impl(JSContext *cx, CallArgs args);
static bool entries(JSContext *cx, unsigned argc, Value *vp);
static bool clear_impl(JSContext *cx, CallArgs args);
static bool clear(JSContext *cx, unsigned argc, Value *vp);
};
extern bool
InitSelfHostingCollectionIteratorFunctions(JSContext *cx, js::HandleObject obj);
} /* namespace js */
extern JSObject *

View File

@ -532,8 +532,8 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp)
#endif /* JS_OLD_GETTER_SETTER_METHODS */
/* ES5 15.2.3.2. */
static bool
obj_getPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
bool
js::obj_getPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@ -703,8 +703,8 @@ obj_unwatch(JSContext *cx, unsigned argc, Value *vp)
#endif /* JS_HAS_OBJ_WATCHPOINT */
/* ECMA 15.2.4.5. */
static bool
obj_hasOwnProperty(JSContext *cx, unsigned argc, Value *vp)
bool
js::obj_hasOwnProperty(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@ -778,8 +778,8 @@ obj_isPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
}
/* ES5 15.2.3.5: Object.create(O [, Properties]) */
static bool
obj_create(JSContext *cx, unsigned argc, Value *vp)
bool
js::obj_create(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() == 0) {
@ -826,8 +826,8 @@ obj_create(JSContext *cx, unsigned argc, Value *vp)
return true;
}
static bool
obj_getOwnPropertyDescriptor(JSContext *cx, unsigned argc, Value *vp)
bool
js::obj_getOwnPropertyDescriptor(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject obj(cx);
@ -951,8 +951,8 @@ GetOwnPropertyKeys(JSContext *cx, const JS::CallArgs &args, unsigned flags)
} // namespace js
static bool
obj_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
bool
js::obj_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return GetOwnPropertyKeys(cx, args, JSITER_OWNONLY | JSITER_HIDDEN);

View File

@ -28,6 +28,22 @@ obj_construct(JSContext *cx, unsigned argc, JS::Value *vp);
bool
obj_valueOf(JSContext *cx, unsigned argc, JS::Value *vp);
// Object methods exposed so they can be installed in the self-hosting global.
bool
obj_create(JSContext *cx, unsigned argc, JS::Value *vp);
bool
obj_getOwnPropertyNames(JSContext *cx, unsigned argc, JS::Value *vp);
bool
obj_getOwnPropertyDescriptor(JSContext *cx, unsigned argc, JS::Value *vp);
bool
obj_getPrototypeOf(JSContext *cx, unsigned argc, JS::Value *vp);
bool
obj_hasOwnProperty(JSContext *cx, unsigned argc, JS::Value *vp);
// Exposed so SelfHosting.cpp can use it in the OwnPropertyKeys intrinsic
bool
GetOwnPropertyKeys(JSContext *cx, const JS::CallArgs &args, unsigned flags);

View File

@ -25,71 +25,18 @@
#include "SelfHostingDefines.h"
// Remove unsafe builtin functions.
Object.defineProperty = null; // See bug 988416.
// Cache builtin functions so using them doesn't require cloning the whole object they're
// installed on.
// All C++-implemented standard builtins library functions used in self-hosted
// code are installed via the std_functions JSFunctionSpec[] in
// SelfHosting.cpp.
//
// WARNING: Do not make std_ references to builtin constructors (like Array and
// Object) below. Setting `var std_Array = Array;`, for instance, would cause
// the entire Array constructor, including its prototype and methods, to be
// cloned into content compartments.
var std_Array_indexOf = ArrayIndexOf;
var std_Array_iterator = Array.prototype.iterator;
var std_Array_join = Array.prototype.join;
var std_Array_push = Array.prototype.push;
var std_Array_pop = Array.prototype.pop;
var std_Array_shift = Array.prototype.shift;
var std_Array_slice = Array.prototype.slice;
var std_Array_sort = Array.prototype.sort;
var std_Array_unshift = Array.prototype.unshift;
var std_Boolean_toString = Boolean.prototype.toString;
var Std_Date = Date;
var std_Date_now = Date.now;
var std_Date_valueOf = Date.prototype.valueOf;
var std_Function_bind = Function.prototype.bind;
var std_Function_apply = Function.prototype.apply;
var std_Math_floor = Math.floor;
var std_Math_max = Math.max;
var std_Math_min = Math.min;
var std_Math_abs = Math.abs;
var std_Math_imul = Math.imul;
var std_Math_log2 = Math.log2;
var std_Number_valueOf = Number.prototype.valueOf;
var std_Number_POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
var std_Object_create = Object.create;
var std_Object_getOwnPropertyNames = Object.getOwnPropertyNames;
var std_Object_hasOwnProperty = Object.prototype.hasOwnProperty;
var std_Object_getPrototypeOf = Object.getPrototypeOf;
var std_Object_getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
var std_RegExp_test = RegExp.prototype.test;
var std_String_fromCharCode = String.fromCharCode;
var std_String_charCodeAt = String.prototype.charCodeAt;
var std_String_indexOf = String.prototype.indexOf;
var std_String_lastIndexOf = String.prototype.lastIndexOf;
var std_String_match = String.prototype.match;
var std_String_replace = String.prototype.replace;
var std_String_split = String.prototype.split;
var std_String_startsWith = String.prototype.startsWith;
var std_String_substring = String.prototype.substring;
var std_String_toLowerCase = String.prototype.toLowerCase;
var std_String_toUpperCase = String.prototype.toUpperCase;
var std_WeakMap = WeakMap;
var std_WeakMap_get = WeakMap.prototype.get;
var std_WeakMap_has = WeakMap.prototype.has;
var std_WeakMap_set = WeakMap.prototype.set;
var std_WeakMap_clear = WeakMap.prototype.clear;
var std_WeakMap_delete = WeakMap.prototype.delete;
var std_Map_has = Map.prototype.has;
var std_Set_has = Set.prototype.has;
// The few items below here are either self-hosted or installing them under a
// std_Foo name would require ugly contortions, so they just get aliased here.
var std_iterator = '@@iterator'; // FIXME: Change to be a symbol.
var std_Array_indexOf = ArrayIndexOf;
// WeakMap is a bare constructor without properties or methods.
var std_WeakMap = WeakMap;
// StopIteration is a bare constructor without properties or methods.
var std_StopIteration = StopIteration;
var std_Map_iterator = Map.prototype[std_iterator];
var std_Set_iterator = Set.prototype[std_iterator];
var std_Map_iterator_next = Object.getPrototypeOf(Map()[std_iterator]()).next;
var std_Set_iterator_next = Object.getPrototypeOf(Set()[std_iterator]()).next;
/********** List specification type **********/

View File

@ -3278,15 +3278,6 @@ JS_DefineProperties(JSContext *cx, HandleObject obj, const JSPropertySpec *ps)
// native one.
JS_ASSERT(!ps->getter.propertyOp.op && !ps->setter.propertyOp.op);
JS_ASSERT(ps->flags & JSPROP_GETTER);
/*
* During creation of the self-hosting global, we ignore all
* self-hosted properties, as that means we're currently setting up
* the global object that the self-hosted code is then compiled
* in. That means that Self-hosted properties can't be used in the
* self-hosting global itself, right now.
*/
if (cx->runtime()->isSelfHostingGlobal(cx->global()))
continue;
ok = DefineSelfHostedProperty(cx, obj, ps->name,
ps->getter.selfHosted.funname,
@ -4129,15 +4120,6 @@ JS_DefineFunctions(JSContext *cx, HandleObject obj, const JSFunctionSpec *fs)
if (fs->selfHostedName) {
JS_ASSERT(!fs->call.op);
JS_ASSERT(!fs->call.info);
/*
* During creation of the self-hosting global, we ignore all
* self-hosted functions, as that means we're currently setting up
* the global object that the self-hosted code is then compiled
* in. Self-hosted functions can access each other via their names,
* but not via the builtin classes they get installed into.
*/
if (cx->runtime()->isSelfHostingGlobal(cx->global()))
continue;
RootedAtom shName(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
if (!shName)

View File

@ -2246,8 +2246,8 @@ js::array_shift(JSContext *cx, unsigned argc, Value *vp)
return SetLengthProperty(cx, obj, newlen);
}
static bool
array_unshift(JSContext *cx, unsigned argc, Value *vp)
bool
js::array_unshift(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject obj(cx, ToObject(cx, args.thisv()));
@ -2702,8 +2702,8 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
return SetLengthProperty(cx, narr, length);
}
static bool
array_slice(JSContext *cx, unsigned argc, Value *vp)
bool
js::array_slice(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@ -2981,7 +2981,7 @@ static const JSFunctionSpec array_methods[] = {
JS_FN(js_toLocaleString_str,array_toLocaleString,0,0),
/* Perl-ish methods. */
JS_FN("join", js::array_join, 1,JSFUN_GENERIC_NATIVE),
JS_FN("join", array_join, 1,JSFUN_GENERIC_NATIVE),
JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE),
JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE),
JS_FN("push", array_push, 1,JSFUN_GENERIC_NATIVE),

View File

@ -179,6 +179,12 @@ ArrayShiftMoveElements(JSObject *obj);
extern bool
array_shift(JSContext *cx, unsigned argc, js::Value *vp);
extern bool
array_unshift(JSContext *cx, unsigned argc, js::Value *vp);
extern bool
array_slice(JSContext *cx, unsigned argc, js::Value *vp);
/*
* Append the given (non-hole) value to the end of an array. The array must be
* a newborn array -- that is, one which has not been exposed to script for

View File

@ -1195,8 +1195,8 @@ NowAsMillis()
return (double) (PRMJ_Now() / PRMJ_USEC_PER_MSEC);
}
static bool
date_now(JSContext *cx, unsigned argc, Value *vp)
bool
js::date_now(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setDouble(NowAsMillis());
@ -2863,8 +2863,8 @@ date_valueOf_impl(JSContext *cx, CallArgs args)
return true;
}
static bool
date_valueOf(JSContext *cx, unsigned argc, Value *vp)
bool
js::date_valueOf(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsDate, date_valueOf_impl>(cx, args);

View File

@ -60,4 +60,15 @@ js_DateGetSeconds(JSObject *obj);
bool
js_Date(JSContext *cx, unsigned argc, JS::Value *vp);
namespace js {
/* Date methods exposed so they can be installed in the self-hosting global. */
bool
date_now(JSContext *cx, unsigned argc, JS::Value *vp);
bool
date_valueOf(JSContext *cx, unsigned argc, JS::Value *vp);
} /* namespace js */
#endif /* jsdate_h */

View File

@ -1582,8 +1582,8 @@ fun_isGenerator(JSContext *cx, unsigned argc, Value *vp)
}
/* ES5 15.3.4.5. */
static bool
fun_bind(JSContext *cx, unsigned argc, Value *vp)
bool
js::fun_bind(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);

View File

@ -536,6 +536,9 @@ fun_resolve(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject ob
extern bool
fun_toString(JSContext *cx, unsigned argc, Value *vp);
extern bool
fun_bind(JSContext *cx, unsigned argc, Value *vp);
/*
* Function extended with reserved slots for use by various kinds of functions.
* Most functions do not have these extensions, but enough do that efficient

View File

@ -2099,17 +2099,24 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto));
}
if (global->getPrototype(JSProto_StopIteration).isUndefined()) {
proto = global->createBlankPrototype(cx, &StopIterationObject::class_);
if (!proto || !JSObject::freeze(cx, proto))
return false;
return GlobalObject::initStopIterationClass(cx, global);
}
// This should use a non-JSProtoKey'd slot, but this is easier for now.
if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_StopIteration, proto, proto))
return false;
/* static */ bool
GlobalObject::initStopIterationClass(JSContext *cx, Handle<GlobalObject *> global)
{
if (!global->getPrototype(JSProto_StopIteration).isUndefined())
return true;
global->setConstructor(JSProto_StopIteration, ObjectValue(*proto));
}
RootedObject proto(cx, global->createBlankPrototype(cx, &StopIterationObject::class_));
if (!proto || !JSObject::freeze(cx, proto))
return false;
// This should use a non-JSProtoKey'd slot, but this is easier for now.
if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_StopIteration, proto, proto))
return false;
global->setConstructor(JSProto_StopIteration, ObjectValue(*proto));
return true;
}

View File

@ -136,7 +136,8 @@ FinishObjectClassInit(JSContext *cx, JS::HandleObject ctor, JS::HandleObject pro
self->setOriginalEval(evalobj);
RootedObject intrinsicsHolder(cx);
if (cx->runtime()->isSelfHostingGlobal(self)) {
bool isSelfHostingGlobal = cx->runtime()->isSelfHostingGlobal(self);
if (isSelfHostingGlobal) {
intrinsicsHolder = self;
} else {
intrinsicsHolder = NewObjectWithGivenProto(cx, &JSObject::class_, proto, self,
@ -158,8 +159,10 @@ FinishObjectClassInit(JSContext *cx, JS::HandleObject ctor, JS::HandleObject pro
* Define self-hosted functions after setting the intrinsics holder
* (which is needed to define self-hosted functions)
*/
if (!JS_DefineFunctions(cx, ctor, object_static_selfhosted_methods))
return false;
if (!isSelfHostingGlobal) {
if (!JS_DefineFunctions(cx, ctor, object_static_selfhosted_methods))
return false;
}
/*
* The global object should have |Object.prototype| as its [[Prototype]].

View File

@ -627,8 +627,8 @@ DoSubstr(JSContext *cx, JSString *str, size_t begin, size_t len)
return NewDependentString(cx, str, begin, len);
}
static bool
str_substring(JSContext *cx, unsigned argc, Value *vp)
bool
js::str_substring(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@ -755,8 +755,8 @@ ToLowerCaseHelper(JSContext *cx, CallReceiver call)
return true;
}
static bool
str_toLowerCase(JSContext *cx, unsigned argc, Value *vp)
bool
js::str_toLowerCase(JSContext *cx, unsigned argc, Value *vp)
{
return ToLowerCaseHelper(cx, CallArgsFromVp(argc, vp));
}
@ -906,8 +906,8 @@ ToUpperCaseHelper(JSContext *cx, CallReceiver call)
return true;
}
static bool
str_toUpperCase(JSContext *cx, unsigned argc, Value *vp)
bool
js::str_toUpperCase(JSContext *cx, unsigned argc, Value *vp)
{
return ToUpperCaseHelper(cx, CallArgsFromVp(argc, vp));
}
@ -1653,8 +1653,8 @@ str_contains(JSContext *cx, unsigned argc, Value *vp)
}
/* ES6 20120927 draft 15.5.4.7. */
static bool
str_indexOf(JSContext *cx, unsigned argc, Value *vp)
bool
js::str_indexOf(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@ -1726,8 +1726,8 @@ LastIndexOfImpl(const TextChar *text, size_t textLen, const PatChar *pat, size_t
return -1;
}
static bool
str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
bool
js::str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedString textstr(cx, ThisToStringForStringProto(cx, args));
@ -1820,8 +1820,8 @@ HasSubstringAt(JSLinearString *text, JSLinearString *pat, size_t start)
}
/* ES6 20131108 draft 21.1.3.18. */
static bool
str_startsWith(JSContext *cx, unsigned argc, Value *vp)
bool
js::str_startsWith(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);

View File

@ -300,6 +300,26 @@ str_fromCharCode(JSContext *cx, unsigned argc, Value *vp);
extern bool
str_fromCharCode_one_arg(JSContext *cx, HandleValue code, MutableHandleValue rval);
/* String methods exposed so they can be installed in the self-hosting global. */
extern bool
str_indexOf(JSContext *cx, unsigned argc, Value *vp);
extern bool
str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp);
extern bool
str_startsWith(JSContext *cx, unsigned argc, Value *vp);
extern bool
str_substring(JSContext *cx, unsigned argc, Value *vp);
extern bool
str_toLowerCase(JSContext *cx, unsigned argc, Value *vp);
extern bool
str_toUpperCase(JSContext *cx, unsigned argc, Value *vp);
} /* namespace js */
extern bool

View File

@ -238,8 +238,8 @@ WeakMap_has_impl(JSContext *cx, 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);
@ -259,8 +259,8 @@ WeakMap_clear_impl(JSContext *cx, CallArgs args)
return true;
}
static bool
WeakMap_clear(JSContext *cx, unsigned argc, Value *vp)
bool
js::WeakMap_clear(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsWeakMap, WeakMap_clear_impl>(cx, args);
@ -291,8 +291,8 @@ WeakMap_get_impl(JSContext *cx, CallArgs args)
return true;
}
static bool
WeakMap_get(JSContext *cx, unsigned argc, Value *vp)
bool
js::WeakMap_get(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsWeakMap, WeakMap_get_impl>(cx, args);
@ -324,8 +324,8 @@ WeakMap_delete_impl(JSContext *cx, 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);
@ -433,8 +433,8 @@ WeakMap_set_impl(JSContext *cx, CallArgs args)
return true;
}
static bool
WeakMap_set(JSContext *cx, unsigned argc, Value *vp)
bool
js::WeakMap_set(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsWeakMap, WeakMap_set_impl>(cx, args);
@ -570,8 +570,8 @@ static const JSFunctionSpec weak_map_methods[] = {
JS_FS_END
};
JSObject *
js_InitWeakMapClass(JSContext *cx, HandleObject obj)
static JSObject *
InitWeakMapClass(JSContext *cx, HandleObject obj, bool defineMembers)
{
JS_ASSERT(obj->isNative());
@ -589,11 +589,25 @@ js_InitWeakMapClass(JSContext *cx, HandleObject obj)
if (!LinkConstructorAndPrototype(cx, ctor, weakMapProto))
return nullptr;
if (!DefinePropertiesAndFunctions(cx, weakMapProto, nullptr, weak_map_methods))
return nullptr;
if (defineMembers) {
if (!DefinePropertiesAndFunctions(cx, weakMapProto, nullptr, weak_map_methods))
return nullptr;
}
if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakMap, ctor, weakMapProto))
return nullptr;
return weakMapProto;
}
JSObject *
js_InitWeakMapClass(JSContext *cx, HandleObject obj)
{
return InitWeakMapClass(cx, obj, true);
}
JSObject *
js::InitBareWeakMapCtor(JSContext *cx, HandleObject obj)
{
return InitWeakMapClass(cx, obj, false);
}

View File

@ -279,6 +279,26 @@ protected:
}
};
/* 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 bool
WeakMap_clear(JSContext *cx, unsigned argc, Value *vp);
} /* namespace js */
extern JSObject *

View File

@ -284,6 +284,57 @@ GlobalObject::initStandardClasses(JSContext *cx, Handle<GlobalObject*> global)
return true;
}
/**
* Initializes a builtin constructor and its prototype without defining any
* properties or functions on it.
*
* Used in self-hosting to install the few builtin constructors required by
* self-hosted builtins.
*/
static bool
InitBareBuiltinCtor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey protoKey)
{
MOZ_ASSERT(cx->runtime()->isSelfHostingGlobal(global));
const Class *clasp = ProtoKeyToClass(protoKey);
RootedObject proto(cx);
proto = clasp->spec.createPrototype(cx, protoKey);
if (!proto)
return false;
RootedObject ctor(cx, clasp->spec.createConstructor(cx, protoKey));
if (!ctor)
return false;
return GlobalObject::initBuiltinConstructor(cx, global, protoKey, ctor, proto);
}
/**
* The self-hosting global only gets a small subset of all standard classes.
* Even those are only created as bare constructors without any properties
* or functions.
*/
/* static */ bool
GlobalObject::initSelfHostingBuiltins(JSContext *cx, Handle<GlobalObject*> global,
const JSFunctionSpec *builtins)
{
/* Define a top-level property 'undefined' with the undefined value. */
if (!JSObject::defineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT | JSPROP_READONLY))
{
return false;
}
return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&
InitBareBuiltinCtor(cx, global, JSProto_Uint32Array) &&
InitBareWeakMapCtor(cx, global) &&
initStopIterationClass(cx, global) &&
InitSelfHostingCollectionIteratorFunctions(cx, global) &&
JS_DefineFunctions(cx, global, builtins);
}
/* static */ bool
GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx, Handle<GlobalObject*> global)
{

View File

@ -611,6 +611,7 @@ class GlobalObject : public JSObject
// Implemented in jsiter.cpp.
static bool initIteratorClasses(JSContext *cx, Handle<GlobalObject*> global);
static bool initStopIterationClass(JSContext *cx, Handle<GlobalObject*> global);
// Implemented in builtin/MapObject.cpp.
static bool initMapIteratorProto(JSContext *cx, Handle<GlobalObject*> global);
@ -626,6 +627,8 @@ class GlobalObject : public JSObject
static bool initTypedObjectModule(JSContext *cx, Handle<GlobalObject*> global);
static bool initStandardClasses(JSContext *cx, Handle<GlobalObject*> global);
static bool initSelfHostingBuiltins(JSContext *cx, Handle<GlobalObject*> global,
const JSFunctionSpec *builtins);
typedef js::Vector<js::Debugger *, 0, js::SystemAllocPolicy> DebuggerVector;

View File

@ -8,9 +8,11 @@
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsdate.h"
#include "jsfriendapi.h"
#include "jshashutil.h"
#include "jsobj.h"
#include "jsweakmap.h"
#include "jswrapper.h"
#include "selfhosted.out.h"
@ -803,7 +805,72 @@ js::intrinsic_IsConstructing(JSContext *cx, unsigned argc, Value *vp)
return true;
}
// The self-hosting global isn't initialized with the normal set of builtins.
// Instead, individual C++-implemented functions that're required by
// self-hosted code are defined as global functions. Accessing these
// functions via a content compartment's builtins would be unsafe, because
// content script might have changed the builtins' prototypes' members.
// Installing the whole set of builtins in the self-hosting compartment, OTOH,
// would be wasteful: it increases memory usage and initialization time for
// self-hosting compartment.
//
// Additionally, a set of C++-implemented helper functions is defined on the
// self-hosting global.
static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("std_Array_join", array_join, 1,0),
JS_FN("std_Array_push", array_push, 1,0),
JS_FN("std_Array_pop", array_pop, 0,0),
JS_FN("std_Array_shift", array_shift, 0,0),
JS_FN("std_Array_unshift", array_unshift, 1,0),
JS_FN("std_Array_slice", array_slice, 2,0),
JS_FN("std_Array_sort", array_sort, 1,0),
JS_FN("std_Date_now", date_now, 0,0),
JS_FN("std_Date_valueOf", date_valueOf, 0,0),
JS_FN("std_Function_bind", fun_bind, 1,0),
JS_FN("std_Function_apply", js_fun_apply, 1,0),
JS_FN("std_Math_floor", math_floor, 1,0),
JS_FN("std_Math_max", math_max, 2,0),
JS_FN("std_Math_min", math_min, 2,0),
JS_FN("std_Math_abs", math_abs, 1,0),
JS_FN("std_Math_imul", math_imul, 2,0),
JS_FN("std_Math_log2", math_log2, 1,0),
JS_FN("std_Map_has", MapObject::has, 1,0),
JS_FN("std_Map_iterator", MapObject::entries, 0,0),
JS_FN("std_Number_valueOf", js_num_valueOf, 0,0),
JS_FN("std_Object_create", obj_create, 2,0),
JS_FN("std_Object_getPrototypeOf", obj_getPrototypeOf, 1,0),
JS_FN("std_Object_getOwnPropertyNames", obj_getOwnPropertyNames, 1,0),
JS_FN("std_Object_getOwnPropertyDescriptor", obj_getOwnPropertyDescriptor, 2,0),
JS_FN("std_Object_hasOwnProperty", obj_hasOwnProperty, 2,0),
JS_FN("std_Set_has", SetObject::has, 1,0),
JS_FN("std_Set_iterator", SetObject::values, 0,0),
JS_FN("std_String_fromCharCode", str_fromCharCode, 1,0),
JS_FN("std_String_charCodeAt", js_str_charCodeAt, 1,0),
JS_FN("std_String_indexOf", str_indexOf, 1,0),
JS_FN("std_String_lastIndexOf", str_lastIndexOf, 1,0),
JS_FN("std_String_match", str_match, 1,0),
JS_FN("std_String_replace", str_replace, 2,0),
JS_FN("std_String_split", str_split, 2,0),
JS_FN("std_String_startsWith", str_startsWith, 2,0),
JS_FN("std_String_substring", str_substring, 2,0),
JS_FN("std_String_toLowerCase", str_toLowerCase, 0,0),
JS_FN("std_String_toUpperCase", str_toUpperCase, 0,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_WeakMap_clear", WeakMap_clear, 0,0),
// Helper funtions after this point.
JS_FN("ToObject", intrinsic_ToObject, 1,0),
JS_FN("IsObject", intrinsic_IsObject, 1,0),
JS_FN("ToInteger", intrinsic_ToInteger, 1,0),
@ -1013,15 +1080,8 @@ JSRuntime::initSelfHosting(JSContext *cx)
Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
selfHostingGlobal_->compartment()->isSelfHosting = true;
selfHostingGlobal_->compartment()->isSystem = true;
/*
* During initialization of standard classes for the self-hosting global,
* all self-hosted functions are ignored. Thus, we don't create cyclic
* dependencies in the order of initialization.
*/
if (!GlobalObject::initStandardClasses(cx, shg))
return false;
if (!JS_DefineFunctions(cx, shg, intrinsic_functions))
if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions))
return false;
JS_FireOnNewGlobalObject(cx, shg);

View File

@ -976,7 +976,7 @@ JSStructuredCloneWriter::traverseMap(HandleObject obj)
RootedObject unwrapped(context(), CheckedUnwrap(obj));
MOZ_ASSERT(unwrapped);
JSAutoCompartment ac(context(), unwrapped);
if (!MapObject::entries(context(), unwrapped, &newEntries))
if (!MapObject::getKeysAndValuesInterleaved(context(), unwrapped, &newEntries))
return false;
}
if (!context()->compartment()->wrap(context(), newEntries))