Bug 220688 - Preload Scanner Incorrectly Fetches Scripts With Malformed or Invalid Type Attributes
Summary: Preload Scanner Incorrectly Fetches Scripts With Malformed or Invalid Type At...
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Page Loading (show other bugs)
Version: Safari 14
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-01-17 11:50 PST by Harry Roberts
Modified: 2023-09-26 19:06 PDT (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Harry Roberts 2021-01-17 11:50:27 PST
Unfortunately, the HTML spec is a little loose/vague/contradictory/not helpful to us here, but, if we take this excerpt:

> Setting the [type] attribute to any other value [than Omitting the attribute, setting it to the empty string, or setting it to a JavaScript MIME type essence match] means that the script is a data block, which is not processed.https://html.spec.whatwg.org/multipage/scripting.html#attr-script-type

This tells us that any script element with a non-matching, malformed, or otherwise illegal type attribute must be skipped by the parser. WebKit’s primary parser does exactly as we’d expect. Take the following example:

```
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, minimum-scale=1.0" />

  <title>Hello, World!</title>

</head>
<body>

  <h1>Test</h1>

  <script type="text/javascript">console.log('Valid type attribute')</script>

  <script>console.log('Absent type attribute')</script>

  <script type="text/_javascript">console.log('Invalid type attribute')</script>

  <script type="foo" src="https://slowfil.es/file?type=js"></script>

</body>
</html>
```

The third and final `console.log` will not fire, nor will the file download.

However, the problem is with the preload scanner, which WILL begin requesting files from scripts with malformed type attributes.

EXAMPLE
=======

I can’t provide a useful, live URL as it’s subject to change, but please compare these waterfall charts: https://www.webpagetest.org/video/compare.php?tests=210117_Di8Q_83799f2f5ad00709f8049ce2d5ba8893-l:Chrome,210117_DiYE_07dc92513dc95cd9fbbbad2d4cda5009-l:Firefox,210117_DiT8_6a471556eeec59693b66ea29b1f07d73-l:Safari&thumbSize=200&ival=100&end=visual

This page uses Cloudflare’s Rocket Loader which hard-defers JS by malforming script tags’ type attributes directly in the HTML at the edge, e.g.:

```
<script defer src="/_ui/build/manifest.bundle.js?v=khnYwIsQ" type="6a915e949552efda43f84cd1-text/javascript"></script>
                                                             ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

```

This means that the HTML payloads’ script tags are all effectively hidden from the browser. Then, later, Rocket Loader kicks in on the client and turns the type attributes back to something valid, causing scripts to run and/or download. In the Chrome and Firefox waterfalls, you’ll see this all working as expected—no *bundle.js downloads until Rocket Loader has run. By comparison, the Safari waterfall shows all of these bundles downloading ahead of time. These downloads are all coming out of the preload scanner.

I’m in a discussion about what the *actual* behaviour should be as the spec skips finer detail, but there is definitely inconsistency between Safari’s primary- and preload-scanners where this is concerned. It would be nice if there was parity here.

I worry that was too wordy to be very clear—let me know if I can clarify anything.

Thanks!
Comment 1 Radar WebKit Bug Importer 2021-01-21 18:24:18 PST
<rdar://problem/73478736>