Skip to content

Commit 34e1c0b

Browse files
committed
refactor(napi/parser): use minifier to generate JS/TS raw transfer deserializers from single source (#14312)
Pure refactor. Makes only minor cosmetic changes to the generated raw transfer deserializer code, mainly just alters *how* that code is generated. Previously we generated the source for the 2 different deserializers (JS and TS) separately, with the JS deserializer leaving out some fields e.g. `typeAnnotation`. Instead, generate only 1 base implementation, with TS-only fields gated by `IS_TS`. `IS_TS` is defined as a `const` at top of the file. ```js const IS_TS = true; function deserializeFunction(pos) { const params = deserializeBoxFormalParameters(pos + 56); if (IS_TS) { const thisParam = deserializeOptionBoxTSThisParameter(pos + 48); if (thisParam !== null) params.unshift(thisParam); } return { type: deserializeFunctionType(pos + 84), params, ...(IS_TS && { declare: deserializeBool(pos + 87), typeParameters: deserializeOptionBoxTSTypeParameterDeclaration(pos + 40), }), // ... etc ... }; } ``` Then we generate both the JS and TS deserializers from this same file, by setting the `IS_TS` const to `true` or `false`, and using minifier to shake out the dead code. This: 1. Simplifies custom deserializers. 2. Opens the door to add more `const` flags, e.g. `RANGES` to switch on/off including `range` field in AST nodes.
1 parent a98757a commit 34e1c0b

File tree

6 files changed

+248
-207
lines changed

6 files changed

+248
-207
lines changed

crates/oxc_ast/src/serialize/js.rs

Lines changed: 44 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ use super::{EmptyArray, Null};
1919
#[ast_meta]
2020
#[estree(raw_deser = "
2121
const pattern = DESER[BindingPatternKind](POS_OFFSET.kind);
22-
/* IF_TS */
23-
pattern.optional = DESER[bool](POS_OFFSET.optional);
24-
pattern.typeAnnotation = DESER[Option<Box<TSTypeAnnotation>>](POS_OFFSET.type_annotation);
25-
/* END_IF_TS */
22+
if (IS_TS) {
23+
pattern.optional = DESER[bool](POS_OFFSET.optional);
24+
pattern.typeAnnotation = DESER[Option<Box<TSTypeAnnotation>>](POS_OFFSET.type_annotation);
25+
}
2626
pattern
2727
")]
2828
pub struct BindingPatternConverter<'a, 'b>(pub &'b BindingPattern<'a>);
@@ -121,17 +121,15 @@ impl ESTree for CatchParameterConverter<'_, '_> {
121121
pos = uint32[(POS_OFFSET.rest) >> 2];
122122
params.push({
123123
type: 'RestElement',
124-
/* IF_TS */
125-
decorators: [],
126-
/* END_IF_TS */
124+
...(IS_TS && { decorators: [] }),
127125
argument: DESER[BindingPatternKind]( POS_OFFSET<BindingRestElement>.argument.kind ),
128-
/* IF_TS */
129-
optional: DESER[bool]( POS_OFFSET<BindingRestElement>.argument.optional ),
130-
typeAnnotation: DESER[Option<Box<TSTypeAnnotation>>](
131-
POS_OFFSET<BindingRestElement>.argument.type_annotation
132-
),
133-
value: null,
134-
/* END_IF_TS */
126+
...(IS_TS && {
127+
optional: DESER[bool]( POS_OFFSET<BindingRestElement>.argument.optional ),
128+
typeAnnotation: DESER[Option<Box<TSTypeAnnotation>>](
129+
POS_OFFSET<BindingRestElement>.argument.type_annotation
130+
),
131+
value: null,
132+
}),
135133
start: DESER[u32]( POS_OFFSET<BindingRestElement>.span.start ),
136134
end: DESER[u32]( POS_OFFSET<BindingRestElement>.span.end ),
137135
});
@@ -183,35 +181,33 @@ impl ESTree for FormalParametersRest<'_, '_> {
183181
#[estree(
184182
ts_type = "FormalParameter | TSParameterProperty",
185183
raw_deser = "
186-
/* IF_JS */
187-
DESER[BindingPatternKind](POS_OFFSET.pattern.kind)
188-
/* END_IF_JS */
189-
190-
/* IF_TS */
191-
const accessibility = DESER[Option<TSAccessibility>](POS_OFFSET.accessibility),
192-
readonly = DESER[bool](POS_OFFSET.readonly),
193-
override = DESER[bool](POS_OFFSET.override);
194184
let param;
195-
if (accessibility === null && !readonly && !override) {
196-
param = DESER[BindingPatternKind](POS_OFFSET.pattern.kind);
197-
param.decorators = DESER[Vec<Decorator>](POS_OFFSET.decorators);
198-
param.optional = DESER[bool](POS_OFFSET.pattern.optional);
199-
param.typeAnnotation = DESER[Option<Box<TSTypeAnnotation>>](POS_OFFSET.pattern.type_annotation);
185+
if (IS_TS) {
186+
const accessibility = DESER[Option<TSAccessibility>](POS_OFFSET.accessibility),
187+
readonly = DESER[bool](POS_OFFSET.readonly),
188+
override = DESER[bool](POS_OFFSET.override);
189+
if (accessibility === null && !readonly && !override) {
190+
param = DESER[BindingPatternKind](POS_OFFSET.pattern.kind);
191+
param.decorators = DESER[Vec<Decorator>](POS_OFFSET.decorators);
192+
param.optional = DESER[bool](POS_OFFSET.pattern.optional);
193+
param.typeAnnotation = DESER[Option<Box<TSTypeAnnotation>>](POS_OFFSET.pattern.type_annotation);
194+
} else {
195+
param = {
196+
type: 'TSParameterProperty',
197+
accessibility,
198+
decorators: DESER[Vec<Decorator>](POS_OFFSET.decorators),
199+
override,
200+
parameter: DESER[BindingPattern](POS_OFFSET.pattern),
201+
readonly,
202+
static: false,
203+
start: DESER[u32]( POS_OFFSET<BindingRestElement>.span.start ),
204+
end: DESER[u32]( POS_OFFSET<BindingRestElement>.span.end ),
205+
};
206+
}
200207
} else {
201-
param = {
202-
type: 'TSParameterProperty',
203-
accessibility,
204-
decorators: DESER[Vec<Decorator>](POS_OFFSET.decorators),
205-
override,
206-
parameter: DESER[BindingPattern](POS_OFFSET.pattern),
207-
readonly,
208-
static: false,
209-
start: DESER[u32]( POS_OFFSET<BindingRestElement>.span.start ),
210-
end: DESER[u32]( POS_OFFSET<BindingRestElement>.span.end ),
211-
};
208+
param = DESER[BindingPatternKind](POS_OFFSET.pattern.kind);
212209
}
213210
param
214-
/* END_IF_TS */
215211
"
216212
)]
217213
pub struct FormalParameterConverter<'a, 'b>(pub &'b FormalParameter<'a>);
@@ -255,10 +251,10 @@ impl ESTree for FormalParameterConverter<'_, '_> {
255251
ts_type = "ParamPattern[]",
256252
raw_deser = "
257253
const params = DESER[Box<FormalParameters>](POS_OFFSET.params);
258-
/* IF_TS */
259-
const thisParam = DESER[Option<Box<TSThisParameter>>](POS_OFFSET.this_param);
260-
if (thisParam !== null) params.unshift(thisParam);
261-
/* END_IF_TS */
254+
if (IS_TS) {
255+
const thisParam = DESER[Option<Box<TSThisParameter>>](POS_OFFSET.this_param);
256+
if (thisParam !== null) params.unshift(thisParam);
257+
}
262258
params
263259
"
264260
)]
@@ -411,15 +407,13 @@ impl ESTree for ArrowFunctionExpressionBody<'_> {
411407
? keyCopy
412408
: {
413409
type: 'AssignmentPattern',
414-
/* IF_TS */
415-
decorators: [],
416-
/* END_IF_TS */
410+
...(IS_TS && { decorators: [] }),
417411
left: keyCopy,
418412
right: init,
419-
/* IF_TS */
420-
optional: false,
421-
typeAnnotation: null,
422-
/* END_IF_TS */
413+
...(IS_TS && {
414+
optional: false,
415+
typeAnnotation: null,
416+
}),
423417
start: THIS.start,
424418
end: THIS.end,
425419
};

crates/oxc_ast/src/serialize/literal.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ impl ESTree for RegExpFlagsConverter<'_> {
195195
#[ast_meta]
196196
#[estree(raw_deser = r#"
197197
const tail = DESER[bool](POS_OFFSET.tail),
198-
start = DESER[u32](POS_OFFSET.span.start) /* IF_TS */ - 1 /* END_IF_TS */,
199-
end = DESER[u32](POS_OFFSET.span.end) /* IF_TS */ + 2 - tail /* END_IF_TS */,
198+
start = IS_TS ? DESER[u32](POS_OFFSET.span.start) - 1 : DESER[u32](POS_OFFSET.span.start),
199+
end = IS_TS ? DESER[u32](POS_OFFSET.span.end) + 2 - tail : DESER[u32](POS_OFFSET.span.end),
200200
value = DESER[TemplateElementValue](POS_OFFSET.value);
201201
if (value.cooked !== null && DESER[bool](POS_OFFSET.lone_surrogates)) {
202202
value.cooked = value.cooked

crates/oxc_ast/src/serialize/mod.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,31 +124,29 @@ impl Program<'_> {
124124
const body = DESER[Vec<Directive>](POS_OFFSET.directives);
125125
body.push(...DESER[Vec<Statement>](POS_OFFSET.body));
126126
127-
/* IF_JS */
128-
const start = DESER[u32](POS_OFFSET.span.start);
129-
/* END_IF_JS */
130-
131127
const end = DESER[u32](POS_OFFSET.span.end);
132128
133-
/* IF_TS */
134129
let start;
135-
if (body.length > 0) {
136-
const first = body[0];
137-
start = first.start;
138-
if (first.type === 'ExportNamedDeclaration' || first.type === 'ExportDefaultDeclaration') {
139-
const { declaration } = first;
140-
if (
141-
declaration !== null && declaration.type === 'ClassDeclaration'
142-
&& declaration.decorators.length > 0
143-
) {
144-
const decoratorStart = declaration.decorators[0].start;
145-
if (decoratorStart < start) start = decoratorStart;
130+
if (IS_TS) {
131+
if (body.length > 0) {
132+
const first = body[0];
133+
start = first.start;
134+
if (first.type === 'ExportNamedDeclaration' || first.type === 'ExportDefaultDeclaration') {
135+
const { declaration } = first;
136+
if (
137+
declaration !== null && declaration.type === 'ClassDeclaration'
138+
&& declaration.decorators.length > 0
139+
) {
140+
const decoratorStart = declaration.decorators[0].start;
141+
if (decoratorStart < start) start = decoratorStart;
142+
}
146143
}
144+
} else {
145+
start = end;
147146
}
148147
} else {
149-
start = end;
148+
start = DESER[u32](POS_OFFSET.span.start);
150149
}
151-
/* END_IF_TS */
152150
153151
const program = {
154152
type: 'Program',

napi/parser/generated/deserialize/js.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ function deserializeWith(buffer, sourceTextInput, sourceByteLenInput, preservePa
3434
function deserializeProgram(pos) {
3535
let body = deserializeVecDirective(pos + 72);
3636
body.push(...deserializeVecStatement(pos + 96));
37-
let start = deserializeU32(pos), end = deserializeU32(pos + 4);
37+
let end = deserializeU32(pos + 4), start;
38+
start = deserializeU32(pos);
3839
return {
3940
type: 'Program',
4041
body,
@@ -778,7 +779,9 @@ function deserializeFormalParameters(pos) {
778779
}
779780

780781
function deserializeFormalParameter(pos) {
781-
return deserializeBindingPatternKind(pos + 32);
782+
let param;
783+
param = deserializeBindingPatternKind(pos + 32);
784+
return param;
782785
}
783786

784787
function deserializeFunctionBody(pos) {

napi/parser/generated/deserialize/ts.js

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,11 @@ function deserializeBindingRestElement(pos) {
814814
}
815815

816816
function deserializeFunction(pos) {
817-
let params = deserializeBoxFormalParameters(pos + 56), thisParam = deserializeOptionBoxTSThisParameter(pos + 48);
818-
thisParam !== null && params.unshift(thisParam);
817+
let params = deserializeBoxFormalParameters(pos + 56);
818+
{
819+
let thisParam = deserializeOptionBoxTSThisParameter(pos + 48);
820+
thisParam !== null && params.unshift(thisParam);
821+
}
819822
return {
820823
type: deserializeFunctionType(pos + 84),
821824
id: deserializeOptionBindingIdentifier(pos + 8),
@@ -851,26 +854,28 @@ function deserializeFormalParameters(pos) {
851854
}
852855

853856
function deserializeFormalParameter(pos) {
854-
let accessibility = deserializeOptionTSAccessibility(pos + 64),
855-
readonly = deserializeBool(pos + 65),
856-
override = deserializeBool(pos + 66),
857-
param;
858-
if (accessibility === null && !readonly && !override) {
859-
param = deserializeBindingPatternKind(pos + 32);
860-
param.decorators = deserializeVecDecorator(pos + 8);
861-
param.optional = deserializeBool(pos + 56);
862-
param.typeAnnotation = deserializeOptionBoxTSTypeAnnotation(pos + 48);
863-
} else {param = {
864-
type: 'TSParameterProperty',
865-
accessibility,
866-
decorators: deserializeVecDecorator(pos + 8),
867-
override,
868-
parameter: deserializeBindingPattern(pos + 32),
869-
readonly,
870-
static: false,
871-
start: deserializeU32(pos),
872-
end: deserializeU32(pos + 4),
873-
};}
857+
let param;
858+
{
859+
let accessibility = deserializeOptionTSAccessibility(pos + 64),
860+
readonly = deserializeBool(pos + 65),
861+
override = deserializeBool(pos + 66);
862+
if (accessibility === null && !readonly && !override) {
863+
param = deserializeBindingPatternKind(pos + 32);
864+
param.decorators = deserializeVecDecorator(pos + 8);
865+
param.optional = deserializeBool(pos + 56);
866+
param.typeAnnotation = deserializeOptionBoxTSTypeAnnotation(pos + 48);
867+
} else {param = {
868+
type: 'TSParameterProperty',
869+
accessibility,
870+
decorators: deserializeVecDecorator(pos + 8),
871+
override,
872+
parameter: deserializeBindingPattern(pos + 32),
873+
readonly,
874+
static: false,
875+
start: deserializeU32(pos),
876+
end: deserializeU32(pos + 4),
877+
};}
878+
}
874879
return param;
875880
}
876881

0 commit comments

Comments
 (0)