1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/server/actors/string.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,145 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +let {Cu} = require("chrome"); 1.11 +let {DebuggerServer} = require("devtools/server/main"); 1.12 + 1.13 +let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); 1.14 +let {Class} = require("sdk/core/heritage"); 1.15 + 1.16 +let protocol = require("devtools/server/protocol"); 1.17 +let {method, Arg, Option, RetVal} = protocol; 1.18 + 1.19 +exports.LongStringActor = protocol.ActorClass({ 1.20 + typeName: "longstractor", 1.21 + 1.22 + initialize: function(conn, str) { 1.23 + protocol.Actor.prototype.initialize.call(this, conn); 1.24 + this.str = str; 1.25 + this.short = (this.str.length < DebuggerServer.LONG_STRING_LENGTH); 1.26 + }, 1.27 + 1.28 + destroy: function() { 1.29 + this.str = null; 1.30 + protocol.Actor.prototype.destroy.call(this); 1.31 + }, 1.32 + 1.33 + form: function() { 1.34 + if (this.short) { 1.35 + return this.str; 1.36 + } 1.37 + return { 1.38 + type: "longString", 1.39 + actor: this.actorID, 1.40 + length: this.str.length, 1.41 + initial: this.str.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH) 1.42 + } 1.43 + }, 1.44 + 1.45 + substring: method(function(start, end) { 1.46 + return promise.resolve(this.str.substring(start, end)); 1.47 + }, { 1.48 + request: { 1.49 + start: Arg(0), 1.50 + end: Arg(1) 1.51 + }, 1.52 + response: { substring: RetVal() }, 1.53 + }), 1.54 + 1.55 + release: method(function() { }, { release: true }) 1.56 +}); 1.57 + 1.58 +/** 1.59 + * When a LongString on the server is short enough to be passed 1.60 + * as a full string, the client will get a ShortLongString instead of 1.61 + * a LongStringFront. Its API should match. 1.62 + * 1.63 + * I'm very proud of this name. 1.64 + */ 1.65 +exports.ShortLongString = Class({ 1.66 + initialize: function(str) { 1.67 + this.str = str; 1.68 + }, 1.69 + 1.70 + get length() { return this.str.length; }, 1.71 + get initial() { return this.str; }, 1.72 + string: function() { return promise.resolve(this.str) }, 1.73 + 1.74 + substring: function(start, end) { 1.75 + return promise.resolve(this.str.substring(start, end)); 1.76 + }, 1.77 + 1.78 + release: function() { 1.79 + this.str = null; 1.80 + return promise.resolve(undefined); 1.81 + } 1.82 +}) 1.83 + 1.84 +exports.LongStringFront = protocol.FrontClass(exports.LongStringActor, { 1.85 + initialize: function(client, form) { 1.86 + // Don't give the form by default, because we're being tricky and it might just 1.87 + // be a string. 1.88 + protocol.Front.prototype.initialize.call(this, client, null); 1.89 + this.form(form); 1.90 + }, 1.91 + 1.92 + destroy: function() { 1.93 + this.initial = null; 1.94 + this.length = null; 1.95 + this.strPromise = null; 1.96 + protocol.Front.prototype.destroy.call(this); 1.97 + }, 1.98 + 1.99 + form: function(form) { 1.100 + this.actorID = form.actorID; 1.101 + this.initial = form.initial; 1.102 + this.length = form.length; 1.103 + }, 1.104 + 1.105 + string: function() { 1.106 + if (!this.strPromise) { 1.107 + let promiseRest = (thusFar) => { 1.108 + if (thusFar.length === this.length) 1.109 + return promise.resolve(thusFar); 1.110 + else { 1.111 + return this.substring(thusFar.length, 1.112 + thusFar.length + DebuggerServer.LONG_STRING_READ_LENGTH) 1.113 + .then((next) => promiseRest(thusFar + next)); 1.114 + } 1.115 + } 1.116 + 1.117 + this.strPromise = promiseRest(this.initial); 1.118 + } 1.119 + return this.strPromise; 1.120 + } 1.121 +}); 1.122 + 1.123 +// The long string actor needs some custom marshalling, because it is sometimes 1.124 +// returned as a primitive rather than a complete form. 1.125 + 1.126 +let stringActorType = protocol.types.getType("longstractor"); 1.127 +protocol.types.addType("longstring", { 1.128 + _actor: true, 1.129 + write: (value, context, detail) => { 1.130 + if (!(context instanceof protocol.Actor)) { 1.131 + throw Error("Passing a longstring as an argument isn't supported."); 1.132 + } 1.133 + if (value.short) { 1.134 + return value.str; 1.135 + } else { 1.136 + return stringActorType.write(value, context, detail); 1.137 + } 1.138 + }, 1.139 + read: (value, context, detail) => { 1.140 + if (context instanceof protocol.Actor) { 1.141 + throw Error("Passing a longstring as an argument isn't supported."); 1.142 + } 1.143 + if (typeof(value) === "string") { 1.144 + return exports.ShortLongString(value); 1.145 + } 1.146 + return stringActorType.read(value, context, detail); 1.147 + } 1.148 +});