Revision 261548ff
Added by koszko about 2 years ago
background/storage.js | ||
---|---|---|
5 | 5 |
* Redistribution terms are gathered in the `copyright' file. |
6 | 6 |
*/ |
7 | 7 |
|
8 |
"use strict"; |
|
9 |
|
|
10 |
(() => { |
|
11 |
const TYPE_PREFIX = window.TYPE_PREFIX; |
|
12 |
const TYPE_NAME = window.TYPE_NAME; |
|
13 |
const list_prefixes = window.list_prefixes; |
|
14 |
const make_lock = window.make_lock; |
|
15 |
const lock = window.lock; |
|
16 |
const unlock = window.unlock; |
|
17 |
const make_once = window.make_once; |
|
18 |
const browser = window.browser; |
|
19 |
const is_chrome = window.is_chrome; |
|
20 |
|
|
21 |
var exports = {}; |
|
22 |
|
|
23 |
/* We're yet to decide how to handle errors... */ |
|
24 |
|
|
25 |
/* Here are some basic wrappers for storage API functions */ |
|
26 |
|
|
27 |
async function get(key) |
|
28 |
{ |
|
29 |
try { |
|
30 |
/* Fix for fact that Chrome does not use promises here */ |
|
31 |
let promise = is_chrome ? |
|
32 |
new Promise((resolve, reject) => |
|
33 |
chrome.storage.local.get(key, |
|
34 |
val => resolve(val))) : |
|
35 |
browser.storage.local.get(key); |
|
36 |
|
|
37 |
return (await promise)[key]; |
|
38 |
} catch (e) { |
|
39 |
console.log(e); |
|
40 |
} |
|
41 |
} |
|
8 |
/* |
|
9 |
* IMPORTS_START |
|
10 |
* IMPORT TYPE_PREFIX |
|
11 |
* IMPORT TYPE_NAME |
|
12 |
* IMPORT list_prefixes |
|
13 |
* IMPORT make_lock |
|
14 |
* IMPORT lock |
|
15 |
* IMPORT unlock |
|
16 |
* IMPORT make_once |
|
17 |
* IMPORT browser |
|
18 |
* IMPORT is_chrome |
|
19 |
* IMPORTS_END |
|
20 |
*/ |
|
42 | 21 |
|
43 |
async function set(key, value) |
|
44 |
{ |
|
45 |
try { |
|
46 |
return browser.storage.local.set({[key]: value}); |
|
47 |
} catch (e) { |
|
48 |
console.log(e); |
|
49 |
} |
|
50 |
} |
|
22 |
var exports = {}; |
|
51 | 23 |
|
52 |
async function setn(keys_and_values) |
|
53 |
{ |
|
54 |
let obj = Object(); |
|
55 |
while (keys_and_values.length > 1) { |
|
56 |
let value = keys_and_values.pop(); |
|
57 |
let key = keys_and_values.pop(); |
|
58 |
obj[key] = value; |
|
59 |
} |
|
24 |
/* We're yet to decide how to handle errors... */ |
|
60 | 25 |
|
61 |
try { |
|
62 |
return browser.storage.local.set(obj); |
|
63 |
} catch (e) { |
|
64 |
console.log(e); |
|
65 |
} |
|
66 |
} |
|
26 |
/* Here are some basic wrappers for storage API functions */ |
|
67 | 27 |
|
68 |
async function set_var(name, value) |
|
69 |
{ |
|
70 |
return set(TYPE_PREFIX.VAR + name, value); |
|
71 |
} |
|
28 |
async function get(key) |
|
29 |
{ |
|
30 |
try { |
|
31 |
/* Fix for fact that Chrome does not use promises here */ |
|
32 |
let promise = is_chrome ? |
|
33 |
new Promise((resolve, reject) => |
|
34 |
chrome.storage.local.get(key, |
|
35 |
val => resolve(val))) : |
|
36 |
browser.storage.local.get(key); |
|
72 | 37 |
|
73 |
async function get_var(name) |
|
74 |
{ |
|
75 |
return get(TYPE_PREFIX.VAR + name); |
|
38 |
return (await promise)[key]; |
|
39 |
} catch (e) { |
|
40 |
console.log(e); |
|
41 |
} |
|
42 |
} |
|
43 |
|
|
44 |
async function set(key, value) |
|
45 |
{ |
|
46 |
try { |
|
47 |
return browser.storage.local.set({[key]: value}); |
|
48 |
} catch (e) { |
|
49 |
console.log(e); |
|
50 |
} |
|
51 |
} |
|
52 |
|
|
53 |
async function setn(keys_and_values) |
|
54 |
{ |
|
55 |
let obj = Object(); |
|
56 |
while (keys_and_values.length > 1) { |
|
57 |
let value = keys_and_values.pop(); |
|
58 |
let key = keys_and_values.pop(); |
|
59 |
obj[key] = value; |
|
76 | 60 |
} |
77 | 61 |
|
78 |
/* |
|
79 |
* A special case of persisted variable is one that contains list |
|
80 |
* of items. |
|
81 |
*/ |
|
82 |
|
|
83 |
async function get_list_var(name) |
|
84 |
{ |
|
85 |
let list = await get_var(name); |
|
86 |
|
|
87 |
return list === undefined ? [] : list; |
|
62 |
try { |
|
63 |
return browser.storage.local.set(obj); |
|
64 |
} catch (e) { |
|
65 |
console.log(e); |
|
88 | 66 |
} |
67 |
} |
|
89 | 68 |
|
90 |
/* We maintain in-memory copies of some stored lists. */ |
|
69 |
async function set_var(name, value) |
|
70 |
{ |
|
71 |
return set(TYPE_PREFIX.VAR + name, value); |
|
72 |
} |
|
91 | 73 |
|
92 |
async function list(prefix)
|
|
93 |
{
|
|
94 |
let name = TYPE_NAME[prefix] + "s"; /* Make plural. */
|
|
95 |
let map = new Map();
|
|
74 |
async function get_var(name)
|
|
75 |
{ |
|
76 |
return get(TYPE_PREFIX.VAR + name);
|
|
77 |
}
|
|
96 | 78 |
|
97 |
for (let item of await get_list_var(name)) |
|
98 |
map.set(item, await get(prefix + item)); |
|
79 |
/* |
|
80 |
* A special case of persisted variable is one that contains list |
|
81 |
* of items. |
|
82 |
*/ |
|
99 | 83 |
|
100 |
return {map, prefix, name, listeners : new Set(), lock : make_lock()}; |
|
101 |
} |
|
84 |
async function get_list_var(name) |
|
85 |
{ |
|
86 |
let list = await get_var(name); |
|
102 | 87 |
|
103 |
var pages; |
|
104 |
var bags; |
|
105 |
var scripts; |
|
88 |
return list === undefined ? [] : list; |
|
89 |
} |
|
106 | 90 |
|
107 |
var list_by_prefix = {};
|
|
91 |
/* We maintain in-memory copies of some stored lists. */
|
|
108 | 92 |
|
109 |
async function init()
|
|
110 |
{
|
|
111 |
for (let prefix of list_prefixes)
|
|
112 |
list_by_prefix[prefix] = await list(prefix);
|
|
93 |
async function list(prefix)
|
|
94 |
{ |
|
95 |
let name = TYPE_NAME[prefix] + "s"; /* Make plural. */
|
|
96 |
let map = new Map();
|
|
113 | 97 |
|
114 |
return exports;
|
|
115 |
}
|
|
98 |
for (let item of await get_list_var(name))
|
|
99 |
map.set(item, await get(prefix + item));
|
|
116 | 100 |
|
117 |
/* |
|
118 |
* Facilitate listening to changes |
|
119 |
*/ |
|
101 |
return {map, prefix, name, listeners : new Set(), lock : make_lock()}; |
|
102 |
} |
|
120 | 103 |
|
121 |
exports.add_change_listener = function (cb, prefixes=list_prefixes) |
|
122 |
{ |
|
123 |
if (typeof(prefixes) === "string") |
|
124 |
prefixes = [prefixes]; |
|
104 |
var pages; |
|
105 |
var bags; |
|
106 |
var scripts; |
|
125 | 107 |
|
126 |
for (let prefix of prefixes) |
|
127 |
list_by_prefix[prefix].listeners.add(cb); |
|
128 |
} |
|
108 |
var list_by_prefix = {}; |
|
129 | 109 |
|
130 |
exports.remove_change_listener = function (cb, prefixes=list_prefixes)
|
|
131 |
{
|
|
132 |
if (typeof(prefixes) === "string")
|
|
133 |
prefixes = [prefixes];
|
|
110 |
async function init()
|
|
111 |
{ |
|
112 |
for (let prefix of list_prefixes)
|
|
113 |
list_by_prefix[prefix] = await list(prefix);
|
|
134 | 114 |
|
135 |
for (let prefix of prefixes) |
|
136 |
list_by_prefix[prefix].listeners.delete(cb); |
|
137 |
} |
|
115 |
return exports; |
|
116 |
} |
|
138 | 117 |
|
139 |
function broadcast_change(change, list) |
|
140 |
{ |
|
141 |
for (let listener_callback of list.listeners) |
|
142 |
listener_callback(change); |
|
143 |
} |
|
118 |
/* |
|
119 |
* Facilitate listening to changes |
|
120 |
*/ |
|
144 | 121 |
|
145 |
/* Prepare some hepler functions to get elements of a list */ |
|
122 |
exports.add_change_listener = function (cb, prefixes=list_prefixes) |
|
123 |
{ |
|
124 |
if (typeof(prefixes) === "string") |
|
125 |
prefixes = [prefixes]; |
|
146 | 126 |
|
147 |
function list_items_it(list, with_values=false) |
|
148 |
{ |
|
149 |
return with_values ? list.map.entries() : list.map.keys(); |
|
150 |
} |
|
127 |
for (let prefix of prefixes) |
|
128 |
list_by_prefix[prefix].listeners.add(cb); |
|
129 |
} |
|
151 | 130 |
|
152 |
function list_entries_it(list)
|
|
153 |
{
|
|
154 |
return list_items_it(list, true);
|
|
155 |
}
|
|
131 |
exports.remove_change_listener = function (cb, prefixes=list_prefixes)
|
|
132 |
{ |
|
133 |
if (typeof(prefixes) === "string")
|
|
134 |
prefixes = [prefixes];
|
|
156 | 135 |
|
157 |
function list_items(list, with_values=false)
|
|
158 |
{
|
|
159 |
let array = [];
|
|
136 |
for (let prefix of prefixes)
|
|
137 |
list_by_prefix[prefix].listeners.delete(cb);
|
|
138 |
}
|
|
160 | 139 |
|
161 |
for (let item of list_items_it(list, with_values)) |
|
162 |
array.push(item); |
|
140 |
function broadcast_change(change, list) |
|
141 |
{ |
|
142 |
for (let listener_callback of list.listeners) |
|
143 |
listener_callback(change); |
|
144 |
} |
|
163 | 145 |
|
164 |
return array; |
|
165 |
} |
|
146 |
/* Prepare some hepler functions to get elements of a list */ |
|
166 | 147 |
|
167 |
function list_entries(list)
|
|
168 |
{
|
|
169 |
return list_items(list, true);
|
|
170 |
}
|
|
148 |
function list_items_it(list, with_values=false)
|
|
149 |
{ |
|
150 |
return with_values ? list.map.entries() : list.map.keys();
|
|
151 |
} |
|
171 | 152 |
|
172 |
/* |
|
173 |
* Below we make additional effort to update map of given kind of items |
|
174 |
* every time an item is added/removed to keep everything coherent. |
|
175 |
*/ |
|
176 |
async function set_item(item, value, list) |
|
177 |
{ |
|
178 |
await lock(list.lock); |
|
179 |
let result = await _set_item(...arguments); |
|
180 |
unlock(list.lock) |
|
181 |
return result; |
|
182 |
} |
|
183 |
async function _set_item(item, value, list) |
|
184 |
{ |
|
185 |
let key = list.prefix + item; |
|
186 |
let old_val = list.map.get(item); |
|
187 |
if (old_val === undefined) { |
|
188 |
let items = list_items(list); |
|
189 |
items.push(item); |
|
190 |
await setn([key, value, "_" + list.name, items]); |
|
191 |
} else { |
|
192 |
await set(key, value); |
|
193 |
} |
|
153 |
function list_entries_it(list) |
|
154 |
{ |
|
155 |
return list_items_it(list, true); |
|
156 |
} |
|
194 | 157 |
|
195 |
list.map.set(item, value) |
|
158 |
function list_items(list, with_values=false) |
|
159 |
{ |
|
160 |
let array = []; |
|
196 | 161 |
|
197 |
let change = { |
|
198 |
prefix : list.prefix, |
|
199 |
item, |
|
200 |
old_val, |
|
201 |
new_val : value |
|
202 |
}; |
|
162 |
for (let item of list_items_it(list, with_values)) |
|
163 |
array.push(item); |
|
203 | 164 |
|
204 |
broadcast_change(change, list); |
|
165 |
return array; |
|
166 |
} |
|
205 | 167 |
|
206 |
return old_val; |
|
207 |
} |
|
168 |
function list_entries(list) |
|
169 |
{ |
|
170 |
return list_items(list, true); |
|
171 |
} |
|
208 | 172 |
|
209 |
// TODO: The actual idea to set value to undefined is good - this way we can |
|
210 |
// also set a new list of items in the same API call. But such key |
|
211 |
// is still stored in the storage. We need to somehow remove it later. |
|
212 |
// For that, we're going to have to store 1 more list of each kind. |
|
213 |
async function remove_item(item, list) |
|
214 |
{ |
|
215 |
await lock(list.lock); |
|
216 |
let result = await _remove_item(...arguments); |
|
217 |
unlock(list.lock) |
|
218 |
return result; |
|
173 |
/* |
|
174 |
* Below we make additional effort to update map of given kind of items |
|
175 |
* every time an item is added/removed to keep everything coherent. |
|
176 |
*/ |
|
177 |
async function set_item(item, value, list) |
|
178 |
{ |
|
179 |
await lock(list.lock); |
|
180 |
let result = await _set_item(...arguments); |
|
181 |
unlock(list.lock) |
|
182 |
return result; |
|
183 |
} |
|
184 |
async function _set_item(item, value, list) |
|
185 |
{ |
|
186 |
let key = list.prefix + item; |
|
187 |
let old_val = list.map.get(item); |
|
188 |
if (old_val === undefined) { |
|
189 |
let items = list_items(list); |
|
190 |
items.push(item); |
|
191 |
await setn([key, value, "_" + list.name, items]); |
|
192 |
} else { |
|
193 |
await set(key, value); |
|
219 | 194 |
} |
220 |
async function _remove_item(item, list) |
|
221 |
{ |
|
222 |
let old_val = list.map.get(item); |
|
195 |
|
|
196 |
list.map.set(item, value) |
|
197 |
|
|
198 |
let change = { |
|
199 |
prefix : list.prefix, |
|
200 |
item, |
|
201 |
old_val, |
|
202 |
new_val : value |
|
203 |
}; |
|
204 |
|
|
205 |
broadcast_change(change, list); |
|
206 |
|
|
207 |
return old_val; |
|
208 |
} |
|
209 |
|
|
210 |
// TODO: The actual idea to set value to undefined is good - this way we can |
|
211 |
// also set a new list of items in the same API call. But such key |
|
212 |
// is still stored in the storage. We need to somehow remove it later. |
|
213 |
// For that, we're going to have to store 1 more list of each kind. |
|
214 |
async function remove_item(item, list) |
|
215 |
{ |
|
216 |
await lock(list.lock); |
|
217 |
let result = await _remove_item(...arguments); |
|
218 |
unlock(list.lock) |
|
219 |
return result; |
|
220 |
} |
|
221 |
async function _remove_item(item, list) |
|
222 |
{ |
|
223 |
let old_val = list.map.get(item); |
|
224 |
if (old_val === undefined) |
|
225 |
return; |
|
226 |
|
|
227 |
let key = list.prefix + item; |
|
228 |
let items = list_items(list); |
|
229 |
let index = items.indexOf(item); |
|
230 |
items.splice(index, 1); |
|
231 |
|
|
232 |
await setn([key, undefined, "_" + list.name, items]); |
|
233 |
|
|
234 |
list.map.delete(item); |
|
235 |
|
|
236 |
let change = { |
|
237 |
prefix : list.prefix, |
|
238 |
item, |
|
239 |
old_val, |
|
240 |
new_val : undefined |
|
241 |
}; |
|
242 |
|
|
243 |
broadcast_change(change, list); |
|
244 |
|
|
245 |
return old_val; |
|
246 |
} |
|
247 |
|
|
248 |
// TODO: same as above applies here |
|
249 |
async function replace_item(old_item, new_item, list, new_val=undefined) |
|
250 |
{ |
|
251 |
await lock(list.lock); |
|
252 |
let result = await _replace_item(...arguments); |
|
253 |
unlock(list.lock) |
|
254 |
return result; |
|
255 |
} |
|
256 |
async function _replace_item(old_item, new_item, list, new_val=undefined) |
|
257 |
{ |
|
258 |
let old_val = list.map.get(old_item); |
|
259 |
if (new_val === undefined) { |
|
223 | 260 |
if (old_val === undefined) |
224 | 261 |
return; |
225 |
|
|
226 |
let key = list.prefix + item; |
|
227 |
let items = list_items(list); |
|
228 |
let index = items.indexOf(item); |
|
229 |
items.splice(index, 1); |
|
230 |
|
|
231 |
await setn([key, undefined, "_" + list.name, items]); |
|
232 |
|
|
233 |
list.map.delete(item); |
|
234 |
|
|
235 |
let change = { |
|
236 |
prefix : list.prefix, |
|
237 |
item, |
|
238 |
old_val, |
|
239 |
new_val : undefined |
|
240 |
}; |
|
241 |
|
|
242 |
broadcast_change(change, list); |
|
243 |
|
|
262 |
new_val = old_val |
|
263 |
} else if (new_val === old_val && new_item === old_item) { |
|
244 | 264 |
return old_val; |
245 | 265 |
} |
246 | 266 |
|
247 |
// TODO: same as above applies here |
|
248 |
async function replace_item(old_item, new_item, list, new_val=undefined) |
|
249 |
{ |
|
250 |
await lock(list.lock); |
|
251 |
let result = await _replace_item(...arguments); |
|
252 |
unlock(list.lock) |
|
253 |
return result; |
|
267 |
if (old_item === new_item || old_val === undefined) { |
|
268 |
await _set_item(new_item, new_val, list); |
|
269 |
return old_val; |
|
254 | 270 |
} |
255 |
async function _replace_item(old_item, new_item, list, new_val=undefined) |
|
256 |
{ |
|
257 |
let old_val = list.map.get(old_item); |
|
258 |
if (new_val === undefined) { |
|
259 |
if (old_val === undefined) |
|
260 |
return; |
|
261 |
new_val = old_val |
|
262 |
} else if (new_val === old_val && new_item === old_item) { |
|
263 |
return old_val; |
|
264 |
} |
|
265 | 271 |
|
266 |
if (old_item === new_item || old_val === undefined) { |
|
267 |
await _set_item(new_item, new_val, list); |
|
268 |
return old_val; |
|
269 |
} |
|
272 |
let new_key = list.prefix + new_item; |
|
273 |
let old_key = list.prefix + old_item; |
|
274 |
let items = list_items(list); |
|
275 |
let index = items.indexOf(old_item); |
|
276 |
items[index] = new_item; |
|
277 |
await setn([old_key, undefined, new_key, new_val, |
|
278 |
"_" + list.name, items]); |
|
270 | 279 |
|
271 |
let new_key = list.prefix + new_item; |
|
272 |
let old_key = list.prefix + old_item; |
|
273 |
let items = list_items(list); |
|
274 |
let index = items.indexOf(old_item); |
|
275 |
items[index] = new_item; |
|
276 |
await setn([old_key, undefined, new_key, new_val, |
|
277 |
"_" + list.name, items]); |
|
280 |
list.map.delete(old_item); |
|
278 | 281 |
|
279 |
list.map.delete(old_item); |
|
282 |
let change = { |
|
283 |
prefix : list.prefix, |
|
284 |
item : old_item, |
|
285 |
old_val, |
|
286 |
new_val : undefined |
|
287 |
}; |
|
280 | 288 |
|
281 |
let change = { |
|
282 |
prefix : list.prefix, |
|
283 |
item : old_item, |
|
284 |
old_val, |
|
285 |
new_val : undefined |
|
286 |
}; |
|
289 |
broadcast_change(change, list); |
|
287 | 290 |
|
288 |
broadcast_change(change, list);
|
|
291 |
list.map.set(new_item, new_val);
|
|
289 | 292 |
|
290 |
list.map.set(new_item, new_val); |
|
293 |
change.item = new_item; |
|
294 |
change.old_val = undefined; |
|
295 |
change.new_val = new_val; |
|
291 | 296 |
|
292 |
change.item = new_item; |
|
293 |
change.old_val = undefined; |
|
294 |
change.new_val = new_val; |
|
297 |
broadcast_change(change, list); |
|
295 | 298 |
|
296 |
broadcast_change(change, list); |
|
297 |
|
|
298 |
return old_val; |
|
299 |
} |
|
299 |
return old_val; |
|
300 |
} |
|
300 | 301 |
|
301 |
/* |
|
302 |
* For scripts, item name is chosen by user, data should be |
|
303 |
* an object containing: |
|
304 |
* - script's url and hash or |
|
305 |
* - script's text or |
|
306 |
* - all three |
|
307 |
*/ |
|
308 |
|
|
309 |
/* |
|
310 |
* For bags, item name is chosen by user, data is an array of 2-element |
|
311 |
* arrays with type prefix and script/bag names. |
|
312 |
*/ |
|
313 |
|
|
314 |
/* |
|
315 |
* For pages data argument is an object with properties `allow' |
|
316 |
* and `components'. Item name is url. |
|
317 |
*/ |
|
318 |
|
|
319 |
exports.set = async function (prefix, item, data) |
|
320 |
{ |
|
321 |
return set_item(item, data, list_by_prefix[prefix]); |
|
322 |
} |
|
302 |
/* |
|
303 |
* For scripts, item name is chosen by user, data should be |
|
304 |
* an object containing: |
|
305 |
* - script's url and hash or |
|
306 |
* - script's text or |
|
307 |
* - all three |
|
308 |
*/ |
|
323 | 309 |
|
324 |
exports.get = function (prefix, item)
|
|
325 |
{
|
|
326 |
return list_by_prefix[prefix].map.get(item);
|
|
327 |
}
|
|
310 |
/*
|
|
311 |
* For bags, item name is chosen by user, data is an array of 2-element
|
|
312 |
* arrays with type prefix and script/bag names.
|
|
313 |
*/
|
|
328 | 314 |
|
329 |
exports.remove = async function (prefix, item)
|
|
330 |
{
|
|
331 |
return remove_item(item, list_by_prefix[prefix]);
|
|
332 |
}
|
|
315 |
/*
|
|
316 |
* For pages data argument is an object with properties `allow'
|
|
317 |
* and `components'. Item name is url.
|
|
318 |
*/
|
|
333 | 319 |
|
334 |
exports.replace = async function (prefix, old_item, new_item, |
|
335 |
new_data=undefined) |
|
336 |
{ |
|
337 |
return replace_item(old_item, new_item, list_by_prefix[prefix], |
|
338 |
new_data); |
|
339 |
} |
|
320 |
exports.set = async function (prefix, item, data) |
|
321 |
{ |
|
322 |
return set_item(item, data, list_by_prefix[prefix]); |
|
323 |
} |
|
324 |
|
|
325 |
exports.get = function (prefix, item) |
|
326 |
{ |
|
327 |
return list_by_prefix[prefix].map.get(item); |
|
328 |
} |
|
329 |
|
|
330 |
exports.remove = async function (prefix, item) |
|
331 |
{ |
|
332 |
return remove_item(item, list_by_prefix[prefix]); |
|
333 |
} |
|
334 |
|
|
335 |
exports.replace = async function (prefix, old_item, new_item, |
|
336 |
new_data=undefined) |
|
337 |
{ |
|
338 |
return replace_item(old_item, new_item, list_by_prefix[prefix], |
|
339 |
new_data); |
|
340 |
} |
|
341 |
|
|
342 |
exports.get_all_names = function (prefix) |
|
343 |
{ |
|
344 |
return list_items(list_by_prefix[prefix]); |
|
345 |
} |
|
346 |
|
|
347 |
exports.get_all_names_it = function (prefix) |
|
348 |
{ |
|
349 |
return list_items_it(list_by_prefix[prefix]); |
|
350 |
} |
|
351 |
|
|
352 |
exports.get_all = function (prefix) |
|
353 |
{ |
|
354 |
return list_entries(list_by_prefix[prefix]); |
|
355 |
} |
|
356 |
|
|
357 |
exports.get_all_it = function (prefix) |
|
358 |
{ |
|
359 |
return list_entries_it(list_by_prefix[prefix]); |
|
360 |
} |
|
361 |
|
|
362 |
/* Finally, a quick way to wipe all the data. */ |
|
363 |
// TODO: maybe delete items in such order that none of them ever references |
|
364 |
// an already-deleted one? |
|
365 |
exports.clear = async function () |
|
366 |
{ |
|
367 |
let lists = list_prefixes.map((p) => list_by_prefix[p]); |
|
368 |
|
|
369 |
for (let list of lists) |
|
370 |
await lock(list.lock); |
|
340 | 371 |
|
341 |
exports.get_all_names = function (prefix) |
|
342 |
{ |
|
343 |
return list_items(list_by_prefix[prefix]); |
|
344 |
} |
|
372 |
for (let list of lists) { |
|
345 | 373 |
|
346 |
exports.get_all_names_it = function (prefix)
|
|
347 |
{
|
|
348 |
return list_items_it(list_by_prefix[prefix]);
|
|
349 |
}
|
|
374 |
let change = {
|
|
375 |
prefix : list.prefix,
|
|
376 |
new_val : undefined
|
|
377 |
};
|
|
350 | 378 |
|
351 |
exports.get_all = function (prefix) |
|
352 |
{ |
|
353 |
return list_entries(list_by_prefix[prefix]); |
|
354 |
} |
|
379 |
for (let [item, val] of list_entries_it(list)) { |
|
380 |
change.item = item; |
|
381 |
change.old_val = val; |
|
382 |
broadcast_change(change, list); |
|
383 |
} |
|
355 | 384 |
|
356 |
exports.get_all_it = function (prefix) |
|
357 |
{ |
|
358 |
return list_entries_it(list_by_prefix[prefix]); |
|
385 |
list.map = new Map(); |
|
359 | 386 |
} |
360 | 387 |
|
361 |
/* Finally, a quick way to wipe all the data. */ |
|
362 |
// TODO: maybe delete items in such order that none of them ever references |
|
363 |
// an already-deleted one? |
|
364 |
exports.clear = async function () |
|
365 |
{ |
|
366 |
let lists = list_prefixes.map((p) => list_by_prefix[p]); |
|
367 |
|
|
368 |
for (let list of lists) |
|
369 |
await lock(list.lock); |
|
370 |
|
|
371 |
for (let list of lists) { |
|
372 |
|
|
373 |
let change = { |
|
374 |
prefix : list.prefix, |
|
375 |
new_val : undefined |
|
376 |
}; |
|
388 |
await browser.storage.local.clear(); |
|
377 | 389 |
|
378 |
for (let [item, val] of list_entries_it(list)) { |
|
379 |
change.item = item; |
|
380 |
change.old_val = val; |
|
381 |
broadcast_change(change, list); |
|
382 |
} |
|
390 |
for (let list of lists) |
|
391 |
unlock(list.lock); |
|
392 |
} |
|
383 | 393 |
|
384 |
list.map = new Map(); |
|
385 |
} |
|
386 |
|
|
387 |
await browser.storage.local.clear(); |
|
394 |
const get_storage = make_once(init); |
|
388 | 395 |
|
389 |
for (let list of lists) |
|
390 |
unlock(list.lock); |
|
391 |
} |
|
392 |
|
|
393 |
window.get_storage = make_once(init); |
|
394 |
})(); |
|
396 |
/* |
|
397 |
* EXPORTS_START |
|
398 |
* EXPORT get_storage |
|
399 |
* EXPORTS_END |
|
400 |
*/ |
Also available in: Unified diff
emply an sh-based build system; make some changes to blocking