/* 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 { extend } = require("devtools/shared/extend"); const { ObjectActorProto } = require("devtools/server/actors/object"); const protocol = require("devtools/shared/protocol"); const { ActorClassWithSpec } = protocol; const { objectSpec } = require("devtools/shared/specs/object"); /** * Protocol.js expects only the prototype object, and does not maintain the prototype * chain when it constructs the ActorClass. For this reason we are using extend to * maintain the properties of ObjectActorProto. **/ const proto = extend({}, ObjectActorProto); Object.assign(proto, { /** * Creates a pause-scoped actor for the specified object. * @see ObjectActor */ initialize: function(obj, hooks, conn) { ObjectActorProto.initialize.call(this, obj, hooks, conn); this.hooks.promote = hooks.promote; this.hooks.isThreadLifetimePool = hooks.isThreadLifetimePool; }, isPaused: function() { return this.threadActor ? this.threadActor.state === "paused" : true; }, withPaused: function(method) { return function() { if (this.isPaused()) { return method.apply(this, arguments); } return { error: "wrongState", message: this.constructor.name + " actors can only be accessed while the thread is paused.", }; }; }, }); const guardWithPaused = [ "decompile", "displayString", "ownPropertyNames", "parameterNames", "property", "prototype", "prototypeAndProperties", "scope", ]; guardWithPaused.forEach(f => { proto[f] = proto.withPaused(ObjectActorProto[f]); }); Object.assign(proto, { /** * Handle a protocol request to promote a pause-lifetime grip to a * thread-lifetime grip. * * @param request object * The protocol request object. */ threadGrip: proto.withPaused(function(request) { this.hooks.promote(); return {}; }), /** * Handle a protocol request to release a thread-lifetime grip. * * @param request object * The protocol request object. */ destroy: proto.withPaused(function(request) { if (this.hooks.isThreadLifetimePool()) { return { error: "notReleasable", message: "Only thread-lifetime actors can be released.", }; } return protocol.Actor.prototype.destroy.call(this); }), }); exports.PauseScopedObjectActor = ActorClassWithSpec(objectSpec, proto); // ActorClassWithSpec(objectSpec, {...ObjectActorProto, ...proto});