Skip to content

Commit ddb9627

Browse files
authored
Merge pull request #16990 from Zlatkovsky/zlatkovsky/trusted-types-options
Allow specifying "onPolicyCreationFailure" mode for trusted types
2 parents ffcb480 + 83d14b1 commit ddb9627

14 files changed

Lines changed: 160 additions & 4 deletions

File tree

declarations/WebpackOptions.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,6 +2263,10 @@ export interface Environment {
22632263
* Use a Trusted Types policy to create urls for chunks.
22642264
*/
22652265
export interface TrustedTypes {
2266+
/**
2267+
* If the call to `trustedTypes.createPolicy(...)` fails -- e.g., due to the policy name missing from the CSP `trusted-types` list, or it being a duplicate name, etc. -- controls whether to continue with loading in the hope that `require-trusted-types-for 'script'` isn't enforced yet, versus fail immediately. Default behavior is 'stop'.
2268+
*/
2269+
onPolicyCreationFailure?: "continue" | "stop";
22662270
/**
22672271
* The name of the Trusted Types policy created by webpack to serve bundle chunks.
22682272
*/

lib/config/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ const applyOutputDefaults = (
961961
() =>
962962
output.uniqueName.replace(/[^a-zA-Z0-9\-#=_/@.%]+/g, "_") || "webpack"
963963
);
964+
D(trustedTypes, "onPolicyCreationFailure", "stop");
964965
}
965966

966967
/**

lib/runtime/GetTrustedTypesPolicyRuntimeModule.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class GetTrustedTypesPolicyRuntimeModule extends HelperRuntimeModule {
2525
const { runtimeTemplate, outputOptions } = compilation;
2626
const { trustedTypes } = outputOptions;
2727
const fn = RuntimeGlobals.getTrustedTypesPolicy;
28+
const wrapPolicyCreationInTryCatch = trustedTypes
29+
? trustedTypes.onPolicyCreationFailure === "continue"
30+
: false;
2831

2932
return Template.asString([
3033
"var policy;",
@@ -58,9 +61,25 @@ class GetTrustedTypesPolicyRuntimeModule extends HelperRuntimeModule {
5861
? [
5962
'if (typeof trustedTypes !== "undefined" && trustedTypes.createPolicy) {',
6063
Template.indent([
61-
`policy = trustedTypes.createPolicy(${JSON.stringify(
62-
trustedTypes.policyName
63-
)}, policy);`
64+
...(wrapPolicyCreationInTryCatch ? ["try {"] : []),
65+
...[
66+
`policy = trustedTypes.createPolicy(${JSON.stringify(
67+
trustedTypes.policyName
68+
)}, policy);`
69+
].map(line =>
70+
wrapPolicyCreationInTryCatch ? Template.indent(line) : line
71+
),
72+
...(wrapPolicyCreationInTryCatch
73+
? [
74+
"} catch (e) {",
75+
Template.indent([
76+
`console.warn('Could not create trusted-types policy ${JSON.stringify(
77+
trustedTypes.policyName
78+
)}');`
79+
]),
80+
"}"
81+
]
82+
: [])
6483
]),
6584
"}"
6685
]

schemas/WebpackOptions.check.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

schemas/WebpackOptions.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5039,6 +5039,10 @@
50395039
"type": "object",
50405040
"additionalProperties": false,
50415041
"properties": {
5042+
"onPolicyCreationFailure": {
5043+
"description": "If the call to `trustedTypes.createPolicy(...)` fails -- e.g., due to the policy name missing from the CSP `trusted-types` list, or it being a duplicate name, etc. -- controls whether to continue with loading in the hope that `require-trusted-types-for 'script'` isn't enforced yet, versus fail immediately. Default behavior is 'stop'.",
5044+
"enum": ["continue", "stop"]
5045+
},
50425046
"policyName": {
50435047
"description": "The name of the Trusted Types policy created by webpack to serve bundle chunks.",
50445048
"type": "string",

test/Defaults.unittest.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,6 +1931,7 @@ describe("snapshots", () => {
19311931
- "trustedTypes": undefined,
19321932
- "uniqueName": "webpack",
19331933
+ "trustedTypes": Object {
1934+
+ "onPolicyCreationFailure": "stop",
19341935
+ "policyName": "@@@Hello_World_",
19351936
+ },
19361937
+ "uniqueName": "@@@Hello World!",

test/__snapshots__/Cli.basictest.js.snap

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6628,6 +6628,23 @@ Object {
66286628
"multiple": false,
66296629
"simpleType": "string",
66306630
},
6631+
"output-trusted-types-on-policy-creation-failure": Object {
6632+
"configs": Array [
6633+
Object {
6634+
"description": "If the call to \`trustedTypes.createPolicy(...)\` fails -- e.g., due to the policy name missing from the CSP \`trusted-types\` list, or it being a duplicate name, etc. -- controls whether to continue with loading in the hope that \`require-trusted-types-for 'script'\` isn't enforced yet, versus fail immediately. Default behavior is 'stop'.",
6635+
"multiple": false,
6636+
"path": "output.trustedTypes.onPolicyCreationFailure",
6637+
"type": "enum",
6638+
"values": Array [
6639+
"continue",
6640+
"stop",
6641+
],
6642+
},
6643+
],
6644+
"description": "If the call to \`trustedTypes.createPolicy(...)\` fails -- e.g., due to the policy name missing from the CSP \`trusted-types\` list, or it being a duplicate name, etc. -- controls whether to continue with loading in the hope that \`require-trusted-types-for 'script'\` isn't enforced yet, versus fail immediately. Default behavior is 'stop'.",
6645+
"multiple": false,
6646+
"simpleType": "string",
6647+
},
66316648
"output-trusted-types-policy-name": Object {
66326649
"configs": Array [
66336650
Object {

test/configCases/trusted-types/continue-on-policy-creation-failure/empty.js

Whitespace-only changes.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
it("can continue on policy creation failure", function () {
2+
// emulate trusted types in a window object
3+
window.trustedTypes = {
4+
createPolicy: () => {
5+
throw new Error("Rejecting createPolicy call");
6+
}
7+
};
8+
9+
const createPolicySpy = jest.spyOn(window.trustedTypes, "createPolicy");
10+
const consoleWarn = jest.spyOn(console, "warn").mockImplementation(() => {});
11+
12+
const promise = import(
13+
"./empty?b" /* webpackChunkName: "continue-on-policy-creation-failure" */
14+
);
15+
var script = document.head._children.pop();
16+
expect(script.src).toBe(
17+
"https://test.cases/path/continue-on-policy-creation-failure.web.js"
18+
);
19+
__non_webpack_require__("./continue-on-policy-creation-failure.web.js");
20+
21+
expect(createPolicySpy).toHaveBeenCalledWith(
22+
"CustomPolicyName",
23+
expect.objectContaining({
24+
createScriptURL: expect.anything()
25+
})
26+
);
27+
expect(createPolicySpy).toThrow();
28+
expect(consoleWarn).toHaveBeenCalledWith(
29+
`Could not create trusted-types policy "CustomPolicyName"`
30+
);
31+
32+
createPolicySpy.mockReset();
33+
consoleWarn.mockReset();
34+
35+
return promise;
36+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = {
2+
target: "web",
3+
output: {
4+
chunkFilename: "[name].web.js",
5+
crossOriginLoading: "anonymous",
6+
trustedTypes: {
7+
policyName: "CustomPolicyName",
8+
onPolicyCreationFailure: "continue"
9+
}
10+
},
11+
performance: {
12+
hints: false
13+
},
14+
optimization: {
15+
minimize: false
16+
}
17+
};

0 commit comments

Comments
 (0)