Issue #1952 - m-c 1383775: Clean up function toString/toSource code, remove remnants of source decompiler

This commit is contained in:
Martok 2022-07-01 12:53:23 +02:00 • committed by roytam1
commit 85af7f6e80
24 changed files with 55 additions and 64 deletions

View file

@ -682,7 +682,7 @@ DefineUnforgeableAttributes(JSContext* cx, JS::Handle<JSObject*> obj,
// funToString ObjectOps member for interface objects.
JSString*
InterfaceObjectToString(JSContext* aCx, JS::Handle<JSObject*> aObject,
unsigned /* indent */)
bool /* isToSource */)
{
const js::Class* clasp = js::GetObjectClass(aObject);
MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp));

View file

@ -459,7 +459,7 @@ typedef bool
* that object. A null return value means OOM.
*/
typedef JSString*
(* JSFunToStringOp)(JSContext* cx, JS::HandleObject obj, unsigned indent);
(* JSFunToStringOp)(JSContext* cx, JS::HandleObject obj, bool isToSource);
/**
* Resolve a lazy property named by id in obj by defining it directly in obj.

View file

@ -326,7 +326,7 @@ class JS_FRIEND_API(BaseProxyHandler)
ESClass* cls) const;
virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const;
virtual const char* className(JSContext* cx, HandleObject proxy) const;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const;
virtual void trace(JSTracer* trc, JSObject* proxy) const;

View file

@ -115,7 +115,7 @@ BEGIN_TEST(testXDR_source)
CHECK(script);
script = FreezeThaw(cx, script);
CHECK(script);
JSString* out = JS_DecompileScript(cx, script, "testing", 0);
JSString* out = JS_DecompileScript(cx, script);
CHECK(out);
bool equal;
CHECK(JS_StringEqualsAscii(cx, out, *s, &equal));

View file

@ -4438,7 +4438,7 @@ JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
}
JS_PUBLIC_API(JSString*)
JS_DecompileScript(JSContext* cx, HandleScript script, const char* name, unsigned indent)
JS_DecompileScript(JSContext* cx, HandleScript script)
{
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
@ -4447,7 +4447,7 @@ JS_DecompileScript(JSContext* cx, HandleScript script, const char* name, unsigne
script->ensureNonLazyCanonicalFunction();
RootedFunction fun(cx, script->functionNonDelazifying());
if (fun)
return JS_DecompileFunction(cx, fun, indent);
return JS_DecompileFunction(cx, fun);
bool haveSource = script->scriptSource()->hasSourceData();
if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
return nullptr;
@ -4456,13 +4456,13 @@ JS_DecompileScript(JSContext* cx, HandleScript script, const char* name, unsigne
}
JS_PUBLIC_API(JSString*)
JS_DecompileFunction(JSContext* cx, HandleFunction fun, unsigned indent)
JS_DecompileFunction(JSContext* cx, HandleFunction fun)
{
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, fun);
return FunctionToString(cx, fun, !(indent & JS_DONT_PRETTY_PRINT));
return FunctionToString(cx, fun, /* isToSource = */ false);
}
MOZ_NEVER_INLINE static bool

View file

@ -4200,16 +4200,10 @@ CompileFunction(JSContext* cx, AutoObjectVector& envChain,
} /* namespace JS */
extern JS_PUBLIC_API(JSString*)
JS_DecompileScript(JSContext* cx, JS::Handle<JSScript*> script, const char* name, unsigned indent);
/*
* API extension: OR this into indent to avoid pretty-printing the decompiled
* source resulting from JS_DecompileFunction.
*/
#define JS_DONT_PRETTY_PRINT ((unsigned)0x8000)
JS_DecompileScript(JSContext* cx, JS::Handle<JSScript*> script);
extern JS_PUBLIC_API(JSString*)
JS_DecompileFunction(JSContext* cx, JS::Handle<JSFunction*> fun, unsigned indent);
JS_DecompileFunction(JSContext* cx, JS::Handle<JSFunction*> fun);
/*

View file

@ -377,7 +377,7 @@ extern JS_FRIEND_API(bool)
proxy_GetElements(JSContext* cx, JS::HandleObject proxy, uint32_t begin, uint32_t end,
ElementAdder* adder);
extern JS_FRIEND_API(JSString*)
proxy_FunToString(JSContext* cx, JS::HandleObject proxy, unsigned indent);
proxy_FunToString(JSContext* cx, JS::HandleObject proxy, bool isToSource);
/**
* A class of objects that return source code on demand.

View file

@ -942,24 +942,24 @@ const Class JSFunction::class_ = {
const Class* const js::FunctionClassPtr = &JSFunction::class_;
JSString*
js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
js::FunctionToString(JSContext* cx, HandleFunction fun, bool isToSource)
{
if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
return nullptr;
if (IsAsmJSModule(fun))
return AsmJSModuleToString(cx, fun, !prettyPrint);
return AsmJSModuleToString(cx, fun, isToSource);
if (IsAsmJSFunction(fun))
return AsmJSFunctionToString(cx, fun);
if (IsWrappedAsyncFunction(fun)) {
RootedFunction unwrapped(cx, GetUnwrappedAsyncFunction(fun));
return FunctionToString(cx, unwrapped, prettyPrint);
return FunctionToString(cx, unwrapped, isToSource);
}
if (IsWrappedAsyncGenerator(fun)) {
RootedFunction unwrapped(cx, GetUnwrappedAsyncGenerator(fun));
return FunctionToString(cx, unwrapped, prettyPrint);
return FunctionToString(cx, unwrapped, isToSource);
}
StringBuffer out(cx);
@ -985,9 +985,9 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
bool haveSource = fun->isInterpreted() && (fun->isClassConstructor() ||
!fun->isSelfHostedBuiltin());
// If we're not in pretty mode, put parentheses around lambda functions
// so that eval returns lambda, not function statement.
bool addParentheses = haveSource && !prettyPrint && (fun->isLambda() && !fun->isArrow());
// If we're in toSource mode, put parentheses around lambda functions so
// that eval returns lambda, not function statement.
bool addParentheses = haveSource && isToSource && (fun->isLambda() && !fun->isArrow());
if (haveSource && !script->scriptSource()->hasSourceData() &&
!JSScript::loadSource(cx, script->scriptSource(), &haveSource))
@ -1066,11 +1066,11 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
}
JSString*
fun_toStringHelper(JSContext* cx, HandleObject obj, unsigned indent)
fun_toStringHelper(JSContext* cx, HandleObject obj, bool isToSource)
{
if (!obj->is<JSFunction>()) {
if (JSFunToStringOp op = obj->getOpsFunToString())
return op(cx, obj, indent);
return op(cx, obj, isToSource);
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_INCOMPATIBLE_PROTO,
@ -1079,7 +1079,7 @@ fun_toStringHelper(JSContext* cx, HandleObject obj, unsigned indent)
}
RootedFunction fun(cx, &obj->as<JSFunction>());
return FunctionToString(cx, fun, indent != JS_DONT_PRETTY_PRINT);
return FunctionToString(cx, fun, isToSource);
}
bool
@ -1102,16 +1102,11 @@ js::fun_toString(JSContext* cx, unsigned argc, Value* vp)
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(IsFunctionObject(args.calleev()));
uint32_t indent = 0;
if (args.length() != 0 && !ToUint32(cx, args[0], &indent))
return false;
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return false;
RootedString str(cx, fun_toStringHelper(cx, obj, indent));
JSString* str = fun_toStringHelper(cx, obj, /* isToSource = */ false);
if (!str)
return false;
@ -1132,12 +1127,12 @@ fun_toSource(JSContext* cx, unsigned argc, Value* vp)
RootedString str(cx);
if (obj->isCallable())
str = fun_toStringHelper(cx, obj, JS_DONT_PRETTY_PRINT);
str = fun_toStringHelper(cx, obj, /* isToSource = */ true);
else
str = ObjectToSource(cx, obj);
if (!str)
return false;
args.rval().setString(str);
return true;
}

View file

@ -670,7 +670,7 @@ static_assert(sizeof(JSFunction) == sizeof(js::shadow::Function),
"shadow interface must match actual interface");
extern JSString*
fun_toStringHelper(JSContext* cx, js::HandleObject obj, unsigned indent);
fun_toStringHelper(JSContext* cx, js::HandleObject obj, bool isToSource);
namespace js {
@ -875,7 +875,7 @@ JSFunction::getExtendedSlot(size_t which) const
namespace js {
JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPring);
JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool isToSource);
template<XDRMode mode>
bool

View file

@ -863,7 +863,7 @@ ToDisassemblySource(JSContext* cx, HandleValue v, JSAutoByteString* bytes)
if (obj.is<JSFunction>()) {
RootedFunction fun(cx, &obj.as<JSFunction>());
JSString* str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
JSString* str = JS_DecompileFunction(cx, fun);
if (!str)
return false;
return bytes->encodeLatin1(cx, str);
@ -1972,7 +1972,7 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, StringBuffer& buf)
if (!AppendJSONProperty(buf, "text", NO_COMMA))
return false;
JSString* str = JS_DecompileScript(cx, script, nullptr, 0);
JSString* str = JS_DecompileScript(cx, script);
if (!str || !(str = StringToSource(cx, str)))
return false;

View file

@ -115,7 +115,7 @@ class JS_FRIEND_API(Wrapper) : public BaseProxyHandler
JS::IsArrayAnswer* answer) const override;
virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
unsigned indent) const override;
bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
RegExpGuard* g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy,
@ -210,7 +210,7 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
bool* bp) const override;
virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject wrapper,
unsigned indent) const override;
bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
@ -272,7 +272,8 @@ class JS_FRIEND_API(OpaqueCrossCompartmentWrapper) : public CrossCompartmentWrap
virtual bool hasInstance(JSContext* cx, HandleObject wrapper,
MutableHandleValue v, bool* bp) const override;
virtual const char* className(JSContext* cx, HandleObject wrapper) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
bool isToSource) const override;
static const OpaqueCrossCompartmentWrapper singleton;
};

View file

@ -315,7 +315,7 @@ BaseProxyHandler::className(JSContext* cx, HandleObject proxy) const
}
JSString*
BaseProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const
BaseProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const
{
if (proxy->isCallable())
return JS_NewStringCopyZ(cx, "function () {\n [native code]\n}");

View file

@ -422,12 +422,12 @@ CrossCompartmentWrapper::className(JSContext* cx, HandleObject wrapper) const
}
JSString*
CrossCompartmentWrapper::fun_toString(JSContext* cx, HandleObject wrapper, unsigned indent) const
CrossCompartmentWrapper::fun_toString(JSContext* cx, HandleObject wrapper, bool isToSource) const
{
RootedString str(cx);
{
AutoCompartment call(cx, wrappedObject(wrapper));
str = Wrapper::fun_toString(cx, wrapper, indent);
str = Wrapper::fun_toString(cx, wrapper, isToSource);
if (!str)
return nullptr;
}

View file

@ -135,7 +135,7 @@ DeadObjectProxy::className(JSContext* cx, HandleObject wrapper) const
}
JSString*
DeadObjectProxy::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const
DeadObjectProxy::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const
{
ReportDead(cx);
return nullptr;

View file

@ -47,7 +47,8 @@ class DeadObjectProxy : public BaseProxyHandler
virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const override;
virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const override;
virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
virtual bool isCallable(JSObject* obj) const override;

View file

@ -191,7 +191,7 @@ OpaqueCrossCompartmentWrapper::className(JSContext* cx,
JSString*
OpaqueCrossCompartmentWrapper::fun_toString(JSContext* cx, HandleObject proxy,
unsigned indent) const
bool isToSource) const
{
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
js_Function_str, js_toString_str, "object");

View file

@ -475,7 +475,7 @@ Proxy::className(JSContext* cx, HandleObject proxy)
}
JSString*
Proxy::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent)
Proxy::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource)
{
JS_CHECK_RECURSION(cx, return nullptr);
const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler();
@ -483,8 +483,8 @@ Proxy::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent)
BaseProxyHandler::GET, /* mayThrow = */ false);
// Do the safe thing if the policy rejects.
if (!policy.allowed())
return handler->BaseProxyHandler::fun_toString(cx, proxy, indent);
return handler->fun_toString(cx, proxy, indent);
return handler->BaseProxyHandler::fun_toString(cx, proxy, isToSource);
return handler->fun_toString(cx, proxy, isToSource);
}
bool
@ -691,9 +691,9 @@ js::proxy_GetElements(JSContext* cx, HandleObject proxy, uint32_t begin, uint32_
}
JSString*
js::proxy_FunToString(JSContext* cx, HandleObject proxy, unsigned indent)
js::proxy_FunToString(JSContext* cx, HandleObject proxy, bool isToSource)
{
return Proxy::fun_toString(cx, proxy, indent);
return Proxy::fun_toString(cx, proxy, isToSource);
}
const ClassOps js::ProxyClassOps = {

View file

@ -60,7 +60,7 @@ class Proxy
static bool getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls);
static bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer);
static const char* className(JSContext* cx, HandleObject proxy);
static JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent);
static JSString* fun_toString(JSContext* cx, HandleObject proxy, bool isToSource);
static bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g);
static bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp);

View file

@ -1257,7 +1257,7 @@ ScriptedProxyHandler::className(JSContext* cx, HandleObject proxy) const
}
JSString*
ScriptedProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const
ScriptedProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const
{
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
js_Function_str, js_toString_str, "object");

View file

@ -67,7 +67,7 @@ class ScriptedProxyHandler : public BaseProxyHandler
JS::IsArrayAnswer* answer) const override;
virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
unsigned indent) const override;
bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
RegExpGuard* g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy,

View file

@ -259,11 +259,11 @@ Wrapper::className(JSContext* cx, HandleObject proxy) const
}
JSString*
Wrapper::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const
Wrapper::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const
{
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
RootedObject target(cx, proxy->as<ProxyObject>().target());
return fun_toStringHelper(cx, target, indent);
return fun_toStringHelper(cx, target, isToSource);
}
bool

View file

@ -4577,7 +4577,7 @@ DecompileFunction(JSContext* cx, unsigned argc, Value* vp)
return true;
}
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
JSString* result = JS_DecompileFunction(cx, fun, 0);
JSString* result = JS_DecompileFunction(cx, fun);
if (!result)
return false;
args.rval().setString(result);
@ -4599,7 +4599,7 @@ DecompileThisScript(JSContext* cx, unsigned argc, Value* vp)
JSAutoCompartment ac(cx, iter.script());
RootedScript script(cx, iter.script());
JSString* result = JS_DecompileScript(cx, script, "test", 0);
JSString* result = JS_DecompileScript(cx, script);
if (!result)
return false;

View file

@ -8849,7 +8849,7 @@ js::IsAsmJSModuleLoadedFromCache(JSContext* cx, unsigned argc, Value* vp)
// asm.js toString/toSource support
JSString*
js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool addParenToLambda)
js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool isToSource)
{
MOZ_ASSERT(IsAsmJSModule(fun));
@ -8860,7 +8860,7 @@ js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool addParenToLambda
StringBuffer out(cx);
if (addParenToLambda && fun->isLambda() && !out.append("("))
if (isToSource && fun->isLambda() && !out.append("("))
return nullptr;
bool haveSource = source->hasSourceData();
@ -8883,7 +8883,7 @@ js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool addParenToLambda
return nullptr;
}
if (addParenToLambda && fun->isLambda() && !out.append(")"))
if (isToSource && fun->isLambda() && !out.append(")"))
return nullptr;
return out.finishString();

View file

@ -76,7 +76,7 @@ extern JSString*
AsmJSFunctionToString(JSContext* cx, HandleFunction fun);
extern JSString*
AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool addParenToLambda);
AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool isToSource);
// asm.js heap: