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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation of implementing instantiate(), notice about race condition #2265

Closed
wants to merge 7 commits into from

Conversation

Jack-Works
Copy link

continue of #2238
馃憖

@github-actions
Copy link

github-actions bot commented Oct 10, 2020

File size impact

extras (0)

No impact on files in extras group.

browser (0)

No impact on files in browser group.

node (0)

No impact on files in node group.

Generated by file size impact during size-impact#299286764

Copy link
Member

@guybedford guybedford left a comment

Choose a reason for hiding this comment

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

The main body of the content is way too long. We should wrap it in a <details> element or simplify it down if possible.

I'm all for explaining this internal, it's just still not a great explanation of the pipeline.

docs/hooks.md Outdated Show resolved Hide resolved
docs/hooks.md Outdated
Comment on lines 68 to 70
By default, a SystemJS module is not marked by an "identifier" (to match ES Module), therefore SystemJS have to use a race condition prone way to register the module. So you must make sure to maintain the execution order of the code.

The [module loading process](https://github.com/systemjs/systemjs/blob/master/src/system-core.js#L65-L77) is like:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
By default, a SystemJS module is not marked by an "identifier" (to match ES Module), therefore SystemJS have to use a race condition prone way to register the module. So you must make sure to maintain the execution order of the code.
The [module loading process](https://github.com/systemjs/systemjs/blob/master/src/system-core.js#L65-L77) is like:
By default, SystemJS modules are not registered by name to match ES Modules. Instead, registration of modules is done by matching a `System.register` call to its caller URL using a synchronous callback.
See below for an outline of the loading lifecycle provided by this default `instantiate` implementation:

Copy link
Author

Choose a reason for hiding this comment

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

a synchronous callback.

It doesn't have to be synchronous, what really important is the order, in my implementation for WebExtension, the callback is async but I maintain the order so things won't break.

docs/hooks.md Outdated Show resolved Hide resolved

The [default implementation](https://github.com/systemjs/systemjs/blob/master/src/features/script-load.js) is based on the creation of `<script>` tag and the `onload` event is emitted just after the System.register call.

If in your environment it is not possible to maintain the execution order (for example, involves the interaction of multiple event loops), you can make the call to the instantiate in a sequent way (Notice: this will slow down the module loading speed if they need to loaded by the network). Here is another [example that implementing System.instantiate](https://github.com/Jack-Works/webextension-systemjs/blob/master/src/content-script.ts#L10-L26) for a speical environment that cannot use `<script>` tag.
Copy link
Member

Choose a reason for hiding this comment

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

Let's rather link to the src/features/fetch-loader.js implementation here as an example.

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

fetch-load is calling getRegister immediately after eval and not showing how to handle the race condition (cause it doesn't have race condition).

My webextension-systemjs involved this topic (cause I'm not using eval but browser.tabs.executeScript which is async and not reliably to get a callback of execution done).

Copy link
Member

Choose a reason for hiding this comment

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

If you're not calling getRegister immediately after eval then you will have race conditions.

Copy link
Author

Choose a reason for hiding this comment

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

It's impossible to know if the script executed synchronously in some environments. I do have race conditions in my early implementation of webextension-systemjs but I successfully workaround on it.
https://github.com/Jack-Works/webextension-systemjs/blob/master/src/content-script.ts#L10-L26, it chains the current promise after the last execution (to make it serial) therefore to maintain the correct order (and still keep asynchronous).

Copy link
Member

Choose a reason for hiding this comment

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

Can you really not just call eval manually? Promise resolution runs the task queue, which means you always have a very small window where a race can still happen even if it hasn't happened in testing, it could be 1 in 100 or 1 in 10000 but the race is still there.

Copy link
Author

Choose a reason for hiding this comment

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

I used it in our products directly, and the current version works well. eval is banned in our environment by CSP policy (banning eval is enabled by default in WebExtension).

Copy link
Member

Choose a reason for hiding this comment

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

What's the reason you can't attach a sync callback in the page with eg a page registration queue handler that messages back both the registration and url together?

Copy link
Author

Choose a reason for hiding this comment

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

Sorry, I didn't get your idea 馃憖 can you write some pseudo-code to explain?

Jack-Works and others added 3 commits October 10, 2020 22:37
Co-authored-by: Guy Bedford <guybedford@gmail.com>
@Jack-Works
Copy link
Author

hmm, hello?

@guybedford
Copy link
Member

Please use a decent tone here. "Hmm hello" is not a way to speak to a maintainer.

Contributors are always welcome to the project, but it requires being constructive. Non constructive comments will be blocked and issues locked.

@Jack-Works
Copy link
Author

Oh I'm sorry if I used offensive tone or words. I'm not native speaker so I can't feel that emotion clearly

@guybedford
Copy link
Member

It's important to just be respectful of a maintainers time. So far this PR has cost me many minutes of work, and there has been nothing in return. The PR is still not of the quality to merge.

I don't think further feedback is going to help.

Closing, but appreciated for the thought of contributing.

@guybedford guybedford closed this Oct 17, 2020
@Jack-Works
Copy link
Author

Fine, feel free to pick any quality changes (if there is any) to improve the documents if you'd like to.

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.

None yet

2 participants