summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/object/symbol.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/actors/object/symbol.js')
-rw-r--r--devtools/server/actors/object/symbol.js109
1 files changed, 109 insertions, 0 deletions
diff --git a/devtools/server/actors/object/symbol.js b/devtools/server/actors/object/symbol.js
new file mode 100644
index 0000000000..bd8bb97005
--- /dev/null
+++ b/devtools/server/actors/object/symbol.js
@@ -0,0 +1,109 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { Actor } = require("resource://devtools/shared/protocol.js");
+const { symbolSpec } = require("resource://devtools/shared/specs/symbol.js");
+loader.lazyRequireGetter(
+ this,
+ "createValueGrip",
+ "resource://devtools/server/actors/object/utils.js",
+ true
+);
+
+/**
+ * Creates an actor for the specified symbol.
+ *
+ * @param {DevToolsServerConnection} conn: The connection to the client.
+ * @param {Symbol} symbol: The symbol we want to create an actor for.
+ */
+class SymbolActor extends Actor {
+ constructor(conn, symbol) {
+ super(conn, symbolSpec);
+ this.symbol = symbol;
+ }
+
+ rawValue() {
+ return this.symbol;
+ }
+
+ destroy() {
+ // Because symbolActors is not a weak map, we won't automatically leave
+ // it so we need to manually leave on destroy so that we don't leak
+ // memory.
+ this._releaseActor();
+ super.destroy();
+ }
+
+ /**
+ * Returns a grip for this actor for returning in a protocol message.
+ */
+ form() {
+ const form = {
+ type: this.typeName,
+ actor: this.actorID,
+ };
+ const name = getSymbolName(this.symbol);
+ if (name !== undefined) {
+ // Create a grip for the name because it might be a longString.
+ form.name = createValueGrip(name, this.getParent());
+ }
+ return form;
+ }
+
+ /**
+ * Handle a request to release this SymbolActor instance.
+ */
+ release() {
+ // TODO: also check if this.getParent() === threadActor.threadLifetimePool
+ // when the web console moves away from manually releasing pause-scoped
+ // actors.
+ this._releaseActor();
+ this.destroy();
+ return {};
+ }
+
+ _releaseActor() {
+ const parent = this.getParent();
+ if (parent && parent.symbolActors) {
+ delete parent.symbolActors[this.symbol];
+ }
+ }
+}
+
+const symbolProtoToString = Symbol.prototype.toString;
+
+function getSymbolName(symbol) {
+ const name = symbolProtoToString.call(symbol).slice("Symbol(".length, -1);
+ return name || undefined;
+}
+
+/**
+ * Create a grip for the given symbol.
+ *
+ * @param sym Symbol
+ * The symbol we are creating a grip for.
+ * @param pool Pool
+ * The actor pool where the new actor will be added.
+ */
+function symbolGrip(sym, pool) {
+ if (!pool.symbolActors) {
+ pool.symbolActors = Object.create(null);
+ }
+
+ if (sym in pool.symbolActors) {
+ return pool.symbolActors[sym].form();
+ }
+
+ const actor = new SymbolActor(pool.conn, sym);
+ pool.manage(actor);
+ pool.symbolActors[sym] = actor;
+ return actor.form();
+}
+
+module.exports = {
+ SymbolActor,
+ symbolGrip,
+};