@wyw-in-js/transform 0.5.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/cache.js +17 -0
- package/esm/cache.js.map +1 -1
- package/esm/plugins/dynamic-import.js +6 -1
- package/esm/plugins/dynamic-import.js.map +1 -1
- package/esm/plugins/preeval.js +1 -1
- package/esm/plugins/preeval.js.map +1 -1
- package/esm/transform/BaseEntrypoint.js +3 -1
- package/esm/transform/BaseEntrypoint.js.map +1 -1
- package/esm/transform/Entrypoint.js +3 -3
- package/esm/transform/Entrypoint.js.map +1 -1
- package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
- package/esm/transform/generators/extract.js.map +1 -1
- package/esm/types.js.map +1 -1
- package/esm/utils/removeDangerousCode.js +113 -1
- package/esm/utils/removeDangerousCode.js.map +1 -1
- package/lib/cache.js +19 -0
- package/lib/cache.js.map +1 -1
- package/lib/plugins/dynamic-import.js +6 -1
- package/lib/plugins/dynamic-import.js.map +1 -1
- package/lib/plugins/preeval.js +1 -1
- package/lib/plugins/preeval.js.map +1 -1
- package/lib/transform/BaseEntrypoint.js +3 -1
- package/lib/transform/BaseEntrypoint.js.map +1 -1
- package/lib/transform/Entrypoint.js +3 -3
- package/lib/transform/Entrypoint.js.map +1 -1
- package/lib/transform/EvaluatedEntrypoint.js.map +1 -1
- package/lib/transform/generators/extract.js.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/removeDangerousCode.js +114 -1
- package/lib/utils/removeDangerousCode.js.map +1 -1
- package/package.json +7 -7
- package/types/cache.d.ts +13 -7
- package/types/cache.js +19 -0
- package/types/plugins/dynamic-import.js +9 -1
- package/types/plugins/preeval.d.ts +1 -1
- package/types/plugins/preeval.js +1 -1
- package/types/transform/BaseEntrypoint.d.ts +3 -1
- package/types/transform/BaseEntrypoint.js +4 -1
- package/types/transform/Entrypoint.d.ts +1 -1
- package/types/transform/Entrypoint.js +3 -5
- package/types/transform/EvaluatedEntrypoint.d.ts +2 -0
- package/types/types.d.ts +1 -0
- package/types/utils/removeDangerousCode.d.ts +2 -1
- package/types/utils/removeDangerousCode.js +142 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.removeDangerousCode = void 0;
|
|
4
|
+
const core_1 = require("@babel/core");
|
|
4
5
|
const findIdentifiers_1 = require("./findIdentifiers");
|
|
5
6
|
const isUnnecessaryReactCall_1 = require("./isUnnecessaryReactCall");
|
|
6
7
|
const scopeHelpers_1 = require("./scopeHelpers");
|
|
7
8
|
const JSXElementsRemover_1 = require("./visitors/JSXElementsRemover");
|
|
9
|
+
const collectExportsAndImports_1 = require("./collectExportsAndImports");
|
|
8
10
|
const isGlobal = (id) => {
|
|
9
11
|
if (!(0, findIdentifiers_1.nonType)(id)) {
|
|
10
12
|
return false;
|
|
@@ -49,7 +51,125 @@ const getPropertyName = (path) => {
|
|
|
49
51
|
}
|
|
50
52
|
return null;
|
|
51
53
|
};
|
|
52
|
-
const
|
|
54
|
+
const getImport = (path) => {
|
|
55
|
+
const programPath = path.findParent((p) => p.isProgram());
|
|
56
|
+
if (!programPath) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const { imports } = (0, collectExportsAndImports_1.collectExportsAndImports)(programPath);
|
|
60
|
+
if (path.isIdentifier()) {
|
|
61
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
62
|
+
const matched = binding &&
|
|
63
|
+
imports.find((imp) => imp.imported !== 'side-effect' && binding.path.isAncestor(imp.local));
|
|
64
|
+
if (matched) {
|
|
65
|
+
return [matched.source, matched.imported];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (path.isMemberExpression()) {
|
|
69
|
+
const leftPath = path.get('object');
|
|
70
|
+
if (!leftPath.isIdentifier()) {
|
|
71
|
+
// Nested member expression. Not supported yet.
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const rightPath = path.get('property');
|
|
75
|
+
if (!rightPath.isIdentifier()) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
const binding = path.scope.getBinding(leftPath.node.name);
|
|
79
|
+
const matched = binding &&
|
|
80
|
+
imports.find((imp) => imp.imported !== 'side-effect' && binding.path.isAncestor(imp.local));
|
|
81
|
+
if (matched) {
|
|
82
|
+
return [matched.source, rightPath.node.name];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
};
|
|
87
|
+
const getTypeImport = (path) => {
|
|
88
|
+
// We are looking for either Identifier or TSQualifiedName in path
|
|
89
|
+
if (path.isIdentifier()) {
|
|
90
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
91
|
+
if (!binding) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
if (!binding.path.isImportSpecifier() ||
|
|
95
|
+
!binding.path.parentPath.isImportDeclaration()) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const importDeclaration = binding.path.parentPath;
|
|
99
|
+
const imported = binding.path.get('imported');
|
|
100
|
+
const source = importDeclaration.node.source.value;
|
|
101
|
+
const importedNode = imported.node;
|
|
102
|
+
return [
|
|
103
|
+
source,
|
|
104
|
+
core_1.types.isIdentifier(importedNode) ? importedNode.name : importedNode.value,
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
if (path.isTSQualifiedName()) {
|
|
108
|
+
const leftPath = path.get('left');
|
|
109
|
+
if (!leftPath.isIdentifier()) {
|
|
110
|
+
// Nested type. Not supported yet.
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
const rightPath = path.get('right');
|
|
114
|
+
const binding = path.scope.getBinding(leftPath.node.name);
|
|
115
|
+
if (!binding) {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
if ((!binding.path.isImportDefaultSpecifier() &&
|
|
119
|
+
!binding.path.isImportNamespaceSpecifier()) ||
|
|
120
|
+
!binding.path.parentPath.isImportDeclaration()) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
return [binding.path.parentPath.node.source.value, rightPath.node.name];
|
|
124
|
+
}
|
|
125
|
+
return undefined;
|
|
126
|
+
};
|
|
127
|
+
const isTypeMatch = (id, types) => {
|
|
128
|
+
const typeAnnotation = id.get('typeAnnotation');
|
|
129
|
+
if (!typeAnnotation.isTSTypeAnnotation()) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const typeReference = typeAnnotation.get('typeAnnotation');
|
|
133
|
+
if (!typeReference.isTSTypeReference()) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
const typeName = typeReference.get('typeName');
|
|
137
|
+
const matchedImport = getTypeImport(typeName);
|
|
138
|
+
return (matchedImport !== undefined &&
|
|
139
|
+
matchedImport[0] in types &&
|
|
140
|
+
types[matchedImport[0]].includes(matchedImport[1]));
|
|
141
|
+
};
|
|
142
|
+
const isHOC = (path, hocs) => {
|
|
143
|
+
let calleePath = path;
|
|
144
|
+
while (calleePath.isCallExpression()) {
|
|
145
|
+
calleePath = calleePath.get('callee');
|
|
146
|
+
}
|
|
147
|
+
const matchedImport = getImport(calleePath);
|
|
148
|
+
return (matchedImport !== undefined &&
|
|
149
|
+
matchedImport[0] in hocs &&
|
|
150
|
+
hocs[matchedImport[0]].includes(matchedImport[1]));
|
|
151
|
+
};
|
|
152
|
+
const defaultPlaceholder = '...';
|
|
153
|
+
const defaultReactComponentTypes = [
|
|
154
|
+
'ExoticComponent',
|
|
155
|
+
'FC',
|
|
156
|
+
'ForwardRefExoticComponent',
|
|
157
|
+
'FunctionComponent',
|
|
158
|
+
'LazyExoticComponent',
|
|
159
|
+
'MemoExoticComponent',
|
|
160
|
+
'NamedExoticComponent',
|
|
161
|
+
];
|
|
162
|
+
const removeDangerousCode = (programPath, options) => {
|
|
163
|
+
const hocs = options?.hocs ?? {};
|
|
164
|
+
const componentTypes = options?.componentTypes ?? {
|
|
165
|
+
react: [defaultPlaceholder],
|
|
166
|
+
};
|
|
167
|
+
if (Array.isArray(componentTypes.react) &&
|
|
168
|
+
componentTypes.react.includes(defaultPlaceholder)) {
|
|
169
|
+
const idx = componentTypes.react.indexOf(defaultPlaceholder);
|
|
170
|
+
componentTypes.react = [...componentTypes.react];
|
|
171
|
+
componentTypes.react.splice(idx, 1, ...defaultReactComponentTypes);
|
|
172
|
+
}
|
|
53
173
|
programPath.traverse({
|
|
54
174
|
// JSX can be replaced with a dummy value,
|
|
55
175
|
// but we have to do it after we processed template tags.
|
|
@@ -58,6 +178,13 @@ const removeDangerousCode = (programPath) => {
|
|
|
58
178
|
if ((0, isUnnecessaryReactCall_1.isUnnecessaryReactCall)(p)) {
|
|
59
179
|
(0, JSXElementsRemover_1.JSXElementsRemover)(p);
|
|
60
180
|
}
|
|
181
|
+
if (isHOC(p, hocs)) {
|
|
182
|
+
(0, scopeHelpers_1.applyAction)([
|
|
183
|
+
'replace',
|
|
184
|
+
p,
|
|
185
|
+
core_1.types.arrowFunctionExpression([], core_1.types.nullLiteral()),
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
61
188
|
},
|
|
62
189
|
},
|
|
63
190
|
JSXElement: {
|
|
@@ -136,6 +263,20 @@ const removeDangerousCode = (programPath) => {
|
|
|
136
263
|
{ type: 'StringLiteral', value: 'undefined' },
|
|
137
264
|
]);
|
|
138
265
|
},
|
|
266
|
+
VariableDeclarator(p) {
|
|
267
|
+
const id = p.get('id');
|
|
268
|
+
const init = p.get('init');
|
|
269
|
+
if (id.isIdentifier() &&
|
|
270
|
+
isTypeMatch(id, componentTypes) &&
|
|
271
|
+
init.isExpression()) {
|
|
272
|
+
// Variable is typed as a React component. We can replace its value with a null-function.
|
|
273
|
+
(0, scopeHelpers_1.applyAction)([
|
|
274
|
+
'replace',
|
|
275
|
+
init,
|
|
276
|
+
core_1.types.arrowFunctionExpression([], core_1.types.nullLiteral()),
|
|
277
|
+
]);
|
|
278
|
+
}
|
|
279
|
+
},
|
|
139
280
|
}, {
|
|
140
281
|
globals: [],
|
|
141
282
|
windowScoped: new Set(),
|