-
-
Notifications
You must be signed in to change notification settings - Fork 35.3k
Expand file tree
/
Copy pathassert.js
More file actions
128 lines (111 loc) Β· 4.24 KB
/
assert.js
File metadata and controls
128 lines (111 loc) Β· 4.24 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
'use strict';
const {
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
ObjectKeys,
ObjectPrototypeHasOwnProperty,
ObjectValues,
} = primordials;
const { validateString } = require('internal/validators');
const { getOptionValue } = require('internal/options');
const {
ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE,
ERR_IMPORT_ATTRIBUTE_MISSING,
ERR_IMPORT_ATTRIBUTE_UNSUPPORTED,
} = require('internal/errors').codes;
// The HTML spec has an implied default type of `'javascript'`.
const kImplicitTypeAttribute = 'javascript';
/**
* Define a map of module formats to import attributes types (the value of
* `type` in `with { type: 'json' }`).
* @type {Map<string, string>}
*/
const formatTypeMap = {
'__proto__': null,
'builtin': kImplicitTypeAttribute,
'commonjs': kImplicitTypeAttribute,
'json': 'json',
'module': kImplicitTypeAttribute,
'wasm': kImplicitTypeAttribute, // It's unclear whether the HTML spec will require an type attribute or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42
};
// NOTE: Don't add bytes support yet as it requires Uint8Arrays backed by immutable ArrayBuffers,
// which V8 does not support yet.
// see: https://github.com/nodejs/node/pull/62300#issuecomment-4079163816
function getFormatType(format) {
if (format === 'text' && getOptionValue('--experimental-import-text')) {
return 'text';
}
return formatTypeMap[format];
}
/**
* The HTML spec disallows the default type to be explicitly specified
* (for now); so `import './file.js'` is okay but
* `import './file.js' with { type: 'javascript' }` throws.
* @type {Array<string, string>}
*/
const supportedTypeAttributes = ArrayPrototypeFilter(
ObjectValues(formatTypeMap),
(type) => type !== kImplicitTypeAttribute);
/**
* Test a module's import attributes.
* @param {string} url The URL of the imported module, for error reporting.
* @param {string} format One of Node's supported translators
* @param {Record<string, string>} importAttributes Validations for the
* module import.
* @returns {true}
* @throws {TypeError} If the format and type attribute are incompatible.
*/
function validateAttributes(url, format,
importAttributes = { __proto__: null }) {
const keys = ObjectKeys(importAttributes);
for (let i = 0; i < keys.length; i++) {
if (keys[i] !== 'type') {
throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED(keys[i], importAttributes[keys[i]], url);
}
}
const validType = getFormatType(format);
switch (validType) {
case undefined:
// Ignore attributes for module formats we don't recognize, to allow new
// formats in the future.
return true;
case kImplicitTypeAttribute:
// This format doesn't allow an import type attribute, so the property
// must not be set on the import attributes object.
if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) {
return true;
}
return handleInvalidType(url, importAttributes.type);
case importAttributes.type:
// The type attribute is the valid type for this format.
return true;
default:
// There is an expected type for this format, but the value of
// `importAttributes.type` might not have been it.
if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) {
// `type` wasn't specified at all.
throw new ERR_IMPORT_ATTRIBUTE_MISSING(url, 'type', validType);
}
return handleInvalidType(url, importAttributes.type);
}
}
/**
* Throw the correct error depending on what's wrong with the type attribute.
* @param {string} url The resolved URL for the module to be imported
* @param {string} type The value of the import attributes' `type` property
*/
function handleInvalidType(url, type) {
// `type` might have not been a string.
validateString(type, 'type');
// `type` might not have been one of the types we understand.
if (!ArrayPrototypeIncludes(supportedTypeAttributes, type) &&
!(type === 'text' && getOptionValue('--experimental-import-text'))) {
throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED('type', type, url);
}
// `type` was the wrong value for this format.
throw new ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE(url, type);
}
module.exports = {
kImplicitTypeAttribute,
validateAttributes,
};