-
Notifications
You must be signed in to change notification settings - Fork 54
/
XULStore.jsm
101 lines (84 loc) · 3.07 KB
/
XULStore.jsm
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
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// This JS module wraps the nsIXULStore XPCOM service with useful abstractions.
// In particular, it wraps the enumerators returned by getIDsEnumerator()
// and getAttributeEnumerator() in JS objects that implement the iterable
// protocol. It also implements the persist() method. JS consumers should use
// this module rather than accessing nsIXULStore directly.
const EXPORTED_SYMBOLS = ["XULStore"];
// Services.xulStore loads this module and returns its `XULStore` symbol
// when this implementation of XULStore is enabled, so using it here
// would loop infinitely. But the mozilla/use-services rule is a good
// requiremnt for every other consumer of XULStore.
// eslint-disable-next-line mozilla/use-services
const xulStore = Cc["@mozilla.org/xul/xulstore;1"].getService(Ci.nsIXULStore);
// Enables logging.
const debugMode = false;
// Internal function for logging debug messages to the Error Console window
function log(message) {
if (!debugMode) {
return;
}
console.log("XULStore: " + message);
}
const XULStore = {
setValue: xulStore.setValue,
hasValue: xulStore.hasValue,
getValue: xulStore.getValue,
removeValue: xulStore.removeValue,
removeDocument: xulStore.removeDocument,
/**
* Sets a value for a specified node's attribute, except in
* the case below:
* If the value is empty and if calling `hasValue` with the node's
* document and ID and `attr` would return true, then the
* value instead gets removed from the store (see Bug 1476680).
*
* @param node - DOM node
* @param attr - attribute to store
*/
persist(node, attr) {
if (!node.id) {
throw new Error("Node without ID passed into persist()");
}
const uri = node.ownerDocument.documentURI;
const value = node.getAttribute(attr);
if (node.localName == "window") {
log("Persisting attributes to windows is handled by AppWindow.");
return;
}
// See Bug 1476680 - we could drop the `hasValue` check so that
// any time there's an empty attribute it gets removed from the
// store. Since this is copying behavior from document.persist,
// callers would need to be updated with that change.
if (!value && xulStore.hasValue(uri, node.id, attr)) {
xulStore.removeValue(uri, node.id, attr);
} else {
xulStore.setValue(uri, node.id, attr, value);
}
},
getIDsEnumerator(docURI) {
return new XULStoreEnumerator(xulStore.getIDsEnumerator(docURI));
},
getAttributeEnumerator(docURI, id) {
return new XULStoreEnumerator(xulStore.getAttributeEnumerator(docURI, id));
},
};
class XULStoreEnumerator {
constructor(enumerator) {
this.enumerator = enumerator;
}
hasMore() {
return this.enumerator.hasMore();
}
getNext() {
return this.enumerator.getNext();
}
*[Symbol.iterator]() {
while (this.enumerator.hasMore()) {
yield this.enumerator.getNext();
}
}
}