-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Replace String.trimRight() with regex in order to support IE10+ #7231
Conversation
I'd rather see
somewhere in the code (or a special include for browsers) than this. |
No need to replace 0 spaces, so this should be:
Might as well also polyfill trimLeft. |
Sure, any suggestions as to where you want this to live? Given how early UrlParams is used, it's going to need to happen early. Do you want me to add a |
I agree you should load it very early and I guess it could be placed here |
We should be able to just add a require before this line https://github.com/adobe/brackets/blob/master/src/brackets.js#L142 or add at to any module and if it is not loaded before that line, add a require to load it. |
I've added a new commit with one possible approach. |
|
||
|
||
// Load compatibility shims--these need to load early, be careful moving this | ||
require("utils/Compatibility"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Require make any guarantees about the order that "sibling" require() calls are loaded in? @dangoor do you have any idea?
If it's not guaranteed, I wonder if it's better to put this directly in src/main.js
(cluttery as that may be) or even load it directly from a separate <script>
tag before we boot up Require?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a similar question + answers: http://stackoverflow.com/questions/11581611/load-files-in-specific-order-with-requirejs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The accepted answer there boils down to 'explicitly require Compatibility.js in every module that calls trimRight(),' which seems clumsy and more than a little fragile.
The second answer listed there -- basically, chaining async require() calls in main.js -- sounds promising though.
However, if there's any sort of guarantee that the code in this PR will work as-is, that's definitely preferable. I couldn't find any docs that said either way. Anyone have a reference or spec for RequireJS's loading order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just found a note in the official doc: http://requirejs.org/docs/1.0/docs/api.html#order
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read that earlier, but it's actually very vague. It seems to only pertain to JS files that aren't wrapped in a define()
.
Normally RequireJS loads and evaluates scripts in an undetermined order
but then...
The order plugin ... is not needed for scripts that use define() to define modules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should go straight to the source :-) @jrburke, does RequireJS make any guarantee about the order that sibling require()
calls are resolved in? We couldn't find anything definitive in the docs. Thanks!
More detail, if needed... if module "main" does this:
define(function(require, exports, module) {
require("A");
require("B");
});
Is the code in the body of A's define()
guaranteed to run before B's (assuming A doesn't require B internally)? I.e., are the dependencies resolved as a sort of depth-first traversal, or is the order more nondeterministic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterflynn the order is not guaranteed, for two reasons:
- other modules could have asked for 'B' before 'main' is loaded or has its dependencies registered.
- module factories are called once they are loaded (if all their dependencies are involved), and that load order is dependent on network load order, which is indeterminate. If 'A' needs 'C', but 'B' has no dependencies, it is likely 'B' will be defined before 'A'.
So how about if I do something like the following in define(function (require, exports, module) {
"use strict";
// Load the brackets module. This is a self-running module that loads and runs the entire application.
require(['utils/Compatibility'], function() {
require("brackets");
});
}); |
@humphd That would lead to 'brackets' executing before 'utils/Compatibility', since that commonjs sugar style effectively "hoists" define(function(require){
require(['utils/Compatibility'], function() {
require(['brackets']);
});
}); |
Done. Thanks to James for the help. |
Bumping to medium priority since this has been languishing for awhile and the Mozilla folks are serious about in-browser :) |
Added to the Kanban board to raise visibility. https://trello.com/c/2f4gK9fi |
Per @peterflynn, sounds like the main work here is to verify that this works with our minified build. |
@@ -37,7 +37,7 @@ | |||
*/ | |||
define(function (require, exports, module) { | |||
"use strict"; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only changes to brackets.js are whitespace changes, so these changes should be removed.
@humphd @jrburke I tried to implement this as a "shim" (Thanks @jasonsanjose for the tip) in pull request #8593, but this also doesn't work in minified build. Brackets works (based on very minimal usage), but the polyfill is not applied. cc @peterflynn @njx |
I do not recommend shim config. That is only useful for scripts that do not call the module APIs. How does it fail after the build step? My guess is that you probably want to manually do an `include ["utils/Compatibility", "brackets"] for the build config (if using r.js optimizer), since the require([]) form of dependencies is skipped in dependency scanning (which is the point, they are dynamic requires, that may not need to happen)? Although worse case in that case is that it should just lead to some dynamic loads, a bit slower, but I would not expect it to error. So knowing more about the failure might be good. Another option is to do the compatibility work above the define() call in that main module, and not as a module, just an IIFE, so that the fixups are done before any module resolution. That may not be practical if you expect to need lots of compatibility fixes, but if it is just those two things, then the main module could just go back to its old form if those trim function work is done just above the main module define(). If that approach does not work, perhaps you are including some helper scripts that do not call define() but use trim functions? In that case, I could see that when those are inlined in a build, they will be above the definitions for those trim fixes, and since not in a define() function, will execute immediately and fail. If that is the case, then two possibilities: In the build config, use wrap.start to inject the polyfills at the top of the build layer (without a define() wrapper, just as an IIFE). Using include: could work too, but it depends on what non-modular script is using trim functions and how it ends up in the build. If you want to work through it in more realtime, you can ping me in IRC, #requirejs on freenode, mention it is about this bug, and I should respond. |
@jrburke Thanks. Very help info. I wasn't sure how to "manually do an 'include ["utils/Compatibility", "brackets"]' for the build config", so I just removed the I have a working version in PR #8595 which is built on top of this branch. The diff is in commit 873e768 @peterflynn @njx @humphd @jasonsanjose Does this address all concerns? |
@redmunds that is probably not what you want. By using synchronous require('brackets'), in order for that to work in a network environment, the module loader will see that dependency, make sure it is executed/defined before running the main module's factory function. So it will likely already run before the The include build option normally goes in the requirejs optimizer config, I would guess around here in the gruntfile. However, you normally want to set it where the |
@redmunds, you might also want to add 'utils/Compatibility' before 'brackets' in that include array, so that it is included in the bundle instead of dynamically loaded (unless that utils/Compatibility gets in the bundle some other way). |
@jrburke I forgot about that from your original comment. Fixed. |
Thanks to all of you for helping taking it over the line! I hope to bring you more like this soon--we're making good progress on in-browser. |
For work I've been doing on brackets-in-browser (see https://blog.webmaker.org/webmaker-experiments-with-brackets) I had to fix this use of
trimRight
so it would work in IE10+. With this change, I'm able to run things in IE10+: