Bug 1038316: Add support for ES6 Symbols to ubi::Node. r=sfink

This commit is contained in:
Jim Blandy 2014-07-30 17:14:19 -07:00
Родитель f21b7a395b
Коммит a3de3d6a60
4 изменённых файлов: 32 добавлений и 18 удалений

Просмотреть файл

@ -23,7 +23,7 @@
// JS::ubi::Node is a pointer-like type designed for internal use by heap // JS::ubi::Node is a pointer-like type designed for internal use by heap
// analysis tools. A ubi::Node can refer to: // analysis tools. A ubi::Node can refer to:
// //
// - a JS value, like a string or object; // - a JS value, like a string, object, or symbol;
// - an internal SpiderMonkey structure, like a shape or a scope chain object // - an internal SpiderMonkey structure, like a shape or a scope chain object
// - an instance of some embedding-provided type: in Firefox, an XPCOM // - an instance of some embedding-provided type: in Firefox, an XPCOM
// object, or an internal DOM node class instance // object, or an internal DOM node class instance
@ -315,10 +315,10 @@ class Node {
return is<T>() ? static_cast<T *>(base()->ptr) : nullptr; return is<T>() ? static_cast<T *>(base()->ptr) : nullptr;
} }
// If this node refers to something that can be represented as a // If this node refers to something that can be represented as a JavaScript
// JavaScript value that is safe to expose to JavaScript code, return that // value that is safe to expose to JavaScript code, return that value.
// value. Otherwise return UndefinedValue(). JSStrings and some (but not // Otherwise return UndefinedValue(). JSStrings, JS::Symbols, and some (but
// all!) JSObjects can be exposed. // not all!) JSObjects can be exposed.
JS::Value exposeToJS() const; JS::Value exposeToJS() const;
const jschar *typeName() const { return base()->typeName(); } const jschar *typeName() const { return base()->typeName(); }
@ -427,6 +427,7 @@ class TracerConcrete : public Base {
template<> struct Concrete<JSObject> : TracerConcrete<JSObject> { }; template<> struct Concrete<JSObject> : TracerConcrete<JSObject> { };
template<> struct Concrete<JSString> : TracerConcrete<JSString> { }; template<> struct Concrete<JSString> : TracerConcrete<JSString> { };
template<> struct Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> { };
template<> struct Concrete<JSScript> : TracerConcrete<JSScript> { }; template<> struct Concrete<JSScript> : TracerConcrete<JSScript> { };
template<> struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> { }; template<> struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> { };
template<> struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> { }; template<> struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> { };

Просмотреть файл

@ -1790,21 +1790,20 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp)
return false; return false;
} }
// We don't ToString non-objects given as 'start' or 'target'. We can't // We don't ToString non-objects given as 'start' or 'target', because this
// see edges to non-string primitive values, and it doesn't make much // test is all about object identity, and ToString doesn't preserve that.
// sense to ask for paths to or from a freshly allocated string, so // Non-GCThing endpoints don't make much sense.
// if a non-string primitive appears here it's probably a mistake. if (!args[0].isObject() && !args[0].isString() && !args[0].isSymbol()) {
if (!args[0].isObject() && !args[0].isString()) {
js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
JSDVG_SEARCH_STACK, args[0], JS::NullPtr(), JSDVG_SEARCH_STACK, args[0], JS::NullPtr(),
"neither an object nor a string", NULL); "not an object, string, or symbol", NULL);
return false; return false;
} }
if (!args[1].isObject() && !args[1].isString()) { if (!args[1].isObject() && !args[1].isString() && !args[1].isSymbol()) {
js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
JSDVG_SEARCH_STACK, args[0], JS::NullPtr(), JSDVG_SEARCH_STACK, args[0], JS::NullPtr(),
"neither an object nor a string", NULL); "not an object, string, or symbol", NULL);
return false; return false;
} }
@ -1837,10 +1836,13 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp)
// Construct a JavaScript array describing the path from the start to the // Construct a JavaScript array describing the path from the start to the
// target. Each element has the form: // target. Each element has the form:
// //
// { node: <object or string>, edge: <string describing outgoing edge from node> } // {
// node: <object or string or symbol>,
// edge: <string describing outgoing edge from node>
// }
// //
// or, if the node is some internal thing, that isn't a proper // or, if the node is some internal thing that isn't a proper JavaScript
// JavaScript value: // value:
// //
// { node: undefined, edge: <string> } // { node: undefined, edge: <string> }
size_t length = nodes.length(); size_t length = nodes.length();
@ -1868,8 +1870,7 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp)
return false; return false;
edgeName.release(); // edgeStr acquired ownership edgeName.release(); // edgeStr acquired ownership
if (!JS_DefineProperty(cx, obj, "edge", edgeStr, if (!JS_DefineProperty(cx, obj, "edge", edgeStr, JSPROP_ENUMERATE, nullptr, nullptr))
JSPROP_ENUMERATE, nullptr, nullptr))
return false; return false;
result->setDenseElement(length - i - 1, ObjectValue(*obj)); result->setDenseElement(length - i - 1, ObjectValue(*obj));

Просмотреть файл

@ -42,3 +42,8 @@ Match.Pattern([{node: {}, edge: "shape"},
.assert(findPath(o, o)); .assert(findPath(o, o));
print(findPath(o, o).map((e) => e.edge).toString()); print(findPath(o, o).map((e) => e.edge).toString());
// Check that we can generate ubi::Nodes for Symbols.
var so = { sym: Symbol() };
Match.Pattern([{node: {}, edge: "sym" }])
.assert(findPath(so, so.sym));
print(findPath(so, so.sym).map((e) => e.edge).toString());

Просмотреть файл

@ -37,6 +37,7 @@ Node::Node(JSGCTraceKind kind, void *ptr)
switch (kind) { switch (kind) {
case JSTRACE_OBJECT: construct(static_cast<JSObject *>(ptr)); break; case JSTRACE_OBJECT: construct(static_cast<JSObject *>(ptr)); break;
case JSTRACE_STRING: construct(static_cast<JSString *>(ptr)); break; case JSTRACE_STRING: construct(static_cast<JSString *>(ptr)); break;
case JSTRACE_SYMBOL: construct(static_cast<JS::Symbol *>(ptr)); break;
case JSTRACE_SCRIPT: construct(static_cast<JSScript *>(ptr)); break; case JSTRACE_SCRIPT: construct(static_cast<JSScript *>(ptr)); break;
case JSTRACE_LAZY_SCRIPT: construct(static_cast<js::LazyScript *>(ptr)); break; case JSTRACE_LAZY_SCRIPT: construct(static_cast<js::LazyScript *>(ptr)); break;
case JSTRACE_JITCODE: construct(static_cast<js::jit::JitCode *>(ptr)); break; case JSTRACE_JITCODE: construct(static_cast<js::jit::JitCode *>(ptr)); break;
@ -55,6 +56,8 @@ Node::Node(Value value)
construct(&value.toObject()); construct(&value.toObject());
else if (value.isString()) else if (value.isString())
construct(value.toString()); construct(value.toString());
else if (value.isSymbol())
construct(value.toSymbol());
else else
construct<void>(nullptr); construct<void>(nullptr);
} }
@ -75,6 +78,8 @@ Node::exposeToJS() const
} }
} else if (is<JSString>()) { } else if (is<JSString>()) {
v.setString(as<JSString>()); v.setString(as<JSString>());
} else if (is<JS::Symbol>()) {
v.setSymbol(as<JS::Symbol>());
} else { } else {
v.setUndefined(); v.setUndefined();
} }
@ -210,6 +215,8 @@ template<> const jschar TracerConcrete<JSObject>::concreteTypeName[] =
MOZ_UTF16("JSObject"); MOZ_UTF16("JSObject");
template<> const jschar TracerConcrete<JSString>::concreteTypeName[] = template<> const jschar TracerConcrete<JSString>::concreteTypeName[] =
MOZ_UTF16("JSString"); MOZ_UTF16("JSString");
template<> const jschar TracerConcrete<JS::Symbol>::concreteTypeName[] =
MOZ_UTF16("JS::Symbol");
template<> const jschar TracerConcrete<JSScript>::concreteTypeName[] = template<> const jschar TracerConcrete<JSScript>::concreteTypeName[] =
MOZ_UTF16("JSScript"); MOZ_UTF16("JSScript");
template<> const jschar TracerConcrete<js::LazyScript>::concreteTypeName[] = template<> const jschar TracerConcrete<js::LazyScript>::concreteTypeName[] =