1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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,
};
|