toolkit/devtools/server/actors/string.js

changeset 0
6474c204b198
     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 +});

mercurial