mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 20:01:50 +00:00
Bug 1845156 - Remove XPCOMUtils.defineLazyProxy r=arai,Gijs"
At this point, there's only one non-test use of this method in FindBarChild.sys.mjs which could be replaced with a simpler solution. Removing this method seems to lower memory usage a bit. https://treeherder.mozilla.org/perfherder/compare?originalProject=try&originalRevision=2dc498c7c81bd00c989cc3b69993ec1a53ff3032&newProject=try&newRevision=32669e95c9609cb07c258ca5fe964e9eb6411ade&page=1&framework=4 Differential Revision: https://phabricator.services.mozilla.com/D184403
This commit is contained in:
parent
d8ef20cc4f
commit
ca2d7cbfc2
@ -381,199 +381,12 @@ export var XPCOMUtils = {
|
||||
writable: false,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Defines a proxy which acts as a lazy object getter that can be passed
|
||||
* around as a reference, and will only be evaluated when something in
|
||||
* that object gets accessed.
|
||||
*
|
||||
* The evaluation can be triggered by a function call, by getting or
|
||||
* setting a property, calling this as a constructor, or enumerating
|
||||
* the properties of this object (e.g. during an iteration).
|
||||
*
|
||||
* Please note that, even after evaluated, the object given to you
|
||||
* remains being the proxy object (which forwards everything to the
|
||||
* real object). This is important to correctly use these objects
|
||||
* in pairs of add+remove listeners, for example.
|
||||
* If your use case requires access to the direct object, you can
|
||||
* get it through the untrap callback.
|
||||
*
|
||||
* @param aObject
|
||||
* The object to define the lazy getter on.
|
||||
*
|
||||
* You can pass null to aObject if you just want to get this
|
||||
* proxy through the return value.
|
||||
*
|
||||
* @param aName
|
||||
* The name of the getter to define on aObject.
|
||||
*
|
||||
* @param aInitFuncOrResource
|
||||
* A function or a module that defines what this object actually
|
||||
* should be when it gets evaluated. This will only ever be called once.
|
||||
*
|
||||
* Short-hand: If you pass a string to this parameter, it will be treated
|
||||
* as the URI of a module to be imported, and aName will be used as
|
||||
* the symbol to retrieve from the module.
|
||||
*
|
||||
* @param aStubProperties
|
||||
* In this parameter, you can provide an object which contains
|
||||
* properties from the original object that, when accessed, will still
|
||||
* prevent the entire object from being evaluated.
|
||||
*
|
||||
* These can be copies or simplified versions of the original properties.
|
||||
*
|
||||
* One example is to provide an alternative QueryInterface implementation
|
||||
* to avoid the entire object from being evaluated when it's added as an
|
||||
* observer (as addObserver calls object.QueryInterface(Ci.nsIObserver)).
|
||||
*
|
||||
* Once the object has been evaluated, the properties from the real
|
||||
* object will be used instead of the ones provided here.
|
||||
*
|
||||
* @param aUntrapCallback
|
||||
* A function that gets called once when the object has just been evaluated.
|
||||
* You can use this to do some work (e.g. setting properties) that you need
|
||||
* to do on this object but that can wait until it gets evaluated.
|
||||
*
|
||||
* Another use case for this is to use during code development to log when
|
||||
* this object gets evaluated, to make sure you're not accidentally triggering
|
||||
* it earlier than expected.
|
||||
*/
|
||||
defineLazyProxy(
|
||||
aObject,
|
||||
aName,
|
||||
aInitFuncOrResource,
|
||||
aStubProperties,
|
||||
aUntrapCallback
|
||||
) {
|
||||
let initFunc = aInitFuncOrResource;
|
||||
|
||||
if (typeof aInitFuncOrResource == "string") {
|
||||
initFunc = () => ChromeUtils.import(aInitFuncOrResource)[aName];
|
||||
}
|
||||
|
||||
let handler = new LazyProxyHandler(
|
||||
aName,
|
||||
initFunc,
|
||||
aStubProperties,
|
||||
aUntrapCallback
|
||||
);
|
||||
|
||||
/*
|
||||
* We cannot simply create a lazy getter for the underlying
|
||||
* object and pass it as the target of the proxy, because
|
||||
* just passing it in `new Proxy` means it would get
|
||||
* evaluated. Becase of this, a full handler needs to be
|
||||
* implemented (the LazyProxyHandler).
|
||||
*
|
||||
* So, an empty object is used as the target, and the handler
|
||||
* replaces it on every call with the real object.
|
||||
*/
|
||||
let proxy = new Proxy({}, handler);
|
||||
|
||||
if (aObject) {
|
||||
Object.defineProperty(aObject, aName, {
|
||||
value: proxy,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
|
||||
return proxy;
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(XPCOMUtils, "_scriptloader", () => {
|
||||
return Services.scriptloader;
|
||||
});
|
||||
|
||||
/**
|
||||
* LazyProxyHandler
|
||||
* This class implements the handler used
|
||||
* in the proxy from defineLazyProxy.
|
||||
*
|
||||
* This handler forwards all calls to an underlying object,
|
||||
* stored as `this.realObject`, which is obtained as the returned
|
||||
* value from aInitFunc, which will be called on the first time
|
||||
* time that it needs to be used (with an exception in the get() trap
|
||||
* for the properties provided in the `aStubProperties` parameter).
|
||||
*/
|
||||
|
||||
class LazyProxyHandler {
|
||||
constructor(aName, aInitFunc, aStubProperties, aUntrapCallback) {
|
||||
this.pending = true;
|
||||
this.name = aName;
|
||||
this.initFuncOrResource = aInitFunc;
|
||||
this.stubProperties = aStubProperties;
|
||||
this.untrapCallback = aUntrapCallback;
|
||||
}
|
||||
|
||||
getObject() {
|
||||
if (this.pending) {
|
||||
this.realObject = this.initFuncOrResource.call(null);
|
||||
|
||||
if (this.untrapCallback) {
|
||||
this.untrapCallback.call(null, this.realObject);
|
||||
this.untrapCallback = null;
|
||||
}
|
||||
|
||||
this.pending = false;
|
||||
this.stubProperties = null;
|
||||
}
|
||||
return this.realObject;
|
||||
}
|
||||
|
||||
getPrototypeOf(target) {
|
||||
return Reflect.getPrototypeOf(this.getObject());
|
||||
}
|
||||
|
||||
setPrototypeOf(target, prototype) {
|
||||
return Reflect.setPrototypeOf(this.getObject(), prototype);
|
||||
}
|
||||
|
||||
isExtensible(target) {
|
||||
return Reflect.isExtensible(this.getObject());
|
||||
}
|
||||
|
||||
preventExtensions(target) {
|
||||
return Reflect.preventExtensions(this.getObject());
|
||||
}
|
||||
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
return Reflect.getOwnPropertyDescriptor(this.getObject(), prop);
|
||||
}
|
||||
|
||||
defineProperty(target, prop, descriptor) {
|
||||
return Reflect.defineProperty(this.getObject(), prop, descriptor);
|
||||
}
|
||||
|
||||
has(target, prop) {
|
||||
return Reflect.has(this.getObject(), prop);
|
||||
}
|
||||
|
||||
get(target, prop, receiver) {
|
||||
if (
|
||||
this.pending &&
|
||||
this.stubProperties &&
|
||||
Object.prototype.hasOwnProperty.call(this.stubProperties, prop)
|
||||
) {
|
||||
return this.stubProperties[prop];
|
||||
}
|
||||
return Reflect.get(this.getObject(), prop, receiver);
|
||||
}
|
||||
|
||||
set(target, prop, value, receiver) {
|
||||
return Reflect.set(this.getObject(), prop, value, receiver);
|
||||
}
|
||||
|
||||
deleteProperty(target, prop) {
|
||||
return Reflect.deleteProperty(this.getObject(), prop);
|
||||
}
|
||||
|
||||
ownKeys(target) {
|
||||
return Reflect.ownKeys(this.getObject());
|
||||
}
|
||||
}
|
||||
|
||||
var XPCU_lazyPreferenceObserverQI = ChromeUtils.generateQI([
|
||||
"nsIObserver",
|
||||
"nsISupportsWeakReference",
|
||||
|
@ -1,113 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This file tests the method defineLazyProxy from XPCOMUtils.sys.mjs.
|
||||
*/
|
||||
|
||||
const {XPCOMUtils} = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs");
|
||||
|
||||
add_task(function test_lazy_proxy() {
|
||||
let tmp = {};
|
||||
let realObject = {
|
||||
"prop1": "value1",
|
||||
"prop2": "value2",
|
||||
};
|
||||
|
||||
let evaluated = false;
|
||||
let untrapCalled = false;
|
||||
|
||||
let lazyProxy = XPCOMUtils.defineLazyProxy(
|
||||
tmp,
|
||||
"myLazyProxy",
|
||||
|
||||
// Initiliazer function
|
||||
function init() {
|
||||
evaluated = true;
|
||||
return realObject;
|
||||
},
|
||||
|
||||
// Stub properties
|
||||
{
|
||||
"prop1": "stub"
|
||||
},
|
||||
|
||||
// Untrap callback
|
||||
function untrapCallback(obj) {
|
||||
Assert.equal(obj, realObject, "The underlying object can be obtained in the untrap callback");
|
||||
untrapCalled = true;
|
||||
}
|
||||
);
|
||||
|
||||
// Check that the proxy returned and the one
|
||||
// defined in tmp are the same.
|
||||
//
|
||||
// Note: Assert.strictEqual can't be used here
|
||||
// because it wants to stringify the two objects
|
||||
// compared, which defeats the lazy proxy.
|
||||
Assert.ok(lazyProxy === tmp.myLazyProxy, "Return value and object defined are the same");
|
||||
|
||||
Assert.ok(Cu.isProxy(lazyProxy), "Returned value is in fact a proxy");
|
||||
|
||||
// Check that just using the proxy above didn't
|
||||
// trigger the lazy getter evaluation.
|
||||
Assert.ok(!evaluated, "The lazy proxy hasn't been evaluated yet");
|
||||
Assert.ok(!untrapCalled, "The untrap callback hasn't been called yet");
|
||||
|
||||
// Accessing a stubbed property returns the stub
|
||||
// value and doesn't trigger evaluation.
|
||||
Assert.equal(lazyProxy.prop1, "stub", "Accessing a stubbed property returns the stubbed value");
|
||||
|
||||
Assert.ok(!evaluated, "The access to the stubbed property above didn't evaluate the lazy proxy");
|
||||
Assert.ok(!untrapCalled, "The untrap callback hasn't been called yet");
|
||||
|
||||
// Now the access to another property will trigger
|
||||
// the evaluation, as expected.
|
||||
Assert.equal(lazyProxy.prop2, "value2", "Property access is correctly forwarded to the underlying object");
|
||||
|
||||
Assert.ok(evaluated, "Accessing a non-stubbed property triggered the proxy evaluation");
|
||||
Assert.ok(untrapCalled, "The untrap callback was called");
|
||||
|
||||
// The value of prop1 is now the real value and not the stub value.
|
||||
Assert.equal(lazyProxy.prop1, "value1", "The value of prop1 is now the real value and not the stub one");
|
||||
});
|
||||
|
||||
add_task(function test_module_version() {
|
||||
// Test that passing a string instead of an initialization function
|
||||
// makes this behave like a lazy module getter.
|
||||
const TEST_FILE_URI = "resource://test/TestFile.jsm";
|
||||
let underlyingObject;
|
||||
|
||||
Cu.unload(TEST_FILE_URI);
|
||||
|
||||
let lazyProxy = XPCOMUtils.defineLazyProxy(
|
||||
null,
|
||||
"TestFile",
|
||||
TEST_FILE_URI,
|
||||
null, /* no stubs */
|
||||
function untrapCallback(object) {
|
||||
underlyingObject = object;
|
||||
}
|
||||
);
|
||||
|
||||
Assert.ok(!Cu.isModuleLoaded(TEST_FILE_URI), "The NetUtil module was not loaded by the lazy proxy definition");
|
||||
|
||||
// Access the object, which will evaluate the proxy.
|
||||
lazyProxy.foo = "bar";
|
||||
|
||||
// Module was loaded.
|
||||
Assert.ok(Cu.isModuleLoaded(TEST_FILE_URI), "The NetUtil module was loaded");
|
||||
|
||||
let { TestFile } = ChromeUtils.import(TEST_FILE_URI, {});
|
||||
|
||||
// Avoids a gigantic stringification in the logs.
|
||||
Assert.ok(TestFile === underlyingObject, "The module loaded is the same as the one directly obtained by ChromeUtils.import");
|
||||
|
||||
// Proxy correctly passed the setter to the underlying object.
|
||||
Assert.equal(TestFile.foo, "bar", "Proxy correctly passed the setter to the underlying object");
|
||||
|
||||
delete lazyProxy.foo;
|
||||
|
||||
// Proxy correctly passed the delete operation to the underlying object.
|
||||
Assert.ok(!TestFile.hasOwnProperty("foo"), "Proxy correctly passed the delete operation to the underlying object");
|
||||
});
|
@ -141,7 +141,6 @@ head = head_ongc.js
|
||||
[test_recursive_import.js]
|
||||
[test_xpcomutils.js]
|
||||
[test_unload.js]
|
||||
[test_lazyproxy.js]
|
||||
[test_attributes.js]
|
||||
[test_params.js]
|
||||
[test_tearoffs.js]
|
||||
|
@ -17,23 +17,36 @@ export class FindBarChild extends JSWindowActorChild {
|
||||
|
||||
this._findKey = null;
|
||||
|
||||
XPCOMUtils.defineLazyProxy(
|
||||
this,
|
||||
"FindBarContent",
|
||||
() => {
|
||||
const { FindBarContent } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FindBarContent.sys.mjs"
|
||||
);
|
||||
return new FindBarContent(this);
|
||||
},
|
||||
{ inQuickFind: false, inPassThrough: false }
|
||||
);
|
||||
this.inQuickFind = false;
|
||||
this.inPassThrough = false;
|
||||
|
||||
ChromeUtils.defineLazyGetter(this, "FindBarContent", () => {
|
||||
const { FindBarContent } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FindBarContent.sys.mjs"
|
||||
);
|
||||
|
||||
let findBarContent = new FindBarContent(this);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
inQuickFind: {
|
||||
get() {
|
||||
return findBarContent.inQuickFind;
|
||||
},
|
||||
},
|
||||
inPassThrough: {
|
||||
get() {
|
||||
return findBarContent.inPassThrough;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return findBarContent;
|
||||
});
|
||||
}
|
||||
|
||||
receiveMessage(msg) {
|
||||
if (msg.name == "Findbar:UpdateState") {
|
||||
let { FindBarContent } = this;
|
||||
FindBarContent.updateState(msg.data);
|
||||
this.FindBarContent.updateState(msg.data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,10 +78,8 @@ export class FindBarChild extends JSWindowActorChild {
|
||||
}
|
||||
|
||||
onKeypress(event) {
|
||||
let { FindBarContent } = this;
|
||||
|
||||
if (!FindBarContent.inPassThrough && this.eventMatchesFindShortcut(event)) {
|
||||
return FindBarContent.start(event);
|
||||
if (!this.inPassThrough && this.eventMatchesFindShortcut(event)) {
|
||||
return this.FindBarContent.start(event);
|
||||
}
|
||||
|
||||
// disable FAYT in about:blank to prevent FAYT opening unexpectedly.
|
||||
@ -88,17 +99,17 @@ export class FindBarChild extends JSWindowActorChild {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (FindBarContent.inPassThrough || FindBarContent.inQuickFind) {
|
||||
return FindBarContent.onKeypress(event);
|
||||
if (this.inPassThrough || this.inQuickFind) {
|
||||
return this.FindBarContent.onKeypress(event);
|
||||
}
|
||||
|
||||
if (event.charCode && this.shouldFastFind(event.target)) {
|
||||
let key = String.fromCharCode(event.charCode);
|
||||
if ((key == "/" || key == "'") && FindBarChild.manualFAYT) {
|
||||
return FindBarContent.startQuickFind(event);
|
||||
return this.FindBarContent.startQuickFind(event);
|
||||
}
|
||||
if (key != " " && FindBarChild.findAsYouType) {
|
||||
return FindBarContent.startQuickFind(event, true);
|
||||
return this.FindBarContent.startQuickFind(event, true);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -22,7 +22,6 @@ const callExpressionDefinitions = [
|
||||
/^ChromeUtils\.defineLazyGetter\((?:globalThis|this), "(\w+)"/,
|
||||
/^ChromeUtils\.defineModuleGetter\((?:globalThis|this), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyPreferenceGetter\((?:globalThis|this), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyProxy\((?:globalThis|this), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyScriptGetter\((?:globalThis|this), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyServiceGetter\((?:globalThis|this), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineConstant\((?:globalThis|this), "(\w+)"/,
|
||||
|
@ -17,7 +17,6 @@ const callExpressionDefinitions = [
|
||||
/^ChromeUtils\.defineLazyGetter\((?:globalThis|window), "(\w+)"/,
|
||||
/^ChromeUtils\.defineModuleGetter\((?:globalThis|window), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyPreferenceGetter\((?:globalThis|window), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyProxy\((?:globalThis|window), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyScriptGetter\((?:globalThis|window), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyServiceGetter\((?:globalThis|window), "(\w+)"/,
|
||||
/^XPCOMUtils\.defineConstant\((?:globalThis|window), "(\w+)"/,
|
||||
|
@ -30,7 +30,6 @@ const callExpressionDefinitions = [
|
||||
/^ChromeUtils\.defineLazyGetter\(lazy, "(\w+)"/,
|
||||
/^ChromeUtils\.defineModuleGetter\(lazy, "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyPreferenceGetter\(lazy, "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyProxy\(lazy, "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyScriptGetter\(lazy, "(\w+)"/,
|
||||
/^XPCOMUtils\.defineLazyServiceGetter\(lazy, "(\w+)"/,
|
||||
/^XPCOMUtils\.defineConstant\(lazy, "(\w+)"/,
|
||||
|
Loading…
x
Reference in New Issue
Block a user