mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1606084 - ValueToSource should be able to handle wrapped objects. r=jwalden
Differential Revision: https://phabricator.services.mozilla.com/D60312 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
99f4d7d6d8
commit
b464660235
@ -942,6 +942,7 @@ enum class ESClass {
|
||||
Arguments,
|
||||
Error,
|
||||
BigInt,
|
||||
Function, // Note: Only JSFunction objects.
|
||||
|
||||
/** None of the above. */
|
||||
Other
|
||||
|
@ -1,29 +1,31 @@
|
||||
// |jit-test| --disable-tosource
|
||||
|
||||
const TEST_CASES = [
|
||||
[undefined, "(void 0)"],
|
||||
[null, "null"],
|
||||
[true, "true"],
|
||||
[Symbol("abc"), `Symbol("abc")`],
|
||||
[15, "15"],
|
||||
[-0, "-0"],
|
||||
["abc", `"abc"`],
|
||||
[function a() { return 1; }, `(function a() { return 1; })`],
|
||||
[[1, 2, 3], `[1, 2, 3]`],
|
||||
[[1, {a: 0, b: 0}, 2], `[1, {a:0, b:0}, 2]`],
|
||||
[{a: [1, 2, 3]}, `({a:[1, 2, 3]})`],
|
||||
[new Error("msg", "file", 1), `(new Error("msg", "file", 1))`],
|
||||
[new TypeError("msg", "file", 1), `(new TypeError("msg", "file", 1))`],
|
||||
[new class X extends Error {
|
||||
[`undefined`, "(void 0)"],
|
||||
[`null`, "null"],
|
||||
[`true`, "true"],
|
||||
[`Symbol("abc")`, `Symbol("abc")`],
|
||||
[`15`, "15"],
|
||||
[`-0`, "-0"],
|
||||
[`"abc"`, `"abc"`],
|
||||
[`(function a() { return 1; })`, `(function a() { return 1; })`],
|
||||
[`[1, 2, 3]`, `[1, 2, 3]`],
|
||||
[`[1, {a: 0, b: 0}, 2]`, `[1, {a:0, b:0}, 2]`],
|
||||
[`({a: [1, 2, 3]})`, `({a:[1, 2, 3]})`],
|
||||
[`new Error("msg", "file", 1)`, `(new Error("msg", "file", 1))`],
|
||||
[`new TypeError("msg", "file", 1)`, `(new TypeError("msg", "file", 1))`],
|
||||
[`new class X extends Error {
|
||||
constructor() {
|
||||
super("msg", "file", 1);
|
||||
this.name = "X";
|
||||
}
|
||||
}, `(new X("msg", "file", 1))`],
|
||||
[/a(b)c/, `/a(b)c/`],
|
||||
[/abc/gi, `/abc/gi`],
|
||||
}`, `(new X("msg", "file", 1))`],
|
||||
[`/a(b)c/`, `/a(b)c/`],
|
||||
[`/abc/gi`, `/abc/gi`],
|
||||
]
|
||||
|
||||
let g = newGlobal({newCompartment: true});
|
||||
for (let [actual, expected] of TEST_CASES) {
|
||||
assertEq(valueToSource(actual), expected);
|
||||
assertEq(valueToSource(eval(actual)), expected);
|
||||
assertEq(valueToSource(g.eval(actual)), expected);
|
||||
}
|
||||
|
@ -302,6 +302,8 @@ JS_FRIEND_API bool js::GetBuiltinClass(JSContext* cx, HandleObject obj,
|
||||
*cls = ESClass::Error;
|
||||
} else if (obj->is<BigIntObject>()) {
|
||||
*cls = ESClass::BigInt;
|
||||
} else if (obj->is<JSFunction>()) {
|
||||
*cls = ESClass::Function;
|
||||
} else {
|
||||
*cls = ESClass::Other;
|
||||
}
|
||||
|
@ -1722,6 +1722,7 @@ bool JSStructuredCloneWriter::startWrite(HandleValue v) {
|
||||
case ESClass::SetIterator:
|
||||
case ESClass::Arguments:
|
||||
case ESClass::Error:
|
||||
case ESClass::Function:
|
||||
break;
|
||||
|
||||
case ESClass::Other: {
|
||||
|
@ -12,12 +12,13 @@
|
||||
|
||||
#include <stdint.h> // uint32_t
|
||||
|
||||
#include "jsfriendapi.h" // CheckRecursionLimit
|
||||
#include "jsfriendapi.h" // CheckRecursionLimit, GetBuiltinClass
|
||||
|
||||
#include "builtin/Array.h" // ArrayToSource
|
||||
#include "builtin/Boolean.h" // BooleanToString
|
||||
#include "builtin/Object.h" // ObjectToSource
|
||||
#include "gc/Allocator.h" // CanGC
|
||||
#include "js/Class.h" // ESClass
|
||||
#include "js/Symbol.h" // SymbolCode, JS::WellKnownSymbolLimit
|
||||
#include "js/TypeDecls.h" // Rooted{Function, Object, String, Value}, HandleValue, Latin1Char
|
||||
#include "js/Utility.h" // UniqueChars
|
||||
@ -27,9 +28,8 @@
|
||||
#include "vm/ErrorObject.h" // ErrorObject, ErrorToSource
|
||||
#include "vm/Interpreter.h" // Call
|
||||
#include "vm/JSContext.h" // JSContext
|
||||
#include "vm/JSFunction.h" // JSFunction, FunctionToString
|
||||
#include "vm/JSFunction.h" // JSFunction, fun_toStringHelper
|
||||
#include "vm/Printer.h" // QuoteString
|
||||
#include "vm/RegExpObject.h" // RegExpObject
|
||||
#include "vm/SelfHosting.h" // CallSelfHostedFunction
|
||||
#include "vm/Stack.h" // FixedInvokeArgs
|
||||
#include "vm/StringType.h" // NewStringCopy{N,Z}, ToString
|
||||
@ -143,30 +143,35 @@ JSString* js::ValueToSource(JSContext* cx, HandleValue v) {
|
||||
return ToString<CanGC>(cx, v);
|
||||
}
|
||||
|
||||
if (obj->is<JSFunction>()) {
|
||||
RootedFunction fun(cx, &obj->as<JSFunction>());
|
||||
return FunctionToString(cx, fun, true);
|
||||
ESClass cls;
|
||||
if (!GetBuiltinClass(cx, obj, &cls)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (obj->is<ArrayObject>()) {
|
||||
return ArrayToSource(cx, obj);
|
||||
}
|
||||
// All ToSource functions must be able to handle wrapped objects!
|
||||
switch (cls) {
|
||||
case ESClass::Function:
|
||||
return fun_toStringHelper(cx, obj, true);
|
||||
|
||||
if (obj->is<ErrorObject>()) {
|
||||
return ErrorToSource(cx, obj);
|
||||
}
|
||||
case ESClass::Array:
|
||||
return ArrayToSource(cx, obj);
|
||||
|
||||
if (obj->is<RegExpObject>()) {
|
||||
FixedInvokeArgs<0> args(cx);
|
||||
RootedValue rval(cx);
|
||||
if (!CallSelfHostedFunction(cx, cx->names().RegExpToString, v, args,
|
||||
&rval)) {
|
||||
return nullptr;
|
||||
case ESClass::Error:
|
||||
return ErrorToSource(cx, obj);
|
||||
|
||||
case ESClass::RegExp: {
|
||||
FixedInvokeArgs<0> args(cx);
|
||||
RootedValue rval(cx);
|
||||
if (!CallSelfHostedFunction(cx, cx->names().RegExpToString, v, args,
|
||||
&rval)) {
|
||||
return nullptr;
|
||||
}
|
||||
return ToString<CanGC>(cx, rval);
|
||||
}
|
||||
return ToString<CanGC>(cx, rval);
|
||||
}
|
||||
|
||||
return ObjectToSource(cx, obj);
|
||||
default:
|
||||
return ObjectToSource(cx, obj);
|
||||
}
|
||||
}
|
||||
|
||||
case JS::ValueType::PrivateGCThing:
|
||||
|
Loading…
Reference in New Issue
Block a user