perf: pass primitives directly through the context bridge, avoids copying (#24531)

This commit is contained in:
Samuel Attard 2020-07-14 18:38:54 -07:00 committed by GitHub
parent 36900df7d9
commit 3f54f240bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 2 deletions

View file

@ -31,7 +31,8 @@
"BUILDFLAG": "readonly",
"ENABLE_DESKTOP_CAPTURER": "readonly",
"ENABLE_REMOTE_MODULE": "readonly",
"ENABLE_VIEWS_API": "readonly"
"ENABLE_VIEWS_API": "readonly",
"BigInt": "readonly"
},
"overrides": [
{

View file

@ -146,6 +146,17 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
"deeper than 1000 are not supported.")));
return v8::MaybeLocal<v8::Value>();
}
// Certain primitives always use the current contexts prototype and we can
// pass these through directly which is significantly more performant than
// copying them. This list of primitives is based on the classification of
// "primitive value" as defined in the ECMA262 spec
// https://tc39.es/ecma262/#sec-primitive-value
if (value->IsString() || value->IsNumber() || value->IsNullOrUndefined() ||
value->IsBoolean() || value->IsSymbol() || value->IsBigInt()) {
return v8::MaybeLocal<v8::Value>(value);
}
// Check Cache
auto cached_value = object_cache->GetCachedProxiedObject(value);
if (!cached_value.IsEmpty()) {

View file

@ -313,6 +313,20 @@ describe('contextBridge', () => {
expect(result).to.deep.equal(['null', 'undefined']);
});
it('should proxy symbols such that symbol equality works', async () => {
await makeBindingWindow(() => {
const mySymbol = Symbol('unique');
contextBridge.exposeInMainWorld('example', {
getSymbol: () => mySymbol,
isSymbol: (s: Symbol) => s === mySymbol
});
});
const result = await callWithBindings((root: any) => {
return root.example.isSymbol(root.example.getSymbol());
});
expect(result).to.equal(true, 'symbols should be equal across contexts');
});
it('should proxy typed arrays and regexps through the serializer', async () => {
await makeBindingWindow(() => {
contextBridge.exposeInMainWorld('example', {
@ -479,6 +493,8 @@ describe('contextBridge', () => {
string: 'string',
boolean: true,
arr: [123, 'string', true, ['foo']],
symbol: Symbol('foo'),
bigInt: 10n,
getObject: () => ({ thing: 123 }),
getNumber: () => 123,
getString: () => 'string',
@ -511,6 +527,8 @@ describe('contextBridge', () => {
[example.arr[2], Boolean],
[example.arr[3], Array],
[example.arr[3][0], String],
[example.symbol, Symbol],
[example.bigInt, BigInt],
[example.getNumber, Function],
[example.getNumber(), Number],
[example.getObject(), Object],

View file

@ -1,7 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"target": "es2020",
"lib": [
"es2019",
"dom",