Skip to content

Commit

Permalink
Merge pull request #14173 from tosmolka/tosmolka/14075
Browse files Browse the repository at this point in the history
Support Trusted Types in EvalSourceMapDevToolPlugin
  • Loading branch information
sokra committed Jan 20, 2022
2 parents e550b2c + 70da0dd commit 1ed8aaf
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 47 deletions.
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 @@ -14,11 +14,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 @@ -40,7 +42,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 @@ -364,15 +368,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

0 comments on commit 1ed8aaf

Please sign in to comment.