Merge pull request #14173 from tosmolka/tosmolka/14075
Support Trusted Types in EvalSourceMapDevToolPlugin
This commit is contained in:
commit
1ed8aaf2e2
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
@ -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)
|
||||
});`
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -168,6 +168,13 @@ 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
|
||||
|
@ -175,6 +182,12 @@ exports.loadScript = "__webpack_require__.l";
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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) => {
|
||||
|
|
|
@ -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;
|
|
@ -10,7 +10,7 @@ const HelperRuntimeModule = require("./HelperRuntimeModule");
|
|||
|
||||
class CreateScriptUrlRuntimeModule extends HelperRuntimeModule {
|
||||
constructor() {
|
||||
super("trusted types");
|
||||
super("trusted types script url");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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"
|
||||
)};`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -6,7 +6,6 @@
|
|||
"use strict";
|
||||
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const CreateScriptUrlRuntimeModule = require("../runtime/CreateScriptUrlRuntimeModule");
|
||||
const StartupChunkDependenciesPlugin = require("../runtime/StartupChunkDependenciesPlugin");
|
||||
const ImportScriptsChunkLoadingRuntimeModule = require("./ImportScriptsChunkLoadingRuntimeModule");
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
it("should pass TrustedScript to eval", function () {
|
||||
var policy = __webpack_require__.tt();
|
||||
policy.createScript = jest.fn(script => {
|
||||
expect(typeof script).toEqual("string");
|
||||
return new TrustedScript(script);
|
||||
});
|
||||
|
||||
require("./test.js");
|
||||
expect(window.module.exports).toBeInstanceOf(Object);
|
||||
expect(window.module.exports.foo).toEqual("bar");
|
||||
|
||||
const testPattern =
|
||||
"var test = {\\s*foo: 'bar'\\s*};\\s*module.exports = test;";
|
||||
expect(policy.createScript).toBeCalledWith(
|
||||
expect.stringMatching(testPattern)
|
||||
);
|
||||
expect(window.eval).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
_script: expect.stringMatching(testPattern)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
class TrustedScript {
|
||||
constructor(script) {
|
||||
this._script = script;
|
||||
}
|
||||
}
|
||||
|
||||
let globalEval;
|
||||
beforeEach(done => {
|
||||
globalEval = eval;
|
||||
window.module = {};
|
||||
window.eval = jest.fn(x => {
|
||||
expect(x).toBeInstanceOf(TrustedScript);
|
||||
return globalEval(x._script);
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
afterEach(done => {
|
||||
delete window.module;
|
||||
window.eval = globalEval;
|
||||
done();
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
var test = {
|
||||
foo: 'bar'
|
||||
};
|
||||
|
||||
module.exports = test;
|
|
@ -0,0 +1,19 @@
|
|||
/** @type {import("../../../../").Configuration[]} */
|
||||
module.exports = [
|
||||
{
|
||||
target: "web",
|
||||
output: {
|
||||
filename: "bundle0.js",
|
||||
trustedTypes: true
|
||||
},
|
||||
devtool: "eval-source-map"
|
||||
},
|
||||
{
|
||||
target: "web",
|
||||
output: {
|
||||
filename: "bundle1.js",
|
||||
trustedTypes: true
|
||||
},
|
||||
devtool: "eval"
|
||||
}
|
||||
];
|
|
@ -12403,7 +12403,9 @@ declare namespace exports {
|
|||
export let uncaughtErrorHandler: string;
|
||||
export let scriptNonce: string;
|
||||
export let loadScript: string;
|
||||
export let createScript: string;
|
||||
export let createScriptUrl: string;
|
||||
export let getTrustedTypesPolicy: string;
|
||||
export let chunkName: string;
|
||||
export let runtimeId: string;
|
||||
export let getChunkScriptFilename: string;
|
||||
|
|
Loading…
Reference in New Issue