Bug 1212794 - Remove decompile-body functionality. r=till

This commit is contained in:
Tom Schuster 2015-10-13 23:43:14 +02:00
parent f6dde272fb
commit 7de30b64ba
12 changed files with 37 additions and 84 deletions

View File

@ -1,4 +0,0 @@
// Binary: cache/js-dbg-64-462106f027af-linux
// Flags:
//
decompileBody(function () { });

View File

@ -2,12 +2,10 @@ var f = Function("a", "b", "return a + b;");
assertEq(f.toString(), "function anonymous(a, b) {\nreturn a + b;\n}"); assertEq(f.toString(), "function anonymous(a, b) {\nreturn a + b;\n}");
assertEq(f.toSource(), "(function anonymous(a, b) {\nreturn a + b;\n})"); assertEq(f.toSource(), "(function anonymous(a, b) {\nreturn a + b;\n})");
assertEq(decompileFunction(f), f.toString()); assertEq(decompileFunction(f), f.toString());
assertEq(decompileBody(f), "return a + b;");
f = Function("a", "...rest", "return rest[42] + b;"); f = Function("a", "...rest", "return rest[42] + b;");
assertEq(f.toString(), "function anonymous(a, ...rest) {\nreturn rest[42] + b;\n}"); assertEq(f.toString(), "function anonymous(a, ...rest) {\nreturn rest[42] + b;\n}");
assertEq(f.toSource(), "(function anonymous(a, ...rest) {\nreturn rest[42] + b;\n})") assertEq(f.toSource(), "(function anonymous(a, ...rest) {\nreturn rest[42] + b;\n})")
assertEq(decompileFunction(f), f.toString()); assertEq(decompileFunction(f), f.toString());
assertEq(decompileBody(f), "return rest[42] + b;");
f = Function(""); f = Function("");
assertEq(f.toString(), "function anonymous() {\n\n}"); assertEq(f.toString(), "function anonymous() {\n\n}");
f = Function("", "(abc)"); f = Function("", "(abc)");

View File

@ -2,7 +2,6 @@ function f1(foo, bar) foo + bar;
assertEq(f1.toString(), "function f1(foo, bar) foo + bar"); assertEq(f1.toString(), "function f1(foo, bar) foo + bar");
assertEq(f1.toString(), f1.toSource()); assertEq(f1.toString(), f1.toSource());
assertEq(decompileFunction(f1), f1.toString()); assertEq(decompileFunction(f1), f1.toString());
assertEq(decompileBody(f1), "foo + bar;");
// No semicolon on purpose // No semicolon on purpose
function f2(foo, bar) foo + bar function f2(foo, bar) foo + bar
assertEq(f2.toString(), "function f2(foo, bar) foo + bar"); assertEq(f2.toString(), "function f2(foo, bar) foo + bar");

View File

@ -4,4 +4,4 @@ function getgen() {
var gen; var gen;
(getgen() for (x of [1])).next(); (getgen() for (x of [1])).next();
assertEq(gen.toSource(), "function genexp() {\n [generator expression]\n}"); assertEq(gen.toSource(), "function genexp() {\n [generator expression]\n}");
assertEq(decompileBody(gen), "\n [generator expression]\n"); assertEq(gen.toString(), gen.toSource());

View File

@ -2,14 +2,11 @@ var f1 = function f0(a, b) { return a + b; }
assertEq(f1.toSource(), "(function f0(a, b) { return a + b; })"); assertEq(f1.toSource(), "(function f0(a, b) { return a + b; })");
assertEq(f1.toString(), "function f0(a, b) { return a + b; }"); assertEq(f1.toString(), "function f0(a, b) { return a + b; }");
assertEq(decompileFunction(f1), f1.toString()); assertEq(decompileFunction(f1), f1.toString());
assertEq(decompileBody(f1), " return a + b; ");
var f2 = function (a, b) { return a + b; }; var f2 = function (a, b) { return a + b; };
assertEq(f2.toSource(), "(function (a, b) { return a + b; })"); assertEq(f2.toSource(), "(function (a, b) { return a + b; })");
assertEq(f2.toString(), "function (a, b) { return a + b; }"); assertEq(f2.toString(), "function (a, b) { return a + b; }");
assertEq(decompileFunction(f2), f2.toString()); assertEq(decompileFunction(f2), f2.toString());
assertEq(decompileBody(f2), " return a + b; ");
var f3 = (function (a, b) { return a + b; }); var f3 = (function (a, b) { return a + b; });
assertEq(f3.toSource(), "(function (a, b) { return a + b; })"); assertEq(f3.toSource(), "(function (a, b) { return a + b; })");
assertEq(f3.toString(), "function (a, b) { return a + b; }"); assertEq(f3.toString(), "function (a, b) { return a + b; }");
assertEq(decompileFunction(f3), f3.toString()); assertEq(decompileFunction(f3), f3.toString());
assertEq(decompileBody(f3), " return a + b; ");

View File

@ -7,7 +7,5 @@ function f2(a, /* ))))pernicious comment */ b,
c, // another comment(( c, // another comment((
d) {} d) {}
assertEq(f2.toString(), "function f2(a, /* ))))pernicious comment */ b,\n c, // another comment((\n d) {}"); assertEq(f2.toString(), "function f2(a, /* ))))pernicious comment */ b,\n c, // another comment((\n d) {}");
assertEq(decompileBody(f2), "");
function f3() { } function f3() { }
assertEq(f3.toString(), "function f3() { }"); assertEq(f3.toString(), "function f3() { }");
assertEq(decompileBody(f3), " ");

View File

@ -4583,17 +4583,7 @@ JS_DecompileFunction(JSContext* cx, HandleFunction fun, unsigned indent)
AssertHeapIsIdle(cx); AssertHeapIsIdle(cx);
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
assertSameCompartment(cx, fun); assertSameCompartment(cx, fun);
return FunctionToString(cx, fun, false, !(indent & JS_DONT_PRETTY_PRINT)); return FunctionToString(cx, fun, !(indent & JS_DONT_PRETTY_PRINT));
}
JS_PUBLIC_API(JSString*)
JS_DecompileFunctionBody(JSContext* cx, HandleFunction fun, unsigned indent)
{
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, fun);
return FunctionToString(cx, fun, true, !(indent & JS_DONT_PRETTY_PRINT));
} }
MOZ_NEVER_INLINE static bool MOZ_NEVER_INLINE static bool

View File

@ -4047,15 +4047,13 @@ JS_DecompileScript(JSContext* cx, JS::Handle<JSScript*> script, const char* name
/* /*
* API extension: OR this into indent to avoid pretty-printing the decompiled * API extension: OR this into indent to avoid pretty-printing the decompiled
* source resulting from JS_DecompileFunction{,Body}. * source resulting from JS_DecompileFunction.
*/ */
#define JS_DONT_PRETTY_PRINT ((unsigned)0x8000) #define JS_DONT_PRETTY_PRINT ((unsigned)0x8000)
extern JS_PUBLIC_API(JSString*) extern JS_PUBLIC_API(JSString*)
JS_DecompileFunction(JSContext* cx, JS::Handle<JSFunction*> fun, unsigned indent); JS_DecompileFunction(JSContext* cx, JS::Handle<JSFunction*> fun, unsigned indent);
extern JS_PUBLIC_API(JSString*)
JS_DecompileFunctionBody(JSContext* cx, JS::Handle<JSFunction*> fun, unsigned indent);
/* /*
* NB: JS_ExecuteScript and the JS::Evaluate APIs come in two flavors: either * NB: JS_ExecuteScript and the JS::Evaluate APIs come in two flavors: either

View File

@ -909,7 +909,7 @@ js::FindBody(JSContext* cx, HandleFunction fun, HandleLinearString src, size_t*
} }
JSString* JSString*
js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lambdaParen) js::FunctionToString(JSContext* cx, HandleFunction fun, bool lambdaParen)
{ {
if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx)) if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
return nullptr; return nullptr;
@ -925,9 +925,9 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
if (fun->hasScript()) { if (fun->hasScript()) {
script = fun->nonLazyScript(); script = fun->nonLazyScript();
if (script->isGeneratorExp()) { if (script->isGeneratorExp()) {
if ((!bodyOnly && !out.append("function genexp() {")) || if (!out.append("function genexp() {") ||
!out.append("\n [generator expression]\n") || !out.append("\n [generator expression]\n") ||
(!bodyOnly && !out.append("}"))) !out.append("}"))
{ {
return nullptr; return nullptr;
} }
@ -937,21 +937,21 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
bool funIsMethodOrNonArrowLambda = (fun->isLambda() && !fun->isArrow()) || fun->isMethod() || bool funIsMethodOrNonArrowLambda = (fun->isLambda() && !fun->isArrow()) || fun->isMethod() ||
fun->isGetter() || fun->isSetter(); fun->isGetter() || fun->isSetter();
if (!bodyOnly) {
// If we're not in pretty mode, put parentheses around lambda functions and methods. // If we're not in pretty mode, put parentheses around lambda functions and methods.
if (fun->isInterpreted() && !lambdaParen && funIsMethodOrNonArrowLambda) { if (fun->isInterpreted() && !lambdaParen && funIsMethodOrNonArrowLambda) {
if (!out.append("(")) if (!out.append("("))
return nullptr; return nullptr;
}
if (!fun->isArrow()) {
if (!(fun->isStarGenerator() ? out.append("function* ") : out.append("function ")))
return nullptr;
}
if (fun->atom()) {
if (!out.append(fun->atom()))
return nullptr;
}
} }
if (!fun->isArrow()) {
if (!(fun->isStarGenerator() ? out.append("function* ") : out.append("function ")))
return nullptr;
}
if (fun->atom()) {
if (!out.append(fun->atom()))
return nullptr;
}
bool haveSource = fun->isInterpreted() && !fun->isSelfHostedBuiltin(); bool haveSource = fun->isInterpreted() && !fun->isSelfHostedBuiltin();
if (haveSource && !script->scriptSource()->hasSourceData() && if (haveSource && !script->scriptSource()->hasSourceData() &&
!JSScript::loadSource(cx, script->scriptSource(), &haveSource)) !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
@ -987,7 +987,7 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
// resulting function will have the same semantics. // resulting function will have the same semantics.
bool addUseStrict = script->strict() && !script->explicitUseStrict() && !fun->isArrow(); bool addUseStrict = script->strict() && !script->explicitUseStrict() && !fun->isArrow();
bool buildBody = funCon && !bodyOnly; bool buildBody = funCon;
if (buildBody) { if (buildBody) {
// This function was created with the Function constructor. We don't // This function was created with the Function constructor. We don't
// have source for the arguments, so we have to generate that. Part // have source for the arguments, so we have to generate that. Part
@ -1012,7 +1012,7 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
if (!out.append(") {\n")) if (!out.append(") {\n"))
return nullptr; return nullptr;
} }
if ((bodyOnly && !funCon) || addUseStrict) { if (addUseStrict) {
// We need to get at the body either because we're only supposed to // We need to get at the body either because we're only supposed to
// return the body or we need to insert "use strict" into the body. // return the body or we need to insert "use strict" into the body.
size_t bodyStart = 0, bodyEnd; size_t bodyStart = 0, bodyEnd;
@ -1043,10 +1043,8 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
} }
} }
// Output just the body (for bodyOnly) or the body and possibly // Output the body and possibly closing braces (for addUseStrict).
// closing braces (for addUseStrict). if (!out.appendSubstring(src, bodyStart, src->length() - bodyStart))
size_t dependentEnd = bodyOnly ? bodyEnd : src->length();
if (!out.appendSubstring(src, bodyStart, dependentEnd - bodyStart))
return nullptr; return nullptr;
} else { } else {
if (!out.append(src)) if (!out.append(src))
@ -1056,32 +1054,30 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
if (!out.append("\n}")) if (!out.append("\n}"))
return nullptr; return nullptr;
} }
if (bodyOnly) { if (!lambdaParen && funIsMethodOrNonArrowLambda) {
// Slap a semicolon on the end of functions with an expression body.
if (exprBody && !out.append(";"))
return nullptr;
} else if (!lambdaParen && funIsMethodOrNonArrowLambda) {
if (!out.append(")")) if (!out.append(")"))
return nullptr; return nullptr;
} }
} else if (fun->isInterpreted() && !fun->isSelfHostedBuiltin()) { } else if (fun->isInterpreted() && !fun->isSelfHostedBuiltin()) {
if ((!bodyOnly && !out.append("() {\n ")) || if (!out.append("() {\n ") ||
!out.append("[sourceless code]") || !out.append("[sourceless code]") ||
(!bodyOnly && !out.append("\n}"))) !out.append("\n}"))
{
return nullptr; return nullptr;
}
if (!lambdaParen && fun->isLambda() && !fun->isArrow() && !out.append(")")) if (!lambdaParen && fun->isLambda() && !fun->isArrow() && !out.append(")"))
return nullptr; return nullptr;
} else { } else {
MOZ_ASSERT(!fun->isExprBody()); MOZ_ASSERT(!fun->isExprBody());
if (fun->isNative() && fun->native() == js::DefaultDerivedClassConstructor) { if (fun->isNative() && fun->native() == js::DefaultDerivedClassConstructor) {
if ((!bodyOnly && !out.append("(...args) {\n ")) || if (!out.append("(...args) {\n ") ||
!out.append("super(...args);\n}")) !out.append("super(...args);\n}"))
{ {
return nullptr; return nullptr;
} }
} else { } else {
if (!bodyOnly && !out.append("() {\n ")) if (!out.append("() {\n "))
return nullptr; return nullptr;
if (!fun->isNative() || fun->native() != js::DefaultClassConstructor) { if (!fun->isNative() || fun->native() != js::DefaultClassConstructor) {
@ -1089,7 +1085,7 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lamb
return nullptr; return nullptr;
} }
if (!bodyOnly && !out.append("\n}")) if (!out.append("\n}"))
return nullptr; return nullptr;
} }
} }
@ -1110,7 +1106,7 @@ fun_toStringHelper(JSContext* cx, HandleObject obj, unsigned indent)
} }
RootedFunction fun(cx, &obj->as<JSFunction>()); RootedFunction fun(cx, &obj->as<JSFunction>());
return FunctionToString(cx, fun, false, indent != JS_DONT_PRETTY_PRINT); return FunctionToString(cx, fun, indent != JS_DONT_PRETTY_PRINT);
} }
bool bool

View File

@ -761,7 +761,7 @@ JSFunction::getExtendedSlot(size_t which) const
namespace js { namespace js {
JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool bodyOnly, bool lambdaParen); JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool lambdaParen);
template<XDRMode mode> template<XDRMode mode>
bool bool

View File

@ -3698,8 +3698,7 @@ NestedShell(JSContext* cx, unsigned argc, Value* vp)
} }
static bool static bool
DecompileFunctionSomehow(JSContext* cx, unsigned argc, Value* vp, DecompileFunction(JSContext* cx, unsigned argc, Value* vp)
JSString* (*decompiler)(JSContext*, HandleFunction, unsigned))
{ {
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1 || !args[0].isObject() || !args[0].toObject().is<JSFunction>()) { if (args.length() < 1 || !args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
@ -3707,25 +3706,13 @@ DecompileFunctionSomehow(JSContext* cx, unsigned argc, Value* vp,
return true; return true;
} }
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>()); RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
JSString* result = decompiler(cx, fun, 0); JSString* result = JS_DecompileFunction(cx, fun, 0);
if (!result) if (!result)
return false; return false;
args.rval().setString(result); args.rval().setString(result);
return true; return true;
} }
static bool
DecompileBody(JSContext* cx, unsigned argc, Value* vp)
{
return DecompileFunctionSomehow(cx, argc, vp, JS_DecompileFunctionBody);
}
static bool
DecompileFunction(JSContext* cx, unsigned argc, Value* vp)
{
return DecompileFunctionSomehow(cx, argc, vp, JS_DecompileFunction);
}
static bool static bool
DecompileThisScript(JSContext* cx, unsigned argc, Value* vp) DecompileThisScript(JSContext* cx, unsigned argc, Value* vp)
{ {
@ -4866,10 +4853,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
"decompileFunction(func)", "decompileFunction(func)",
" Decompile a function."), " Decompile a function."),
JS_FN_HELP("decompileBody", DecompileBody, 1, 0,
"decompileBody(func)",
" Decompile a function's body."),
JS_FN_HELP("decompileThis", DecompileThisScript, 0, 0, JS_FN_HELP("decompileThis", DecompileThisScript, 0, 0,
"decompileThis()", "decompileThis()",
" Decompile the currently executing script."), " Decompile the currently executing script."),

View File

@ -10,8 +10,6 @@ function testRunOptionStrictMode(str, arg, result) {
} }
assertEq(eval(uneval(testRunOptionStrictMode()))(), true); assertEq(eval(uneval(testRunOptionStrictMode()))(), true);
if (typeof decompileBody !== "undefined") { assertEq((new Function('x', 'return x*2;')).toSource().includes('\n"use strict"'), true);
assertEq(decompileBody(new Function('x', 'return x*2;')).includes('\n"use strict"'), true);
}
reportCompare(true, true); reportCompare(true, true);