WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
148897
[ES6] Integrate ES6 Modules into WebCore
https://bugs.webkit.org/show_bug.cgi?id=148897
Summary
[ES6] Integrate ES6 Modules into WebCore
Yusuke Suzuki
Reported
2015-09-05 01:50:01 PDT
Now, it's implemented in JSC shell. It's time to integrate it to WebCore! (first, we'll enable it only inside WebKit, not expose it to user space, because the loader spec is not mature yet.)
Attachments
Patch
(42.70 KB, patch)
2015-09-10 01:24 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(42.02 KB, patch)
2015-09-10 21:03 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(84.83 KB, patch)
2015-09-14 15:21 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(91.40 KB, patch)
2015-09-15 03:00 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(70.03 KB, patch)
2015-09-18 17:36 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(65.69 KB, patch)
2015-09-18 20:23 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(66.79 KB, patch)
2015-09-18 21:16 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(83.12 KB, patch)
2015-09-21 11:56 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(86.18 KB, patch)
2015-09-23 14:18 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(101.65 KB, patch)
2015-09-23 15:35 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(128.85 KB, patch)
2015-09-23 17:31 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(128.90 KB, patch)
2015-09-23 17:41 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(129.06 KB, patch)
2015-09-23 22:01 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(130.21 KB, patch)
2015-09-24 11:49 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(132.49 KB, patch)
2015-09-24 13:22 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(132.53 KB, patch)
2015-09-24 13:46 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(132.53 KB, patch)
2015-09-24 13:49 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(130.28 KB, patch)
2015-09-25 15:06 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(144.37 KB, patch)
2016-08-20 00:59 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(144.71 KB, patch)
2016-08-20 23:01 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(144.71 KB, patch)
2016-08-20 23:17 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(144.83 KB, patch)
2016-08-25 21:01 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(151.95 KB, patch)
2016-08-26 11:18 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(159.03 KB, patch)
2016-08-26 15:50 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews114 for mac-yosemite
(1.53 MB, application/zip)
2016-08-26 17:07 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews107 for mac-yosemite-wk2
(1.15 MB, application/zip)
2016-08-26 17:08 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews123 for ios-simulator-elcapitan-wk2
(868.44 KB, application/zip)
2016-08-26 17:27 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews101 for mac-yosemite
(1.05 MB, application/zip)
2016-08-26 19:10 PDT
,
Build Bot
no flags
Details
Patch
(199.77 KB, patch)
2016-08-28 02:10 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews103 for mac-yosemite
(899.60 KB, application/zip)
2016-08-28 03:23 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews106 for mac-yosemite-wk2
(1003.31 KB, application/zip)
2016-08-28 03:27 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews116 for mac-yosemite
(2.01 MB, application/zip)
2016-08-28 03:37 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews126 for ios-simulator-elcapitan-wk2
(773.28 KB, application/zip)
2016-08-28 03:37 PDT
,
Build Bot
no flags
Details
Patch
(199.99 KB, patch)
2016-08-28 23:05 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews102 for mac-yosemite
(845.28 KB, application/zip)
2016-08-29 00:25 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews105 for mac-yosemite-wk2
(995.51 KB, application/zip)
2016-08-29 00:28 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews113 for mac-yosemite
(1.46 MB, application/zip)
2016-08-29 00:30 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews121 for ios-simulator-elcapitan-wk2
(717.40 KB, application/zip)
2016-08-29 00:39 PDT
,
Build Bot
no flags
Details
Patch
(215.99 KB, patch)
2016-08-29 10:10 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(217.04 KB, patch)
2016-08-29 10:35 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews103 for mac-yosemite
(1.07 MB, application/zip)
2016-08-29 11:38 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews107 for mac-yosemite-wk2
(901.25 KB, application/zip)
2016-08-29 11:45 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews117 for mac-yosemite
(1.47 MB, application/zip)
2016-08-29 11:49 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews125 for ios-simulator-elcapitan-wk2
(6.07 MB, application/zip)
2016-08-29 11:55 PDT
,
Build Bot
no flags
Details
Patch
(221.30 KB, patch)
2016-08-29 14:27 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(199.65 KB, patch)
2016-08-30 21:04 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(199.73 KB, patch)
2016-08-31 01:14 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(199.72 KB, patch)
2016-08-31 14:52 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews122 for ios-simulator-elcapitan-wk2
(9.39 MB, application/zip)
2016-08-31 16:34 PDT
,
Build Bot
no flags
Details
Patch
(136.87 KB, patch)
2016-08-31 21:44 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(137.73 KB, patch)
2016-09-01 11:43 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(139.49 KB, patch)
2016-09-01 15:23 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(138.57 KB, patch)
2016-09-01 16:06 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(142.51 KB, patch)
2016-09-01 19:47 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(139.89 KB, patch)
2016-09-01 20:52 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(140.72 KB, patch)
2016-09-01 21:17 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(143.23 KB, patch)
2016-09-01 22:18 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews103 for mac-yosemite
(1.22 MB, application/zip)
2016-09-01 23:34 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews107 for mac-yosemite-wk2
(1.22 MB, application/zip)
2016-09-01 23:38 PDT
,
Build Bot
no flags
Details
Patch
(142.95 KB, patch)
2016-09-01 23:50 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews112 for mac-yosemite
(2.25 MB, application/zip)
2016-09-02 01:30 PDT
,
Build Bot
no flags
Details
Patch
(149.56 KB, patch)
2016-09-02 09:21 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(152.42 KB, patch)
2016-09-02 11:07 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(160.47 KB, patch)
2016-09-02 17:18 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews100 for mac-yosemite
(1.05 MB, application/zip)
2016-09-02 18:34 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from ews117 for mac-yosemite
(1.60 MB, application/zip)
2016-09-02 18:44 PDT
,
Build Bot
no flags
Details
Patch
(158.98 KB, patch)
2016-09-02 19:09 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(189.68 KB, patch)
2016-09-06 15:07 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(189.96 KB, patch)
2016-09-06 15:18 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(202.51 KB, patch)
2016-09-06 16:29 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
WIP
(157.13 KB, patch)
2016-09-08 22:44 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(161.94 KB, patch)
2016-09-09 17:55 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(161.44 KB, patch)
2016-10-14 13:17 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(161.49 KB, patch)
2016-10-22 00:51 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews114 for mac-yosemite
(2.75 MB, application/zip)
2016-10-22 18:04 PDT
,
Build Bot
no flags
Details
Patch
(175.23 KB, patch)
2016-10-28 00:04 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(181.38 KB, patch)
2016-10-31 23:06 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(193.43 KB, patch)
2016-11-01 15:33 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(210.49 KB, patch)
2016-11-09 01:58 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(249.26 KB, patch)
2016-11-10 23:54 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(245.92 KB, patch)
2016-11-11 00:20 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews115 for mac-yosemite
(1.77 MB, application/zip)
2016-11-11 01:43 PST
,
Build Bot
no flags
Details
Patch
(246.04 KB, patch)
2016-11-11 02:08 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(242.83 KB, patch)
2016-11-12 00:38 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(242.74 KB, patch)
2016-11-12 01:12 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(242.74 KB, patch)
2016-11-12 01:38 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(241.92 KB, patch)
2016-11-13 01:17 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(246.31 KB, patch)
2016-11-14 17:34 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(246.23 KB, patch)
2016-11-14 20:37 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(236.94 KB, patch)
2016-11-14 21:21 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(246.30 KB, patch)
2016-11-14 21:28 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews101 for mac-yosemite
(1.12 MB, application/zip)
2016-11-14 22:36 PST
,
Build Bot
no flags
Details
Archive of layout-test-results from ews105 for mac-yosemite-wk2
(1.05 MB, application/zip)
2016-11-14 22:43 PST
,
Build Bot
no flags
Details
Archive of layout-test-results from ews116 for mac-yosemite
(1.91 MB, application/zip)
2016-11-14 22:47 PST
,
Build Bot
no flags
Details
Patch
(246.32 KB, patch)
2016-11-14 22:52 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews106 for mac-yosemite-wk2
(1.05 MB, application/zip)
2016-11-15 00:08 PST
,
Build Bot
no flags
Details
Archive of layout-test-results from ews121 for ios-simulator-wk2
(9.37 MB, application/zip)
2016-11-15 00:17 PST
,
Build Bot
no flags
Details
Archive of layout-test-results from ews101 for mac-yosemite
(993.75 KB, application/zip)
2016-11-15 00:36 PST
,
Build Bot
no flags
Details
Archive of layout-test-results from ews112 for mac-yosemite
(1.71 MB, application/zip)
2016-11-15 00:41 PST
,
Build Bot
no flags
Details
Patch
(246.33 KB, patch)
2016-11-15 01:13 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(246.33 KB, patch)
2016-11-15 01:50 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Checking EWS
(259.88 KB, patch)
2016-11-16 02:45 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch for landing
(259.02 KB, patch)
2016-11-16 02:49 PST
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Show Obsolete
(101)
View All
Add attachment
proposed patch, testcase, etc.
Yusuke Suzuki
Comment 1
2015-09-10 01:24:45 PDT
Created
attachment 260914
[details]
Patch WIP: initial naive implementation, still considering the design
Yusuke Suzuki
Comment 2
2015-09-10 21:03:54 PDT
Created
attachment 260987
[details]
Patch WIP: part2
Yusuke Suzuki
Comment 3
2015-09-14 15:21:22 PDT
Created
attachment 261138
[details]
Patch WIP: part3
Yusuke Suzuki
Comment 4
2015-09-15 03:00:36 PDT
Created
attachment 261183
[details]
Patch WIP: part4
Yusuke Suzuki
Comment 5
2015-09-18 17:36:49 PDT
Created
attachment 261547
[details]
Patch WIP: part5
Yusuke Suzuki
Comment 6
2015-09-18 20:23:36 PDT
Created
attachment 261562
[details]
Patch WIP: part6
WebKit Commit Bot
Comment 7
2015-09-18 20:25:19 PDT
Attachment 261562
[details]
did not pass style-queue: ERROR: Source/WebCore/ChangeLog:8: You should remove the 'No new tests' and either add and list tests, or explain why no new tests were possible. [changelog/nonewtests] [5] Total errors found: 1 in 26 files If any of these errors are false positives, please file a bug against check-webkit-style.
Yusuke Suzuki
Comment 8
2015-09-18 21:16:03 PDT
Created
attachment 261570
[details]
Patch WIP: part7
Yusuke Suzuki
Comment 9
2015-09-21 11:56:13 PDT
Created
attachment 261672
[details]
Patch WIP: part8
Yusuke Suzuki
Comment 10
2015-09-23 14:18:55 PDT
Created
attachment 261841
[details]
Patch WIP: part9, adding tests
Yusuke Suzuki
Comment 11
2015-09-23 15:35:37 PDT
Created
attachment 261844
[details]
Patch WIP: part10, adding more tests
Yusuke Suzuki
Comment 12
2015-09-23 17:31:48 PDT
Created
attachment 261852
[details]
Patch
Yusuke Suzuki
Comment 13
2015-09-23 17:41:52 PDT
Created
attachment 261854
[details]
Patch
Yusuke Suzuki
Comment 14
2015-09-23 22:01:55 PDT
Created
attachment 261861
[details]
Patch
Alex Christensen
Comment 15
2015-09-24 11:31:24 PDT
Comment on
attachment 261861
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261861&action=review
> Source/WebCore/WebCore.vcxproj/WebCore.vcxproj:14439 > + <ClCompile Include="..\dom\ModuleGraph.cpp">
Add this to DOMAllInOne.cpp.
> Source/WebCore/WebCore.vcxproj/WebCore.vcxproj:18892 > + <ClCompile Include="..\bindings\js\ModuleFetcher.cpp">
Add these to JSBindingsAllInOne.cpp
Yusuke Suzuki
Comment 16
2015-09-24 11:49:43 PDT
Created
attachment 261880
[details]
Patch
Yusuke Suzuki
Comment 17
2015-09-24 11:50:29 PDT
Comment on
attachment 261861
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261861&action=review
Thank you!
>> Source/WebCore/WebCore.vcxproj/WebCore.vcxproj:14439 >> + <ClCompile Include="..\dom\ModuleGraph.cpp"> > > Add this to DOMAllInOne.cpp.
Thanks. I've added.
>> Source/WebCore/WebCore.vcxproj/WebCore.vcxproj:18892 >> + <ClCompile Include="..\bindings\js\ModuleFetcher.cpp"> > > Add these to JSBindingsAllInOne.cpp
Ditto.
Yusuke Suzuki
Comment 18
2015-09-24 13:22:49 PDT
Created
attachment 261889
[details]
Patch
Yusuke Suzuki
Comment 19
2015-09-24 13:46:41 PDT
Created
attachment 261892
[details]
Patch
Yusuke Suzuki
Comment 20
2015-09-24 13:49:32 PDT
Created
attachment 261893
[details]
Patch
Yusuke Suzuki
Comment 21
2015-09-24 14:02:36 PDT
Comment on
attachment 261893
[details]
Patch I'll split the patch into several small pieces.
Yusuke Suzuki
Comment 22
2015-09-25 15:06:47 PDT
Created
attachment 261946
[details]
Patch WIP: big picture, I'll split the patch into smaller ones
Alexey Proskuryakov
Comment 23
2015-09-25 16:58:57 PDT
Comment on
attachment 261946
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261946&action=review
I only looked through parts that seemed more closely related to loading.
> Source/WebCore/bindings/js/ModuleFetcher.cpp:71 > + request.setCharset(ASCIILiteral("utf-8"));
What would we do when the response includes a Content-Type with a different charset? If we are to only support utf-8, we should detect that as a fatal error, and refuse to decode - but this code forces utf-8 on top of explicit charset. That's a violation of the http spec, which is a lot more influential than gihub specs are. But also, the requirement to only support utf-8 is a silly political stance. Discussion in
https://github.com/whatwg/loader/issues/83
references worker loader, but we intentionally support arbitrary encodings with workers.
> Source/WebCore/bindings/js/ModuleFetcher.cpp:74 > + // FIXME: Should handle "crossorigin" options. > + // Once the spec describes the details, we will follow it.
Are these details any different than for <img> or <video> elements?
> Source/WebCore/bindings/js/ModuleFetcher.cpp:75 > + request.setInitiator(AtomicString(m_sourceURL.string()));
The initiator field doesn't appear to take URLs - it's either an element, or a predefined constant (not quite sure what the name constructor takes, but that doesn't sound like an URL either).
> Source/WebCore/bindings/js/ModuleFetcher.cpp:126 > + m_deferred->reject(exec, JSC::Symbol::create(exec->vm(), *(frame->script().moduleLoaderAlreadyReportedErrorSymbol().uid())));
Is this where we get if the web page is closed while loading a module? I'm not sure if rejecting is the right thing to do in this case.
> Source/WebCore/bindings/js/ModuleLoader.cpp:76 > + completedURL = m_document.completeURL(moduleName, URL(ParsedURLString, referrer));
The ParsedURLString constructor may only be used for strings that originated as URL.string(), and only if the URL was not invalid. I'm not sure where the JSValue, but it seems like it may not be.
> Source/WebCore/bindings/js/ModuleLoader.cpp:120 > + sourceURL = URL(ParsedURLString, asString(moduleKeyValue)->value(exec));
Ditto.
> Source/WebCore/dom/ScriptElement.cpp:352 > + String sourceUrl = sourceAttributeValue();
Style nit: should be "sourceURL"
> LayoutTests/js/dom/module-src-dynamic.html:1 > +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
Please use HTML5 doctype in new tests. If these are generated by some script, it should be updated (not in this patch).
Yusuke Suzuki
Comment 24
2015-09-25 17:29:37 PDT
Comment on
attachment 261946
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261946&action=review
Thank you for your comments!
>> Source/WebCore/bindings/js/ModuleFetcher.cpp:71 >> + request.setCharset(ASCIILiteral("utf-8")); > > What would we do when the response includes a Content-Type with a different charset? If we are to only support utf-8, we should detect that as a fatal error, and refuse to decode - but this code forces utf-8 on top of explicit charset. That's a violation of the http spec, which is a lot more influential than gihub specs are. > > But also, the requirement to only support utf-8 is a silly political stance. Discussion in
https://github.com/whatwg/loader/issues/83
references worker loader, but we intentionally support arbitrary encodings with workers.
However, it raises severe problem allowing charset for modules because the execution result of the same module is cached. <script type="module" charset="euc-jp" src="A.js"></script> <script type="module" charset="utf-8" src="B.js"></script> A.js: import "C.js" B.js: import "C.js" In this case, we only execute the C.js once. And A.js and B.js share the result of C.js. At that time, we cannot determine which charset should be applied to C.js. I think forcing utf-8 is good simple solution for this. We have an alternative solution: when the charset is different, load C.js twice in the above case and distinguish these modules. But I'm not sure it's worth doing. Since the module code contains the different syntax and semantics, I think we don't need to maintain the compatibility for the code written in the different charset. They don't contain any module syntax. "What would we do when the response includes a Content-Type with a different charset? If we are to only support utf-8, we should detect that as a fatal error, and refuse to decode - but this code forces utf-8 on top of explicit charset. That's a violation of the http spec, which is a lot more influential than gihub specs are." Nice catch, you're right. We should refuse if the response includes a Content-Type with a different charset. I'll investigate it and fix the implementation.
>> Source/WebCore/bindings/js/ModuleFetcher.cpp:74 >> + // Once the spec describes the details, we will follow it. > > Are these details any different than for <img> or <video> elements?
This is similar to the above problem. <script type="module" crossorigin="use-credentials" src="A.js"></script> <script type="module" crossorigin="anonymous" src="B.js"></script> A.js: import "C.js" B.js: import "C.js" In the above case, we cannot determine which cross origin option should be applied to the C.js. This is still discussed.
>> Source/WebCore/bindings/js/ModuleFetcher.cpp:75 >> + request.setInitiator(AtomicString(m_sourceURL.string())); > > The initiator field doesn't appear to take URLs - it's either an element, or a predefined constant (not quite sure what the name constructor takes, but that doesn't sound like an URL either).
Thanks. In the current case, we don't know which script initiate this code. This is also the similar to the above problem. <script type="module" src="A.js"></script> <script type="module" src="B.js"></script> A.js: import "C.js" B.js: import "C.js" In the above case, the initiator of the C.js is non-deterministic. So, I'm now planning to modify the request to allow the other thing (like module key, or URL) as an initiator.
>> Source/WebCore/bindings/js/ModuleFetcher.cpp:126 >> + m_deferred->reject(exec, JSC::Symbol::create(exec->vm(), *(frame->script().moduleLoaderAlreadyReportedErrorSymbol().uid()))); > > Is this where we get if the web page is closed while loading a module? I'm not sure if rejecting is the right thing to do in this case.
No, this is where we get if we encountered an error with resource fetching. For example, when we found 404. So I think rejecting is the right for this.
>> Source/WebCore/bindings/js/ModuleLoader.cpp:76 >> + completedURL = m_document.completeURL(moduleName, URL(ParsedURLString, referrer)); > > The ParsedURLString constructor may only be used for strings that originated as URL.string(), and only if the URL was not invalid. I'm not sure where the JSValue, but it seems like it may not be.
In the current implementation, this referrerValue's string is ensured it is always valid URL. Because, 1. We only allow URL or Symbol for module key now by this resolve implementation. 2. The resolved module key will be used as a referrer value. Or if there is no referrer value, it becomes undefined. (referrer value means, the module key of the importing module. so resolve(imported-mod-name, importing-mod-key) will be called). 3. We already filtered symbol case and undefined case, so here, the referrer is always string and valid URL. But, in the future, once the reflective dynamic module loader is introduced (now it's very early stage), the condition may become different. So I'll rewrite here to the more defensive code :D (Any value may come here)
>> Source/WebCore/bindings/js/ModuleLoader.cpp:120 >> + sourceURL = URL(ParsedURLString, asString(moduleKeyValue)->value(exec)); > > Ditto.
Fixed.
>> Source/WebCore/dom/ScriptElement.cpp:352 >> + String sourceUrl = sourceAttributeValue(); > > Style nit: should be "sourceURL"
Thanks. Fixed.
>> LayoutTests/js/dom/module-src-dynamic.html:1 >> +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> > > Please use HTML5 doctype in new tests. > > If these are generated by some script, it should be updated (not in this patch).
Thanks. I copied header part from the other Promise tests. I'll fix test cases.
Yusuke Suzuki
Comment 25
2015-09-25 18:24:48 PDT
(In reply to
comment #24
) I've fixed hook related things in
https://bugs.webkit.org/show_bug.cgi?id=149574
and updated the patch :D
Yusuke Suzuki
Comment 26
2015-09-26 00:59:40 PDT
TODO: Add tests for SVG script element with type="module"
Yusuke Suzuki
Comment 27
2016-08-20 00:59:57 PDT
Created
attachment 286536
[details]
Patch WIP: Rebaselining & updating
Yusuke Suzuki
Comment 28
2016-08-20 23:01:22 PDT
Created
attachment 286556
[details]
Patch WIP
Yusuke Suzuki
Comment 29
2016-08-20 23:17:09 PDT
Created
attachment 286558
[details]
Patch WIP
Radar WebKit Bug Importer
Comment 30
2016-08-22 08:59:37 PDT
<
rdar://problem/27948010
>
Yusuke Suzuki
Comment 31
2016-08-25 21:01:31 PDT
Created
attachment 287071
[details]
Patch WIP
Yusuke Suzuki
Comment 32
2016-08-26 11:18:30 PDT
Created
attachment 287124
[details]
Patch WIP
Yusuke Suzuki
Comment 33
2016-08-26 15:50:33 PDT
Created
attachment 287165
[details]
Patch WIP: preloader is fixed
Build Bot
Comment 34
2016-08-26 17:07:33 PDT
Comment on
attachment 287165
[details]
Patch
Attachment 287165
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/1950143
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 35
2016-08-26 17:07:38 PDT
Created
attachment 287175
[details]
Archive of layout-test-results from ews114 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews114 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 36
2016-08-26 17:08:02 PDT
Comment on
attachment 287165
[details]
Patch
Attachment 287165
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/1950166
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 37
2016-08-26 17:08:07 PDT
Created
attachment 287176
[details]
Archive of layout-test-results from ews107 for mac-yosemite-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews107 Port: mac-yosemite-wk2 Platform: Mac OS X 10.10.5
Build Bot
Comment 38
2016-08-26 17:27:46 PDT
Comment on
attachment 287165
[details]
Patch
Attachment 287165
[details]
did not pass ios-sim-ews (ios-simulator-wk2): Output:
http://webkit-queues.webkit.org/results/1950242
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 39
2016-08-26 17:27:53 PDT
Created
attachment 287179
[details]
Archive of layout-test-results from ews123 for ios-simulator-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews123 Port: ios-simulator-elcapitan-wk2 Platform: Mac OS X 10.11.5
Build Bot
Comment 40
2016-08-26 19:10:23 PDT
Comment on
attachment 287165
[details]
Patch
Attachment 287165
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/1950806
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 41
2016-08-26 19:10:28 PDT
Created
attachment 287187
[details]
Archive of layout-test-results from ews101 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews101 Port: mac-yosemite Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 42
2016-08-28 02:10:06 PDT
Created
attachment 287223
[details]
Patch WIP
Build Bot
Comment 43
2016-08-28 03:23:14 PDT
Comment on
attachment 287223
[details]
Patch
Attachment 287223
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/1958804
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-not-found-error-event.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-event.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 44
2016-08-28 03:23:20 PDT
Created
attachment 287225
[details]
Archive of layout-test-results from ews103 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews103 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 45
2016-08-28 03:26:59 PDT
Comment on
attachment 287223
[details]
Patch
Attachment 287223
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/1958807
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-not-found-error-event.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-event.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 46
2016-08-28 03:27:06 PDT
Created
attachment 287226
[details]
Archive of layout-test-results from ews106 for mac-yosemite-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews106 Port: mac-yosemite-wk2 Platform: Mac OS X 10.10.5
Build Bot
Comment 47
2016-08-28 03:37:08 PDT
Comment on
attachment 287223
[details]
Patch
Attachment 287223
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/1958819
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-not-found-error-event.html js/dom/module-incorrect-relative-specifier.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-event.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 48
2016-08-28 03:37:15 PDT
Created
attachment 287227
[details]
Archive of layout-test-results from ews116 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews116 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 49
2016-08-28 03:37:41 PDT
Comment on
attachment 287223
[details]
Patch
Attachment 287223
[details]
did not pass ios-sim-ews (ios-simulator-wk2): Output:
http://webkit-queues.webkit.org/results/1958814
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-not-found-error-event.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-event.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-execution-order-mixed.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html
Build Bot
Comment 50
2016-08-28 03:37:52 PDT
Created
attachment 287228
[details]
Archive of layout-test-results from ews126 for ios-simulator-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews126 Port: ios-simulator-elcapitan-wk2 Platform: Mac OS X 10.11.5
Yusuke Suzuki
Comment 51
2016-08-28 23:05:59 PDT
Created
attachment 287247
[details]
Patch WIP
Build Bot
Comment 52
2016-08-29 00:25:26 PDT
Comment on
attachment 287247
[details]
Patch
Attachment 287247
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/1963922
New failing tests: js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-not-found-error-event.html
Build Bot
Comment 53
2016-08-29 00:25:30 PDT
Created
attachment 287253
[details]
Archive of layout-test-results from ews102 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews102 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 54
2016-08-29 00:27:53 PDT
Comment on
attachment 287247
[details]
Patch
Attachment 287247
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/1963917
New failing tests: js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-not-found-error-event.html
Build Bot
Comment 55
2016-08-29 00:28:00 PDT
Created
attachment 287254
[details]
Archive of layout-test-results from ews105 for mac-yosemite-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews105 Port: mac-yosemite-wk2 Platform: Mac OS X 10.10.5
Build Bot
Comment 56
2016-08-29 00:30:33 PDT
Comment on
attachment 287247
[details]
Patch
Attachment 287247
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/1963921
New failing tests: js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-not-found-error-event.html
Build Bot
Comment 57
2016-08-29 00:30:39 PDT
Created
attachment 287255
[details]
Archive of layout-test-results from ews113 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews113 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 58
2016-08-29 00:39:17 PDT
Comment on
attachment 287247
[details]
Patch
Attachment 287247
[details]
did not pass ios-sim-ews (ios-simulator-wk2): Output:
http://webkit-queues.webkit.org/results/1963930
New failing tests: js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-not-found-error-event.html
Build Bot
Comment 59
2016-08-29 00:39:25 PDT
Created
attachment 287257
[details]
Archive of layout-test-results from ews121 for ios-simulator-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews121 Port: ios-simulator-elcapitan-wk2 Platform: Mac OS X 10.11.5
Yusuke Suzuki
Comment 60
2016-08-29 10:10:30 PDT
Created
attachment 287277
[details]
Patch WIP
Yusuke Suzuki
Comment 61
2016-08-29 10:35:44 PDT
Created
attachment 287279
[details]
Patch WIP
Build Bot
Comment 62
2016-08-29 11:38:00 PDT
Comment on
attachment 287279
[details]
Patch
Attachment 287279
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/1966716
New failing tests: transitions/default-timing-function.html js/dom/module-not-found-error-event.html
Build Bot
Comment 63
2016-08-29 11:38:10 PDT
Created
attachment 287292
[details]
Archive of layout-test-results from ews103 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews103 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 64
2016-08-29 11:45:50 PDT
Comment on
attachment 287279
[details]
Patch
Attachment 287279
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/1966746
New failing tests: js/dom/module-not-found-error-event.html
Build Bot
Comment 65
2016-08-29 11:45:58 PDT
Created
attachment 287294
[details]
Archive of layout-test-results from ews107 for mac-yosemite-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews107 Port: mac-yosemite-wk2 Platform: Mac OS X 10.10.5
Build Bot
Comment 66
2016-08-29 11:49:28 PDT
Comment on
attachment 287279
[details]
Patch
Attachment 287279
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/1966743
New failing tests: js/dom/module-not-found-error-event.html
Build Bot
Comment 67
2016-08-29 11:49:34 PDT
Created
attachment 287297
[details]
Archive of layout-test-results from ews117 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews117 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 68
2016-08-29 11:55:45 PDT
Comment on
attachment 287279
[details]
Patch
Attachment 287279
[details]
did not pass ios-sim-ews (ios-simulator-wk2): Output:
http://webkit-queues.webkit.org/results/1966757
New failing tests: js/dom/module-not-found-error-event.html
Build Bot
Comment 69
2016-08-29 11:55:53 PDT
Created
attachment 287300
[details]
Archive of layout-test-results from ews125 for ios-simulator-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews125 Port: ios-simulator-elcapitan-wk2 Platform: Mac OS X 10.11.5
Yusuke Suzuki
Comment 70
2016-08-29 14:27:35 PDT
Created
attachment 287329
[details]
Patch WIP
Yusuke Suzuki
Comment 71
2016-08-29 15:02:20 PDT
OK, the tests have passed. I'm now cleaning up the patch. Maybe, I'll split the patch into reasonable pieces.
Yusuke Suzuki
Comment 72
2016-08-30 21:04:18 PDT
Created
attachment 287479
[details]
Patch WIP: rebaselining after
r205218
Yusuke Suzuki
Comment 73
2016-08-31 01:14:37 PDT
Created
attachment 287504
[details]
Patch WIP
Yusuke Suzuki
Comment 74
2016-08-31 14:52:02 PDT
Created
attachment 287545
[details]
Patch WIP: update. Let's spawn the JSC part next
Build Bot
Comment 75
2016-08-31 16:34:29 PDT
Comment on
attachment 287545
[details]
Patch
Attachment 287545
[details]
did not pass ios-sim-ews (ios-simulator-wk2): Output:
http://webkit-queues.webkit.org/results/1982837
New failing tests: fast/scrolling/ios/scrollTo-at-page-load.html
Build Bot
Comment 76
2016-08-31 16:34:35 PDT
Created
attachment 287563
[details]
Archive of layout-test-results from ews122 for ios-simulator-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews122 Port: ios-simulator-elcapitan-wk2 Platform: Mac OS X 10.11.5
Yusuke Suzuki
Comment 77
2016-08-31 21:44:22 PDT
Created
attachment 287596
[details]
Patch WIP: Rebaselining after
r205276
and
r205278
Yusuke Suzuki
Comment 78
2016-09-01 11:43:45 PDT
Created
attachment 287646
[details]
Patch WIP: Make ScriptModuleFetcher ActiveDOMObject
Yusuke Suzuki
Comment 79
2016-09-01 15:23:49 PDT
Created
attachment 287690
[details]
Patch WIP: Intentionally allow charset attribute
Yusuke Suzuki
Comment 80
2016-09-01 16:04:00 PDT
Comment on
attachment 261946
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=261946&action=review
>>> Source/WebCore/bindings/js/ModuleFetcher.cpp:71 >>> + request.setCharset(ASCIILiteral("utf-8")); >> >> What would we do when the response includes a Content-Type with a different charset? If we are to only support utf-8, we should detect that as a fatal error, and refuse to decode - but this code forces utf-8 on top of explicit charset. That's a violation of the http spec, which is a lot more influential than gihub specs are. >> >> But also, the requirement to only support utf-8 is a silly political stance. Discussion in
https://github.com/whatwg/loader/issues/83
references worker loader, but we intentionally support arbitrary encodings with workers. > > However, it raises severe problem allowing charset for modules because the execution result of the same module is cached. > > <script type="module" charset="euc-jp" src="A.js"></script> > <script type="module" charset="utf-8" src="B.js"></script> > > A.js: > import "C.js" > > B.js: > import "C.js" > > In this case, we only execute the C.js once. > And A.js and B.js share the result of C.js. > At that time, we cannot determine which charset should be applied to C.js. > I think forcing utf-8 is good simple solution for this. > > We have an alternative solution: when the charset is different, load C.js twice in the above case and distinguish these modules. > But I'm not sure it's worth doing. > Since the module code contains the different syntax and semantics, I think we don't need to maintain the compatibility for the code written in the different charset. They don't contain any module syntax. > > "What would we do when the response includes a Content-Type with a different charset? If we are to only support utf-8, we should detect that as a fatal error, and refuse to decode - but this code forces utf-8 on top of explicit charset. That's a violation of the http spec, which is a lot more influential than gihub specs are." > > Nice catch, you're right. > We should refuse if the response includes a Content-Type with a different charset. > I'll investigate it and fix the implementation.
Now, we intentionally use the "character" attribute even if the module script is fetched. In the above described case, we use the first one, "A". This is somewhat strange, but is consistent to the current spec's "nonce", "crossorigin" etc. attributes handling.
>>> Source/WebCore/bindings/js/ModuleFetcher.cpp:74 >>> + // Once the spec describes the details, we will follow it. >> >> Are these details any different than for <img> or <video> elements? > > This is similar to the above problem. > > <script type="module" crossorigin="use-credentials" src="A.js"></script> > <script type="module" crossorigin="anonymous" src="B.js"></script> > > A.js: > import "C.js" > > B.js: > import "C.js" > > In the above case, we cannot determine which cross origin option should be applied to the C.js. > This is still discussed.
Now the spec describes the behavior. In the above case, the first fetching request (In this case, request from A) should be used and shared.
>>> Source/WebCore/bindings/js/ModuleFetcher.cpp:75 >>> + request.setInitiator(AtomicString(m_sourceURL.string())); >> >> The initiator field doesn't appear to take URLs - it's either an element, or a predefined constant (not quite sure what the name constructor takes, but that doesn't sound like an URL either). > > Thanks. In the current case, we don't know which script initiate this code. This is also the similar to the above problem. > > <script type="module" src="A.js"></script> > <script type="module" src="B.js"></script> > > A.js: > import "C.js" > > B.js: > import "C.js" > > In the above case, the initiator of the C.js is non-deterministic. > So, I'm now planning to modify the request to allow the other thing (like module key, or URL) as an initiator.
Fixed. Now ScriptModuleFetcher uses the element to construct the request.
>>> Source/WebCore/bindings/js/ModuleFetcher.cpp:126 >>> + m_deferred->reject(exec, JSC::Symbol::create(exec->vm(), *(frame->script().moduleLoaderAlreadyReportedErrorSymbol().uid()))); >> >> Is this where we get if the web page is closed while loading a module? I'm not sure if rejecting is the right thing to do in this case. > > No, this is where we get if we encountered an error with resource fetching. For example, when we found 404. > So I think rejecting is the right for this.
We now changed the ScriptModuleLoader code to the form intentionally using DeferredWrapper. It won't call the callback when the active DOM objects have been suspended. So the module pipeline stops.
Yusuke Suzuki
Comment 81
2016-09-01 16:06:21 PDT
Created
attachment 287698
[details]
Patch WIP
Yusuke Suzuki
Comment 82
2016-09-01 19:47:45 PDT
Created
attachment 287716
[details]
Patch WIP: almost completed patch. needs testing!
Yusuke Suzuki
Comment 83
2016-09-01 20:52:11 PDT
Created
attachment 287725
[details]
Patch WIP: rebaselining after
r205335
. JSC part is landed
Yusuke Suzuki
Comment 84
2016-09-01 21:17:07 PDT
Created
attachment 287727
[details]
Patch WIP
Yusuke Suzuki
Comment 85
2016-09-01 22:18:45 PDT
Created
attachment 287733
[details]
Patch WIP
Build Bot
Comment 86
2016-09-01 23:34:46 PDT
Comment on
attachment 287733
[details]
Patch
Attachment 287733
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/1991993
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-will-fire-beforeload.html js/dom/module-incorrect-relative-specifier.html js/dom/module-load-event-with-src.html js/dom/module-src-simple.html js/dom/module-execution-order-mixed.html
Build Bot
Comment 87
2016-09-01 23:34:56 PDT
Created
attachment 287742
[details]
Archive of layout-test-results from ews103 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews103 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 88
2016-09-01 23:38:28 PDT
Comment on
attachment 287733
[details]
Patch
Attachment 287733
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/1991998
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-will-fire-beforeload.html js/dom/module-incorrect-relative-specifier.html js/dom/module-load-event-with-src.html js/dom/module-src-simple.html js/dom/module-execution-order-mixed.html
Build Bot
Comment 89
2016-09-01 23:38:37 PDT
Created
attachment 287743
[details]
Archive of layout-test-results from ews107 for mac-yosemite-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews107 Port: mac-yosemite-wk2 Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 90
2016-09-01 23:50:55 PDT
Created
attachment 287744
[details]
Patch WIP
Build Bot
Comment 91
2016-09-02 01:30:49 PDT
Comment on
attachment 287744
[details]
Patch
Attachment 287744
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/1992404
New failing tests: js/dom/module-execution-error-should-be-propagated-to-onerror.html js/dom/module-src-simple.html js/dom/module-type-case-insensitive.html js/dom/module-load-event-with-src.html js/dom/module-load-event.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-inline-simple.html js/dom/module-execution-order-mixed.html js/dom/module-src-dynamic.html js/dom/module-execution-order-inline.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-inline-dynamic.html
Build Bot
Comment 92
2016-09-02 01:30:57 PDT
Created
attachment 287750
[details]
Archive of layout-test-results from ews112 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews112 Port: mac-yosemite Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 93
2016-09-02 09:21:26 PDT
Created
attachment 287764
[details]
Patch WIP
Yusuke Suzuki
Comment 94
2016-09-02 11:07:48 PDT
Created
attachment 287781
[details]
Patch WIP: finishing the implementation. adding bunch of tests...
Yusuke Suzuki
Comment 95
2016-09-02 17:18:24 PDT
Created
attachment 287836
[details]
Patch OK. Still I'm adding tests, but early review is welcome! For EWS, now I commented out ES6_MODULES flag check, but this will be fixed when landing
Yusuke Suzuki
Comment 96
2016-09-02 17:22:10 PDT
Comment on
attachment 287836
[details]
Patch Oops. Fixing tests.
Build Bot
Comment 97
2016-09-02 18:34:27 PDT
Comment on
attachment 287836
[details]
Patch
Attachment 287836
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/1997441
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-will-fire-beforeload.html js/dom/module-inline-simple.html js/dom/module-type-case-insensitive.html js/dom/module-load-event-with-src.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-src-current-script.html js/dom/module-src-simple.html js/dom/module-execution-order-mixed.html js/dom/module-src-dynamic.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-inline-dynamic.html
Build Bot
Comment 98
2016-09-02 18:34:34 PDT
Created
attachment 287843
[details]
Archive of layout-test-results from ews100 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews100 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 99
2016-09-02 18:44:08 PDT
Comment on
attachment 287836
[details]
Patch
Attachment 287836
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/1997466
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-will-fire-beforeload.html js/dom/module-src-simple.html js/dom/module-type-case-insensitive.html js/dom/module-load-event-with-src.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-src-current-script.html js/dom/module-inline-simple.html js/dom/module-execution-order-mixed.html js/dom/module-src-dynamic.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-inline-dynamic.html
Build Bot
Comment 100
2016-09-02 18:44:15 PDT
Created
attachment 287844
[details]
Archive of layout-test-results from ews117 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews117 Port: mac-yosemite Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 101
2016-09-02 19:09:16 PDT
Created
attachment 287846
[details]
Patch Still adding tests. Now tests become green
Ryosuke Niwa
Comment 102
2016-09-02 19:43:04 PDT
Comment on
attachment 287846
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=287846&action=review
> Source/JavaScriptCore/runtime/PrivateName.h:57 > - Ref<SymbolImpl> m_uid; > + RefPtr<SymbolImpl> m_uid;
Why are we changing this back to RefPtr?
> Source/WebCore/dom/ScriptElement.cpp:432 > +bool ScriptElement::requestModuleScript(const TextPosition& scriptStartPosition)
I'd call this requestModuleScriptGraph or requestScriptModuleDependencies instead since you're loading all its dependences.
> Source/WebCore/dom/ScriptElement.cpp:437 > + // The browser module loader loads the module sources. > + // Since the module involves loading of the dependent modules and the dependent modules does not have corresponding script elements, > + // the functionality of loading modules is separated from the script element. > +
With that rename, I don't think we need this comment.
> Source/WebCore/dom/ScriptElement.cpp:449 > + // Script element may be detached and attached to a different document while executing the event listener. > + if (!m_element.inDocument() || &m_element.document() != originalDocument.ptr())
We should definitely add a test for this. But WebKit's way of adding a comment like this is to use a local variable of a descriptive name instead. e.g. bool didEventListenerDisconnectThisElement = !m_element.inDocument() || &m_element.document() != originalDocument.ptr()
> Source/WebCore/dom/ScriptElement.cpp:467 > + // Reset line numbering for nested writes.
I don't think we need this comment.
> Source/WebCore/dom/ScriptRunner.cpp:74 > +void ScriptRunner::queueScriptModuleGraphForExecution(ScriptElement* scriptElement, ScriptModuleGraph& moduleGraph, ExecutionType executionType)
Is it possible to introduce an abstract interface from which both ScriptModuleGraph and CachedResourceHandle<CachedScript> (or a new wrapper for it) inherit so that we don't have to duplicate code like this?
Yusuke Suzuki
Comment 103
2016-09-03 00:29:19 PDT
Comment on
attachment 287846
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=287846&action=review
Thank you!
>> Source/JavaScriptCore/runtime/PrivateName.h:57 >> + RefPtr<SymbolImpl> m_uid; > > Why are we changing this back to RefPtr?
This is because it is the simple way to make this PrivateName copyable.
>> Source/WebCore/dom/ScriptElement.cpp:432 >> +bool ScriptElement::requestModuleScript(const TextPosition& scriptStartPosition) > > I'd call this requestModuleScriptGraph or requestScriptModuleDependencies instead since you're loading all its dependences.
Right. Sounds nice. Fixed.
>> Source/WebCore/dom/ScriptElement.cpp:437 >> + > > With that rename, I don't think we need this comment.
OK. Dropped.
>> Source/WebCore/dom/ScriptElement.cpp:449 >> + if (!m_element.inDocument() || &m_element.document() != originalDocument.ptr()) > > We should definitely add a test for this. But WebKit's way of adding a comment like this is to use a local variable of a descriptive name instead. > e.g. > bool didEventListenerDisconnectThisElement = !m_element.inDocument() || &m_element.document() != originalDocument.ptr()
Nice. Fixed. And I also applied this fix to the requestClassicScript.
>> Source/WebCore/dom/ScriptElement.cpp:467 >> + // Reset line numbering for nested writes. > > I don't think we need this comment.
OK. Dropped. And I also dropped the same comment in the requestClassicScript.
>> Source/WebCore/dom/ScriptRunner.cpp:74 >> +void ScriptRunner::queueScriptModuleGraphForExecution(ScriptElement* scriptElement, ScriptModuleGraph& moduleGraph, ExecutionType executionType) > > Is it possible to introduce an abstract interface from which both ScriptModuleGraph and CachedResourceHandle<CachedScript> (or a new wrapper for it) inherit > so that we don't have to duplicate code like this?
Yeah, we can do that. I think it is cleaner to provide a new wrapper, since these two things are managed by the different somewhat ref-counting system. (While we use CachedResourceHandle for CachedScript, ScriptModuleGraph is managed by RefPtr).
Yusuke Suzuki
Comment 104
2016-09-06 15:07:37 PDT
Created
attachment 288049
[details]
Patch Adding tests now
Yusuke Suzuki
Comment 105
2016-09-06 15:12:46 PDT
Comment on
attachment 288049
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288049&action=review
> Source/WebCore/dom/LoadableScript.h:1 > +/*
Add LoadableScript, LoadableScriptModuleGraph, and LoadableClassicScript. The latter 2 classes are derived classes from LoadableScript.
Yusuke Suzuki
Comment 106
2016-09-06 15:14:16 PDT
I'll rebaseline the patch.
Yusuke Suzuki
Comment 107
2016-09-06 15:18:34 PDT
Created
attachment 288051
[details]
Patch Adding tests now
Yusuke Suzuki
Comment 108
2016-09-06 15:23:38 PDT
Comment on
attachment 288051
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288051&action=review
> Source/WebCore/dom/LoadableClassicScript.h:57 > + HashCountedSet<LoadableScriptClient*> m_clients;
Oops. This will be dropped.
Yusuke Suzuki
Comment 109
2016-09-06 15:33:33 PDT
Comment on
attachment 288051
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288051&action=review
> Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp:925 > + m_pendingScript = &downcast<LoadableClassicScript>(*scriptElement->loadableScript()).cachedScript();
Oops. This part will be slightly updated & cleaned up.
Yusuke Suzuki
Comment 110
2016-09-06 15:39:06 PDT
Comment on
attachment 288051
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288051&action=review
>> Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp:925 >> + m_pendingScript = &downcast<LoadableClassicScript>(*scriptElement->loadableScript()).cachedScript(); > > Oops. This part will be slightly updated & cleaned up.
I think this XML Document parser's scripting needs refactoring. In the meantime, I disable "module" feature for the XML document, but this should be enabled later. Specifically, XMLDocumentParser should use PendingScript to construct such a logic I think.
Yusuke Suzuki
Comment 111
2016-09-06 16:29:43 PDT
Created
attachment 288066
[details]
Patch Fix EFL build, add tests for mime type checking
Yusuke Suzuki
Comment 112
2016-09-06 16:35:28 PDT
Comment on
attachment 288066
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288066&action=review
> Source/WebCore/dom/ScriptElement.cpp:178 > +// #endif
Note that this commenting out and TestExpectation is now modified to test modules in EWS. When landing, we will make this guard back.
Yusuke Suzuki
Comment 113
2016-09-06 16:56:32 PDT
Comment on
attachment 288066
[details]
Patch Discussed with rniwa offline. I'll first split this patch into smaller ones, especially, I'll extract the LoadableScript part.
Ryosuke Niwa
Comment 114
2016-09-06 16:57:45 PDT
Comment on
attachment 288051
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288051&action=review
I think we may want to split the part to add LoadableScript as a wrapper for CachedScript as a separate patch so that the related refactoring can be landed separately. That'll make this patch easier to review & reason through.
> Source/JavaScriptCore/ChangeLog:10 > + * runtime/PrivateName.h: PrivateName should be copyable. I completely forgot that in the previous patch. > + (JSC::PrivateName::PrivateName): > + (JSC::PrivateName::uid):
Can we land this in a separate patch?
> Source/WebCore/ChangeLog:28 > + 3. ScriptModuleFetcher
We might want to call this CachedModuleScriptLoader or something since this class doesn't really fetch the module file if it's already cached.
> Source/WebCore/bindings/js/ScriptModuleFetcher.cpp:80 > + m_loaded = true;
Don't we need to clear m_deferred here? Also, if we've done that, do we still need a separate m_loaded boolean?
> Source/WebCore/bindings/js/ScriptModuleFetcher.cpp:89 > + if (m_client) > + m_client->notifyFinished(*this);
Why don't we just call this with m_deferred here instead of keeping it around in the fetcher object and calling deferred() in ScriptModuleLoader::notifyFinished ? That way, we can even use WTFMove() and remove the ownership the callee.
> Source/WebCore/bindings/js/ScriptModuleFetcher.h:73 > + RefPtr<DeferredWrapper> m_deferred;
We might want to call this m_promise instead.
> Source/WebCore/bindings/js/ScriptModuleGraph.h:49 > + bool errorOccurred() const { return m_errored; }
I'd call this wasErrored for consistency.
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:99 > + if (importerModuleKey.isSymbol() || importerModuleKey.isUndefined()) { > + // When the module is root module, we resolve the specifier with the document.
It's better to define a descriptive local variable. e.g. bool isRootModule = importerModuleKey.isSymbol() || importerModuleKey.isUndefined().
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:108 > + // The base URL is a response URL while the module key is a request URL.
I don't know what this comment means.
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:110 > + URL importerModuleResponseURL = m_baseURLMap.get(importerModuleRequestURL); > + if (!importerModuleResponseURL.isValid()) {
It's strange that m_baseURLMap contains response URLs. Having said that, I don't think we need a separate comment about this especially with the error message describing the situation right beneath it.
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:133 > - JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject); > + return JSC::jsCast<JSC::JSInternalPromise*>(resolvePromise(m_document, *exec, *JSC::jsCast<JSDOMGlobalObject*>(globalObject), moduleNameValue, importerModuleKey)); > +}
Why do we need to split into a separate function?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:219 > + RefPtr<Element> element = fetcher.element(); > + RefPtr<DeferredWrapper> deferred = fetcher.deferred();
We can't use Ref<> here?
> Source/WebCore/dom/ScriptElement.cpp:309 > +bool ScriptElement::requestClassicScript(const String& sourceURL)
Can we keep this as the first function so that the diff looks saner?
> Source/WebCore/dom/ScriptElement.cpp:354 > + if (is<LoadableClassicScript>(m_loadableScript)) { > + auto& cachedScript = downcast<LoadableClassicScript>(*m_loadableScript)->cachedScript(); > + if (!cachedScript.mimeTypeAllowedByNosniff()) {
Can we just add mimeTypeAllowedByNosniff on LoadableScript so that we don't have to do this check? We can just always return true for modules, right?
> Source/WebCore/dom/ScriptElement.cpp:534 > +bool ScriptElement::attemptToHandleCrossOriginScriptLoad(CachedScript* cachedScript) > +{
I think this should move to LoadableScript with a name like shouldLoadCrossOriginScript, and then just have the error spit out in ScriptElement::notifyFinished.
Daniel Bates
Comment 115
2016-09-06 17:00:40 PDT
Comment on
attachment 288066
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288066&action=review
> Source/JavaScriptCore/runtime/PrivateName.h:51 > + SymbolImpl& uid() const { return *m_uid.get(); }
I know that this class has an implicit invariant that it is passed a non-null SymbolImpl. What guarantees that this invariant is not violated and m_uid is not nullptr?
> Source/JavaScriptCore/runtime/PrivateName.h:57 > - Ref<SymbolImpl> m_uid; > + RefPtr<SymbolImpl> m_uid;
This does not seem like the correct idiom to use to make PrivateName copyable. I suggest that we implement a custom copy-constructor to handle the copying of Ref<SymbolImpl>.
Yusuke Suzuki
Comment 116
2016-09-06 17:38:55 PDT
Comment on
attachment 288066
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288066&action=review
Thanks!
>> Source/JavaScriptCore/runtime/PrivateName.h:51 >> + SymbolImpl& uid() const { return *m_uid.get(); } > > I know that this class has an implicit invariant that it is passed a non-null SymbolImpl. What guarantees that this invariant is not violated and m_uid is not nullptr?
We do not allow nullptr SymbolImpl in SymbolImpl users. We may have nullptr UniquedStringImpl* (parent class of SymbolImpl). But in that case, (the wrapper of this class).isSymbol() returns false if the UniquedStringImpl* is nullptr. For example, Identifier::isSymbol() returns false for nullptr. And Identifier::fromUid(vm, nullptr).isSymbol() is also false. Before performing downcast (like static_cast<SymbolImpl&>()), we ensure the invariant that SymbolImpl* never becomes nullptr.
>> Source/JavaScriptCore/runtime/PrivateName.h:57 >> + RefPtr<SymbolImpl> m_uid; > > This does not seem like the correct idiom to use to make PrivateName copyable. I suggest that we implement a custom copy-constructor to handle the copying of Ref<SymbolImpl>.
Looks nice. I'll create the separate patch based on this approach.
Yusuke Suzuki
Comment 117
2016-09-06 17:44:04 PDT
Comment on
attachment 288066
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288066&action=review
>>> Source/JavaScriptCore/runtime/PrivateName.h:51 >>> + SymbolImpl& uid() const { return *m_uid.get(); } >> >> I know that this class has an implicit invariant that it is passed a non-null SymbolImpl. What guarantees that this invariant is not violated and m_uid is not nullptr? > > We do not allow nullptr SymbolImpl in SymbolImpl users. We may have nullptr UniquedStringImpl* (parent class of SymbolImpl). But in that case, (the wrapper of this class).isSymbol() returns false if the UniquedStringImpl* is nullptr. > For example, Identifier::isSymbol() returns false for nullptr. And Identifier::fromUid(vm, nullptr).isSymbol() is also false. > Before performing downcast (like static_cast<SymbolImpl&>()), we ensure the invariant that SymbolImpl* never becomes nullptr.
For this class, we have 3 constructors. 1. PrivateName() 2. explicit PrivateName(DescriptionTag, const String& description) 3. explicit PrivateName(SymbolImpl& uid) In the cases of 1 and 2, since StringImpl::createXXXSymbol() never returns nullptr (And its type is Ref<SymbolImpl>), this PrivateName does not become m_uid = nullptr. In the case of 3, we ensure this invariant by taking SymbolImpl&.
Yusuke Suzuki
Comment 118
2016-09-08 22:44:23 PDT
Created
attachment 288389
[details]
WIP WIP
Yusuke Suzuki
Comment 119
2016-09-09 17:20:44 PDT
Comment on
attachment 288051
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=288051&action=review
Thanks!
>> Source/JavaScriptCore/ChangeLog:10 >> + (JSC::PrivateName::uid): > > Can we land this in a separate patch?
OK, I'll split it soon :)
>> Source/WebCore/ChangeLog:28 >> + 3. ScriptModuleFetcher > > We might want to call this CachedModuleScriptLoader or something since this class doesn't really fetch the module file if it's already cached.
Looks better. Changed.
>> Source/WebCore/bindings/js/ScriptModuleFetcher.cpp:80 >> + m_loaded = true; > > Don't we need to clear m_deferred here? > Also, if we've done that, do we still need a separate m_loaded boolean?
Make sense. Changed.
>> Source/WebCore/bindings/js/ScriptModuleFetcher.cpp:89 >> + m_client->notifyFinished(*this); > > Why don't we just call this with m_deferred here instead of keeping it around in the fetcher object and calling deferred() in ScriptModuleLoader::notifyFinished ? > That way, we can even use WTFMove() and remove the ownership the callee.
Nice, fixed.
>> Source/WebCore/bindings/js/ScriptModuleFetcher.h:73 >> + RefPtr<DeferredWrapper> m_deferred; > > We might want to call this m_promise instead.
OK, fixed.
>> Source/WebCore/bindings/js/ScriptModuleGraph.h:49 >> + bool errorOccurred() const { return m_errored; } > > I'd call this wasErrored for consistency.
Fixed in LoadableScript patch.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:99 >> + // When the module is root module, we resolve the specifier with the document. > > It's better to define a descriptive local variable. e.g. > bool isRootModule = importerModuleKey.isSymbol() || importerModuleKey.isUndefined().
Sounds nice. Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:108 >> + // The base URL is a response URL while the module key is a request URL. > > I don't know what this comment means.
The module key - which maintains identity of each module - should be request URL (URL used when requesting), since we need to detect duplicate module requests before actually sending requests over network. On the other hand, when we resolve the given module name (`import A from "./A.js")'s "./A.js" part) with a parent module, this "./A.js" should be resolved with the response URL of the parent module.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:110 >> + if (!importerModuleResponseURL.isValid()) { > > It's strange that m_baseURLMap contains response URLs. > Having said that, I don't think we need a separate comment about this especially with the error message describing the situation right beneath it.
OK, this comment is dropped. And rename this map more descriptive name, "m_requestURLToResponseURLMap".
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:133 >> +} > > Why do we need to split into a separate function?
Oops, due to previous design of this function. Now, it is not necessary. Merged.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:219 >> + RefPtr<DeferredWrapper> deferred = fetcher.deferred(); > > We can't use Ref<> here?
We now take RefPtr<DeferredWrapper> as this function's argument.
>> Source/WebCore/dom/ScriptElement.cpp:309 >> +bool ScriptElement::requestClassicScript(const String& sourceURL) > > Can we keep this as the first function so that the diff looks saner?
Done in LoadableScript patch and it makes the diff nicer.
>> Source/WebCore/dom/ScriptElement.cpp:354 >> + if (!cachedScript.mimeTypeAllowedByNosniff()) { > > Can we just add mimeTypeAllowedByNosniff on LoadableScript so that we don't have to do this check? > We can just always return true for modules, right?
Move this check to the LoadableClassicScript in LoadableScript patch, thanks!
>> Source/WebCore/dom/ScriptElement.cpp:534 >> +{ > > I think this should move to LoadableScript with a name like shouldLoadCrossOriginScript, > and then just have the error spit out in ScriptElement::notifyFinished.
Nice, I've moved this check to the LoadableClassicScript. And now the error is propagated to the ScriptElement through wasErrored().
Yusuke Suzuki
Comment 120
2016-09-09 17:55:20 PDT
Created
attachment 288462
[details]
Patch Update!
Yusuke Suzuki
Comment 121
2016-10-14 13:17:43 PDT
Created
attachment 291662
[details]
Patch Just rebaselining...
Yusuke Suzuki
Comment 122
2016-10-22 00:51:31 PDT
Created
attachment 292487
[details]
Patch WIP
Build Bot
Comment 123
2016-10-22 18:04:47 PDT
Comment on
attachment 292487
[details]
Patch
Attachment 292487
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/2347408
New failing tests: js/dom/module-not-found-error-event-with-src-and-import.html js/dom/module-not-found-error-event-with-src.html js/dom/module-will-fire-beforeload.html http/tests/security/module-requires-javascript-mime-types.html js/dom/module-not-found-error-event.html http/tests/security/module-correct-mime-types.html http/tests/security/module-no-mime-type.html js/dom/module-load-same-module-from-different-entry-point.html js/dom/module-load-event-with-src.html js/dom/module-load-same-module-from-different-entry-point-dynamic.html http/tests/security/module-incorrect-mime-types.html http/tests/misc/module-script-async.html js/dom/module-type-case-insensitive.html js/dom/module-src-current-script.html js/dom/module-inline-simple.html js/dom/module-execution-order-mixed.html js/dom/module-src-dynamic.html js/dom/module-src-simple.html js/dom/module-execution-error-inside-dependent-module-should-be-propagated-to-onerror.html js/dom/module-inline-dynamic.html
Build Bot
Comment 124
2016-10-22 18:04:55 PDT
Created
attachment 292524
[details]
Archive of layout-test-results from ews114 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews114 Port: mac-yosemite Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 125
2016-10-28 00:04:19 PDT
Created
attachment 293120
[details]
Patch
Yusuke Suzuki
Comment 126
2016-10-31 23:06:35 PDT
Created
attachment 293531
[details]
Patch
Yusuke Suzuki
Comment 127
2016-11-01 15:33:18 PDT
Created
attachment 293606
[details]
Patch
Yusuke Suzuki
Comment 128
2016-11-09 01:58:11 PST
Created
attachment 294227
[details]
Patch WIP
Yusuke Suzuki
Comment 129
2016-11-10 23:54:41 PST
Created
attachment 294478
[details]
Patch WIP
Yusuke Suzuki
Comment 130
2016-11-11 00:20:02 PST
Created
attachment 294479
[details]
Patch
Build Bot
Comment 131
2016-11-11 01:43:47 PST
Comment on
attachment 294479
[details]
Patch
Attachment 294479
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/2496757
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect-same-origin.html
Build Bot
Comment 132
2016-11-11 01:43:56 PST
Created
attachment 294483
[details]
Archive of layout-test-results from ews115 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews115 Port: mac-yosemite Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 133
2016-11-11 02:08:44 PST
Created
attachment 294488
[details]
Patch
Ryosuke Niwa
Comment 134
2016-11-11 16:06:46 PST
Comment on
attachment 294488
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294488&action=review
Here's the first round o review comments. I need a few more rounds of read through.
> Source/WebCore/ChangeLog:18 > + 1. ScriptModuleGraph > + > + ScriptModuleGraph wraps the promise based JSModuleLoader pipeline and offers > + similar APIs to CachedScript. ScriptElement and PendingScript interact with > + ScriptModuleGraph when the script tag is the module tag instead of CachedScript. > + ScriptElement and PendingScript will receive the notification from > + ScriptModuleGraph by implementing ScriptModuleGraphClient.
I think it's very misleading to call this object a "graph". A graph is a collection of nodes. Here, what we have is a node in a graph. How about CachedModuleScript or ModuleScriptVertex?
> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:67 > + // Note: If the content is already cached, this immeidately calls notifyFinished.
We don't normally prefix a comment with "Node:".
> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:75 > + if (!m_promise) > + return;
How could notifyFinished be called multiple times per CachedResourceClient!?
> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:87 > + // A CachedResourceHandle alone does not prevent the underlying CachedResource > + // from purging its data buffer. Until we finish using the backing buffer of the > + // cached script, we don't remove the client.
I don't understand what this comment is saying. Are we trying to retain the cache? Or are we trying to clear the cache?
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:63 > + // For CachedResourceClient.
I don't think we need this comment given we're only inheriting from RefCounted and CachedResourceClient
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:64 > + void notifyFinished(CachedResource&) override;
Use final instead.
> Source/WebCore/bindings/js/ScriptController.cpp:371 > + // NOTE: It is not guaranteed that either fulfillHandler or rejectHandler is eventually called. > + // For example, if the page load is canceled, the DeferredPromise used in the module loader pipeline will stop executing JS code. > + // Thus the promise returned from this function could remain unresolved.
Wouldn't that result in the leak of ScriptModuleGraph?
> Source/WebCore/bindings/js/ScriptController.cpp:373 > + RefPtr<ScriptModuleGraph> protector(&moduleGraph);
Why don't we call this moduleGraph and the argument moduleGraphRef. Alternatively, you can just modify the argument to be Ref<ScriptModuleGraph>. Regardless, we should be using Ref here, not RefPtr.
> Source/WebCore/bindings/js/ScriptController.cpp:400 > + else if (errorStatus == ErrorStatus::AlreadyReported) { > + protector->notifyErrored(LoadableScript::Error { > + LoadableScript::ErrorType::CachedScript, > + Nullopt > + }); > + } else {
Why don't we just put the logic at where we check symbol->privateName() == moduleLoaderAlreadyReportedErrorSymbol and then exit early there instead? That is, if (Symbol* symbol = ~) { if (ymbol->privateName() == moduleLoaderAlreadyReportedErrorSymbol) { ... return JSValue::encode(jsUndefined()); } if (symbol->privateName() == moduleLoaderFetchingIsCanceledSymbol) { protector->notifyCanceled(); return JSValue::encode(jsUndefined()); } } If we did that, we don't even need the enum.
> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:56 > + Ref<Document> document(initiator.document());
This is yet another protector object? Might be better call it documentProtector.
> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:63 > + Ref<Document> document(initiator.document());
Ditto.
> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:91 > + RefPtr<ScriptModuleGraph> protectedThis(this);
nit: protector as the variable name.
> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:95 > + Vector<ScriptModuleGraphClient*> vector; > + for (auto& pair : m_clients) > + vector.append(pair.key);
Can't we just do copyToVector(m_clients, clients) instead? btw, we should call this variable clients instead of "vector".
> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:103 > + if (isLoaded()) {
We normally prefer an early exit.
> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:104 > + Ref<ScriptModuleGraph> protectedThis(*this);
Ditto about calling this protector.
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:76 > + promise->reject(TypeError, "Module specifier is not Symbol or String.");
Should we wrap these strings in ASCIILiteral? You're doing it in some places but not everywhere.
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:221 > + else if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(cachedScript->response().mimeType())) { > + //
https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
Does the list of mime types in isSupportedJavaScriptMIMEType match the ones in the spec?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:247 > + // The module loader pipeline is constructed as a chain of promises. > + // Rejecting a promise when some error occurs is important because the execution flow of > + // the promise chain is driven by "rejected" or "fulfilled" events. > + // If the promise is not rejected while error occurs, reject handler won't be executed > + // and all the subsequent promise chain will wait the result forever. > + // > + // As a result, even if the error is already reported to the inspector elsewhere, > + // it should be propagated in the pipeline. For example, the error of loading > + // CachedResource is already reported to the inspector by the loader. But we still need > + // to reject the promise to propagate this error to the script element. > + // > + // At that time, we don't want to report the same error twice. When we propagate the error > + // that is already reported to the inspector, we throw moduleLoaderAlreadyReportedErrorSymbol > + // symbol instead. By comparing the thrown error with this symbol, we can distinguish errors raised > + // when checking syntax of a module script from errors reported already. > + // In the reject handler of the promise, we only report a error that is not this symbol.
You might want to put this long version in the change log. In the code, it's probably sufficient to say that "Reject a promise to propagate the error back all the way through module promise chains to the script element"
> Source/WebCore/dom/Document.cpp:4792 > - ASSERT(newCurrentScript); > + // HTMLScriptElement may be nullptr.
Since we also need to return nullptr when we're running the script inside a shadow tree, we might want to do this check in Document::currentScript instead and keep this function unchanged.
> Source/WebCore/dom/LoadableScriptModuleGraph.h:35 > +class LoadableScriptModuleGraph final : public LoadableScript, private ScriptModuleGraphClient {
Again, this class name is misleading. This isn't really a graph. It's a node/vertex in a graph.
> Source/WebCore/dom/LoadableScriptModuleGraph.h:42 > + Optional<Error> wasErrored() const override;
We might want to call this function error() if it returns Optional<Error> since wasError is a question.
> Source/WebCore/dom/ScriptElement.cpp:165 > -#if ENABLE(ES6_MODULES) > +// #if ENABLE(ES6_MODULES)
What's up with this?
> Source/WebCore/dom/ScriptElement.cpp:226 > + // We intentionally use the charset attribute even if the script is the module script.
Why is that? We prefer why comments over what comments.
> Source/WebCore/dom/ScriptElement.cpp:243 > + if ((scriptType == ScriptType::Classic && hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) || (scriptType == ScriptType::Module && m_parserInserted && !asyncAttributeValue())) {
This predicate is getting really long. Can we put it into a helper function with a descriptive name? Alternatively, since this is the first predicate we check, we can just declare a local boolean variable with a descriptive name.
> Source/WebCore/dom/ScriptElement.cpp:310 > + bool didEventListenerDisconnectThisElement = !m_element.inDocument() || &m_element.document() != originalDocument.ptr(); > + if (didEventListenerDisconnectThisElement)
Are these checks spec'ed somewhere? Can we add a URL to reference that? The ordering here is quite important as it's observable from scripts.
> Source/WebCore/dom/ScriptElement.cpp:328 > + } else {
Why not early return here?
> Source/WebCore/dom/ScriptElement.cpp:412 > + if (Frame* frame = document->frame()) {
Why not an early return instead?
> Source/WebCore/dom/ScriptElement.cpp:414 > + // If the script is from an external file, or the script's type is "module", > + // then increment the ignore-destructive-writes counter of the script element's node document. Let neutralized doc be that Document.
I don't think we need this comment since the class name is pretty descriptive and there are a only few steps.
> Source/WebCore/dom/ScriptElement.cpp:417 > + // Set the script element's node document's currentScript attribute to null.
Ditto.
> Source/WebCore/html/parser/HTMLPreloadScanner.cpp:150 > + // We intentionally use the character attribute even if the given script tag loads the module script.
Ditto about explaining why instead of stating what.
> Source/WebCore/html/parser/HTMLResourcePreloader.h:39 > + enum class ModuleScriptMode { > + Yes, > + No, > + };
I think it would be nicer to say ScriptType: Module/Classic.
Yusuke Suzuki
Comment 135
2016-11-12 00:18:41 PST
Comment on
attachment 294488
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294488&action=review
Thanks!
>> Source/WebCore/ChangeLog:18 >> + ScriptModuleGraph by implementing ScriptModuleGraphClient. > > I think it's very misleading to call this object a "graph". A graph is a collection of nodes. Here, what we have is a node in a graph. > How about CachedModuleScript or ModuleScriptVertex?
Yup, that is named after the internal implementation (dependency graph of the scripts). Actually, it manages the graph of CachedScripts(node) with dependency edges. But it should not be exposed to WebCore side. CachedModuleScript seems fine. It is consistent with CachedModuleScriptLoader. Changed.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:67 >> + // Note: If the content is already cached, this immeidately calls notifyFinished. > > We don't normally prefix a comment with "Node:".
Dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:75 >> + return; > > How could notifyFinished be called multiple times per CachedResourceClient!?
Yeah, ok, it should not be called. This guard is meaningless. Dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:87 >> + // cached script, we don't remove the client. > > I don't understand what this comment is saying. > Are we trying to retain the cache? Or are we trying to clear the cache?
We are trying to retain the cache until we call m_client->notifyFinished. To do so, removeClient(this) should not be called before calling `m_client->notifyFinished`. Changed the comment. // A CachedResourceHandle alone does not prevent the underlying CachedResource // from purging its data buffer. To keep the underlying CachedResource during // processing, we remove the client after calling client's notifyFinished.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:63 >> + // For CachedResourceClient. > > I don't think we need this comment given we're only inheriting from RefCounted and CachedResourceClient
Dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:64 >> + void notifyFinished(CachedResource&) override; > > Use final instead.
Nice, changed.
>> Source/WebCore/bindings/js/ScriptController.cpp:371 >> + // Thus the promise returned from this function could remain unresolved. > > Wouldn't that result in the leak of ScriptModuleGraph?
When the module cache is cleared (page is refreshed), they should be released. Since module instances are cached (the same module key returns the same module instance), resource combined with the module may be retained while this page is live. But once the page & context is destroyed, they should be collected by GC. (& GC will call destroy function, and it will destroy ScriptModuleGraph).
>> Source/WebCore/bindings/js/ScriptController.cpp:373 >> + RefPtr<ScriptModuleGraph> protector(&moduleGraph); > > Why don't we call this moduleGraph and the argument moduleGraphRef. > Alternatively, you can just modify the argument to be Ref<ScriptModuleGraph>. > Regardless, we should be using Ref here, not RefPtr.
It's because 2 functions reference this protector: fulfillHandler and rejectHandler. But I think we can alleviate this situation by using C++14 generalized capture. I'll change the argument to Ref<CachedModuleScript>, and use generalized capture like `[moduleScript = protector.copyRef()]`.
>> Source/WebCore/bindings/js/ScriptController.cpp:400 >> + } else { > > Why don't we just put the logic at where we check symbol->privateName() == moduleLoaderAlreadyReportedErrorSymbol > and then exit early there instead? > > That is, > if (Symbol* symbol = ~) { > if (ymbol->privateName() == moduleLoaderAlreadyReportedErrorSymbol) { > ... > return JSValue::encode(jsUndefined()); > } > if (symbol->privateName() == moduleLoaderFetchingIsCanceledSymbol) { > protector->notifyCanceled(); > return JSValue::encode(jsUndefined()); > } > } > > If we did that, we don't even need the enum.
It should be fine. Changed.
>> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:56 >> + Ref<Document> document(initiator.document()); > > This is yet another protector object? Might be better call it documentProtector.
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:63 >> + Ref<Document> document(initiator.document()); > > Ditto.
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:95 >> + vector.append(pair.key); > > Can't we just do copyToVector(m_clients, clients) instead? > btw, we should call this variable clients instead of "vector".
Nice, copyToVector function works. Fixed.
>> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:103 >> + if (isLoaded()) { > > We normally prefer an early exit.
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:104 >> + Ref<ScriptModuleGraph> protectedThis(*this); > > Ditto about calling this protector.
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:76 >> + promise->reject(TypeError, "Module specifier is not Symbol or String."); > > Should we wrap these strings in ASCIILiteral? You're doing it in some places but not everywhere.
Oops, right. We should do that. Changed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:221 >> + //
https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
> > Does the list of mime types in isSupportedJavaScriptMIMEType match the ones in the spec?
Yeah, completely the same. :)
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:247 >> + // In the reject handler of the promise, we only report a error that is not this symbol. > > You might want to put this long version in the change log. In the code, it's probably sufficient to say that > "Reject a promise to propagate the error back all the way through module promise chains to the script element"
OK, I've moved the above comment to the ChangeLog. And use this short version.
>> Source/WebCore/dom/Document.cpp:4792 >> + // HTMLScriptElement may be nullptr. > > Since we also need to return nullptr when we're running the script inside a shadow tree, > we might want to do this check in Document::currentScript instead and keep this function unchanged.
You mean that we should check ScriptType in Document::currentScript() side, correct?
>> Source/WebCore/dom/LoadableScriptModuleGraph.h:35 >> +class LoadableScriptModuleGraph final : public LoadableScript, private ScriptModuleGraphClient { > > Again, this class name is misleading. This isn't really a graph. It's a node/vertex in a graph.
Changed it to LoadableModuleScript.
>> Source/WebCore/dom/LoadableScriptModuleGraph.h:42 >> + Optional<Error> wasErrored() const override; > > We might want to call this function error() if it returns Optional<Error> since wasError is a question.
OK, changed. We also need to change wasErrored() functions in LoadableClassicScript, PendingScript etc. Done.
>> Source/WebCore/dom/ScriptElement.cpp:165 >> +// #if ENABLE(ES6_MODULES) > > What's up with this?
This is just commented out to check this patch on EWS. When landing it, we should revert this change. And we should remove # of TestExpectations.
>> Source/WebCore/dom/ScriptElement.cpp:226 >> + // We intentionally use the charset attribute even if the script is the module script. > > Why is that? We prefer why comments over what comments.
Add comment that is noted in ChangeLog. According to the spec, the module tag ignores the "charset" attribute as the same to the worker's importScript. But WebKit supports the "charset" for importScript intentionally. So to be consistent, even for the module tags, we handle the "charset" attribute.
>> Source/WebCore/dom/ScriptElement.cpp:243 >> + if ((scriptType == ScriptType::Classic && hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) || (scriptType == ScriptType::Module && m_parserInserted && !asyncAttributeValue())) { > > This predicate is getting really long. Can we put it into a helper function with a descriptive name? > Alternatively, since this is the first predicate we check, we can just declare a local boolean variable with a descriptive name.
Changed. BTW, the above condition is strictly aligned to the spec.
https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
Named it as isParserInsertedDeferredScript.
>> Source/WebCore/dom/ScriptElement.cpp:310 >> + if (didEventListenerDisconnectThisElement) > > Are these checks spec'ed somewhere? Can we add a URL to reference that? > The ordering here is quite important as it's observable from scripts.
No. The before load event for the script tag is not specified in whatwg HTML5 spec. This is the extension in WebKit. It is originally implemented for the classic script. And the module script is just using the completely same semantics. BTW, it seems that blink dropped before load event support.
>> Source/WebCore/dom/ScriptElement.cpp:328 >> + } else { > > Why not early return here?
Fixed.
>> Source/WebCore/dom/ScriptElement.cpp:412 >> + if (Frame* frame = document->frame()) { > > Why not an early return instead?
Fixed.
>> Source/WebCore/dom/ScriptElement.cpp:414 >> + // then increment the ignore-destructive-writes counter of the script element's node document. Let neutralized doc be that Document. > > I don't think we need this comment since the class name is pretty descriptive and there are a only few steps.
OK, dropped.
>> Source/WebCore/dom/ScriptElement.cpp:417 >> + // Set the script element's node document's currentScript attribute to null. > > Ditto.
Dropped.
>> Source/WebCore/html/parser/HTMLPreloadScanner.cpp:150 >> + // We intentionally use the character attribute even if the given script tag loads the module script. > > Ditto about explaining why instead of stating what.
Add the same comment. According to the spec, the module tag ignores the "charset" attribute as the same to the worker's importScript. But WebKit supports the "charset" for importScript intentionally. So to be consistent, even for the module tags, we handle the "charset" attribute.
>> Source/WebCore/html/parser/HTMLResourcePreloader.h:39 >> + }; > > I think it would be nicer to say ScriptType: Module/Classic.
Changed.
Yusuke Suzuki
Comment 136
2016-11-12 00:21:18 PST
Comment on
attachment 294488
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294488&action=review
>> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:91 >> + RefPtr<ScriptModuleGraph> protectedThis(this); > > nit: protector as the variable name.
Oh, but according to the webkit-check-style script, in the above case, we should name it as `protectedThis`.
>>> Source/WebCore/bindings/js/ScriptModuleGraph.cpp:104 >>> + Ref<ScriptModuleGraph> protectedThis(*this); >> >> Ditto about calling this protector. > > Fixed.
But according to the webkit-check-style script, in the above case, we should name it as `protectedThis`.
Yusuke Suzuki
Comment 137
2016-11-12 00:38:07 PST
Created
attachment 294609
[details]
Patch
Yusuke Suzuki
Comment 138
2016-11-12 01:09:03 PST
Comment on
attachment 294488
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294488&action=review
>>> Source/WebCore/bindings/js/ScriptController.cpp:373 >>> + RefPtr<ScriptModuleGraph> protector(&moduleGraph); >> >> Why don't we call this moduleGraph and the argument moduleGraphRef. >> Alternatively, you can just modify the argument to be Ref<ScriptModuleGraph>. >> Regardless, we should be using Ref here, not RefPtr. > > It's because 2 functions reference this protector: fulfillHandler and rejectHandler. > But I think we can alleviate this situation by using C++14 generalized capture. > I'll change the argument to Ref<CachedModuleScript>, and use generalized capture like `[moduleScript = protector.copyRef()]`.
Hm, the above one does not work. It causes compile error. It seems there are no good way to share Ref<> in 2 lambdas. Ref<> is not copyable. Even if you write like, [moduleScript = protector.copyRef()]` it causes compile error since it causes copy. And I also ensured that we cannot compile like `[moduleScript = WTFMove(protector.copyRef())]`. Reverted it to RefPtr<>.
Yusuke Suzuki
Comment 139
2016-11-12 01:12:24 PST
Created
attachment 294610
[details]
Patch
Yusuke Suzuki
Comment 140
2016-11-12 01:38:20 PST
Created
attachment 294611
[details]
Patch
Yusuke Suzuki
Comment 141
2016-11-12 01:39:06 PST
OK, the review comments are addressed. Ready for second review.
Ryosuke Niwa
Comment 142
2016-11-12 16:20:19 PST
Comment on
attachment 294488
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294488&action=review
> Source/WebCore/dom/CurrentScriptIncrementer.h:44 > m_document.pushCurrentScript(&downcast<HTMLScriptElement>(element));
Actually, on my second thought, what we should do is to update the condition the line above here which already checks whether element in a shadow tree or not to check if it's classic script not. There's already a bug here that we should be setting currentScript to nullptr when the element in a shadow tree so let me fix that one first.
Ryosuke Niwa
Comment 143
2016-11-12 16:58:27 PST
(In reply to
comment #142
)
> Comment on
attachment 294488
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=294488&action=review
> > > Source/WebCore/dom/CurrentScriptIncrementer.h:44 > > m_document.pushCurrentScript(&downcast<HTMLScriptElement>(element)); > > Actually, on my second thought, what we should do is to update the condition > the line above here > which already checks whether element in a shadow tree or not to check if > it's classic script not. > There's already a bug here that we should be setting currentScript to nullptr > when the element in a shadow tree so let me fix that one first.
Uploaded a patch to fix this on
https://bugs.webkit.org/show_bug.cgi?id=164693
.
Ryosuke Niwa
Comment 144
2016-11-13 01:03:04 PST
It looks like this patch failed on all EWSes?
Yusuke Suzuki
Comment 145
2016-11-13 01:04:57 PST
(In reply to
comment #144
)
> It looks like this patch failed on all EWSes?
Oops, it's related to super simple compile error. Soon, (maybe, in 10mins), I'll upload the patch with your current script change.
Yusuke Suzuki
Comment 146
2016-11-13 01:17:47 PST
Created
attachment 294662
[details]
Patch
WebKit Commit Bot
Comment 147
2016-11-13 01:21:20 PST
Attachment 294662
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:376: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 159 files If any of these errors are false positives, please file a bug against check-webkit-style.
Darin Adler
Comment 148
2016-11-14 09:57:49 PST
Comment on
attachment 294662
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294662&action=review
Started reviewing, but only got half way through the patch before I had to leave.
> Source/WebCore/bindings/js/CachedModuleScript.cpp:56 > + Ref<Document> documentProtector(initiator.document());
I think protectedDocument would be a slightly better name. I am a bit confused about why protecting the document if valuable, though. The only thing we do with the document is call Frame on it. Why protection here? Should this protection be done at a different level?
> Source/WebCore/bindings/js/CachedModuleScript.cpp:58 > + if (Frame* frame = documentProtector->frame()) > + frame->script().loadModuleScript(*this, rootURL.string(), initiator);
Is silently doing nothing the right thing to do in a document without a frame?
> Source/WebCore/bindings/js/CachedModuleScript.cpp:65 > + Ref<Document> documentProtector(initiator.document()); > + if (Frame* frame = documentProtector->frame()) > + frame->script().loadModuleScript(*this, sourceCode, initiator);
Ditto.
> Source/WebCore/bindings/js/CachedModuleScript.cpp:77 > + if (!m_error) > + m_error = WTFMove(error);
When can we get notified about multiple errors?
> Source/WebCore/bindings/js/CachedModuleScript.cpp:91 > + RefPtr<CachedModuleScript> protectedThis(this);
Should be Ref, not RefPtr. What is the rationale for protection here?
> Source/WebCore/bindings/js/CachedModuleScript.cpp:101 > + m_clients.add(&client);
Assert m_clients does not contain client?
> Source/WebCore/bindings/js/CachedModuleScript.cpp:105 > + Ref<CachedModuleScript> protectedThis(*this); > + client.notifyFinished(*this);
What is the rationale for protection here?
> Source/WebCore/bindings/js/CachedModuleScript.cpp:110 > + m_clients.remove(&client);
Assert m_clients contains client?
> Source/WebCore/bindings/js/CachedModuleScript.h:31 > +#include <wtf/Noncopyable.h>
No need for this include?
> Source/WebCore/bindings/js/CachedModuleScript.h:32 > +#include <wtf/WeakPtr.h>
No need for this include?
> Source/WebCore/bindings/js/CachedModuleScript.h:38 > +class Element; > +class ScriptSourceCode; > +class CachedModuleScriptClient;
Please sort in alphabetical order.
> Source/WebCore/bindings/js/CachedModuleScript.h:46 > + void notifyLoaded(UniquedStringImpl* moduleKey);
Can this be null? If not, take a reference?
> Source/WebCore/bindings/js/CachedModuleScript.h:47 > + void notifyErrored(LoadableScript::Error&&);
I have never been a big fan of the "notifyXXX" naming scheme, but this one in particular is not grammatical. Maybe notifyErrorOccured or notifyLoadFailed. If we are going to stick with the notify prefix, then I suggest: notifyLoadCompleted, notifyLoadFailed, notifyLoadWasCanceled.
> Source/WebCore/bindings/js/CachedModuleScript.h:50 > + Optional<LoadableScript::Error> error() const { return m_error; }
const Optional& return type?
> Source/WebCore/bindings/js/CachedModuleScript.h:76 > + bool m_canceled { false }; > + bool m_loaded { false };
m_wasCanceled? m_isLoaded?
> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:67 > + // If the content is already cached, this immeidately calls notifyFinished.
Typo: "immediately" is spelled wrong.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:30 > +#include "JSDOMPromise.h"
I don’t think this include is needed. Forward declaration of DeferredPromise should suffice.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:31 > +#include "ScriptElement.h"
I don’t think this include is needed. There is a forward declaration below.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:32 > +#include "URL.h"
This include is not needed; forward declaration of URL should suffice.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:33 > +#include <runtime/JSInternalPromiseDeferred.h>
I don’t think this include is needed. Forward declaration of DeferredPromise should suffice.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:34 > +#include <wtf/Noncopyable.h>
This include is not needed.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:39 > +class Document;
Not used.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:40 > +class JSDOMGlobalObject;
Not used.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:41 > +class ScriptElement;
Only needed if we don’t remove ScriptElement.h above.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:42 > +class CachedModuleScriptLoaderClient;
Please sort alphabetically.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:48 > + ~CachedModuleScriptLoader();
In our coding style we include virtual here.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:67 > + CachedResourceHandle<CachedScript> m_cachedScript { };
Is the { } needed? I don’t think that does anything different from the default, but I may be mistaken.
> Source/WebCore/bindings/js/JSDOMBinding.cpp:159 > +String retrieveErrorMessage(ExecState* exec, VM& vm, JSValue exceptionValue, CatchScope& catchScope)
Please use ExecState& state in new functions, unless there is a good reason not to.
> Source/WebCore/bindings/js/JSDOMBinding.cpp:162 > + if (ExceptionBase* exceptionBase = toExceptionBase(exceptionValue))
auto?
> Source/WebCore/bindings/js/JSDOMBinding.cpp:163 > + errorMessage = exceptionBase->toString();
I suggest a return here, and use of early return instead of if/else with a local variable.
> Source/WebCore/bindings/js/JSDOMBinding.cpp:167 > + if (ErrorInstance* error = jsDynamicDowncast<ErrorInstance*>(exceptionValue))
auto?
> Source/WebCore/bindings/js/JSDOMBinding.cpp:170 > + errorMessage = exceptionValue.toString(exec)->value(exec);
toWTFString?
> Source/WebCore/bindings/js/JSDOMBinding.h:185 > +String retrieveErrorMessage(JSC::ExecState*, JSC::VM&, JSC::JSValue exceptionValue, JSC::CatchScope&);
Not sure we need the word "value" in "exceptionValue".
> Source/WebCore/bindings/js/ScriptController.cpp:94 > + , m_moduleLoaderAlreadyReportedErrorSymbol() > + , m_moduleLoaderFetchingIsCanceledSymbol()
Why is this needed?
> Source/WebCore/bindings/js/ScriptController.cpp:193 > + JSDOMWindowShell* shell = windowShell(world);
Please use a reference in new code unless there is a reason not to. auto& shell = *windowShell(world);
> Source/WebCore/bindings/js/ScriptController.cpp:194 > + ExecState* exec = shell->window()->globalExec();
Please use ExecState& state in new code unless there is a reason not to.
> Source/WebCore/bindings/js/ScriptController.cpp:208 > + JSDOMWindowShell* shell = windowShell(world);
Please use a reference in new code unless there is a reason not to.
> Source/WebCore/bindings/js/ScriptController.cpp:209 > + ExecState* exec = shell->window()->globalExec();
Please use ExecState& state in new code unless there is a reason not to.
> Source/WebCore/bindings/js/ScriptController.cpp:224 > + JSDOMWindowShell* shell = windowShell(world); > + ExecState* exec = shell->window()->globalExec();
Ditto.
> Source/WebCore/bindings/js/ScriptController.cpp:226 > + Ref<Frame> protector(m_frame);
Unclear why a protector is helpful here. I am really concerned about adding protectors when it’s not clear exactly what they are needed for.
> Source/WebCore/bindings/js/ScriptController.cpp:231 > + // FIXME: Give a chance to dump the stack trace if the "corssorigin" attribute allows.
Typo: "corssorigin".
> Source/WebCore/bindings/js/ScriptController.cpp:247 > + const SourceCode& jsSourceCode = moduleRecord->sourceCode();
auto&
> Source/WebCore/bindings/js/ScriptController.cpp:250 > + JSDOMWindowShell* shell = windowShell(world); > + ExecState* exec = shell->window()->globalExec();
auto&, references, state instead of exec
> Source/WebCore/bindings/js/ScriptController.cpp:251 > + const String* savedSourceURL = m_sourceURL;
auto*; also, save/restore is not great, but I suppose we don’t have a good alternative
> Source/WebCore/bindings/js/ScriptController.cpp:254 > + Ref<Frame> protector(m_frame);
rationale for protector
> Source/WebCore/bindings/js/ScriptController.cpp:256 > + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, jsSourceCode.firstLine());
auto
> Source/WebCore/bindings/js/ScriptController.cpp:258 > + JSValue returnValue = moduleRecord->evaluate(exec);
auto
> Source/WebCore/bindings/js/ScriptController.cpp:350 > +static Identifier jsValueToModuleKey(ExecState* exec, JSValue value)
ExecState& state please
> Source/WebCore/bindings/js/ScriptController.cpp:364 > +void ScriptController::setupModuleScriptHandlers(CachedModuleScript& moduleScriptRef, JSInternalPromise* promise, DOMWrapperWorld& world)
Can the promise argument be a reference?
> Source/WebCore/bindings/js/ScriptController.cpp:367 > + JSDOMWindowShell* shell = windowShell(world); > + ExecState* exec = shell->window()->globalExec();
auto, state
> Source/WebCore/bindings/js/ScriptController.cpp:374 > + PrivateName moduleLoaderAlreadyReportedErrorSymbol = m_moduleLoaderAlreadyReportedErrorSymbol; > + PrivateName moduleLoaderFetchingIsCanceledSymbol = m_moduleLoaderFetchingIsCanceledSymbol;
auto?
> Source/WebCore/bindings/js/ScriptController.cpp:378 > + JSFunction* fulfillHandler = JSNativeStdFunction::create(exec->vm(), shell->window(), 1, String(), [moduleScript](ExecState* exec) {
auto
> Source/WebCore/bindings/js/ScriptController.cpp:384 > + JSFunction* rejectHandler = JSNativeStdFunction::create(exec->vm(), shell->window(), 1, String(), [moduleScript, moduleLoaderAlreadyReportedErrorSymbol, moduleLoaderFetchingIsCanceledSymbol](ExecState* exec) {
auto
> Source/WebCore/bindings/js/ScriptController.cpp:386 > + if (Symbol* symbol = jsDynamicCast<Symbol*>(error)) {
auto
> Source/WebCore/bindings/js/ScriptController.cpp:679 > + Ref<Frame> protector(m_frame); // Script execution can destroy the frame, and thus the ScriptController.
Even this comment does not make it clear why the protector is a good idea. What‘s the harm in the ScriptController being destroyed? The harm comes in if code uses the script controller after destroyed, and the code below does not do that. So the protector belongs somewhere else I think. This is a real concern long term about our code structure.
> Source/WebCore/bindings/js/ScriptController.h:48 > class JSGlobalObject; > +class JSModuleRecord; > +class JSInternalPromise; > class ExecState;
Alphabetical order please.
> Source/WebCore/bindings/js/ScriptController.h:64 > class Frame; > class HTMLDocument; > class HTMLPlugInElement; > +class CachedModuleScript; > class ScriptSourceCode; > class SecurityOrigin; > class Widget;
Alphabetical order please.
> Source/WebCore/bindings/js/ScriptController.h:129 > + JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord*, DOMWrapperWorld&); > + JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord*);
References for JSModuleRecord&?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:61 > + JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
auto&
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:63 > + Ref<DeferredPromise> promise = DeferredPromise::create(globalObject, jsPromise);
auto
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:133 > + JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
auto&
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:135 > + Ref<DeferredPromise> deferred = DeferredPromise::create(globalObject, jsPromise);
auto
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:159 > + RefPtr<CachedModuleScriptLoader> loader = CachedModuleScriptLoader::create(*this, deferred.get());
auto
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:209 > + CachedScript* cachedScript = loader.cachedScript();
auto*
> Source/WebCore/bindings/js/ScriptModuleLoader.h:66 > + HashSet<RefPtr<CachedModuleScriptLoader>> m_loaders;
Ref instead of RefPtr?
> Source/WebCore/dom/LoadableModuleScript.h:37 > + ~LoadableModuleScript();
WebKit coding style says virtual here
> Source/WebCore/dom/LoadableModuleScript.h:43 > + bool isLoaded() const override; > + Optional<Error> error() const override; > + bool wasCanceled() const override;
final instead of override; can some of these be private too, if they are not called non-polymorphically?
> Source/WebCore/dom/LoadableModuleScript.h:48 > + void execute(ScriptElement&) override;
Ditto.
> Source/WebCore/dom/ScriptElement.cpp:165 > -#if ENABLE(ES6_MODULES) > +// #if ENABLE(ES6_MODULES)
???
> Source/WebCore/dom/ScriptElement.cpp:170 > -#endif > +// #endif
???
Yusuke Suzuki
Comment 149
2016-11-14 13:27:50 PST
Comment on
attachment 294662
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294662&action=review
Quick reply. Still WIP. Soon, I'll reply to the all review comments. And update the patch.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:56 >> + Ref<Document> documentProtector(initiator.document()); > > I think protectedDocument would be a slightly better name. I am a bit confused about why protecting the document if valuable, though. The only thing we do with the document is call Frame on it. Why protection here? Should this protection be done at a different level?
This behavior is aligned to the ScriptElement's executeScript function. But this function is not changed from 2011. From this time, so much code is changed. And now, document() always returns Document&. So I think this becomes meaningless. We can just use `initiator.document().frame()`. Changed this code. And ScriptElement::executeScript is also changed.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:58 >> + frame->script().loadModuleScript(*this, rootURL.string(), initiator); > > Is silently doing nothing the right thing to do in a document without a frame?
This behavior is aligned to ScriptElement. ScriptElement gives up loading / executing when a document does not have a frame.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:65 >> + frame->script().loadModuleScript(*this, sourceCode, initiator); > > Ditto.
Ditto.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:77 >> + m_error = WTFMove(error); > > When can we get notified about multiple errors?
No. We just use `m_error = WTFMove(error)`.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:91 >> + RefPtr<CachedModuleScript> protectedThis(this); > > Should be Ref, not RefPtr. What is the rationale for protection here?
During `client->notifyFinished()`, CachedModuleScript's owner can drop this. So this is necessary.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:101 >> + m_clients.add(&client); > > Assert m_clients does not contain client?
We use HashCountedSet to allow clients to register themselves multiple times.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:105 >> + client.notifyFinished(*this); > > What is the rationale for protection here?
During `client.notifyFinished(*this)`, the owner can drop the ref to this `CachedModuleScript`. Until `client.notifyFinished(*this)` is done, this protectedThis ensures that the given argument `CachedModuleScript&` is live.
>> Source/WebCore/bindings/js/CachedModuleScript.cpp:110 >> + m_clients.remove(&client); > > Assert m_clients contains client?
We use HashCountedSet to allow clients to register themselves multiple times.
>> Source/WebCore/bindings/js/CachedModuleScript.h:31 >> +#include <wtf/Noncopyable.h> > > No need for this include?
Dropped.
>> Source/WebCore/bindings/js/CachedModuleScript.h:32 >> +#include <wtf/WeakPtr.h> > > No need for this include?
Dropped.
>> Source/WebCore/bindings/js/CachedModuleScript.h:38 >> +class CachedModuleScriptClient; > > Please sort in alphabetical order.
Done.
>> Source/WebCore/bindings/js/CachedModuleScript.h:46 >> + void notifyLoaded(UniquedStringImpl* moduleKey); > > Can this be null? If not, take a reference?
Fixed.
>> Source/WebCore/bindings/js/CachedModuleScript.h:47 >> + void notifyErrored(LoadableScript::Error&&); > > I have never been a big fan of the "notifyXXX" naming scheme, but this one in particular is not grammatical. Maybe notifyErrorOccured or notifyLoadFailed. > > If we are going to stick with the notify prefix, then I suggest: notifyLoadCompleted, notifyLoadFailed, notifyLoadWasCanceled.
Your suggestion sounds super nice to me. Fixed.
>> Source/WebCore/bindings/js/CachedModuleScript.h:50 >> + Optional<LoadableScript::Error> error() const { return m_error; } > > const Optional& return type?
Yeah, done.
>> Source/WebCore/bindings/js/CachedModuleScript.h:76 >> + bool m_loaded { false }; > > m_wasCanceled? > m_isLoaded?
It sounds nice. Fixed.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:67 >> + // If the content is already cached, this immeidately calls notifyFinished. > > Typo: "immediately" is spelled wrong.
Oops, fixed.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:30 >> +#include "JSDOMPromise.h" > > I don’t think this include is needed. Forward declaration of DeferredPromise should suffice.
Right. Dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:31 >> +#include "ScriptElement.h" > > I don’t think this include is needed. There is a forward declaration below.
Right. Fixed.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:32 >> +#include "URL.h" > > This include is not needed; forward declaration of URL should suffice.
Right.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:33 >> +#include <runtime/JSInternalPromiseDeferred.h> > > I don’t think this include is needed. Forward declaration of DeferredPromise should suffice.
Dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:34 >> +#include <wtf/Noncopyable.h> > > This include is not needed.
Yeah, dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:39 >> +class Document; > > Not used.
Dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:40 >> +class JSDOMGlobalObject; > > Not used.
Dropped.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:41 >> +class ScriptElement; > > Only needed if we don’t remove ScriptElement.h above.
Yeah, leave this. And remove ScriptElement.h include.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:42 >> +class CachedModuleScriptLoaderClient; > > Please sort alphabetically.
Done.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:48 >> + ~CachedModuleScriptLoader(); > > In our coding style we include virtual here.
Oops, fixed.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:67 >> + CachedResourceHandle<CachedScript> m_cachedScript { }; > > Is the { } needed? I don’t think that does anything different from the default, but I may be mistaken.
Not necessary. Thanks, dropped.
>> Source/WebCore/bindings/js/JSDOMBinding.cpp:159 >> +String retrieveErrorMessage(ExecState* exec, VM& vm, JSValue exceptionValue, CatchScope& catchScope) > > Please use ExecState& state in new functions, unless there is a good reason not to.
Yeah, done.
>> Source/WebCore/bindings/js/JSDOMBinding.cpp:162 >> + if (ExceptionBase* exceptionBase = toExceptionBase(exceptionValue)) > > auto?
Should be. Changed.
>> Source/WebCore/bindings/js/JSDOMBinding.cpp:163 >> + errorMessage = exceptionBase->toString(); > > I suggest a return here, and use of early return instead of if/else with a local variable.
Nice! Yeah, we should do that. Fixed.
>> Source/WebCore/bindings/js/JSDOMBinding.cpp:167 >> + if (ErrorInstance* error = jsDynamicDowncast<ErrorInstance*>(exceptionValue)) > > auto?
Fixed.
>> Source/WebCore/bindings/js/JSDOMBinding.cpp:170 >> + errorMessage = exceptionValue.toString(exec)->value(exec); > > toWTFString?
Yeah, it should be nice. Fixed.
>> Source/WebCore/bindings/js/JSDOMBinding.h:185 >> +String retrieveErrorMessage(JSC::ExecState*, JSC::VM&, JSC::JSValue exceptionValue, JSC::CatchScope&); > > Not sure we need the word "value" in "exceptionValue".
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:94 >> + , m_moduleLoaderFetchingIsCanceledSymbol() > > Why is this needed?
This is noted in ChangeLog. Pasting. 147 The module loader pipeline is constructed as a chain of promises. 148 Rejecting a promise when some error occurs is important because the execution flow of 149 the promise chain is driven by "rejected" or "fulfilled" events. 150 If the promise is not rejected while error occurs, reject handler won't be executed 151 and all the subsequent promise chain will wait the result forever. 152 As a result, even if the error is already reported to the inspector elsewhere, 153 it should be propagated in the pipeline. For example, the error of loading 154 CachedResource is already reported to the inspector by the loader. But we still need 155 to reject the promise to propagate this error to the script element. 156 At that time, we don't want to report the same error twice. When we propagate the error 157 that is already reported to the inspector, we throw moduleLoaderAlreadyReportedErrorSymbol 158 symbol instead. By comparing the thrown error with this symbol, we can distinguish errors raised 159 when checking syntax of a module script from errors reported already. 160 In the reject handler of the promise, we only report a error that is not this symbol.
>> Source/WebCore/dom/ScriptElement.cpp:165 >> +// #if ENABLE(ES6_MODULES) > > ???
To make EWS work, this patch temporary comments out this ifdef. When landing this patch, this comment out should be reverted. And TestExpectations' [ Skip ] should be reverted too.
>> Source/WebCore/dom/ScriptElement.cpp:170 >> +// #endif > > ???
Ditto.
Yusuke Suzuki
Comment 150
2016-11-14 15:46:57 PST
Comment on
attachment 294662
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294662&action=review
Thanks. OK. I've replied all the review comments. I'll upload the updated patch once I ensured that can be built.
>> Source/WebCore/bindings/js/ScriptController.cpp:193 >> + JSDOMWindowShell* shell = windowShell(world); > > Please use a reference in new code unless there is a reason not to. > > auto& shell = *windowShell(world);
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:194 >> + ExecState* exec = shell->window()->globalExec(); > > Please use ExecState& state in new code unless there is a reason not to.
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:208 >> + JSDOMWindowShell* shell = windowShell(world); > > Please use a reference in new code unless there is a reason not to.
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:209 >> + ExecState* exec = shell->window()->globalExec(); > > Please use ExecState& state in new code unless there is a reason not to.
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:224 >> + ExecState* exec = shell->window()->globalExec(); > > Ditto.
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:226 >> + Ref<Frame> protector(m_frame); > > Unclear why a protector is helpful here. I am really concerned about adding protectors when it’s not clear exactly what they are needed for.
This is the same to ScriptController::executeScript. Script execution can destroy the frame.
>> Source/WebCore/bindings/js/ScriptController.cpp:231 >> + // FIXME: Give a chance to dump the stack trace if the "corssorigin" attribute allows. > > Typo: "corssorigin".
Oops, fixed. And add bugzilla URL here.
>> Source/WebCore/bindings/js/ScriptController.cpp:247 >> + const SourceCode& jsSourceCode = moduleRecord->sourceCode(); > > auto&
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:250 >> + ExecState* exec = shell->window()->globalExec(); > > auto&, references, state instead of exec
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:251 >> + const String* savedSourceURL = m_sourceURL; > > auto*; also, save/restore is not great, but I suppose we don’t have a good alternative
Currently, we change it `const auto* String` thing, and leave save / restore. In JSC, we have some helper like SetForScope<>. I'll move this to WTF in the subsequent patch.
>> Source/WebCore/bindings/js/ScriptController.cpp:254 >> + Ref<Frame> protector(m_frame); > > rationale for protector
According to the ScriptController::executeScript, script evaluation can destroy the frame. We would like to keep it until calling InspectorInstrumentation::didEvaluateScript.
>> Source/WebCore/bindings/js/ScriptController.cpp:256 >> + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, jsSourceCode.firstLine()); > > auto
Fixed. BTW, these things are the same in non module evaluation code. I'll upload the subsequent patch that will change like this after this patch.
>> Source/WebCore/bindings/js/ScriptController.cpp:258 >> + JSValue returnValue = moduleRecord->evaluate(exec); > > auto
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:364 >> +void ScriptController::setupModuleScriptHandlers(CachedModuleScript& moduleScriptRef, JSInternalPromise* promise, DOMWrapperWorld& world) > > Can the promise argument be a reference?
Yes. This dereference should be done at JSC <-> WebCore border. So dereferencing this in JSMainThreadExecState.h. And passing the reference.
>> Source/WebCore/bindings/js/ScriptController.cpp:367 >> + ExecState* exec = shell->window()->globalExec(); > > auto, state
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:374 >> + PrivateName moduleLoaderFetchingIsCanceledSymbol = m_moduleLoaderFetchingIsCanceledSymbol; > > auto?
No, we would like to copy this PrivateName into the lambda.
>> Source/WebCore/bindings/js/ScriptController.cpp:378 >> + JSFunction* fulfillHandler = JSNativeStdFunction::create(exec->vm(), shell->window(), 1, String(), [moduleScript](ExecState* exec) { > > auto
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:384 >> + JSFunction* rejectHandler = JSNativeStdFunction::create(exec->vm(), shell->window(), 1, String(), [moduleScript, moduleLoaderAlreadyReportedErrorSymbol, moduleLoaderFetchingIsCanceledSymbol](ExecState* exec) { > > auto
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:386 >> + if (Symbol* symbol = jsDynamicCast<Symbol*>(error)) { > > auto
Fixed.
>> Source/WebCore/bindings/js/ScriptController.cpp:679 >> + Ref<Frame> protector(m_frame); // Script execution can destroy the frame, and thus the ScriptController. > > Even this comment does not make it clear why the protector is a good idea. What‘s the harm in the ScriptController being destroyed? The harm comes in if code uses the script controller after destroyed, and the code below does not do that. So the protector belongs somewhere else I think. This is a real concern long term about our code structure.
Hm, right. So I think keeping protector for module script evaluation is fine in the meantime. And in the other patch, we should drop these protectors and place appropriate protectors instead.
>> Source/WebCore/bindings/js/ScriptController.h:48 >> class ExecState; > > Alphabetical order please.
Fixed.
>> Source/WebCore/bindings/js/ScriptController.h:64 >> class Widget; > > Alphabetical order please.
Fixed.
>> Source/WebCore/bindings/js/ScriptController.h:129 >> + JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord*); > > References for JSModuleRecord&?
We can do that thing by dereferencing it in WebCore ScriptModuleLoader.cpp. Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:61 >> + JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject); > > auto&
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:63 >> + Ref<DeferredPromise> promise = DeferredPromise::create(globalObject, jsPromise); > > auto
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:133 >> + JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject); > > auto&
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:135 >> + Ref<DeferredPromise> deferred = DeferredPromise::create(globalObject, jsPromise); > > auto
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:159 >> + RefPtr<CachedModuleScriptLoader> loader = CachedModuleScriptLoader::create(*this, deferred.get()); > > auto
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:209 >> + CachedScript* cachedScript = loader.cachedScript(); > > auto*
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.h:66 >> + HashSet<RefPtr<CachedModuleScriptLoader>> m_loaders; > > Ref instead of RefPtr?
Code becomes a bit weird (Ref<> cannot be copied, so in some place, we will use `copyRef` if we would like to continue using the original Ref<>). But we can. Ref<> loader = ...; m_loaders.add(loader.copyRef()); loader->... Changed.
>> Source/WebCore/dom/LoadableModuleScript.h:37 >> + ~LoadableModuleScript(); > > WebKit coding style says virtual here
Fixed.
>> Source/WebCore/dom/LoadableModuleScript.h:43 >> + bool wasCanceled() const override; > > final instead of override; can some of these be private too, if they are not called non-polymorphically?
Fixed. Currently they are polymorphically called in ScriptElement.cpp.
>> Source/WebCore/dom/LoadableModuleScript.h:48 >> + void execute(ScriptElement&) override; > > Ditto.
Fixed.
Yusuke Suzuki
Comment 151
2016-11-14 16:05:33 PST
Comment on
attachment 294662
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294662&action=review
>>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:30 >>> +#include "JSDOMPromise.h" >> >> I don’t think this include is needed. Forward declaration of DeferredPromise should suffice. > > Right. Dropped.
Ah, no. Unfortunately, RefPtr<DeferredPromise> requires complete class declaration since it will instantiate `->ref()` and `->deref()` calls.
Yusuke Suzuki
Comment 152
2016-11-14 17:34:23 PST
Created
attachment 294786
[details]
Patch
WebKit Commit Bot
Comment 153
2016-11-14 17:39:12 PST
Attachment 294786
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:377: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 160 files If any of these errors are false positives, please file a bug against check-webkit-style.
Darin Adler
Comment 154
2016-11-14 17:59:48 PST
Comment on
attachment 294662
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294662&action=review
Thanks for considering all my comments! I have a few follow-up thoughts.
>>> Source/WebCore/bindings/js/CachedModuleScript.cpp:91 >>> + RefPtr<CachedModuleScript> protectedThis(this); >> >> Should be Ref, not RefPtr. What is the rationale for protection here? > > During `client->notifyFinished()`, CachedModuleScript's owner can drop this. So this is necessary.
Oh, I see, it’s needed because we pass *this to the other notifyFinished functions.
>>> Source/WebCore/bindings/js/CachedModuleScript.cpp:105 >>> + client.notifyFinished(*this); >> >> What is the rationale for protection here? > > During `client.notifyFinished(*this)`, the owner can drop the ref to this `CachedModuleScript`. > Until `client.notifyFinished(*this)` is done, this protectedThis ensures that the given argument `CachedModuleScript&` is live.
I guess you are saying we want to protect "this" because we passed it in.
>>>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:30 >>>> +#include "JSDOMPromise.h" >>> >>> I don’t think this include is needed. Forward declaration of DeferredPromise should suffice. >> >> Right. Dropped. > > Ah, no. Unfortunately, RefPtr<DeferredPromise> requires complete class declaration since it will instantiate `->ref()` and `->deref()` calls.
Not super important but: That would only be when compiling constructors, destructors, and other code that makes use of the data member. I would expect that we could include JSPromise.h in .cpp files and not in this header. I wonder what specific case drives the need for this?
>>> Source/WebCore/bindings/js/ScriptController.cpp:94 >>> + , m_moduleLoaderFetchingIsCanceledSymbol() >> >> Why is this needed? > > This is noted in ChangeLog. Pasting. > > 147 The module loader pipeline is constructed as a chain of promises. > 148 Rejecting a promise when some error occurs is important because the execution flow of > 149 the promise chain is driven by "rejected" or "fulfilled" events. > 150 If the promise is not rejected while error occurs, reject handler won't be executed > 151 and all the subsequent promise chain will wait the result forever. > 152 As a result, even if the error is already reported to the inspector elsewhere, > 153 it should be propagated in the pipeline. For example, the error of loading > 154 CachedResource is already reported to the inspector by the loader. But we still need > 155 to reject the promise to propagate this error to the script element. > 156 At that time, we don't want to report the same error twice. When we propagate the error > 157 that is already reported to the inspector, we throw moduleLoaderAlreadyReportedErrorSymbol > 158 symbol instead. By comparing the thrown error with this symbol, we can distinguish errors raised > 159 when checking syntax of a module script from errors reported already. > 160 In the reject handler of the promise, we only report a error that is not this symbol.
I was asking a much more narrow question. Why do we need to explicitly specify the initialization of these data members in the constructor. Wouldn’t the same thing happen if we didn’t write those two lines of code?
>>> Source/WebCore/bindings/js/ScriptController.cpp:226 >>> + Ref<Frame> protector(m_frame); >> >> Unclear why a protector is helpful here. I am really concerned about adding protectors when it’s not clear exactly what they are needed for. > > This is the same to ScriptController::executeScript. Script execution can destroy the frame.
OK, but why is it a problem that the frame was destroyed at that point? Presumably once the script is executed we don’t use the ScriptController or the Frame before returning from the function. It must be some code after the script is executed but before this function returns. I don’t see what code that is, which benefits from the protection.
>>> Source/WebCore/bindings/js/ScriptController.cpp:251 >>> + const String* savedSourceURL = m_sourceURL; >> >> auto*; also, save/restore is not great, but I suppose we don’t have a good alternative > > Currently, we change it `const auto* String` thing, and leave save / restore. > In JSC, we have some helper like SetForScope<>. I'll move this to WTF in the subsequent patch.
I think we have multiple helpers like that; another one is called TemporaryChange, I think.
>>> Source/WebCore/bindings/js/ScriptController.cpp:254 >>> + Ref<Frame> protector(m_frame); >> >> rationale for protector > > According to the ScriptController::executeScript, script evaluation can destroy the frame. > We would like to keep it until calling InspectorInstrumentation::didEvaluateScript.
OK, makes sense.
Yusuke Suzuki
Comment 155
2016-11-14 20:33:08 PST
Comment on
attachment 294662
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294662&action=review
>>>> Source/WebCore/bindings/js/CachedModuleScript.cpp:105 >>>> + client.notifyFinished(*this); >>> >>> What is the rationale for protection here? >> >> During `client.notifyFinished(*this)`, the owner can drop the ref to this `CachedModuleScript`. >> Until `client.notifyFinished(*this)` is done, this protectedThis ensures that the given argument `CachedModuleScript&` is live. > > I guess you are saying we want to protect "this" because we passed it in.
Yup, right.
>>>> Source/WebCore/bindings/js/ScriptController.cpp:94 >>>> + , m_moduleLoaderFetchingIsCanceledSymbol() >>> >>> Why is this needed? >> >> This is noted in ChangeLog. Pasting. >> >> 147 The module loader pipeline is constructed as a chain of promises. >> 148 Rejecting a promise when some error occurs is important because the execution flow of >> 149 the promise chain is driven by "rejected" or "fulfilled" events. >> 150 If the promise is not rejected while error occurs, reject handler won't be executed >> 151 and all the subsequent promise chain will wait the result forever. >> 152 As a result, even if the error is already reported to the inspector elsewhere, >> 153 it should be propagated in the pipeline. For example, the error of loading >> 154 CachedResource is already reported to the inspector by the loader. But we still need >> 155 to reject the promise to propagate this error to the script element. >> 156 At that time, we don't want to report the same error twice. When we propagate the error >> 157 that is already reported to the inspector, we throw moduleLoaderAlreadyReportedErrorSymbol >> 158 symbol instead. By comparing the thrown error with this symbol, we can distinguish errors raised >> 159 when checking syntax of a module script from errors reported already. >> 160 In the reject handler of the promise, we only report a error that is not this symbol. > > I was asking a much more narrow question. Why do we need to explicitly specify the initialization of these data members in the constructor. Wouldn’t the same thing happen if we didn’t write those two lines of code?
Aha! I see. Yeah, default constructor is enough. Dropped.
>>>> Source/WebCore/bindings/js/ScriptController.cpp:226 >>>> + Ref<Frame> protector(m_frame); >>> >>> Unclear why a protector is helpful here. I am really concerned about adding protectors when it’s not clear exactly what they are needed for. >> >> This is the same to ScriptController::executeScript. Script execution can destroy the frame. > > OK, but why is it a problem that the frame was destroyed at that point? Presumably once the script is executed we don’t use the ScriptController or the Frame before returning from the function. It must be some code after the script is executed but before this function returns. I don’t see what code that is, which benefits from the protection.
Yeah, right. As you mentioned in ScriptController::executeScript, this Ref<> protection may be used for some weird thing. Like, there are some missing protector, and instead, it guards against the crash. I think keeping protector for module script evaluation is fine in the meantime. This bug should be fixed in the other patch and at that time, both classic scripts and module scripts should be fixed at once. I've filed it.
https://bugs.webkit.org/show_bug.cgi?id=164763
And add FIXME comments.
>>>> Source/WebCore/bindings/js/ScriptController.cpp:251 >>>> + const String* savedSourceURL = m_sourceURL; >>> >>> auto*; also, save/restore is not great, but I suppose we don’t have a good alternative >> >> Currently, we change it `const auto* String` thing, and leave save / restore. >> In JSC, we have some helper like SetForScope<>. I'll move this to WTF in the subsequent patch. > > I think we have multiple helpers like that; another one is called TemporaryChange, I think.
Yeah! That's completely the same. Use TemporaryChange<const String*> here.
>>> Source/WebCore/bindings/js/ScriptController.cpp:374 >>> + PrivateName moduleLoaderFetchingIsCanceledSymbol = m_moduleLoaderFetchingIsCanceledSymbol; >> >> auto? > > No, we would like to copy this PrivateName into the lambda.
Ah, oops. I misread it as `auto&`. Use auto here.
Yusuke Suzuki
Comment 156
2016-11-14 20:37:04 PST
Created
attachment 294802
[details]
Patch
WebKit Commit Bot
Comment 157
2016-11-14 20:42:16 PST
Attachment 294802
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:375: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 160 files If any of these errors are false positives, please file a bug against check-webkit-style.
Yusuke Suzuki
Comment 158
2016-11-14 21:21:08 PST
Created
attachment 294805
[details]
Patch
Yusuke Suzuki
Comment 159
2016-11-14 21:23:02 PST
Comment on
attachment 294805
[details]
Patch Oops, failed.
WebKit Commit Bot
Comment 160
2016-11-14 21:25:18 PST
Attachment 294805
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:376: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 143 files If any of these errors are false positives, please file a bug against check-webkit-style.
Yusuke Suzuki
Comment 161
2016-11-14 21:28:46 PST
Created
attachment 294806
[details]
Patch
WebKit Commit Bot
Comment 162
2016-11-14 21:32:39 PST
Attachment 294806
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:376: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 160 files If any of these errors are false positives, please file a bug against check-webkit-style.
Build Bot
Comment 163
2016-11-14 22:36:04 PST
Comment on
attachment 294806
[details]
Patch
Attachment 294806
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/2518032
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-blocked.html http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html
Build Bot
Comment 164
2016-11-14 22:36:13 PST
Created
attachment 294813
[details]
Archive of layout-test-results from ews101 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews101 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 165
2016-11-14 22:43:33 PST
Comment on
attachment 294806
[details]
Patch
Attachment 294806
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/2518063
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-blocked.html http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html
Build Bot
Comment 166
2016-11-14 22:43:42 PST
Created
attachment 294815
[details]
Archive of layout-test-results from ews105 for mac-yosemite-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews105 Port: mac-yosemite-wk2 Platform: Mac OS X 10.10.5
Build Bot
Comment 167
2016-11-14 22:46:58 PST
Comment on
attachment 294806
[details]
Patch
Attachment 294806
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/2518035
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-blocked.html http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html
Build Bot
Comment 168
2016-11-14 22:47:07 PST
Created
attachment 294817
[details]
Archive of layout-test-results from ews116 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews116 Port: mac-yosemite Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 169
2016-11-14 22:52:36 PST
Created
attachment 294818
[details]
Patch
WebKit Commit Bot
Comment 170
2016-11-14 22:57:13 PST
Attachment 294818
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:376: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 160 files If any of these errors are false positives, please file a bug against check-webkit-style.
Build Bot
Comment 171
2016-11-15 00:08:03 PST
Comment on
attachment 294818
[details]
Patch
Attachment 294818
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.webkit.org/results/2518409
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-blocked.html http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html
Build Bot
Comment 172
2016-11-15 00:08:12 PST
Created
attachment 294823
[details]
Archive of layout-test-results from ews106 for mac-yosemite-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews106 Port: mac-yosemite-wk2 Platform: Mac OS X 10.10.5
Build Bot
Comment 173
2016-11-15 00:17:11 PST
Comment on
attachment 294818
[details]
Patch
Attachment 294818
[details]
did not pass ios-sim-ews (ios-simulator-wk2): Output:
http://webkit-queues.webkit.org/results/2518411
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-blocked.html http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html
Build Bot
Comment 174
2016-11-15 00:17:20 PST
Created
attachment 294824
[details]
Archive of layout-test-results from ews121 for ios-simulator-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews121 Port: ios-simulator-wk2 Platform: Mac OS X 10.11.6
Build Bot
Comment 175
2016-11-15 00:36:17 PST
Comment on
attachment 294818
[details]
Patch
Attachment 294818
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/2518517
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-blocked.html http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html
Build Bot
Comment 176
2016-11-15 00:36:26 PST
Created
attachment 294826
[details]
Archive of layout-test-results from ews101 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews101 Port: mac-yosemite Platform: Mac OS X 10.10.5
Build Bot
Comment 177
2016-11-15 00:41:36 PST
Comment on
attachment 294818
[details]
Patch
Attachment 294818
[details]
did not pass mac-debug-ews (mac): Output:
http://webkit-queues.webkit.org/results/2518503
New failing tests: http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-blocked.html http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html
Build Bot
Comment 178
2016-11-15 00:41:44 PST
Created
attachment 294827
[details]
Archive of layout-test-results from ews112 for mac-yosemite The attached test failures were seen while running run-webkit-tests on the mac-debug-ews. Bot: ews112 Port: mac-yosemite Platform: Mac OS X 10.10.5
Yusuke Suzuki
Comment 179
2016-11-15 01:13:48 PST
Created
attachment 294829
[details]
Patch
WebKit Commit Bot
Comment 180
2016-11-15 01:17:19 PST
Attachment 294829
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:376: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 160 files If any of these errors are false positives, please file a bug against check-webkit-style.
Yusuke Suzuki
Comment 181
2016-11-15 01:48:10 PST
Comment on
attachment 294662
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294662&action=review
>>>>> Source/WebCore/bindings/js/CachedModuleScriptLoader.h:30 >>>>> +#include "JSDOMPromise.h" >>>> >>>> I don’t think this include is needed. Forward declaration of DeferredPromise should suffice. >>> >>> Right. Dropped. >> >> Ah, no. Unfortunately, RefPtr<DeferredPromise> requires complete class declaration since it will instantiate `->ref()` and `->deref()` calls. > > Not super important but: That would only be when compiling constructors, destructors, and other code that makes use of the data member. I would expect that we could include JSPromise.h in .cpp files and not in this header. I wonder what specific case drives the need for this?
Oops, it was wrong. I need to include `<wtf/RefPtr.h>`. Fixed.
Yusuke Suzuki
Comment 182
2016-11-15 01:50:13 PST
Created
attachment 294830
[details]
Patch
WebKit Commit Bot
Comment 183
2016-11-15 01:55:11 PST
Attachment 294830
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:376: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 160 files If any of these errors are false positives, please file a bug against check-webkit-style.
Yusuke Suzuki
Comment 184
2016-11-15 02:04:14 PST
The patch is ready.
Ryosuke Niwa
Comment 185
2016-11-15 18:57:22 PST
Comment on
attachment 294830
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294830&action=review
> Source/WebCore/bindings/js/CachedModuleScriptClient.h:32 > +class CachedModuleScriptClient {
I'm not saying that we should do it in this patch but we should consider using std::function / lambda in the lieu of these client classes with one function.
> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:69 > + // If the content is already cached, this immediately calls notifyFinished. > + m_cachedScript->addClient(*this);
What is the significant of this comment? Why do we care that it may synchronously call notifyFinished?
> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:85 > + // from purging its data buffer. To keep the underlying CachedResource during > + // processing, we remove the client after calling client's notifyFinished.
It's not clear to me why removing the client keeps the data buffer. Or are you saying that we can't do this before calling notifyFinished? i.e. the data buffer may now be purged? If so, a better way of phrasing this would be something like "Remove the client after calling notifyFinished to keep the data buffer in CachedResource alive while notifyFinished processes the resource."
> Source/WebCore/bindings/js/ScriptController.cpp:210 > + setupModuleScriptHandlers(moduleScript, JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), toJS(&state, shell.window(), &element)), world);
There's a lot of nesting going on here. Can we split some of it to a separate line?
> Source/WebCore/bindings/js/ScriptController.cpp:362 > +enum class ErrorStatus { > + AlreadyReported, > + FetchingCanceled, > + ErrorThrown, > +};
We don't need this enum anymore do we?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:100 > + bool isRootModule = importerModuleKey.isSymbol() || importerModuleKey.isUndefined();
Can this logic be extracted as a separate static local helper function?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:150 > + deferred->reject(TypeError, ASCIILiteral("Module key is an invalid URL."));
I think it's more natural to say "module key is not a valid URL" for an error message.
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:155 > + auto* scriptElement = toScriptElementIfPossible(&JSC::jsCast<JSElement*>(initiator)->wrapped());
Should we just call jsCast<HTMLScriptElement*>? Or does SVG script element also support module?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:209 > + auto* cachedScript = loader.cachedScript();
Why not a reference? Also, why is it guaranteed that cachedScript is not null?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:226 > + "Refused to execute module script from '", cachedScript->url().stringCenterEllipsizedToLength(), > + "' because its MIME type ('", cachedScript->response().mimeType(), "') is not executable."));
"refused to execute" is quite a departure from other kinds of error messages we have. How about simply "~ is not a valid JavaScript MIME type".
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:230 > + if (auto* frame = m_document.frame()) {
We can just exit early when frame is null since that's not a formal flow of control.
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:234 > + } else if (cachedScript->wasCanceled())
Why not an early return instead of else iff for the same reason?
> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:235 > + promise->reject(frame->script().moduleLoaderFetchingIsCanceledSymbol());
Ditto to add an early exit instead.
> Source/WebCore/bindings/js/ScriptModuleLoader.h:50 > +WTF_MAKE_NONCOPYABLE(ScriptModuleLoader); WTF_MAKE_FAST_ALLOCATED;
I think we indent these.
> Source/WebCore/dom/ScriptElement.cpp:246 > + bool isParserInsertedDeferredScript = (scriptType == ScriptType::Classic && hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) || (scriptType == ScriptType::Module && m_parserInserted && !asyncAttributeValue());
It seems like this can make a use of a line break in the middle.
> Source/WebCore/dom/ScriptElement.cpp:250 > + } else if (scriptType == ScriptType::Classic && hasSourceAttribute() && m_parserInserted && !asyncAttributeValue()) {
It seems like we keep checking scriptType == ScriptType::Classic && hasSourceAttribute() multiple types. How about declaring a local variable like isClassicExternalScript?
> Source/WebCore/dom/ScriptElement.cpp:253 > + } else if ((scriptType == ScriptType::Classic && hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) || (scriptType == ScriptType::Module && !asyncAttributeValue() && !m_forceAsync)) {
It looks like both classic & module scripts want to check !asyncAttributeValue() && !m_forceAsync. I think it's cleaner to put that outside ||. e.g. (isClassicExternalScript || scriptType == ScriptType::Module) && !asyncAttributeValue() && !m_forceAsync Also, it might be worth adding a comment (better yet an assertion) here or above all these if-else that inline module would be processed within requestModuleScript. It's not great that our implementation is further away from the spec text:
https://html.spec.whatwg.org/#prepare-a-script
We should probably refactor at some point to make it more aligned with the spec'ed text given the complexity. Alternatively, we can split into two functions and use this if-else for module as well. I'm inclined to say that's probably more preferrable because that'll align our code more with the spec text.
> Source/WebCore/dom/ScriptElement.cpp:258 > + } else if (hasSourceAttribute() || scriptType == ScriptType::Module) { > ASSERT(m_loadableScript);
So this is an async case. Can we assert that asyncAttributeValue() is true here?
> Source/WebCore/dom/ScriptElement.cpp:286 > + String nonceAttribute = m_element.attributeWithoutSynchronization(HTMLNames::nonceAttr); > + String crossOriginMode = m_element.attributeWithoutSynchronization(HTMLNames::crossoriginAttr); > + auto request = requestScriptWithCache(m_element.document().completeURL(sourceURL), ScriptType::Classic, nonceAttribute, crossOriginMode);
Can we set crossOriginMode to "omit" as spec'ed in step 15 of
https://html.spec.whatwg.org/#prepare-a-script
instead of changing it in CachedResourceRequest::setAsPotentiallyCrossOrigin? That'll better match the spec and we don't have to make CachedResourceRequest aware of script type we're fetching.
> Source/WebCore/dom/ScriptElement.cpp:395 > return;
Should we rename this to executeClassicScript for clarity?
> Source/WebCore/dom/ScriptElement.cpp:408 > + // Create a script from the script element node, using the script > + // block's source and the script block's type. > + // Note: This is where the script is compiled and actually executed.
I don't think we really need this comment. We call a function called "evaluate" right beneath it.
> Source/WebCore/html/parser/CSSPreloadScanner.cpp:206 > - m_requests->append(std::make_unique<PreloadRequest>("css", url, baseElementURL, CachedResource::CSSStyleSheet, String())); > + m_requests->append(std::make_unique<PreloadRequest>("css", url, baseElementURL, CachedResource::CSSStyleSheet, String(), PreloadRequest::ScriptType::Classic));
!? Does why CSS preloader specifying a script type? It doesn't load or run any scripts, right?
> Source/WebCore/html/parser/HTMLResourcePreloader.h:39 > + enum class ScriptType { > + Classic, > + Module, > + };
Maybe we should declare this in a separate header like ScriptType.h and share it with ScriptElement. It's redundant to have two enums. Although I could see us wanting to add more types. e.g. ClassicScript, ModuleScript, CSS. Yet another alternative is to split CachedResource::Script to CachedResource::ClassicScript and CachedResource::ModuleScript.
> Source/WebCore/loader/cache/CachedResourceRequest.cpp:85 > -void CachedResourceRequest::setAsPotentiallyCrossOrigin(const String& mode, Document& document) > +void CachedResourceRequest::setAsPotentiallyCrossOriginImpl(const String& mode, Document& document, CrossOriginSettingContext crossOriginSettingContext)
We normally suffix these functions with "Internal" instead. e.g. setAsPotentiallyCrossOriginInternal here.
> Source/WebCore/loader/cache/CachedResourceRequest.cpp:98 > + //
https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
> + m_options.mode = FetchOptions::Mode::Cors; > + m_options.credentials = FetchOptions::Credentials::Omit; > + m_options.allowCredentials = DoNotAllowStoredCredentials;
These defaults appear to come from:
https://html.spec.whatwg.org/#prepare-a-script
I think we should do this in prepareScript to better match the spec instead.
> LayoutTests/ChangeLog:66 > + * js/dom/module-and-dom-content-loaded-expected.txt: Added.
We probably want to another directly inside dom or js since you've got so many tests here.
> LayoutTests/http/tests/misc/module-script-async.html:17 > + if (!window.status_) > + window.status_ = ''; > + window.status_ += ' ' + msg + ' ';
Can we use a more regular name like window.log and use an array instead of concatenating scripts?
> LayoutTests/http/tests/misc/module-script-async.html:32 > + var expectedA = " async external inline DOMContentLoaded slowAsync "; > + var expectedB = " external async inline DOMContentLoaded slowAsync "; > + var expectedC = " external inline async DOMContentLoaded slowAsync "; > + var expectedD = " external inline DOMContentLoaded async slowAsync "; > + var results = "PASS"; > + if (window.status_ != expectedA && window.status_ != expectedB && window.status_ != expectedC && window.status_ != expectedD) > + results = "FAIL: Expected one of '" + expectedA + "' || '" + expectedB + "' || '" + expectedC + "' || '" + expectedD + "', Actual='" + window.status_ + "'";
It appears to me that a better way of doing this would be something like const expectedOrderings = [['async', 'external', 'inline', 'DOMContentLoaded', 'slowAsync'], ...] if (!expectedOrderings.find((expected) => JSON.stringify(expected) == JSON.stringify(window.log))) results = 'FAIL: ...';
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-and-scripthash.html:24 > + <script type="module" nonce="nonceynonce"> > + alert('PASS (3/3)'); > + done("PASS"); > + </script>
I think we should move one of these passes to the end so that we know for sure FAIL cases did run instead of the test finishing prematurely.
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-basic-blocked.html:6 > + <script nonce="noncynonce"> > + if (window.testRunner) {
Maybe indent the script once more to be consistent?
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-basic-blocked.html:32 > + </script>
It seems like we should add a test case for using eval statement & calling eval function in inline scripts and external scripts and make sure they're blocked.
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-ignore-unsafeinline.html:4 > + <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-noncynonce' 'nonce-noncy+/=nonce' 'unsafe-inline'">
I guess unsafe-inline doesn't allow inline module scripts? Where is that spec'ed? Could you mention that in the change log?
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-ignore-unsafeinline.html:26 > + <script type="module"> > + alert('FAIL (1/1)'); > + </script>
Again, I think it's better to have a FAIL case not appear at the very end.
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html:22 > + <p> > + None of these scripts should execute, as all the nonces are invalid.
Inconsistent indentation.
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect-same-origin.html:9 > + <script nonce="noncynonce"> > + if (window.testRunner) {
Nit: inconsistent indentation.
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect-same-origin.html:17 > + var preloaded = internals.isPreloaded("../resources/redir.php?url=
http://127.0.0.1:8000/security/contentSecurityPolicy/resources/alert-pass.js
"); > + document.querySelector("#preloaded").innerText = preloaded ? "YES" : "NO";
Shouldn't this always be NO? If so, why don't we just assert with a comment clarifying what we should do when we change the behavior of our preloader instead? If that's going to change, that seems to make this test flaky, which needs to be avoided.
> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect.html:17 > + var preloaded = internals.isPreloaded("../resources/redir.php?url=
http://localhost:8000/security/contentSecurityPolicy/resources/alert-pass.js
"); > + document.querySelector("#preloaded").innerText = preloaded ? "YES" : "NO";
Ditto.
> LayoutTests/http/tests/security/contentSecurityPolicy/resources/multiple-iframe-module-test.js:38 > + iframe.src = baseURL + "resources/echo-module-script-src.pl?" + > + "experimental=" + (experimental ? "true" : "false") + > + "&should_run=" + encodeURIComponent(current[0]) + > + "&csp=" + policy + "&q=" + scriptToLoad;
Nit: + should be at the beginning of each line and these should not be aligned against =. (Same rule as C++).
> LayoutTests/http/tests/security/contentSecurityPolicy/resources/multiple-iframe-module-test.js:40 > + if (current[3] !== undefined) > + iframe.src += "&nonce=" + encodeURIComponent(current[3]);
Wrong indentation. Instead of building strings like this, can we just create an array of key-value pair and join them together at the end? e.g. const queries = {}; queries['experimental'] = (!!experimental).toString(); Object.getPropertyNames(queries).map((key) => key + '=' + queries[key]).join('&');
> LayoutTests/http/tests/security/module-correct-mime-types.html:8 > +description('Test module rejects scripts with correct mime types.');
Did you mean to say module scripts with correct mime types *run*? They're certainly not rejected here.
> LayoutTests/http/tests/security/module-correct-mime-types.html:52 > + debug('Module rejects scripts with correct mime types.');
Ditto.
> LayoutTests/http/tests/security/module-crossorigin-loads-same-origin.html:10 > +function loaded() { > + document.querySelector("pre").innerHTML = "PASS";
This checks we've fired load script but not quite whether script had run or not. Can we check the value of "secretness" defined in localScript.js to make sure the script had run? You may need to modify localScript.js to export some symbol, etc... though...
> LayoutTests/http/tests/security/module-no-mime-type.html:19 > +function done() > +{ > + debug('Module rejects a script with no mime type.'); > + finishJSTest(); > +}
Is it possible to check that the script actually didn't run via a global state, etc...?
> LayoutTests/http/tests/security/module-requires-javascript-mime-types.html:8 > +description('Test module rejects scripts with no mime type.');
How is this test different from module-no-mime-type.html?
> LayoutTests/js/dom/module-and-dom-content-loaded.html:21 > +window.addEventListener('DOMContentLoaded', function () > +{ > + finishJSTest(); > +}, false);
Can we add a event listener in a classic inline script to make sure DOMContentLoaded is not fired until the module script had run? Also, can we assert that document.readyState is not "loading" until modules had ran? Otherwise, this test would only timeout when the semantics of type=module is violated, which isn't a great way to signal that the semantics is actually violated.
> LayoutTests/js/dom/module-and-window-load.html:22 > +<script type="module"> > +window.onload = function () > +{ > + finishJSTest(); > +} > +</script>
Ditto. I think we should change some state in the module script and have a separate classic script which attaches a load event handler which checks that the module had ran.
> LayoutTests/js/dom/module-async-and-window-load.html:18 > +window.onload = function ()
Ditto.
> LayoutTests/js/dom/module-execution-order-mixed.html:23 > +shouldBe("count++", "6");
Could you add another test where classical scripts and module scripts are mixed?
> LayoutTests/js/dom/module-incorrect-relative-specifier.html:15 > + debug(`${current}`);
Can we push "this" into a set and verify at the end that all module script elements are in the set?
> LayoutTests/js/dom/module-load-event-with-src.html:14 > +<script src="../../resources/js-test-post.js"></script> > +<script type="module" onload="finishJSTest()" src="script-tests/module-load-event-with-src.js"></script>
Can we also check some global state for making sure the script had run instead of relying the expected result to contain some text? When this starts failing, some people might think it's okay to just rebaseline the test if glanced it quickly. Whereas if it's explicitly checked via shouldBe, people are a lot more likely to realize that something is broken.
> LayoutTests/js/dom/module-load-event.html:16 > +<script type="module" onload="finishJSTest()"> > +debug('Executing an inlined module.'); > +</script>
Ditto about changing the global state instead of just emitting text.
> LayoutTests/js/dom/module-load-same-module-from-different-entry-point-dynamic.html:20 > +element.type = "module"; > +element.innerText = "script-tests/module-load-same-module-from-different-entry-point.js";
Ditto about checking the global state explicitly.
> LayoutTests/js/dom/module-load-same-module-from-different-entry-point.html:17 > +debug('Executing the module.');
Ditto about change the global state instead of just emitting text.
> LayoutTests/js/dom/module-not-found-error-event-with-src.html:16 > +function onError() > +{ > + successfullyParsed = true; > + finishJSTest() > +}
Instead of just finishing script we should explicitly check that the error event had fired by e.g. adding another module script that loads and checking this condition in that module script or on its load event handler.
> LayoutTests/js/dom/module-not-found-error-event.html:19 > +<script type="module" onerror="onError()">
Ditto about more explicitly checking the error being dispatched.
Yusuke Suzuki
Comment 186
2016-11-16 02:14:17 PST
Comment on
attachment 294830
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=294830&action=review
Thanks!!
>> Source/WebCore/bindings/js/CachedModuleScriptClient.h:32 >> +class CachedModuleScriptClient { > > I'm not saying that we should do it in this patch but we should consider > using std::function / lambda in the lieu of these client classes with one function.
It's interesting clean up!
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:69 >> + m_cachedScript->addClient(*this); > > What is the significant of this comment? > Why do we care that it may synchronously call notifyFinished?
It means that setting m_cachedScript should be done before this. notifyFinished requires that m_cachedScript is not null.
>> Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp:85 >> + // processing, we remove the client after calling client's notifyFinished. > > It's not clear to me why removing the client keeps the data buffer. > Or are you saying that we can't do this before calling notifyFinished? > i.e. the data buffer may now be purged? > If so, a better way of phrasing this would be something like > "Remove the client after calling notifyFinished to keep > the data buffer in CachedResource alive while notifyFinished processes the resource."
Right. Changed.
>> Source/WebCore/bindings/js/ScriptController.cpp:210 >> + setupModuleScriptHandlers(moduleScript, JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), toJS(&state, shell.window(), &element)), world); > > There's a lot of nesting going on here. Can we split some of it to a separate line?
Yeah, I've split it, like, auto& promise = JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), toJS(&state, shell.window(), &element)); setupModuleScriptHandlers(moduleScript, promise, world);
>> Source/WebCore/bindings/js/ScriptController.cpp:362 >> +}; > > We don't need this enum anymore do we?
Ah, right! Dropped.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:100 >> + bool isRootModule = importerModuleKey.isSymbol() || importerModuleKey.isUndefined(); > > Can this logic be extracted as a separate static local helper function?
Extracted it as `bool isRootModule(JSC::JSValue)`.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:150 >> + deferred->reject(TypeError, ASCIILiteral("Module key is an invalid URL.")); > > I think it's more natural to say "module key is not a valid URL" for an error message.
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:155 >> + auto* scriptElement = toScriptElementIfPossible(&JSC::jsCast<JSElement*>(initiator)->wrapped()); > > Should we just call jsCast<HTMLScriptElement*>? > Or does SVG script element also support module?
Right now, we implemented it in ScriptElement. So SVG script element should support it.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:209 >> + auto* cachedScript = loader.cachedScript(); > > Why not a reference? Also, why is it guaranteed that cachedScript is not null?
notifyFinished is called only when cachedScript is non null. It never becomes nullptr. Taking reference instead.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:226 >> + "' because its MIME type ('", cachedScript->response().mimeType(), "') is not executable.")); > > "refused to execute" is quite a departure from other kinds of error messages we have. > How about simply "~ is not a valid JavaScript MIME type".
Looks good. Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:230 >> + if (auto* frame = m_document.frame()) { > > We can just exit early when frame is null since that's not a formal flow of control.
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:234 >> + } else if (cachedScript->wasCanceled()) > > Why not an early return instead of else iff for the same reason?
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.cpp:235 >> + promise->reject(frame->script().moduleLoaderFetchingIsCanceledSymbol()); > > Ditto to add an early exit instead.
Fixed.
>> Source/WebCore/bindings/js/ScriptModuleLoader.h:50 >> +WTF_MAKE_NONCOPYABLE(ScriptModuleLoader); WTF_MAKE_FAST_ALLOCATED; > > I think we indent these.
Fixed.
>> Source/WebCore/dom/ScriptElement.cpp:246 >> + bool isParserInsertedDeferredScript = (scriptType == ScriptType::Classic && hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) || (scriptType == ScriptType::Module && m_parserInserted && !asyncAttributeValue()); > > It seems like this can make a use of a line break in the middle.
Inserted a line break.
>> Source/WebCore/dom/ScriptElement.cpp:250 >> + } else if (scriptType == ScriptType::Classic && hasSourceAttribute() && m_parserInserted && !asyncAttributeValue()) { > > It seems like we keep checking scriptType == ScriptType::Classic && hasSourceAttribute() multiple types. > How about declaring a local variable like isClassicExternalScript?
Sounds nice. Fixed.
>> Source/WebCore/dom/ScriptElement.cpp:253 >> + } else if ((scriptType == ScriptType::Classic && hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) || (scriptType == ScriptType::Module && !asyncAttributeValue() && !m_forceAsync)) { > > It looks like both classic & module scripts want to check !asyncAttributeValue() && !m_forceAsync. > I think it's cleaner to put that outside ||. > e.g. (isClassicExternalScript || scriptType == ScriptType::Module) && !asyncAttributeValue() && !m_forceAsync > > Also, it might be worth adding a comment (better yet an assertion) here > or above all these if-else that inline module would be processed within requestModuleScript. > It's not great that our implementation is further away from the spec text: >
https://html.spec.whatwg.org/#prepare-a-script
> > We should probably refactor at some point to make it more aligned with the spec'ed text given the complexity. > > Alternatively, we can split into two functions and use this if-else for module as well. > I'm inclined to say that's probably more preferrable because that'll align our code more with the spec text.
The above fix is done. And I added the comment here.
>> Source/WebCore/dom/ScriptElement.cpp:258 >> ASSERT(m_loadableScript); > > So this is an async case. Can we assert that asyncAttributeValue() is true here?
Inserted, ASSERT(asyncAttributeValue() || m_forceAsync);.
>> Source/WebCore/dom/ScriptElement.cpp:286 >> + auto request = requestScriptWithCache(m_element.document().completeURL(sourceURL), ScriptType::Classic, nonceAttribute, crossOriginMode); > > Can we set crossOriginMode to "omit" as spec'ed in step 15 of
https://html.spec.whatwg.org/#prepare-a-script
> instead of changing it in CachedResourceRequest::setAsPotentiallyCrossOrigin? > That'll better match the spec and we don't have to make CachedResourceRequest aware of script type we're fetching.
Fixed.
>> Source/WebCore/dom/ScriptElement.cpp:395 >> return; > > Should we rename this to executeClassicScript for clarity?
Currently, XML script element is not handled. Once it is done, we will rename this function.
>> Source/WebCore/dom/ScriptElement.cpp:408 >> + // Note: This is where the script is compiled and actually executed. > > I don't think we really need this comment. > We call a function called "evaluate" right beneath it.
OK, dropped. Maybe this is ancient comment :)
>> Source/WebCore/html/parser/CSSPreloadScanner.cpp:206 >> + m_requests->append(std::make_unique<PreloadRequest>("css", url, baseElementURL, CachedResource::CSSStyleSheet, String(), PreloadRequest::ScriptType::Classic)); > > !? Does why CSS preloader specifying a script type? > It doesn't load or run any scripts, right?
Yes, this is because PreloadRequest always needs all the fields right now. That's why I selected PreloadRequest::ModuleScript::{Yes, No} previously. At that time, we can pass PreloadRequest::ModuleScript::No. Maybe, it is better for now, reverted. Once the refactoring noted below is landed, this should be fixed.
>> Source/WebCore/html/parser/HTMLResourcePreloader.h:39 >> + }; > > Maybe we should declare this in a separate header like ScriptType.h and share it with ScriptElement. > It's redundant to have two enums. > Although I could see us wanting to add more types. e.g. ClassicScript, ModuleScript, CSS. > Yet another alternative is to split CachedResource::Script to CachedResource::ClassicScript and CachedResource::ModuleScript.
Right. It should be better. In the meantime, I reverted this ScriptType to ModuleScript { Yes, No }. The above refactoring will be done in the separate patch.
>> Source/WebCore/loader/cache/CachedResourceRequest.cpp:85 >> +void CachedResourceRequest::setAsPotentiallyCrossOriginImpl(const String& mode, Document& document, CrossOriginSettingContext crossOriginSettingContext) > > We normally suffix these functions with "Internal" instead. e.g. setAsPotentiallyCrossOriginInternal here.
Now, setAsPotentiallyCrossOriginImpl is dropped since crossOriginMode is changed in the caller side.
>> Source/WebCore/loader/cache/CachedResourceRequest.cpp:98 >> + m_options.allowCredentials = DoNotAllowStoredCredentials; > > These defaults appear to come from: >
https://html.spec.whatwg.org/#prepare-a-script
> I think we should do this in prepareScript to better match the spec instead.
Instead, we set "omit" to crossOriginMode. So we can drop this if clause and the else side is extended to accept "omit". And we cannot move the above things to ScriptElement since it is also used from the preloader.
>> LayoutTests/ChangeLog:66 >> + * js/dom/module-and-dom-content-loaded-expected.txt: Added. > > We probably want to another directly inside dom or js since you've got so many tests here.
Nice. Moved to js/dom/module.
>> LayoutTests/http/tests/misc/module-script-async.html:17 >> + window.status_ += ' ' + msg + ' '; > > Can we use a more regular name like window.log and use an array instead of concatenating scripts?
Fixed.
>> LayoutTests/http/tests/misc/module-script-async.html:32 >> + results = "FAIL: Expected one of '" + expectedA + "' || '" + expectedB + "' || '" + expectedC + "' || '" + expectedD + "', Actual='" + window.status_ + "'"; > > It appears to me that a better way of doing this would be something like > const expectedOrderings = [['async', 'external', 'inline', 'DOMContentLoaded', 'slowAsync'], ...] > if (!expectedOrderings.find((expected) => JSON.stringify(expected) == JSON.stringify(window.log))) > results = 'FAIL: ...';
Fixed.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-and-scripthash.html:24 >> + </script> > > I think we should move one of these passes to the end so that we know for sure FAIL cases did run instead of the test finishing prematurely.
Fixed.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-basic-blocked.html:6 >> + if (window.testRunner) { > > Maybe indent the script once more to be consistent?
Fixed.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-basic-blocked.html:32 >> + </script> > > It seems like we should add a test case for using eval statement & calling eval function > in inline scripts and external scripts and make sure they're blocked.
Added.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-ignore-unsafeinline.html:4 >> + <meta http-equiv="Content-Security-Policy" content="script-src 'nonce-noncynonce' 'nonce-noncy+/=nonce' 'unsafe-inline'"> > > I guess unsafe-inline doesn't allow inline module scripts? > Where is that spec'ed? > Could you mention that in the change log?
https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script
Step 11, "If the script element does not have a src content attribute, and the Should element's inline behavior be blocked by Content Security Policy? algorithm returns "Blocked" when executed upon the script element, "script", and the script element's child text content, then abort these steps. The script is not executed. [CSP]" So, if the script tag does not have src (it should include inline module scripts), CSP unsafe-inline should be applied. Noted.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-ignore-unsafeinline.html:26 >> + </script> > > Again, I think it's better to have a FAIL case not appear at the very end.
Fixed.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-invalidnonce.html:22 >> + None of these scripts should execute, as all the nonces are invalid. > > Inconsistent indentation.
Fixed.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect-same-origin.html:9 >> + if (window.testRunner) { > > Nit: inconsistent indentation.
Fixed.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect-same-origin.html:17 >> + document.querySelector("#preloaded").innerText = preloaded ? "YES" : "NO"; > > Shouldn't this always be NO? If so, why don't we just assert with a comment clarifying > what we should do when we change the behavior of our preloader instead? > If that's going to change, that seems to make this test flaky, which needs to be avoided.
OK, dropped.
>> LayoutTests/http/tests/security/contentSecurityPolicy/1.1/module-scriptnonce-redirect.html:17 >> + document.querySelector("#preloaded").innerText = preloaded ? "YES" : "NO"; > > Ditto.
Dropped.
>> LayoutTests/http/tests/security/contentSecurityPolicy/resources/multiple-iframe-module-test.js:40 >> + iframe.src += "&nonce=" + encodeURIComponent(current[3]); > > Wrong indentation. > > Instead of building strings like this, can we just create an array of key-value pair and join them together at the end? > e.g. > const queries = {}; > queries['experimental'] = (!!experimental).toString(); > Object.getPropertyNames(queries).map((key) => key + '=' + queries[key]).join('&');
OK, fixed like this.
>> LayoutTests/http/tests/security/module-correct-mime-types.html:8 >> +description('Test module rejects scripts with correct mime types.'); > > Did you mean to say module scripts with correct mime types *run*? They're certainly not rejected here.
Oops, right. Fixed.
>> LayoutTests/http/tests/security/module-correct-mime-types.html:52 >> + debug('Module rejects scripts with correct mime types.'); > > Ditto.
Fixed.
>> LayoutTests/http/tests/security/module-crossorigin-loads-same-origin.html:10 >> + document.querySelector("pre").innerHTML = "PASS"; > > This checks we've fired load script but not quite whether script had run or not. > Can we check the value of "secretness" defined in localScript.js to make sure the script had run? > You may need to modify localScript.js to export some symbol, etc... though...
Fixed.
>> LayoutTests/http/tests/security/module-no-mime-type.html:19 >> +} > > Is it possible to check that the script actually didn't run via a global state, etc...?
Fixed.
>> LayoutTests/http/tests/security/module-requires-javascript-mime-types.html:8 >> +description('Test module rejects scripts with no mime type.'); > > How is this test different from module-no-mime-type.html?
Oops, dropped.
>> LayoutTests/js/dom/module-and-dom-content-loaded.html:21 >> +}, false); > > Can we add a event listener in a classic inline script to make sure DOMContentLoaded is not fired until the module script had run? > Also, can we assert that document.readyState is not "loading" until modules had ran? > > Otherwise, this test would only timeout when the semantics of type=module is violated, > which isn't a great way to signal that the semantics is actually violated.
Fixed.
>> LayoutTests/js/dom/module-and-window-load.html:22 >> +</script> > > Ditto. I think we should change some state in the module script and have a separate classic script > which attaches a load event handler which checks that the module had ran.
Fixed.
>> LayoutTests/js/dom/module-async-and-window-load.html:18 >> +window.onload = function () > > Ditto.
Fixed.
>> LayoutTests/js/dom/module-execution-order-mixed.html:23 >> +shouldBe("count++", "6"); > > Could you add another test where classical scripts and module scripts are mixed?
Added.
>> LayoutTests/js/dom/module-incorrect-relative-specifier.html:15 >> + debug(`${current}`); > > Can we push "this" into a set and verify at the end that all module script elements are in the set?
Fixed.
>> LayoutTests/js/dom/module-load-event-with-src.html:14 >> +<script type="module" onload="finishJSTest()" src="script-tests/module-load-event-with-src.js"></script> > > Can we also check some global state for making sure the script had run instead of relying the expected result to contain some text? > When this starts failing, some people might think it's okay to just rebaseline the test if glanced it quickly. > Whereas if it's explicitly checked via shouldBe, people are a lot more likely to realize that something is broken.
Fixed.
>> LayoutTests/js/dom/module-load-event.html:16 >> +</script> > > Ditto about changing the global state instead of just emitting text.
Fixed.
>> LayoutTests/js/dom/module-load-same-module-from-different-entry-point-dynamic.html:20 >> +element.innerText = "script-tests/module-load-same-module-from-different-entry-point.js"; > > Ditto about checking the global state explicitly.
Fixed.
>> LayoutTests/js/dom/module-load-same-module-from-different-entry-point.html:17 >> +debug('Executing the module.'); > > Ditto about change the global state instead of just emitting text.
Fixed.
>> LayoutTests/js/dom/module-not-found-error-event-with-src.html:16 >> +} > > Instead of just finishing script we should explicitly check that the error event had fired > by e.g. adding another module script that loads and checking this condition in that module script > or on its load event handler.
Fixed.
>> LayoutTests/js/dom/module-not-found-error-event.html:19 >> +<script type="module" onerror="onError()"> > > Ditto about more explicitly checking the error being dispatched.
Fixed.
Yusuke Suzuki
Comment 187
2016-11-16 02:45:11 PST
Created
attachment 294928
[details]
Checking EWS
Yusuke Suzuki
Comment 188
2016-11-16 02:49:41 PST
Created
attachment 294929
[details]
Patch for landing
WebKit Commit Bot
Comment 189
2016-11-16 02:51:12 PST
Attachment 294928
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:372: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 169 files If any of these errors are false positives, please file a bug against check-webkit-style.
WebKit Commit Bot
Comment 190
2016-11-16 02:54:53 PST
Attachment 294929
[details]
did not pass style-queue: ERROR: Source/WebCore/bindings/js/ScriptController.cpp:372: 'moduleScript' is incorrectly named. It should be named 'protector' or 'protectedModuleScriptRef'. [readability/naming/protected] [4] Total errors found: 1 in 169 files If any of these errors are false positives, please file a bug against check-webkit-style.
Yusuke Suzuki
Comment 191
2016-11-16 03:39:59 PST
Committed
r208788
: <
http://trac.webkit.org/changeset/208788
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug