I’m experimenting with the ECMAScript proposal for ShadowRealm and ran into some deeply unintuitive behavior around object identity, function bindings, and prototype inheritance across realms.
Consider this example (run in an environment that supports ShadowRealm, like recent Chrome or Node.js with flags):
const realm = new ShadowRealm();
const fn = realm.evaluate(`
globalThis.shared = { x: 1 };
function getShared() { return shared; }
getShared;
`);
const objFromRealm = fn();
console.log(objFromRealm); // [object Object]
console.log(Object.getPrototypeOf(objFromRealm) === Object.prototype); // false
console.log(objFromRealm instanceof Object); // false
console.log(typeof objFromRealm); // 'object'
Questions:
Why is the object returned from the ShadowRealm not an instance of Object in the main realm?
If realms are isolated, why does typeof objFromRealm still return 'object', even though it has a different prototype chain?
From the ECMAScript spec perspective: how is object identity and prototype linkage handled between different realms or compartments? Does the engine ever "wrap" or "proxy" objects to preserve memory safety?
Could this lead to identity leaks, instanceof inconsistencies, or cross-realm Function issues?
I tried accessing an object created inside a ShadowRealm from the main execution context. I expected it to behave like a normal object — for example, instanceof Object should return true, and the prototype should match the main realm’s Object.prototype. Instead, I found that objects from the ShadowRealm are not recognized as instances of Object in the main realm, and their prototype chains are completely separate. This behavior seems to break conventional expectations about object identity and typeof, so I’m trying to understand what’s really happening behind the scenes and whether this is by design or a side effect of compartment isolation.
const objFromRealm = fn();should not return an object but rather throw an exception from GetWrappedValue since yoursharedis neither callable nor a primitive. So this would be a bug in environment you're testing this with.