Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

closes #218: adding Realm.prototype.import(specifier) #223

Merged
merged 3 commits into from
Mar 4, 2020

Conversation

caridy
Copy link
Collaborator

@caridy caridy commented Feb 26, 2020

Realm.prototype.import(specifier):

  • equivalent to import(specifier)
  • works even when CSP blocks any script evaluation
  • matches API for the compartments/evaluator proposal

<emu-alg>
1. Let _O_ be *this* value.
1. Perform ? RequireInternalSlot(_O_, [[Realm]]).
1. Let _referencingScriptOrModule_ be *null*.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erights @littledan @ljharb this is an interesting question to be answered. What is the referencing scriptOrModule when calling r.import()? should be null? should be the code that creates the Realm object? if so, what are the implications?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be an optional parameter passed to Realm.prototype.import? otherwise it'd have to be "null", because this isn't syntactic, it's API.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import method called here is a first class function, not a special form. When it calls the underlying operation, it should pass null as the referrer. The first class import method should not take an optional referrer parameter, nor should it provide a referrer based on any relationship to the creator of the Realm or Compartment. Just null.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's hard for me to understand what kind of value would be passed into this second argument. We need a script or module record, but those aren't exposed as first-class values to JavaScript.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notes from SES meeting (yesterday) about this question:

  • @erights convinced me that a second argument is problematic. the convincing factor was that if evaluation is available, then myRealm.globalThis.eval('import("./something")') should work, and at that point, you will have no way to provide a value to the referencing scriptOrModule.
  • we need to decide whether the value should be *null* or *undefined*.
  • in the meeting, we reached consensus about the behavior here, the realm object will ask the host for the resolution, by passing null, and it is the host's responsibility to decide what value to use for the referencing scriptOrModule.
  • eventually, once we have a way to control the host (via compartment/evaluator), you will be able to control the behavior of such resolution.

@erights did I miss anything here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the Realm proposal, yes, I think that's everything relevant.

For reference, the meeting is at https://www.youtube.com/watch?v=hqKGKDw-FCY&list=PLzDw4TTug5O1jzKodRDp3qec8zl88oxGd which includes further considerations relevant to the SES / Compartment proposal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erights convinced me that a second argument is problematic. the convincing factor was that if evaluation is available, then myRealm.globalThis.eval('import("./something")') should work, and at that point, you will have no way to provide a value to the referencing scriptOrModule.

So what did you think of my idea to provide a "base" string to hosts?

we need to decide whether the value should be null or undefined.

I think the choice of null vs undefined is just editorial--this is only visible to hosts. I'm fine with either.

in the meeting, we reached consensus about the behavior here, the realm object will ask the host for the resolution, by passing null, and it is the host's responsibility to decide what value to use for the referencing scriptOrModule.

I think we should think through what to do for some environments before Stage 3 (#225). For HTML, for example, do you think this should be relative to where the whole page is, or should paths be forced to be absolute? And what should this be in Node.js? (I think the experience with ES6 modules showed that putting these decisions off has cost.)

eventually, once we have a way to control the host (via compartment/evaluator), you will be able to control the behavior of such resolution.

Would this have a way to tell the host the "base URL" or equivalent, for environments where this is meaningful? Are there proposals that I could review on this?

For reference, the meeting is at ...

FWIW, if there are written notes, these are generally easier for me to follow than a video.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@littledan yes, we discussed the resolution in browsers as well, sorry I didn't add that part to the relevant notes above. The reasoning was that doing r.import('...') works just like doing <script type="module" src="..."> in browsers. In other words, the module that creates the realm does not have a saying on the resolution or base referral definition. These two features will be available as part of the compartment/evaluator where you control every aspect of the host for any realm object underneath. In other words, "relative to where the whole page" if the specifier is relative. If it is absolute, then the base has no saying in the resolution.

As for the notes, no, we don't have written notes for SES meetings as far as I can tell, only the video recorded by @erights

1. Let _specifierString_ be ? ToString(_specifier_).
1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).
1. IfAbruptRejectPromise(_specifierString_, _promiseCapability_).
1. Perform ! HostImportModuleDynamically(_referencingScriptOrModule_, _specifierString_, _promiseCapability_).
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erights @littledan @ljharb this is another surprising part for me, I could not find any reference to the realm in the import call specification. Is it underspecified? or am I missing something? I'm talking about https://tc39.es/ecma262/#sec-import-calls and the abstract operations called from there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's probably assumed to be implicit? not sure tho.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"assumed implicit" === underspecified. I suspect the spec has a lot of these bugs that we'll need to fix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTML figures this out using the ES spec's current realm concept. I imagine other hosts could do the same. That works today (there's nothing unspecified, and even import() within an evaluate in a Realm should work fine), but wouldn't work for the implementation of this method, and needs to be updated.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@littledan let's work on that particular piece in another PR to avoid confusion.

Copy link
Member

@littledan littledan Feb 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this a bit more, I think the simplest way through this issue would be to add a dummy execution context stack entry to set the current realm appropriately. This can be done by cribbing lines 2-6 of InitializeHostDefinedRealm, and saving and restoring the surrounding calling execution context as in steps 1, 9 and 11 of [[Call]]. What would you think of applying that change as part of this patch? We could do the more comprehensive refactoring as part of upstreaming the Realm proposal into the main spec.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix proposed in #233

Copy link
Member

@littledan littledan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API looks good to me, but it seems like we have some spec work ahead of us, e.g., in #225 .

<emu-alg>
1. Let _O_ be *this* value.
1. Perform ? RequireInternalSlot(_O_, [[Realm]]).
1. Let _referencingScriptOrModule_ be *null*.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's hard for me to understand what kind of value would be passed into this second argument. We need a script or module record, but those aren't exposed as first-class values to JavaScript.

1. Let _specifierString_ be ? ToString(_specifier_).
1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%).
1. IfAbruptRejectPromise(_specifierString_, _promiseCapability_).
1. Perform ! HostImportModuleDynamically(_referencingScriptOrModule_, _specifierString_, _promiseCapability_).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTML figures this out using the ES spec's current realm concept. I imagine other hosts could do the same. That works today (there's nothing unspecified, and even import() within an evaluate in a Realm should work fine), but wouldn't work for the implementation of this method, and needs to be updated.

* Normative: Run HostImportModuleDynamically in the correct Realm

* Update spec/index.emu

Co-Authored-By: Jordan Harband <ljharb@gmail.com>

Co-authored-by: Caridy Patiño <caridy@gmail.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
@caridy caridy merged commit 3bffb70 into master Mar 4, 2020
@caridy caridy deleted the caridy/issue-218 branch March 4, 2020 19:40
@littledan
Copy link
Member

Happy to see that this landed; retroactive LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants