зеркало из https://github.com/electron/electron.git
refactor: replace V8 hidden values with WeakMap / WeakSet (#26659)
This commit is contained in:
Родитель
0be6c92aa9
Коммит
c8d77cae4a
|
@ -1,11 +1,11 @@
|
||||||
import { WebContents } from 'electron/main';
|
import { WebContents } from 'electron/main';
|
||||||
|
|
||||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
|
||||||
|
|
||||||
const getOwnerKey = (webContents: WebContents, contextId: string) => {
|
const getOwnerKey = (webContents: WebContents, contextId: string) => {
|
||||||
return `${webContents.id}-${contextId}`;
|
return `${webContents.id}-${contextId}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const electronIds = new WeakMap<Object, number>();
|
||||||
|
|
||||||
class ObjectsRegistry {
|
class ObjectsRegistry {
|
||||||
private nextId: number = 0
|
private nextId: number = 0
|
||||||
|
|
||||||
|
@ -81,14 +81,14 @@ class ObjectsRegistry {
|
||||||
|
|
||||||
// Private: Saves the object into storage and assigns an ID for it.
|
// Private: Saves the object into storage and assigns an ID for it.
|
||||||
saveToStorage (object: any) {
|
saveToStorage (object: any) {
|
||||||
let id: number = v8Util.getHiddenValue(object, 'electronId');
|
let id = electronIds.get(object);
|
||||||
if (!id) {
|
if (!id) {
|
||||||
id = ++this.nextId;
|
id = ++this.nextId;
|
||||||
this.storage[id] = {
|
this.storage[id] = {
|
||||||
count: 0,
|
count: 0,
|
||||||
object: object
|
object: object
|
||||||
};
|
};
|
||||||
v8Util.setHiddenValue(object, 'electronId', id);
|
electronIds.set(object, id);
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ class ObjectsRegistry {
|
||||||
}
|
}
|
||||||
pointer.count -= 1;
|
pointer.count -= 1;
|
||||||
if (pointer.count === 0) {
|
if (pointer.count === 0) {
|
||||||
v8Util.deleteHiddenValue(pointer.object, 'electronId');
|
electronIds.delete(pointer.object);
|
||||||
delete this.storage[id];
|
delete this.storage[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,8 @@ function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebCont
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const locationInfo = new WeakMap<Object, string>();
|
||||||
|
|
||||||
// Return the description of object's members:
|
// Return the description of object's members:
|
||||||
const getObjectMembers = function (object: any): ObjectMember[] {
|
const getObjectMembers = function (object: any): ObjectMember[] {
|
||||||
let names = Object.getOwnPropertyNames(object);
|
let names = Object.getOwnPropertyNames(object);
|
||||||
|
@ -186,7 +188,7 @@ const throwRPCError = function (message: string) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...args: any[]) => void) => {
|
const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...args: any[]) => void) => {
|
||||||
const location = v8Util.getHiddenValue(callIntoRenderer, 'location');
|
const location = locationInfo.get(callIntoRenderer);
|
||||||
let message = 'Attempting to call a function in a renderer window that has been closed or released.' +
|
let message = 'Attempting to call a function in a renderer window that has been closed or released.' +
|
||||||
`\nFunction provided here: ${location}`;
|
`\nFunction provided here: ${location}`;
|
||||||
|
|
||||||
|
@ -269,7 +271,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
|
||||||
removeRemoteListenersAndLogWarning(this, callIntoRenderer);
|
removeRemoteListenersAndLogWarning(this, callIntoRenderer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
|
locationInfo.set(callIntoRenderer, meta.location);
|
||||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
|
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
|
||||||
|
|
||||||
setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);
|
setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);
|
||||||
|
|
|
@ -23,6 +23,9 @@ const finalizationRegistry = new (window as any).FinalizationRegistry((id: numbe
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const electronIds = new WeakMap<Object, number>();
|
||||||
|
const isReturnValue = new WeakSet<Object>();
|
||||||
|
|
||||||
function getCachedRemoteObject (id: number) {
|
function getCachedRemoteObject (id: number) {
|
||||||
const ref = remoteObjectCache.get(id);
|
const ref = remoteObjectCache.get(id);
|
||||||
if (ref !== undefined) {
|
if (ref !== undefined) {
|
||||||
|
@ -90,10 +93,10 @@ function wrapArgs (args: any[], visited = new Set()): any {
|
||||||
value.then(onFulfilled, onRejected);
|
value.then(onFulfilled, onRejected);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
} else if (v8Util.getHiddenValue(value, 'electronId')) {
|
} else if (electronIds.has(value)) {
|
||||||
return {
|
return {
|
||||||
type: 'remote-object',
|
type: 'remote-object',
|
||||||
id: v8Util.getHiddenValue(value, 'electronId')
|
id: electronIds.get(value)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +114,7 @@ function wrapArgs (args: any[], visited = new Set()): any {
|
||||||
}
|
}
|
||||||
visited.delete(value);
|
visited.delete(value);
|
||||||
return meta;
|
return meta;
|
||||||
} else if (typeof value === 'function' && v8Util.getHiddenValue(value, 'returnValue')) {
|
} else if (typeof value === 'function' && isReturnValue.has(value)) {
|
||||||
return {
|
return {
|
||||||
type: 'function-with-return-value',
|
type: 'function-with-return-value',
|
||||||
value: valueToMeta(value())
|
value: valueToMeta(value())
|
||||||
|
@ -120,7 +123,7 @@ function wrapArgs (args: any[], visited = new Set()): any {
|
||||||
return {
|
return {
|
||||||
type: 'function',
|
type: 'function',
|
||||||
id: callbacksRegistry.add(value),
|
id: callbacksRegistry.add(value),
|
||||||
location: v8Util.getHiddenValue(value, 'location'),
|
location: callbacksRegistry.getLocation(value),
|
||||||
length: value.length
|
length: value.length
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -287,7 +290,7 @@ function metaToValue (meta: MetaType): any {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track delegate obj's lifetime & tell browser to clean up when object is GCed.
|
// Track delegate obj's lifetime & tell browser to clean up when object is GCed.
|
||||||
v8Util.setHiddenValue(ret, 'electronId', meta.id);
|
electronIds.set(ret, meta.id);
|
||||||
setCachedRemoteObject(meta.id, ret);
|
setCachedRemoteObject(meta.id, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +376,7 @@ Object.defineProperty(exports, 'process', {
|
||||||
// Create a function that will return the specified value when called in browser.
|
// Create a function that will return the specified value when called in browser.
|
||||||
export function createFunctionWithReturnValue<T> (returnValue: T): () => T {
|
export function createFunctionWithReturnValue<T> (returnValue: T): () => T {
|
||||||
const func = () => returnValue;
|
const func = () => returnValue;
|
||||||
v8Util.setHiddenValue(func, 'returnValue', true);
|
isReturnValue.add(func);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
const callbackIds = new WeakMap<Function, number>();
|
||||||
|
const locationInfo = new WeakMap<Function, string>();
|
||||||
|
|
||||||
export class CallbacksRegistry {
|
export class CallbacksRegistry {
|
||||||
private nextId: number = 0
|
private nextId: number = 0
|
||||||
|
@ -6,7 +7,7 @@ export class CallbacksRegistry {
|
||||||
|
|
||||||
add (callback: Function) {
|
add (callback: Function) {
|
||||||
// The callback is already added.
|
// The callback is already added.
|
||||||
let id = v8Util.getHiddenValue<number>(callback, 'callbackId');
|
let id = callbackIds.get(callback);
|
||||||
if (id != null) return id;
|
if (id != null) return id;
|
||||||
|
|
||||||
id = this.nextId += 1;
|
id = this.nextId += 1;
|
||||||
|
@ -17,7 +18,7 @@ export class CallbacksRegistry {
|
||||||
const stackString = (new Error()).stack;
|
const stackString = (new Error()).stack;
|
||||||
if (!stackString) return;
|
if (!stackString) return;
|
||||||
|
|
||||||
let filenameAndLine;
|
let filenameAndLine: string;
|
||||||
let match;
|
let match;
|
||||||
|
|
||||||
while ((match = regexp.exec(stackString)) !== null) {
|
while ((match = regexp.exec(stackString)) !== null) {
|
||||||
|
@ -32,8 +33,8 @@ export class CallbacksRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callbacks.set(id, callback);
|
this.callbacks.set(id, callback);
|
||||||
v8Util.setHiddenValue(callback, 'callbackId', id);
|
callbackIds.set(callback, id);
|
||||||
v8Util.setHiddenValue(callback, 'location', filenameAndLine);
|
locationInfo.set(callback, filenameAndLine!);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +42,10 @@ export class CallbacksRegistry {
|
||||||
return this.callbacks.get(id) || function () {};
|
return this.callbacks.get(id) || function () {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLocation (callback: Function) {
|
||||||
|
return locationInfo.get(callback);
|
||||||
|
}
|
||||||
|
|
||||||
apply (id: number, ...args: any[]) {
|
apply (id: number, ...args: any[]) {
|
||||||
return this.get(id).apply(global, ...args);
|
return this.get(id).apply(global, ...args);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +53,7 @@ export class CallbacksRegistry {
|
||||||
remove (id: number) {
|
remove (id: number) {
|
||||||
const callback = this.callbacks.get(id);
|
const callback = this.callbacks.get(id);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
v8Util.deleteHiddenValue(callback, 'callbackId');
|
callbackIds.delete(callback);
|
||||||
this.callbacks.delete(id);
|
this.callbacks.delete(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче