Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Trusted Types in EvalSourceMapDevToolPlugin #14173

Merged
merged 11 commits into from Jan 20, 2022
17 changes: 16 additions & 1 deletion lib/EvalDevToolModulePlugin.js
Expand Up @@ -8,6 +8,7 @@
const { ConcatSource, RawSource } = require("webpack-sources");
const ExternalModule = require("./ExternalModule");
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
const RuntimeGlobals = require("./RuntimeGlobals");
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");

/** @typedef {import("webpack-sources").Source} Source */
Expand Down Expand Up @@ -77,7 +78,13 @@ class EvalDevToolModulePlugin {
.replace(/^\//, "")
);
const result = new RawSource(
`eval(${JSON.stringify(content + footer)});`
`eval(${
compilation.outputOptions.trustedTypes
? `${RuntimeGlobals.createScript}(${JSON.stringify(
content + footer
)})`
: JSON.stringify(content + footer)
});`
);
cache.set(source, result);
return result;
Expand All @@ -95,6 +102,14 @@ class EvalDevToolModulePlugin {
hash.update("EvalDevToolModulePlugin");
hash.update("2");
});
if (compilation.outputOptions.trustedTypes) {
compilation.hooks.additionalModuleRuntimeRequirements.tap(
"EvalDevToolModulePlugin",
(module, set, context) => {
set.add(RuntimeGlobals.createScript);
}
);
}
});
}
}
Expand Down
19 changes: 18 additions & 1 deletion lib/EvalSourceMapDevToolPlugin.js
Expand Up @@ -8,6 +8,7 @@
const { ConcatSource, RawSource } = require("webpack-sources");
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
const NormalModule = require("./NormalModule");
const RuntimeGlobals = require("./RuntimeGlobals");
const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin");
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
const ConcatenatedModule = require("./optimize/ConcatenatedModule");
Expand Down Expand Up @@ -165,7 +166,15 @@ class EvalSourceMapDevToolPlugin {
) + `\n//# sourceURL=webpack-internal:///${moduleId}\n`; // workaround for chrome bug

return result(
new RawSource(`eval(${JSON.stringify(content + footer)});`)
new RawSource(
`eval(${
compilation.outputOptions.trustedTypes
? `${RuntimeGlobals.createScript}(${JSON.stringify(
content + footer
)})`
: JSON.stringify(content + footer)
});`
)
);
}
);
Expand All @@ -181,6 +190,14 @@ class EvalSourceMapDevToolPlugin {
hash.update("EvalSourceMapDevToolPlugin");
hash.update("2");
});
if (compilation.outputOptions.trustedTypes) {
compilation.hooks.additionalModuleRuntimeRequirements.tap(
"EvalSourceMapDevToolPlugin",
(module, set, context) => {
set.add(RuntimeGlobals.createScript);
}
);
}
}
);
}
Expand Down
13 changes: 13 additions & 0 deletions lib/RuntimeGlobals.js
Expand Up @@ -168,13 +168,26 @@ exports.scriptNonce = "__webpack_require__.nc";
*/
exports.loadScript = "__webpack_require__.l";

/**
* function to promote a string to a TrustedScript using webpack's Trusted
* Types policy
* Arguments: (script: string) => TrustedScript
*/
exports.createScript = "__webpack_require__.ts";

/**
* function to promote a string to a TrustedScriptURL using webpack's Trusted
* Types policy
* Arguments: (url: string) => TrustedScriptURL
*/
exports.createScriptUrl = "__webpack_require__.tu";

/**
* function to return webpack's Trusted Types policy
* Arguments: () => TrustedTypePolicy
*/
exports.getTrustedTypesPolicy = "__webpack_require__.tt";

/**
* the chunk name of the chunk with the runtime
*/
Expand Down
25 changes: 25 additions & 0 deletions lib/RuntimePlugin.js
Expand Up @@ -13,11 +13,13 @@ const AutoPublicPathRuntimeModule = require("./runtime/AutoPublicPathRuntimeModu
const CompatGetDefaultExportRuntimeModule = require("./runtime/CompatGetDefaultExportRuntimeModule");
const CompatRuntimeModule = require("./runtime/CompatRuntimeModule");
const CreateFakeNamespaceObjectRuntimeModule = require("./runtime/CreateFakeNamespaceObjectRuntimeModule");
const CreateScriptRuntimeModule = require("./runtime/CreateScriptRuntimeModule");
const CreateScriptUrlRuntimeModule = require("./runtime/CreateScriptUrlRuntimeModule");
const DefinePropertyGettersRuntimeModule = require("./runtime/DefinePropertyGettersRuntimeModule");
const EnsureChunkRuntimeModule = require("./runtime/EnsureChunkRuntimeModule");
const GetChunkFilenameRuntimeModule = require("./runtime/GetChunkFilenameRuntimeModule");
const GetMainFilenameRuntimeModule = require("./runtime/GetMainFilenameRuntimeModule");
const GetTrustedTypesPolicyRuntimeModule = require("./runtime/GetTrustedTypesPolicyRuntimeModule");
const GlobalRuntimeModule = require("./runtime/GlobalRuntimeModule");
const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModule");
const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
Expand All @@ -39,7 +41,9 @@ const GLOBALS_ON_REQUIRE = [
RuntimeGlobals.runtimeId,
RuntimeGlobals.compatGetDefaultExport,
RuntimeGlobals.createFakeNamespaceObject,
RuntimeGlobals.createScript,
RuntimeGlobals.createScriptUrl,
RuntimeGlobals.getTrustedTypesPolicy,
RuntimeGlobals.definePropertyGetters,
RuntimeGlobals.ensureChunk,
RuntimeGlobals.entryModuleId,
Expand Down Expand Up @@ -331,15 +335,36 @@ class RuntimePlugin {
);
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.createScript)
.tap("RuntimePlugin", (chunk, set) => {
if (compilation.outputOptions.trustedTypes) {
set.add(RuntimeGlobals.getTrustedTypesPolicy);
}
compilation.addRuntimeModule(chunk, new CreateScriptRuntimeModule());
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.createScriptUrl)
.tap("RuntimePlugin", (chunk, set) => {
if (compilation.outputOptions.trustedTypes) {
set.add(RuntimeGlobals.getTrustedTypesPolicy);
}
compilation.addRuntimeModule(
chunk,
new CreateScriptUrlRuntimeModule()
);
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.getTrustedTypesPolicy)
.tap("RuntimePlugin", (chunk, set) => {
compilation.addRuntimeModule(
chunk,
new GetTrustedTypesPolicyRuntimeModule(set)
);
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.relativeUrl)
.tap("RuntimePlugin", (chunk, set) => {
Expand Down
36 changes: 36 additions & 0 deletions lib/runtime/CreateScriptRuntimeModule.js
@@ -0,0 +1,36 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
*/

"use strict";

const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const HelperRuntimeModule = require("./HelperRuntimeModule");

class CreateScriptRuntimeModule extends HelperRuntimeModule {
constructor() {
super("trusted types script");
}

/**
* @returns {string} runtime code
*/
generate() {
const { compilation } = this;
const { runtimeTemplate, outputOptions } = compilation;
const { trustedTypes } = outputOptions;
const fn = RuntimeGlobals.createScript;

return Template.asString(
`${fn} = ${runtimeTemplate.returningFunction(
trustedTypes
? `${RuntimeGlobals.getTrustedTypesPolicy}().createScript(script)`
: "script",
"script"
)};`
);
}
}

module.exports = CreateScriptRuntimeModule;
43 changes: 9 additions & 34 deletions lib/runtime/CreateScriptUrlRuntimeModule.js
Expand Up @@ -10,7 +10,7 @@ const HelperRuntimeModule = require("./HelperRuntimeModule");

class CreateScriptUrlRuntimeModule extends HelperRuntimeModule {
constructor() {
super("trusted types");
super("trusted types script url");
}

/**
Expand All @@ -22,39 +22,14 @@ class CreateScriptUrlRuntimeModule extends HelperRuntimeModule {
const { trustedTypes } = outputOptions;
const fn = RuntimeGlobals.createScriptUrl;

if (!trustedTypes) {
// Skip Trusted Types logic.
return Template.asString([
`${fn} = ${runtimeTemplate.returningFunction("url", "url")};`
]);
}

return Template.asString([
"var policy;",
`${fn} = ${runtimeTemplate.basicFunction("url", [
"// Create Trusted Type policy if Trusted Types are available and the policy doesn't exist yet.",
"if (policy === undefined) {",
Template.indent([
"policy = {",
Template.indent([
`createScriptURL: ${runtimeTemplate.returningFunction(
"url",
"url"
)}`
]),
"};",
'if (typeof trustedTypes !== "undefined" && trustedTypes.createPolicy) {',
Template.indent([
`policy = trustedTypes.createPolicy(${JSON.stringify(
trustedTypes.policyName
)}, policy);`
]),
"}"
]),
"}",
"return policy.createScriptURL(url);"
])};`
]);
return Template.asString(
`${fn} = ${runtimeTemplate.returningFunction(
trustedTypes
? `${RuntimeGlobals.getTrustedTypesPolicy}().createScriptURL(url)`
: "url",
"url"
)};`
);
}
}

Expand Down
76 changes: 76 additions & 0 deletions lib/runtime/GetTrustedTypesPolicyRuntimeModule.js
@@ -0,0 +1,76 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
*/

"use strict";

const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const HelperRuntimeModule = require("./HelperRuntimeModule");

class GetTrustedTypesPolicyRuntimeModule extends HelperRuntimeModule {
/**
* @param {Set<string>} runtimeRequirements runtime requirements
*/
constructor(runtimeRequirements) {
super("trusted types policy");
this.runtimeRequirements = runtimeRequirements;
}

/**
* @returns {string} runtime code
*/
generate() {
const { compilation } = this;
const { runtimeTemplate, outputOptions } = compilation;
const { trustedTypes } = outputOptions;
const fn = RuntimeGlobals.getTrustedTypesPolicy;

return Template.asString([
"var policy;",
`${fn} = ${runtimeTemplate.basicFunction("", [
"// Create Trusted Type policy if Trusted Types are available and the policy doesn't exist yet.",
"if (policy === undefined) {",
Template.indent([
"policy = {",
Template.indent(
[
...(this.runtimeRequirements.has(RuntimeGlobals.createScript)
? [
`createScript: ${runtimeTemplate.returningFunction(
"script",
"script"
)}`
]
: []),
...(this.runtimeRequirements.has(RuntimeGlobals.createScriptUrl)
? [
`createScriptURL: ${runtimeTemplate.returningFunction(
"url",
"url"
)}`
]
: [])
].join(",\n")
),
"};",
...(trustedTypes
? [
'if (typeof trustedTypes !== "undefined" && trustedTypes.createPolicy) {',
Template.indent([
`policy = trustedTypes.createPolicy(${JSON.stringify(
trustedTypes.policyName
)}, policy);`
]),
"}"
]
: [])
]),
"}",
"return policy;"
])};`
]);
}
}

module.exports = GetTrustedTypesPolicyRuntimeModule;
14 changes: 3 additions & 11 deletions lib/webworker/ImportScriptsChunkLoadingPlugin.js
Expand Up @@ -6,7 +6,6 @@
"use strict";

const RuntimeGlobals = require("../RuntimeGlobals");
const CreateScriptUrlRuntimeModule = require("../runtime/CreateScriptUrlRuntimeModule");
const StartupChunkDependenciesPlugin = require("../runtime/StartupChunkDependenciesPlugin");
const ImportScriptsChunkLoadingRuntimeModule = require("./ImportScriptsChunkLoadingRuntimeModule");

Expand Down Expand Up @@ -43,7 +42,9 @@ class ImportScriptsChunkLoadingPlugin {
const withCreateScriptUrl = !!compilation.outputOptions.trustedTypes;
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
set.add(RuntimeGlobals.hasOwnProperty);
if (withCreateScriptUrl) set.add(RuntimeGlobals.createScriptUrl);
if (withCreateScriptUrl) {
set.add(RuntimeGlobals.createScriptUrl);
}
compilation.addRuntimeModule(
chunk,
new ImportScriptsChunkLoadingRuntimeModule(set, withCreateScriptUrl)
Expand All @@ -61,15 +62,6 @@ class ImportScriptsChunkLoadingPlugin {
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.baseURI)
.tap("ImportScriptsChunkLoadingPlugin", handler);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.createScriptUrl)
.tap("RuntimePlugin", (chunk, set) => {
compilation.addRuntimeModule(
chunk,
new CreateScriptUrlRuntimeModule()
);
return true;
});

compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.ensureChunkHandlers)
Expand Down