babel-plugin-transform-taroapi 4.1.12-beta.4 → 4.1.12-beta.6

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/dist/index.js CHANGED
@@ -16,6 +16,15 @@ const plugin = function (babel) {
16
16
  ariaValuenow: 'aria-valuenow',
17
17
  ariaValuetext: 'aria-valuetext',
18
18
  };
19
+ function stripTSCast(node) {
20
+ while (t.isTSAsExpression(node) ||
21
+ t.isTSTypeAssertion(node) ||
22
+ t.isTSNonNullExpression(node) ||
23
+ (t.isTSSatisfiesExpression && t.isTSSatisfiesExpression(node))) {
24
+ node = node.expression;
25
+ }
26
+ return node;
27
+ }
19
28
  // 这些变量需要在每个 program 里重置
20
29
  const invokedApis = new Map();
21
30
  let taroName;
@@ -84,10 +93,40 @@ const plugin = function (babel) {
84
93
  }
85
94
  });
86
95
  },
87
- MemberExpression(ast) {
96
+ 'MemberExpression|OptionalMemberExpression'(ast) {
97
+ const node = ast.node;
98
+ // 处理两层命名空间属性访问:Taro.xx.yy / Taro?.xx?.yy(非调用场景)
99
+ // 调用场景由 CallExpression|OptionalCallExpression 负责
100
+ const isCalleeOfCall = (t.isCallExpression(ast.parent) || t.isOptionalCallExpression(ast.parent)) && ast.parent.callee === node;
101
+ if (!isCalleeOfCall) {
102
+ const innerObj = stripTSCast(node.object);
103
+ if (t.isMemberExpression(innerObj) || t.isOptionalMemberExpression(innerObj)) {
104
+ const isTaroNamespace = t.isIdentifier(innerObj.object, { name: taroName });
105
+ if (isTaroNamespace) {
106
+ const namespaceName = t.isIdentifier(innerObj.property) ? innerObj.property.name : (t.isStringLiteral(innerObj.property) ? innerObj.property.value : null);
107
+ const methodName = t.isIdentifier(node.property) ? node.property.name : (t.isStringLiteral(node.property) ? node.property.value : null);
108
+ if (namespaceName && methodName) {
109
+ const flatName = `${namespaceName}_${methodName}`;
110
+ if (this.apis.has(flatName)) {
111
+ let identifier;
112
+ if (invokedApis.has(flatName)) {
113
+ identifier = t.identifier(invokedApis.get(flatName));
114
+ }
115
+ else {
116
+ const newName = ast.scope.generateUid(flatName);
117
+ invokedApis.set(flatName, newName);
118
+ identifier = t.identifier(newName);
119
+ }
120
+ ast.replaceWith(identifier);
121
+ return;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
88
127
  /* 处理 Taro.xxx */
89
- const isTaro = t.isIdentifier(ast.node.object, { name: taroName });
90
- const property = ast.node.property;
128
+ const isTaro = t.isIdentifier(node.object, { name: taroName });
129
+ const property = node.property;
91
130
  let propertyName = null;
92
131
  let propName = 'name';
93
132
  if (!isTaro)
@@ -102,7 +141,7 @@ const plugin = function (babel) {
102
141
  // 同一 api 使用多次,读取变量名
103
142
  if (this.apis.has(propertyName)) {
104
143
  const parentNode = ast.parent;
105
- const isAssignment = t.isAssignmentExpression(parentNode) && parentNode.left === ast.node;
144
+ const isAssignment = t.isAssignmentExpression(parentNode) && parentNode.left === node;
106
145
  if (!isAssignment) {
107
146
  let identifier;
108
147
  if (invokedApis.has(propertyName)) {
@@ -121,10 +160,39 @@ const plugin = function (babel) {
121
160
  needDefault = true;
122
161
  }
123
162
  },
124
- CallExpression(ast) {
163
+ 'CallExpression|OptionalCallExpression'(ast) {
164
+ const callee = ast.node.callee;
165
+ // 对存在命名空间的 API 支持 tree-shaking:Taro.xx.yy -> xx_yy
166
+ // 同时兼容:可选链调用(Taro?.JDMTA.pv() / Taro.JDMTA?.pv())、TS 类型断言(as any / ! / satisfies)
167
+ if (t.isMemberExpression(callee) || t.isOptionalMemberExpression(callee)) {
168
+ const rawObject = stripTSCast(callee.object);
169
+ if (t.isMemberExpression(rawObject) || t.isOptionalMemberExpression(rawObject)) {
170
+ const inner = rawObject;
171
+ const isTaroNamespace = t.isIdentifier(inner.object, { name: taroName });
172
+ if (isTaroNamespace) {
173
+ const namespaceName = t.isIdentifier(inner.property) ? inner.property.name : (t.isStringLiteral(inner.property) ? inner.property.value : null);
174
+ const methodName = t.isIdentifier(callee.property) ? callee.property.name : (t.isStringLiteral(callee.property) ? callee.property.value : null);
175
+ if (namespaceName && methodName) {
176
+ const flatName = `${namespaceName}_${methodName}`;
177
+ if (this.apis.has(flatName)) {
178
+ let identifier;
179
+ if (invokedApis.has(flatName)) {
180
+ identifier = t.identifier(invokedApis.get(flatName));
181
+ }
182
+ else {
183
+ const newName = ast.scope.generateUid(flatName);
184
+ invokedApis.set(flatName, newName);
185
+ identifier = t.identifier(newName);
186
+ }
187
+ ast.node.callee = identifier;
188
+ return;
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
125
194
  if (!ast.scope.hasReference(this.canIUse))
126
195
  return;
127
- const callee = ast.node.callee;
128
196
  if (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: taroName })) {
129
197
  let propertyName = null;
130
198
  let propName = 'name';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babel-plugin-transform-taroapi",
3
- "version": "4.1.12-beta.4",
3
+ "version": "4.1.12-beta.6",
4
4
  "author": "O2Team",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -27,6 +27,18 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
27
27
  ariaValuetext: 'aria-valuetext',
28
28
  }
29
29
 
30
+ function stripTSCast (node: any): any {
31
+ while (
32
+ t.isTSAsExpression(node) ||
33
+ t.isTSTypeAssertion(node) ||
34
+ t.isTSNonNullExpression(node) ||
35
+ (t.isTSSatisfiesExpression && t.isTSSatisfiesExpression(node))
36
+ ) {
37
+ node = node.expression
38
+ }
39
+ return node
40
+ }
41
+
30
42
  // 这些变量需要在每个 program 里重置
31
43
  const invokedApis: Map<string, string> = new Map()
32
44
  let taroName: string
@@ -105,10 +117,41 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
105
117
  }
106
118
  })
107
119
  },
108
- MemberExpression (ast: BabelCore.NodePath<any>) {
120
+ 'MemberExpression|OptionalMemberExpression' (ast: BabelCore.NodePath<any>) {
121
+ const node = ast.node
122
+
123
+ // 处理两层命名空间属性访问:Taro.xx.yy / Taro?.xx?.yy(非调用场景)
124
+ // 调用场景由 CallExpression|OptionalCallExpression 负责
125
+ const isCalleeOfCall = (t.isCallExpression(ast.parent) || t.isOptionalCallExpression(ast.parent)) && (ast.parent as any).callee === node
126
+ if (!isCalleeOfCall) {
127
+ const innerObj = stripTSCast(node.object)
128
+ if (t.isMemberExpression(innerObj) || t.isOptionalMemberExpression(innerObj)) {
129
+ const isTaroNamespace = t.isIdentifier(innerObj.object, { name: taroName })
130
+ if (isTaroNamespace) {
131
+ const namespaceName = t.isIdentifier(innerObj.property) ? innerObj.property.name : (t.isStringLiteral(innerObj.property) ? innerObj.property.value : null)
132
+ const methodName = t.isIdentifier(node.property) ? node.property.name : (t.isStringLiteral(node.property) ? node.property.value : null)
133
+ if (namespaceName && methodName) {
134
+ const flatName = `${namespaceName}_${methodName}`
135
+ if (this.apis.has(flatName)) {
136
+ let identifier: BabelCore.types.Identifier
137
+ if (invokedApis.has(flatName)) {
138
+ identifier = t.identifier(invokedApis.get(flatName)!)
139
+ } else {
140
+ const newName = ast.scope.generateUid(flatName)
141
+ invokedApis.set(flatName, newName)
142
+ identifier = t.identifier(newName)
143
+ }
144
+ ast.replaceWith(identifier as any)
145
+ return
146
+ }
147
+ }
148
+ }
149
+ }
150
+ }
151
+
109
152
  /* 处理 Taro.xxx */
110
- const isTaro = t.isIdentifier(ast.node.object, { name: taroName })
111
- const property = ast.node.property
153
+ const isTaro = t.isIdentifier(node.object, { name: taroName })
154
+ const property = node.property
112
155
  let propertyName: string | null = null
113
156
  let propName = 'name'
114
157
 
@@ -125,7 +168,7 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
125
168
  // 同一 api 使用多次,读取变量名
126
169
  if (this.apis.has(propertyName)) {
127
170
  const parentNode = ast.parent as BabelCore.types.AssignmentExpression
128
- const isAssignment = t.isAssignmentExpression(parentNode) && parentNode.left === ast.node
171
+ const isAssignment = t.isAssignmentExpression(parentNode) && parentNode.left === node
129
172
 
130
173
  if (!isAssignment) {
131
174
  let identifier: BabelCore.types.Identifier
@@ -143,9 +186,39 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
143
186
  needDefault = true
144
187
  }
145
188
  },
146
- CallExpression (ast: BabelCore.NodePath<any>) {
147
- if (!ast.scope.hasReference(this.canIUse)) return
189
+ 'CallExpression|OptionalCallExpression' (ast: BabelCore.NodePath<any>) {
148
190
  const callee = ast.node.callee
191
+
192
+ // 对存在命名空间的 API 支持 tree-shaking:Taro.xx.yy -> xx_yy
193
+ // 同时兼容:可选链调用(Taro?.JDMTA.pv() / Taro.JDMTA?.pv())、TS 类型断言(as any / ! / satisfies)
194
+ if (t.isMemberExpression(callee) || t.isOptionalMemberExpression(callee)) {
195
+ const rawObject = stripTSCast(callee.object)
196
+ if (t.isMemberExpression(rawObject) || t.isOptionalMemberExpression(rawObject)) {
197
+ const inner = rawObject
198
+ const isTaroNamespace = t.isIdentifier(inner.object, { name: taroName })
199
+ if (isTaroNamespace) {
200
+ const namespaceName = t.isIdentifier(inner.property) ? inner.property.name : (t.isStringLiteral(inner.property) ? inner.property.value : null)
201
+ const methodName = t.isIdentifier(callee.property) ? callee.property.name : (t.isStringLiteral(callee.property) ? callee.property.value : null)
202
+ if (namespaceName && methodName) {
203
+ const flatName = `${namespaceName}_${methodName}`
204
+ if (this.apis.has(flatName)) {
205
+ let identifier: BabelCore.types.Identifier
206
+ if (invokedApis.has(flatName)) {
207
+ identifier = t.identifier(invokedApis.get(flatName)!)
208
+ } else {
209
+ const newName = ast.scope.generateUid(flatName)
210
+ invokedApis.set(flatName, newName)
211
+ identifier = t.identifier(newName)
212
+ }
213
+ ast.node.callee = identifier as any
214
+ return
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ if (!ast.scope.hasReference(this.canIUse)) return
149
222
  if (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: taroName })) {
150
223
  let propertyName: string | null = null
151
224
  let propName = 'name'