Skip to content

Commit

Permalink
fix: @W-11771403 support proxies that have get traps but not getOwnPr…
Browse files Browse the repository at this point in the history
…opertyDescriptor traps (#392)
  • Loading branch information
jdalton authored Sep 16, 2022
1 parent e79ec03 commit c80f082
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 42 deletions.
61 changes: 47 additions & 14 deletions packages/near-membrane-base/src/membrane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2623,14 +2623,23 @@ export function createMembraneMarshall(
} else {
result = localValue;
}
} else if (
key === SymbolToStringTag &&
foreignTargetTraits & TargetTraits.IsObject
) {
let toStringTag;
} else {
const transferableReceiver =
proxy === receiver
? foreignTargetPointer
: // Inline getTransferableValue().
(typeof receiver === 'object' && receiver !== null) ||
typeof receiver === 'function'
? getTransferablePointer(receiver)
: receiver;
let pointerOrPrimitive: PointerOrPrimitive;
try {
toStringTag =
foreignCallableGetToStringTagOfTarget(foreignTargetPointer);
pointerOrPrimitive = foreignCallableGet(
foreignTargetPointer,
foreignTargetTraits,
key,
transferableReceiver
);
} catch (error: any) {
const errorToThrow = selectedTarget ?? error;
selectedTarget = undefined;
Expand All @@ -2639,12 +2648,37 @@ export function createMembraneMarshall(
}
throw errorToThrow;
}
// The default language toStringTag is "Object". If we
// receive "Object" we return `undefined` to let the
// language resolve it naturally without projecting a
// value.
if (toStringTag !== 'Object') {
result = toStringTag;
if (typeof pointerOrPrimitive === 'function') {
pointerOrPrimitive();
result = selectedTarget;
selectedTarget = undefined;
} else {
result = pointerOrPrimitive;
}
if (
result === undefined &&
key === SymbolToStringTag &&
foreignTargetTraits & TargetTraits.IsObject
) {
let toStringTag;
try {
toStringTag =
foreignCallableGetToStringTagOfTarget(foreignTargetPointer);
} catch (error: any) {
const errorToThrow = selectedTarget ?? error;
selectedTarget = undefined;
if (LOCKER_DEBUG_MODE_INSTRUMENTATION_FLAG) {
activity!.error(errorToThrow);
}
throw errorToThrow;
}
// The default language toStringTag is "Object". If we
// receive "Object" we return `undefined` to let the
// language resolve it naturally without projecting a
// value.
if (toStringTag !== 'Object') {
result = toStringTag;
}
}
}
if (LOCKER_DEBUG_MODE_INSTRUMENTATION_FLAG) {
Expand Down Expand Up @@ -2699,7 +2733,6 @@ export function createMembraneMarshall(
);
if (safeDesc) {
const { get: getter, value: localValue } = safeDesc;

if (getter) {
if (safeDesc.foreign) {
const foreignGetterPointer = getTransferablePointer(getter);
Expand Down
23 changes: 23 additions & 0 deletions test/membrane/get-trap.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import createVirtualEnvironment from '@locker/near-membrane-dom';

describe('get trap', () => {
it('does retrieve values when missing a getOwnPropertyDescriptor trap', () => {
const ve = createVirtualEnvironment(window);
const get = ve.evaluate('(object, key) => object[key]');
const proxiedObject = new Proxy(
{},
{
get() {
return 1;
},
}
);
const proxiedTypedArray = new Proxy(new Uint8Array(), {
get() {
return 1;
},
});
expect(get(proxiedObject, 'a')).toBe(1);
expect(get(proxiedTypedArray, 'a')).toBe(1);
});
});
30 changes: 30 additions & 0 deletions test/membrane/ownKeys-trap.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import createVirtualEnvironment from '@locker/near-membrane-dom';

let exported;
function exportData(arg) {
exported = arg;
}

describe('ownKeys trap', () => {
it('does not throw ownKeys trap invariant for classes or strict mode functions', () => {
const envOne = createVirtualEnvironment(window, {
endowments: Object.getOwnPropertyDescriptors({ exportData }),
});
envOne.evaluate(`
exportData([
class Foo {},
function() {'use strict'}
]);
`);
const envTwo = createVirtualEnvironment(window, {
endowments: Object.getOwnPropertyDescriptors({ exportData, imported: exported }),
});
envTwo.evaluate(`
exportData(imported.map(Reflect.ownKeys));
`);
const matcher = jasmine.arrayWithExactContents(['length', 'name', 'prototype']);
exported.forEach((ownKeys) => {
expect(ownKeys).toEqual(matcher);
});
});
});
28 changes: 0 additions & 28 deletions test/membrane/ownKeys.spec.js

This file was deleted.

0 comments on commit c80f082

Please sign in to comment.