[BUG] Is it something wrong with this part of code?
cyfung1031 opened this issue · comments
cyfung1031 commented
violentmonkey/src/injected/web/gm-api.js
Lines 15 to 140 in f3b9fb2
bound: { | |
__proto__: null, | |
/** @this {GMContext} */ | |
GM_deleteValue(key) { | |
const { id } = this; | |
const values = loadValues(id); | |
const oldRaw = values[key]; | |
delete values[key]; | |
// using `undefined` to match the documentation and TM for GM_addValueChangeListener | |
return dumpValue(id, key, undefined, null, oldRaw, this); | |
}, | |
/** @this {GMContext} */ | |
GM_getValue(key, def) { | |
const raw = loadValues(this.id)[key]; | |
return resolveOrReturn(this, raw ? decodeValue(raw) : def); | |
}, | |
/** @this {GMContext} */ | |
GM_listValues() { | |
return resolveOrReturn(this, objectKeys(loadValues(this.id))); | |
}, | |
/** @this {GMContext} */ | |
GM_setValue(key, val) { | |
const { id } = this; | |
const raw = dumpScriptValue(val, jsonDump) || null; | |
const values = loadValues(id); | |
const oldRaw = values[key]; | |
values[key] = raw; | |
return dumpValue(id, key, val, raw, oldRaw, this); | |
}, | |
/** | |
* @callback GMValueChangeListener | |
* @param {String} key | |
* @param {?} oldValue - `undefined` means value was created | |
* @param {?} newValue - `undefined` means value was removed | |
* @param {boolean} remote - `true` means value was modified in another tab | |
*/ | |
/** | |
* @this {GMContext} | |
* @param {String} key - name of the value to monitor | |
* @param {GMValueChangeListener} fn - callback | |
* @returns {String} listenerId | |
*/ | |
GM_addValueChangeListener(key, fn) { | |
if (!isString(key)) key = `${key}`; | |
if (!isFunction(fn)) return; | |
const hooks = ensureNestedProp(changeHooks, this.id, key); | |
const i = objectValues(hooks)::indexOf(fn); | |
let listenerId = i >= 0 && objectKeys(hooks)[i]; | |
if (!listenerId) { | |
listenerId = safeGetUniqId('VMvc'); | |
hooks[listenerId] = fn; | |
} | |
return listenerId; | |
}, | |
/** | |
* @this {GMContext} | |
* @param {String} listenerId | |
*/ | |
GM_removeValueChangeListener(listenerId) { | |
const keyHooks = changeHooks[this.id]; | |
if (!keyHooks) return; | |
if (process.env.DEBUG) throwIfProtoPresent(keyHooks); | |
for (const key in keyHooks) { /* proto is null */// eslint-disable-line guard-for-in | |
const hooks = keyHooks[key]; | |
if (listenerId in hooks) { | |
delete hooks[listenerId]; | |
if (isEmpty(hooks)) delete keyHooks[key]; | |
break; | |
} | |
} | |
if (isEmpty(keyHooks)) delete changeHooks[this.id]; | |
}, | |
/** @this {GMContext} */ | |
GM_getResourceText(name) { | |
return getResource(this, name); | |
}, | |
GM_getResourceURL: gmGetResourceURL, | |
/** @this {GMContext} */ | |
GM_registerMenuCommand(text, cb, opts) { | |
opts = nullObjFrom(opts); | |
opts.text = text = `${text}`; | |
if (!text) throw new SafeError('Menu caption text is required!'); | |
const { id } = this; | |
const key = opts.id || text; | |
const cmd = ensureNestedProp(commands, id, key); | |
cmd.cb = cb; | |
cmd.text = text; | |
bridge.post('RegisterMenu', { id, key, val: opts }); | |
return key; | |
}, | |
/** @this {GMContext} */ | |
GM_unregisterMenuCommand(key) { | |
const { id } = this; | |
const hub = commands[id]; | |
if (hub && (hub[key] || (key = findCommandIdByText(key, hub)))) { | |
delete hub[key]; | |
bridge.post('UnregisterMenu', { id, key }); | |
} | |
}, | |
/** | |
* @this {GMContext} | |
* @param {VMScriptGMDownloadOptions|string} opts | |
* @param {string} [name] | |
*/ | |
GM_download(opts, name) { | |
if (isString(opts)) { | |
opts = { url: opts, name, __proto__: null }; | |
} else if (opts) { | |
opts = nullObjFrom(opts); | |
name = opts.name; | |
} | |
if (!name ? (name = 'missing') : !isString(name) && (name = 'not a string')) { | |
onRequestInitError(opts, new SafeError(`Required parameter "name" is ${name}.`)); | |
return; | |
} | |
assign(opts, { | |
[kResponseType]: 'blob', | |
data: null, | |
method: 'GET', | |
overrideMimeType: 'application/octet-stream', | |
}); | |
return onRequestCreate(opts, this, name); | |
}, | |
GM_notification: createNotification, | |
GM_xmlhttpRequest: gmXmlHttpRequest, | |
}, |
It seems that it created nested functions.
Or due to any object reference chain? (WeakRef should solve this case)
tophf commented
I don't see anything wrong. The memory snapshot doesn't show object hierarchy, it's not console.log.