ObjectActorPool.js (3482B)
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 { Pool } = require("devtools/shared/protocol"); 8 9 loader.lazyRequireGetter( 10 this, 11 "ObjectActor", 12 "resource://devtools/server/actors/object.js", 13 true 14 ); 15 loader.lazyRequireGetter( 16 this, 17 "PauseScopedObjectActor", 18 "resource://devtools/server/actors/pause-scoped.js", 19 true 20 ); 21 22 /** 23 * A Pool dedicated to host only Object Actors for given JS values. 24 * 25 * It optionaly ensures that we instantate only one Object Actor 26 * for any unique JS value. 27 * 28 * @param {ThreadActor} threadActor 29 * The related Thread Actor from which JS values are coming from. 30 * @param {string} label 31 * Pool's description (for debugging purpose) 32 * @param {boolean} uniqueActorPerValue 33 * Ensure instantiating only one Object Actor for each unique JS Value 34 * passed to createObjectGrip. 35 */ 36 class ObjectActorPool extends Pool { 37 constructor(threadActor, label, uniqueActorPerValue = false) { 38 super(threadActor.conn, label); 39 this.threadActor = threadActor; 40 41 this.uniqueActorPerValue = uniqueActorPerValue; 42 } 43 44 objectActors = new WeakMap(); 45 46 /** 47 * Create a grip for the given object. 48 * 49 * @param object object 50 * The object you want. 51 * @param Number depth 52 * Depth of the object compared to the top level object, 53 * when we are inspecting nested attributes. 54 * @param object [objectActorAttributes] 55 * An optional object whose properties will be assigned to the ObjectActor being created. 56 * @return object 57 * The object actor form, aka "grip" 58 */ 59 createObjectGrip( 60 object, 61 depth, 62 objectActorAttributes = {}, 63 ) { 64 // When we are creating object actors within the thread or JS tracer actor pools, 65 // we have some caching to prevent instantiating object actors twice for the same JS object. 66 if (this.uniqueActorPerValue) { 67 if (this.objectActors.has(object)) { 68 return this.objectActors.get(object).form({ depth }); 69 } 70 71 // Even if we are currently creating objects actors while being paused, 72 // in threadActor.pauseLifetimePool, we are looking into threadLifetimePool 73 // in case we created an actor for that object *before* pausing. 74 if (this.threadActor.threadLifetimePool.objectActors.has(object)) { 75 return this.threadActor.threadLifetimePool.objectActors.get(object).form({ depth }); 76 } 77 } 78 79 // We instantiate PauseScopedObjectActor instances for any actor created by the Thread Actor 80 const isGripForThreadActor = this == this.threadActor.threadLifetimePool || this == this.threadActor.pauseLifetimePool; 81 82 const ActorClass = isGripForThreadActor ? PauseScopedObjectActor : ObjectActor; 83 84 const actor = new ActorClass(this.threadActor, object, { 85 // custom formatters are injecting their own attributes here 86 ...objectActorAttributes, 87 }); 88 this.manage(actor); 89 90 if (this.uniqueActorPerValue) { 91 this.objectActors.set(object, actor); 92 } 93 94 // Pass the current depth to form method so that it can communicate it to the previewers. 95 // So that the actor form output may change depending on the current depth of the object within the requested preview. 96 return actor.form({ depth }); 97 } 98 } 99 100 exports.ObjectActorPool = ObjectActorPool;