source: frontend/node_modules/webpack/lib/runtime/LoadScriptRuntimeModule.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3*/
4
5"use strict";
6
7const { SyncWaterfallHook } = require("tapable");
8const Compilation = require("../Compilation");
9const RuntimeGlobals = require("../RuntimeGlobals");
10const Template = require("../Template");
11const HelperRuntimeModule = require("./HelperRuntimeModule");
12
13/** @typedef {import("../Chunk")} Chunk */
14
15/**
16 * @typedef {object} LoadScriptCompilationHooks
17 * @property {SyncWaterfallHook<[string, Chunk]>} createScript
18 */
19
20/** @type {WeakMap<Compilation, LoadScriptCompilationHooks>} */
21const compilationHooksMap = new WeakMap();
22
23class LoadScriptRuntimeModule extends HelperRuntimeModule {
24 /**
25 * @param {Compilation} compilation the compilation
26 * @returns {LoadScriptCompilationHooks} hooks
27 */
28 static getCompilationHooks(compilation) {
29 if (!(compilation instanceof Compilation)) {
30 throw new TypeError(
31 "The 'compilation' argument must be an instance of Compilation"
32 );
33 }
34 let hooks = compilationHooksMap.get(compilation);
35 if (hooks === undefined) {
36 hooks = {
37 createScript: new SyncWaterfallHook(["source", "chunk"])
38 };
39 compilationHooksMap.set(compilation, hooks);
40 }
41 return hooks;
42 }
43
44 /**
45 * @param {boolean=} withCreateScriptUrl use create script url for trusted types
46 * @param {boolean=} withFetchPriority use `fetchPriority` attribute
47 */
48 constructor(withCreateScriptUrl, withFetchPriority) {
49 super("load script");
50 /** @type {boolean | undefined} */
51 this._withCreateScriptUrl = withCreateScriptUrl;
52 /** @type {boolean | undefined} */
53 this._withFetchPriority = withFetchPriority;
54 }
55
56 /**
57 * Generates runtime code for this runtime module.
58 * @returns {string | null} runtime code
59 */
60 generate() {
61 const compilation = /** @type {Compilation} */ (this.compilation);
62 const { runtimeTemplate, outputOptions } = compilation;
63 const {
64 scriptType,
65 chunkLoadTimeout: loadTimeout,
66 crossOriginLoading,
67 uniqueName,
68 charset
69 } = outputOptions;
70 const fn = RuntimeGlobals.loadScript;
71
72 const { createScript } =
73 LoadScriptRuntimeModule.getCompilationHooks(compilation);
74
75 const code = Template.asString([
76 "script = document.createElement('script');",
77 scriptType ? `script.type = ${JSON.stringify(scriptType)};` : "",
78 charset ? "script.charset = 'utf-8';" : "",
79 `if (${RuntimeGlobals.scriptNonce}) {`,
80 Template.indent(
81 `script.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
82 ),
83 "}",
84 uniqueName
85 ? 'script.setAttribute("data-webpack", dataWebpackPrefix + key);'
86 : "",
87 this._withFetchPriority
88 ? Template.asString([
89 "if(fetchPriority) {",
90 Template.indent(
91 'script.setAttribute("fetchpriority", fetchPriority);'
92 ),
93 "}"
94 ])
95 : "",
96 `script.src = ${
97 this._withCreateScriptUrl
98 ? `${RuntimeGlobals.createScriptUrl}(url)`
99 : "url"
100 };`,
101 crossOriginLoading
102 ? crossOriginLoading === "use-credentials"
103 ? 'script.crossOrigin = "use-credentials";'
104 : Template.asString([
105 "if (script.src.indexOf(window.location.origin + '/') !== 0) {",
106 Template.indent(
107 `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
108 ),
109 "}"
110 ])
111 : ""
112 ]);
113
114 return Template.asString([
115 "var inProgress = {};",
116 uniqueName
117 ? `var dataWebpackPrefix = ${JSON.stringify(`${uniqueName}:`)};`
118 : "// data-webpack is not used as build has no uniqueName",
119 "// loadScript function to load a script via script tag",
120 `${fn} = ${runtimeTemplate.basicFunction(
121 `url, done, key, chunkId${
122 this._withFetchPriority ? ", fetchPriority" : ""
123 }`,
124 [
125 "if(inProgress[url]) { inProgress[url].push(done); return; }",
126 "var script, needAttach;",
127 "if(key !== undefined) {",
128 Template.indent([
129 'var scripts = document.getElementsByTagName("script");',
130 "for(var i = 0; i < scripts.length; i++) {",
131 Template.indent([
132 "var s = scripts[i];",
133 `if(s.getAttribute("src") == url${
134 uniqueName
135 ? ' || s.getAttribute("data-webpack") == dataWebpackPrefix + key'
136 : ""
137 }) { script = s; break; }`
138 ]),
139 "}"
140 ]),
141 "}",
142 "if(!script) {",
143 Template.indent([
144 "needAttach = true;",
145 createScript.call(code, /** @type {Chunk} */ (this.chunk))
146 ]),
147 "}",
148 "inProgress[url] = [done];",
149 `var onScriptComplete = ${runtimeTemplate.basicFunction(
150 "prev, event",
151 Template.asString([
152 "// avoid mem leaks in IE.",
153 "script.onerror = script.onload = null;",
154 "clearTimeout(timeout);",
155 "var doneFns = inProgress[url];",
156 "delete inProgress[url];",
157 "script.parentNode && script.parentNode.removeChild(script);",
158 `doneFns && doneFns.forEach(${runtimeTemplate.returningFunction(
159 "fn(event)",
160 "fn"
161 )});`,
162 "if(prev) return prev(event);"
163 ])
164 )}`,
165 `var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), ${loadTimeout});`,
166 "script.onerror = onScriptComplete.bind(null, script.onerror);",
167 "script.onload = onScriptComplete.bind(null, script.onload);",
168 "needAttach && document.head.appendChild(script);"
169 ]
170 )};`
171 ]);
172 }
173}
174
175module.exports = LoadScriptRuntimeModule;
Note: See TracBrowser for help on using the repository browser.