proposal-first-class-protocols icon indicating copy to clipboard operation
proposal-first-class-protocols copied to clipboard

Cross Realm Interfaces

Open bmeck opened this issue 8 years ago • 8 comments

As long as interfaces do not inherit from Object, is it possible to have them be cross realm?

bmeck avatar Aug 02 '17 20:08 bmeck

Meaning that if you create an interface, it would become a global in all realms?

As-is, if you pass the first-class interface value across realms, I'd expect it to work.

ljharb avatar Aug 02 '17 21:08 ljharb

@ljharb global, mmm no it would still have a home realm, but being safely passable between home/target realms without leaking the home realm.

this would require:

protocol InterfaceName {
  youGetThisMethodForFree(...parameters) {
  }
}

To make a youGetThisMethodForFree closure in the target realm though.

bmeck avatar Aug 02 '17 21:08 bmeck

ah, you're saying that runtime lookups of globals inside an interface method should use the current realm, not the realm in which they were defined?

ljharb avatar Aug 02 '17 21:08 ljharb

I need to rephrase all of this with a more concrete example.

// safe realm
const vm = require('vm');
const unsafeRealm = vm.createContext();
let lastId = 1;
const ids = new WeakMap;
protocol HasId {
  id() {
    if (ids.has(this)) return ids.get(this);
    const id = lastId++;
    ids.set(this, id);
    return id;
  }
}
// setup our interface
const implement = vm.runInContext(`(_HasId => HasId = _HasId)`, unsafeRealm);
implement(HasId);

If id is not from the unsafeRealm then we need to start doing wrappers around it. However this is not entirely possible since it is assigned via .implement(...).

In order for HasId/HasId.id to not leak the safe realm, it needs to not have any way to Reflect back to the realm. That means HasId cannot have a prototype that has a reference back to the safe realm via reflection, and the same of HasId.id.

bmeck avatar Aug 02 '17 21:08 bmeck

ahhh thanks.

How would you have a function that doesn't inherit from a specific Realm's Function.prototype?

ljharb avatar Aug 02 '17 21:08 ljharb

@ljharb .implement(target, iface) can specifically see the target before assigning the HasId.id and hook up the prototype/primordials. However, this means o1[HasId.id] === o2[HasId.id] is not always true.

bmeck avatar Aug 02 '17 22:08 bmeck

looking back on this, it would be a channel to get primordials that would not otherwise be accessible like grabbing them off Object.create(null). However, if .implement does it based upon Realm it was called in rather than target object I can't think of a similar leak.

bmeck avatar Aug 02 '17 23:08 bmeck

FYI. I have a library in which I implemented my own custom protocols long before I was aware of this proposal. I too ran into the realm issue when I was running my code in MS Dynamics where for security purposes the platform creates separate realms for different components.

I ran into issues when my protocols balked at not being able to lookup the symbol on an array. Turns out the array was created in another realm where protocols hadn't been applied. To solve the issue I applied them to all known realms. It seemed heavy handed but worked.

The crossrealm situation is not a simple one to address. You'll see in my README I had to observe certain principles to avoid issues. It's also worth noting I implemented this support long after I had implemented protocols for use in a single realm. So this feature need not encumber the initial specification.

mlanza avatar May 05 '23 17:05 mlanza