mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 03:05:34 +00:00
Bug 1271653 - Implement a C++ interface for forceLexicalInitializationByName;r=jimb
This commit is contained in:
parent
4abd87fad9
commit
0de6d7d691
@ -8620,6 +8620,47 @@ DebuggerObject_apply(JSContext* cx, unsigned argc, Value* vp)
|
||||
return object->call(cx, object, thisv, args, callArgs.rval());
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_asEnvironment(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "asEnvironment", args, dbg, referent);
|
||||
if (!RequireGlobalObject(cx, args.thisv(), referent))
|
||||
return false;
|
||||
|
||||
Rooted<Env*> env(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, referent);
|
||||
env = GetDebugScopeForGlobalLexicalScope(cx);
|
||||
if (!env)
|
||||
return false;
|
||||
}
|
||||
|
||||
return dbg->wrapEnvironment(cx, env, args.rval());
|
||||
}
|
||||
|
||||
// Lookup a binding on the referent's global scope and change it to undefined
|
||||
// if it is an uninitialized lexical, otherwise do nothing. The method's
|
||||
// JavaScript return value is true _only_ when an uninitialized lexical has been
|
||||
// altered, otherwise it is false.
|
||||
bool
|
||||
DebuggerObject_forceLexicalInitializationByName(JSContext *cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT(cx, argc, vp, "forceLexicalInitializationByName", args, object)
|
||||
if (!args.requireAtLeast(cx, "Debugger.Object.prototype.forceLexicalInitializationByName", 1))
|
||||
return false;
|
||||
|
||||
RootedId id(cx);
|
||||
if (!ValueToIdentifier(cx, args[0], &id))
|
||||
return false;
|
||||
|
||||
bool result;
|
||||
if (!DebuggerObject::forceLexicalInitializationByName(cx, object, id, result))
|
||||
return false;
|
||||
|
||||
args.rval().setBoolean(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_executeInGlobal(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
@ -8697,67 +8738,6 @@ DebuggerObject_makeDebuggeeValue(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lookup a binding on the referent's global scope and change it to undefined
|
||||
// if it is an uninitialized lexical, otherwise do nothing. The method's return
|
||||
// value is true _only_ when an uninitialized lexical has been altered, otherwise
|
||||
// it is false.
|
||||
bool
|
||||
DebuggerObject_forceLexicalInitializationByName(JSContext *cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "forceLexicalInitializationByname", args, referent);
|
||||
if (!args.requireAtLeast(cx, "Debugger.Object.prototype.forceLexicalInitializationByName", 1))
|
||||
return false;
|
||||
if (!RequireGlobalObject(cx, args.thisv(), referent))
|
||||
return false;
|
||||
|
||||
RootedObject globalLexical(cx, &referent->as<GlobalObject>().lexicalScope());
|
||||
|
||||
if (!args[0].isString()) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_NOT_EXPECTED_TYPE, "Debugger.Object.prototype.forceLexicalInitializationByName",
|
||||
"string", InformalValueTypeName(args[0]));
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedId id(cx);
|
||||
if (!ValueToIdentifier(cx, args[0], &id))
|
||||
return false;
|
||||
|
||||
RootedObject pobj(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!LookupProperty(cx, globalLexical, id, &pobj, &shape))
|
||||
return false;
|
||||
|
||||
bool initialized = false;
|
||||
if (shape) {
|
||||
Value v = globalLexical->as<NativeObject>().getSlot(shape->slot());
|
||||
if (shape->hasSlot() && v.isMagic() && v.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
|
||||
globalLexical->as<NativeObject>().setSlot(shape->slot(), UndefinedValue());
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
args.rval().setBoolean(initialized);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_asEnvironment(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "asEnvironment", args, dbg, referent);
|
||||
if (!RequireGlobalObject(cx, args.thisv(), referent))
|
||||
return false;
|
||||
|
||||
Rooted<Env*> env(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, referent);
|
||||
env = GetDebugScopeForGlobalLexicalScope(cx);
|
||||
if (!env)
|
||||
return false;
|
||||
}
|
||||
|
||||
return dbg->wrapEnvironment(cx, env, args.rval());
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_unwrap(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
@ -8833,7 +8813,6 @@ const JSPropertySpec DebuggerObject::promiseProperties_[] = {
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
const JSFunctionSpec DebuggerObject::methods_[] = {
|
||||
JS_FN("forceLexicalInitializationByName", DebuggerObject_forceLexicalInitializationByName, 1, 0),
|
||||
JS_FN("isExtensible", DebuggerObject_isExtensible, 0, 0),
|
||||
JS_FN("isSealed", DebuggerObject_isSealed, 0, 0),
|
||||
JS_FN("isFrozen", DebuggerObject_isFrozen, 0, 0),
|
||||
@ -8848,10 +8827,11 @@ const JSFunctionSpec DebuggerObject::methods_[] = {
|
||||
JS_FN("deleteProperty", DebuggerObject_deleteProperty, 1, 0),
|
||||
JS_FN("call", DebuggerObject_call, 0, 0),
|
||||
JS_FN("apply", DebuggerObject_apply, 0, 0),
|
||||
JS_FN("asEnvironment", DebuggerObject_asEnvironment, 0, 0),
|
||||
JS_FN("forceLexicalInitializationByName", DebuggerObject_forceLexicalInitializationByName, 1, 0),
|
||||
JS_FN("executeInGlobal", DebuggerObject_executeInGlobal, 1, 0),
|
||||
JS_FN("executeInGlobalWithBindings", DebuggerObject_executeInGlobalWithBindings, 2, 0),
|
||||
JS_FN("makeDebuggeeValue", DebuggerObject_makeDebuggeeValue, 1, 0),
|
||||
JS_FN("asEnvironment", DebuggerObject_asEnvironment, 0, 0),
|
||||
JS_FN("unwrap", DebuggerObject_unwrap, 0, 0),
|
||||
JS_FN("unsafeDereference", DebuggerObject_unsafeDereference, 0, 0),
|
||||
JS_FS_END
|
||||
@ -9183,23 +9163,96 @@ DebuggerObject::call(JSContext* cx, Handle<DebuggerObject*> object, HandleValue
|
||||
return dbg->receiveCompletionValue(ac, ok, result, result);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::forceLexicalInitializationByName(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
HandleId id, bool& result)
|
||||
{
|
||||
if (!DebuggerObject::requireGlobalObject(cx, object))
|
||||
return false;
|
||||
|
||||
if (!JSID_IS_STRING(id)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_NOT_EXPECTED_TYPE, "Debugger.Object.prototype.forceLexicalInitializationByName",
|
||||
"string", InformalValueTypeName(IdToValue(id)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
RootedObject referent(cx, object->referent());
|
||||
|
||||
RootedObject globalLexical(cx, &referent->as<GlobalObject>().lexicalScope());
|
||||
|
||||
RootedObject pobj(cx);
|
||||
RootedShape shape(cx);
|
||||
if (!LookupProperty(cx, globalLexical, id, &pobj, &shape))
|
||||
return false;
|
||||
|
||||
result = false;
|
||||
if (shape) {
|
||||
Value v = globalLexical->as<NativeObject>().getSlot(shape->slot());
|
||||
if (shape->hasSlot() && v.isMagic() && v.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
|
||||
globalLexical->as<NativeObject>().setSlot(shape->slot(), UndefinedValue());
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
mozilla::Range<const char16_t> chars, HandleObject bindings,
|
||||
const EvalOptions& options, MutableHandleValue result)
|
||||
{
|
||||
if (!DebuggerObject::requireGlobalObject(cx, object))
|
||||
return false;
|
||||
|
||||
RootedObject referent(cx, object->referent());
|
||||
Debugger* dbg = object->owner();
|
||||
|
||||
RootedValue dbgobj(cx, ObjectValue(*object));
|
||||
if (!RequireGlobalObject(cx, dbgobj, referent))
|
||||
return false;
|
||||
RootedObject globalLexical(cx, &referent->as<GlobalObject>().lexicalScope());
|
||||
|
||||
return DebuggerGenericEval(cx, chars, bindings, options, result, dbg, globalLexical,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::requireGlobalObject(JSContext* cx, Handle<DebuggerObject*> object)
|
||||
{
|
||||
RootedObject referent(cx, object->referent());
|
||||
|
||||
if (!referent->is<GlobalObject>()) {
|
||||
const char* isWrapper = "";
|
||||
const char* isWindowProxy = "";
|
||||
|
||||
/* Help the poor programmer by pointing out wrappers around globals... */
|
||||
if (referent->is<WrapperObject>()) {
|
||||
referent = js::UncheckedUnwrap(referent);
|
||||
isWrapper = "a wrapper around ";
|
||||
}
|
||||
|
||||
/* ... and WindowProxies around Windows. */
|
||||
if (IsWindowProxy(referent)) {
|
||||
referent = ToWindowIfWindowProxy(referent);
|
||||
isWindowProxy = "a WindowProxy referring to ";
|
||||
}
|
||||
|
||||
RootedValue dbgobj(cx, ObjectValue(*object));
|
||||
if (referent->is<GlobalObject>()) {
|
||||
ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_WRAPPER_IN_WAY,
|
||||
JSDVG_SEARCH_STACK, dbgobj, nullptr,
|
||||
isWrapper, isWindowProxy);
|
||||
} else {
|
||||
ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_BAD_REFERENT,
|
||||
JSDVG_SEARCH_STACK, dbgobj, nullptr,
|
||||
"a global object", nullptr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*** Debugger.Environment ************************************************************************/
|
||||
|
||||
|
@ -1071,6 +1071,8 @@ class DebuggerObject : public NativeObject
|
||||
ObjectOpResult& result);
|
||||
static bool call(JSContext* cx, Handle<DebuggerObject*> object, HandleValue thisv,
|
||||
Handle<ValueVector> args, MutableHandleValue result);
|
||||
static bool forceLexicalInitializationByName(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
HandleId id, bool& result);
|
||||
static bool executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
mozilla::Range<const char16_t> chars, HandleObject bindings,
|
||||
const EvalOptions& options, MutableHandleValue result);
|
||||
@ -1088,6 +1090,8 @@ class DebuggerObject : public NativeObject
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
static const JSFunctionSpec methods_[];
|
||||
|
||||
static bool requireGlobalObject(JSContext* cx, Handle<DebuggerObject*> object);
|
||||
|
||||
JSObject* referent() const {
|
||||
JSObject* obj = (JSObject*) getPrivate();
|
||||
MOZ_ASSERT(obj);
|
||||
|
Loading…
Reference in New Issue
Block a user