tc39 / proposal-dynamic-import

import() proposal for JavaScript

Home Page:https://tc39.github.io/proposal-dynamic-import/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Should module completion value be fulfillment value of the promise?

allenwb opened this issue · comments

When the initialization of a module completes normally it has a completion value that is generally the value of the last expression evaluated within the module body (see 15.2.1.20). For static imports this completion value is discarded because there is no way for ES code to capture and process it.

However, dynamic-import is a different situation in that it returns a Promise to the ES code. The fulfillment value of that promise could be used to transmit the module completion value back to the ES code that dynamically imported the module.

For this to work with multiple imports (either static or dynamic) of the same module, the completion value would have to be captured in the module record by the import that actually evaluates the body.

A Use Case

One reason that might be desirable is to enable a dynamically imported module to return a require-like export object:

//foo.js
//static exports accessible via static import
export function bar() {}
export function baz() {}
//make foo and bar available to dynamic importers
({bar, baz});   //this is the module completion value

//client.js
import("./foo.js").then(foo => {
   foo.bar();
   foo.baz();
});

A Concern

(attention @erights)

It seems like such a dynamic module completion value could be used to create a communications channel that could pierce an intra-realm membrane. Consider a collaborator, outside of the membrane, does a dynamic import of module "X" and obtains an object as the module's completion value. The collaborator adds a property to the object and uses it to store private data that only exists outside the membrane. Code within the membrane also does a dynamic import of module "X" and obtains the same completion value object. That code now has access to the private data stored in the object by the collaborator.

My understanding is that the promise already currently resolves to an object containing all the exports - ie, in your example, even without the last line of foo.js, your client.js example should work.

@ljharb You're right, I missed that.

Membrane penetration still seems a concern. Returning the module namespace object means that any module that has an export whose value is a mutable object (eg, any exported function) could be used to pierce a membrane.

Right, I don't plan to change the fulfillment value of the promise, or start giving meaning to the completion value of a module. (This isn't an eval API; it's an import API.)

I don't understand how there could be an issue with membranes here that is not also present with static imports, or with the host-specific mechanisms that are present in specs currently. I'd like to close this issue for now, but if we believe the membrane issue is worth investigation then we should open a separate issue for that.

if we believe the membrane issue is worth investigation then we should open a separate issue for that.

We do.

#26