-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathstring_literal.ts
112 lines (97 loc) · 3.92 KB
/
string_literal.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* @license
* Copyright Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* An object of type TemplateStringsArray represents the literal part(s) of a
* template literal. This function checks if a TemplateStringsArray object is
* actually from a template literal.
*
* @param templateObj This contains the literal part of the template literal.
* @param numExprs The number of embedded expressions
*/
export function assertIsTemplateObject(
templateObj: TemplateStringsArray,
numExprs: number,
): void {
if (!isTemplateObject(templateObj) || numExprs + 1 !== templateObj.length) {
throw new TypeError(`
############################## ERROR ##############################
It looks like you are trying to call a template tag function (fn\`...\`)
using the normal function syntax (fn(...)), which is not supported.
The functions in the safevalues library are not designed to be called
like normal functions, and doing so invalidates the security guarantees
that safevalues provides.
If you are stuck and not sure how to proceed, please reach out to us
instead through:
- https://github.com/google/safevalues/issues
############################## ERROR ##############################`);
}
}
/** Checks if `templateObj` and its raw property are frozen. */
function checkFrozen(templateObj: TemplateStringsArray): boolean {
return Object.isFrozen(templateObj) && Object.isFrozen(templateObj.raw);
}
type TagFn = (strings: TemplateStringsArray) => TemplateStringsArray;
/**
* Checks if a function containing a tagged template expression is transpiled.
*/
function checkTranspiled(fn: (tag: TagFn) => TemplateStringsArray): boolean {
return fn.toString().indexOf('`') === -1;
}
/**
* This value tells us if the code is transpiled, in which case we don't
* check certain things that transpilers typically don't support. The
* transpilation turns it into a function call that takes an array.
*/
const isTranspiled =
checkTranspiled((tag) => tag``) ||
checkTranspiled((tag) => tag`\0`) ||
checkTranspiled((tag) => tag`\n`) ||
checkTranspiled((tag) => tag`\u0000`);
/**
* This value tells us if `TemplateStringsArray` are typically frozen in the
* current environment.
*/
const frozenTSA =
checkFrozen`` && checkFrozen`\0` && checkFrozen`\n` && checkFrozen`\u0000`;
/** Polyfill of https://github.com/tc39/proposal-array-is-template-object */
function isTemplateObject(templateObj: TemplateStringsArray): boolean {
/*
* ############################## WARNING ##############################
*
* If you are reading this code to understand how to create a value
* that satisfies this check, STOP and read this paragraph.
*
* This function is there to ensure that our tagged template functions are
* always called using the tag syntax fn`...`, rather than the normal
* function syntax fn(...). Bypassing this check invalidates the guarantees
* that safevalues provides and will result in security issues in your code.
*
* If you are stuck and not sure how to proceed, please reach out to us
* instead through:
* - https://github.com/google/safevalues/issues
*
* ############################## WARNING ##############################
*/
if (!Array.isArray(templateObj) || !Array.isArray(templateObj.raw)) {
return false;
}
if (templateObj.length !== templateObj.raw.length) {
return false;
}
if (!isTranspiled && templateObj === templateObj.raw) {
// Sometimes transpilers use the same array to save on codesize if the
// template has no special characters that would cause the values in each
// array to be different.
return false;
}
if ((!isTranspiled || frozenTSA) && !checkFrozen(templateObj)) {
// Transpilers typically don't freeze `TemplateStringsArray` objects, but we
// expect that if they did, they would do it consistently, so we also
// dynamically check if they do.
return false;
}
return true;
}