1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
/* 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");
});
|