Skip to content

Commit 1917c0f

Browse files
coadofacebook-github-bot
authored andcommitted
Add support for Symbol member expression in class method definition (#1602)
Summary: ## Summary: This diff introduces support for [Symbol.iterator] and [Symbol.asyncIterator] as a method definition in flow defs generation. It can be confirmed in the flow lexer that these are the only two tokens prefixed with `@@`. Previously, that type of code wasn't supported and caused an exception: ```js export default { [Symbol.iterator]() {}; [Symbol.asyncIterator]() {}; } ``` The generated output if the type is not specified should be: ```js declare export default { @iterator(): void; @asyncIterator(): void; } ``` There are a few places in react-native source that will benefit from this, like: DOMRectList, URLSeachParams, NodeList and HTMLCollection. Changelog: [flow-api-translator] - Added support for Symbol member expression in class method definition Reviewed By: pieterv Differential Revision: D68766740
1 parent bfb595f commit 1917c0f

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

tools/hermes-parser/js/flow-api-translator/__tests__/flowToFlowDef-test.js

+10
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,16 @@ describe('flowToFlowDef', () => {
444444
static 2(): void;
445445
}`,
446446
);
447+
await expectTranslate(
448+
`export class A {
449+
[Symbol.iterator]() {}
450+
static get [Symbol.asyncIterator]() {}
451+
}`,
452+
`declare export class A {
453+
@@iterator(): void;
454+
static get @@asyncIterator(): void;
455+
}`,
456+
);
447457
});
448458
});
449459
describe('InterfaceDeclaration', () => {

tools/hermes-parser/js/flow-api-translator/src/flowToFlowDef.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ import {
8585
isStringLiteral,
8686
isNumericLiteral,
8787
isIdentifier,
88+
isMemberExpressionWithNonComputedProperty,
8889
} from 'hermes-estree';
8990

9091
const EMPTY_TRANSLATION_RESULT = [null, []];
@@ -1218,7 +1219,13 @@ function convertClassMember(
12181219
if (
12191220
!isIdentifier(member.key) &&
12201221
!isStringLiteral(member.key) &&
1221-
!isNumericLiteral(member.key)
1222+
!isNumericLiteral(member.key) &&
1223+
!(
1224+
isMemberExpressionWithNonComputedProperty(member.key) &&
1225+
member.key.object.type === 'Identifier' &&
1226+
member.key.object.name === 'Symbol' &&
1227+
['iterator', 'asyncIterator'].includes(member.key.property.name)
1228+
)
12221229
) {
12231230
throw translationError(
12241231
member.key,
@@ -1229,15 +1236,23 @@ function convertClassMember(
12291236

12301237
const [resultValue, deps] = convertAFunction(member.value, context);
12311238

1239+
const newKey =
1240+
isMemberExpressionWithNonComputedProperty(member.key) &&
1241+
member.key.object.type === 'Identifier' &&
1242+
member.key.object.name === 'Symbol'
1243+
? t.Identifier({name: `@@${member.key.property.name}`})
1244+
: member.key;
1245+
12321246
if (member.kind === 'get' || member.kind === 'set') {
12331247
// accessors are methods - but flow accessor signatures are properties
12341248
const kind = member.kind;
1249+
12351250
return [
12361251
t.ObjectTypeAccessorSignature({
12371252
// $FlowFixMe[incompatible-call]
12381253
key: asDetachedNode<
12391254
ClassPropertyNameComputed | ClassPropertyNameNonComputed,
1240-
>(member.key),
1255+
>(newKey),
12411256
value: resultValue,
12421257
static: member.static,
12431258
kind,
@@ -1251,7 +1266,7 @@ function convertClassMember(
12511266
// $FlowFixMe[incompatible-call]
12521267
key: asDetachedNode<
12531268
ClassPropertyNameComputed | ClassPropertyNameNonComputed,
1254-
>(member.key),
1269+
>(newKey),
12551270
value: resultValue,
12561271
static: member.static,
12571272
}),

0 commit comments

Comments
 (0)