[Pkg-mozext-commits] [greasemonkey] 01/55: avoid holding duplicate script source strings in memory

David Prévot taffit at moszumanska.debian.org
Thu Oct 29 15:38:01 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository greasemonkey.

commit 70a16c451cd56e827ae01956315e3fbd91280727
Author: The8472 <git at infinite-source.de>
Date:   Tue Aug 18 20:57:43 2015 +0200

    avoid holding duplicate script source strings in memory
    
    old: strings sent via e10s message manager are duplicated and the
    sandbox holds onto them as source code, this causes unnecessary memory
    overhead.
    
    new: load scripts from file:// URIs and use lazy getters for
    scriptSource
---
 modules/ipcscript.js    | 19 ++---------
 modules/miscapis.js     |  7 ++++-
 modules/sandbox.js      | 84 ++++++++++++++++++++++++++++++++++++++++---------
 modules/util.js         |  1 +
 modules/util/fileXHR.js | 15 +++++++++
 5 files changed, 94 insertions(+), 32 deletions(-)

diff --git a/modules/ipcscript.js b/modules/ipcscript.js
index 896746e..99f530f 100644
--- a/modules/ipcscript.js
+++ b/modules/ipcscript.js
@@ -1,6 +1,5 @@
 var EXPORTED_SYMBOLS = ['IPCScript'];
 
-Components.utils.import("chrome://greasemonkey-modules/content/extractMeta.js");
 Components.utils.import("chrome://greasemonkey-modules/content/util.js");
 
 function IPCScript(aScript, addonVersion) {
@@ -17,15 +16,13 @@ function IPCScript(aScript, addonVersion) {
   this.namespace = aScript.namespace;
   this.noframes = aScript.noframes;
   this.runAt = aScript.runAt;
-  this.textContent = aScript.textContent;
   this.uuid = aScript.uuid;
   this.version = aScript.version;
   this.willUpdate = aScript.isRemoteUpdateAllowed();
 
   this.requires = aScript.requires.map(function(req) {
     return {
-      'fileURL': req.fileURL,
-      'textContent': req.textContent
+      'fileURL': req.fileURL
     };
   });
 
@@ -33,21 +30,11 @@ function IPCScript(aScript, addonVersion) {
     return {
       'name': res.name,
       'mimetype': res.mimetype,
-      'textContent': res.textContent,
       'url': GM_util.getUriFromFile(res.file).spec
     };
   });
 };
 
-IPCScript.prototype.__defineGetter__('metaStr',
-function IPCScript_getMetaStr() {
-  if (!this._metaStr) {
-    this._metaStr = extractMeta(this.textContent);
-  }
-
-  return this._metaStr;
-});
-
 IPCScript.prototype.info = function() {
   var resources = {};
   for (var i = 0, r = null; r = this.resources[i]; i++) {
@@ -60,8 +47,6 @@ IPCScript.prototype.info = function() {
   return {
     'uuid': this.uuid,
     'version': this.addonVersion,
-    'scriptMetaStr': this.metaStr,
-    'scriptSource': this.textContent,
     'scriptWillUpdate': this.willUpdate,
     'script': {
       'description': this.description,
@@ -80,4 +65,4 @@ IPCScript.prototype.info = function() {
       'version': this.version
     }
   };
-};
+};
\ No newline at end of file
diff --git a/modules/miscapis.js b/modules/miscapis.js
index a925edd..70f0e41 100644
--- a/modules/miscapis.js
+++ b/modules/miscapis.js
@@ -24,8 +24,13 @@ GM_Resources.prototype.getResourceURL = function(aScript, name) {
   return ['greasemonkey-script:', aScript.uuid, '/', name].join('');
 };
 
+
 GM_Resources.prototype.getResourceText = function(name) {
-  return this._getDep(name).textContent;
+  var dep = this._getDep(name)
+  if(dep.textContent !== undefined)
+    return dep.textContent;
+  // lazy resources in IPC scripts
+  return GM_util.fileXHR(dep.url, "text/plain");
 };
 
 GM_Resources.prototype._getDep = function(name) {
diff --git a/modules/sandbox.js b/modules/sandbox.js
index f2ed4e7..9a70b62 100644
--- a/modules/sandbox.js
+++ b/modules/sandbox.js
@@ -11,12 +11,15 @@ Cu.import("chrome://greasemonkey-modules/content/miscapis.js");
 Cu.import("chrome://greasemonkey-modules/content/storageFront.js");
 Cu.import("chrome://greasemonkey-modules/content/util.js");
 Cu.import("chrome://greasemonkey-modules/content/xmlhttprequester.js");
+Cu.import("chrome://greasemonkey-modules/content/extractMeta.js");
 
 var gStringBundle = Cc["@mozilla.org/intl/stringbundle;1"]
     .getService(Ci.nsIStringBundleService)
     .createBundle("chrome://greasemonkey/locale/greasemonkey.properties");
 var gInvalidAccesskeyErrorStr = gStringBundle
     .GetStringFromName('error.menu-invalid-accesskey');
+var subLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+    .getService(Components.interfaces.mozIJSSubScriptLoader);
 
 // Only a particular set of strings are allowed.  See: http://goo.gl/ex2LJ
 var gMaxJSVersion = "ECMAv5";
@@ -35,9 +38,8 @@ function createSandbox(aScript, aContentWin, aUrl, aFrameScope) {
           'wantXrays': false,
         });
     // GM_info is always provided.
-    // TODO: lazy getter? XPCOMUtils.defineLazyGetter
-    Components.utils.evalInSandbox(
-        'const GM_info = ' + uneval(aScript.info()), contentSandbox);
+    injectGMInfo(aScript, contentSandbox);
+
     // Alias unsafeWindow for compatibility.
     Components.utils.evalInSandbox(
         'const unsafeWindow = window;', contentSandbox);
@@ -124,19 +126,70 @@ function createSandbox(aScript, aContentWin, aUrl, aFrameScope) {
         'contentStartRequest');
   }
 
-  // TODO: lazy getter?
-  Components.utils.evalInSandbox(
-      'const GM_info = ' + uneval(aScript.info()), sandbox);
+  injectGMInfo(aScript, sandbox);
 
   return sandbox;
 }
 
 
+
+function injectGMInfo(aScript, sandbox) {
+  var rawInfo = aScript.info();
+  var scriptURL = aScript.fileURL;
+
+  // TODO: also delay top level clone via lazy getter? XPCOMUtils.defineLazyGetter
+  sandbox.GM_info = Cu.cloneInto(rawInfo, sandbox);
+  
+  var waivedInfo = Components.utils.waiveXrays(sandbox.GM_info);
+  
+  var fileCache = new Map();
+
+  // lazy getters for heavyweight strings that aren't sent down through IPC
+  Object.defineProperty(waivedInfo,
+    "scriptSource",
+    { get: Cu.exportFunction(
+      function() {
+        var content = fileCache.get("scriptSource");
+        if(content === undefined) {
+          content = GM_util.fileXHR(scriptURL, "application/javascript");
+          fileCache.set("scriptSource", content);
+        }
+        return content;
+      }, sandbox)
+    }
+  );
+  
+  // meta depends on content, so we need a lazy one here too
+  Object.defineProperty(waivedInfo,
+    'scriptMetaStr',
+    {get: Cu.exportFunction(
+      function() {
+        var meta = fileCache.get("meta");
+        if(meta === undefined) {
+          meta = extractMeta(this.scriptSource);
+          fileCache.set("meta", meta);
+        }
+        return meta;
+      }, sandbox)
+    }
+  );
+
+}
+
+function uriToString(uri) {
+  var channel = NetUtil.newChannel({ uri: NetUtil.newURI(uri, "UTF-8"), loadUsingSystemPrincipal: true});
+  var stream = channel.open();
+
+  var count = stream.available();
+  var data = NetUtil.readInputStreamToString(stream, count, { charset : "utf-8" });
+  return data;
+}
+
 function runScriptInSandbox(script, sandbox) {
   // Eval the code, with anonymous wrappers when/if appropriate.
-  function evalWithWrapper(code, fileName) {
+  function evalWithWrapper(uri) {
     try {
-      Components.utils.evalInSandbox(code, sandbox, gMaxJSVersion, fileName, 1);
+    	subLoader.loadSubScript(uri, sandbox, "UTF-8");
     } catch (e) {
       if ("return not in function" == e.message) {
         // See #1592; we never anon wrap anymore, unless forced to by a return
@@ -147,8 +200,11 @@ function runScriptInSandbox(script, sandbox) {
             fileName,
             e.lineNumber
             );
+        
+        var code = GM_util.fileXHR(uri, "application/javascript");
+        
         Components.utils.evalInSandbox(
-            '(function(){ '+code+'\n})()', sandbox, gMaxJSVersion, fileName, 1);
+            '(function(){ '+code+'\n})()', sandbox, gMaxJSVersion, uri, 1);
       } else {
         // Otherwise raise.
         throw e;
@@ -157,12 +213,12 @@ function runScriptInSandbox(script, sandbox) {
   }
 
   // Eval the code, with a try/catch to report errors cleanly.
-  function evalWithCatch(code, fileName) {
+  function evalWithCatch(uri) {
     try {
-      evalWithWrapper(code, fileName);
+      evalWithWrapper(uri);
     } catch (e) {
       // Log it properly.
-      GM_util.logError(e, false, fileName, e.lineNumber);
+      GM_util.logError(e, false, e.fileName, e.lineNumber);
       // Stop the script, in the case of requires, as if it was one big script.
       return false;
     }
@@ -170,9 +226,9 @@ function runScriptInSandbox(script, sandbox) {
   }
 
   for (var i = 0, require = null; require = script.requires[i]; i++) {
-    if (!evalWithCatch(require.textContent, require.fileURL)) {
+    if (!evalWithCatch(require.fileURL)) {
       return;
     }
   }
-  evalWithCatch(script.textContent, script.fileURL);
+  evalWithCatch(script.fileURL);
 }
diff --git a/modules/util.js b/modules/util.js
index 874f3ba..b53a4ff 100644
--- a/modules/util.js
+++ b/modules/util.js
@@ -27,6 +27,7 @@ XPCOMUtils.defineLazyModuleGetter(GM_util, 'alert', 'chrome://greasemonkey-modul
 XPCOMUtils.defineLazyModuleGetter(GM_util, 'compareFirefoxVersion', 'chrome://greasemonkey-modules/content/util/compareFirefoxVersion.js');
 XPCOMUtils.defineLazyModuleGetter(GM_util, 'emptyEl', 'chrome://greasemonkey-modules/content/util/emptyEl.js');
 XPCOMUtils.defineLazyModuleGetter(GM_util, 'enqueueRemoveFile', 'chrome://greasemonkey-modules/content/util/enqueueRemoveFile.js');
+XPCOMUtils.defineLazyModuleGetter(GM_util, 'fileXHR', 'chrome://greasemonkey-modules/content/util/fileXHR.js');
 XPCOMUtils.defineLazyModuleGetter(GM_util, 'findMessageManager', 'chrome://greasemonkey-modules/content/util/findMessageManager.js');
 XPCOMUtils.defineLazyModuleGetter(GM_util, 'getBestLocaleMatch', 'chrome://greasemonkey-modules/content/util/getBestLocaleMatch.js');
 XPCOMUtils.defineLazyModuleGetter(GM_util, 'getBinaryContents', 'chrome://greasemonkey-modules/content/util/getBinaryContents.js');
diff --git a/modules/util/fileXHR.js b/modules/util/fileXHR.js
new file mode 100644
index 0000000..ccc13d2
--- /dev/null
+++ b/modules/util/fileXHR.js
@@ -0,0 +1,15 @@
+'use strict';
+
+var EXPORTED_SYMBOLS = ['fileXHR'];
+
+Components.utils.importGlobalProperties(["XMLHttpRequest"]);
+
+// sync XHR. it's just meant to fetch file:// uris that aren't otherwise accessible in content
+// don't use it in the parent process or for web URLs
+function fileXHR(uri, mimetype) {
+  var xhr = new XMLHttpRequest();
+  xhr.open("open", uri, false);
+  xhr.overrideMimeType(mimetype);
+  xhr.send(null);  
+  return xhr.responseText;
+}
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/greasemonkey.git



More information about the Pkg-mozext-commits mailing list