symbol.js (2996B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const { Actor } = require("resource://devtools/shared/protocol.js"); 8 const { symbolSpec } = require("resource://devtools/shared/specs/symbol.js"); 9 loader.lazyRequireGetter( 10 this, 11 "createValueGrip", 12 "resource://devtools/server/actors/object/utils.js", 13 true 14 ); 15 16 /** 17 * Creates an actor for the specified symbol. 18 * 19 * @param {ThreadActor} threadActor: The related thread actor. 20 * @param {symbol} symbol: The symbol we want to create an actor for. 21 */ 22 class SymbolActor extends Actor { 23 constructor(threadActor, symbol) { 24 super(threadActor.conn, symbolSpec); 25 this.threadActor = threadActor; 26 this.symbol = symbol; 27 28 // Align with Object Actor interface 29 // (this is used from eval-with-debugger) 30 this.rawObj = this.symbol; 31 } 32 33 destroy() { 34 // Because symbolActors is not a weak map, we won't automatically leave 35 // it so we need to manually leave on destroy so that we don't leak 36 // memory. 37 this._releaseActor(); 38 super.destroy(); 39 40 this.threadActor = null; 41 } 42 43 /** 44 * Returns a grip for this actor for returning in a protocol message. 45 */ 46 form() { 47 const form = { 48 type: this.typeName, 49 actor: this.actorID, 50 }; 51 const name = getSymbolName(this.symbol); 52 if (name !== undefined) { 53 // Create a grip for the name because it might be a longString. 54 form.name = createValueGrip(this.threadActor, name, this.getParent()); 55 } 56 return form; 57 } 58 59 /** 60 * Handle a request to release this SymbolActor instance. 61 */ 62 release() { 63 // TODO: also check if this.getParent() === threadActor.threadLifetimePool 64 // when the web console moves away from manually releasing pause-scoped 65 // actors. 66 this._releaseActor(); 67 this.destroy(); 68 return {}; 69 } 70 71 _releaseActor() { 72 const parent = this.getParent(); 73 if (parent && parent.symbolActors) { 74 delete parent.symbolActors[this.symbol]; 75 } 76 } 77 } 78 79 const symbolProtoToString = Symbol.prototype.toString; 80 81 function getSymbolName(symbol) { 82 const name = symbolProtoToString.call(symbol).slice("Symbol(".length, -1); 83 return name || undefined; 84 } 85 86 /** 87 * Create a grip for the given symbol. 88 * 89 * @param threadActor ThreadActor 90 * The related Thread Actor 91 * @param sym Symbol 92 * The symbol we are creating a grip for. 93 * @param pool Pool 94 * The actor pool where the new actor will be added. 95 */ 96 function symbolGrip(threadActor, sym, pool) { 97 if (!pool.symbolActors) { 98 pool.symbolActors = Object.create(null); 99 } 100 101 if (sym in pool.symbolActors) { 102 return pool.symbolActors[sym].form(); 103 } 104 105 const actor = new SymbolActor(threadActor, sym); 106 pool.manage(actor); 107 pool.symbolActors[sym] = actor; 108 return actor.form(); 109 } 110 111 module.exports = { 112 SymbolActor, 113 symbolGrip, 114 };