Skip to content

Commit 0503a78

Browse files
committed
perf(napi/parser, linter/plugins): faster deserialization of raw fields (#20923)
`raw` field of `NumericLiteral`, `StringLiteral`, `BigIntLiteral`, `RegExpLiteral`, and `JSXText` are slices of source text. So in raw transfer deserializer, skip going through `deserializeStr`, which can be slow when source contains any non-ASCII characters. Instead just slice the string from the source text directly with `sourceText.slice(start, end)`. String decoding is the slowest part of raw transfer, so this should be a significant speed gain.
1 parent f9ef1bd commit 0503a78

14 files changed

Lines changed: 449 additions & 206 deletions

File tree

apps/oxlint/src-js/generated/deserialize.js

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,30 +3243,37 @@ function deserializeNullLiteral(pos) {
32433243
}
32443244

32453245
function deserializeNumericLiteral(pos) {
3246-
let start, end;
3246+
let start = deserializeU32(pos),
3247+
end = deserializeU32(pos + 4);
32473248
return {
32483249
__proto__: NodeProto,
32493250
type: "Literal",
32503251
value: deserializeF64(pos + 32),
3251-
raw: deserializeOptionStr(pos + 16),
3252-
start: (start = deserializeU32(pos)),
3253-
end: (end = deserializeU32(pos + 4)),
3252+
raw:
3253+
uint32[(pos + 16) >> 2] === 0 && uint32[(pos + 20) >> 2] === 0
3254+
? null
3255+
: sourceText.slice(start, end),
3256+
start,
3257+
end,
32543258
range: [start, end],
32553259
parent,
32563260
};
32573261
}
32583262

32593263
function deserializeStringLiteral(pos) {
3260-
let start,
3261-
end,
3264+
let start = deserializeU32(pos),
3265+
end = deserializeU32(pos + 4),
32623266
previousParent = parent,
32633267
node = (parent = {
32643268
__proto__: NodeProto,
32653269
type: "Literal",
32663270
value: null,
3267-
raw: deserializeOptionStr(pos + 32),
3268-
start: (start = deserializeU32(pos)),
3269-
end: (end = deserializeU32(pos + 4)),
3271+
raw:
3272+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
3273+
? null
3274+
: sourceText.slice(start, end),
3275+
start,
3276+
end,
32703277
range: [start, end],
32713278
parent,
32723279
}),
@@ -3279,17 +3286,20 @@ function deserializeStringLiteral(pos) {
32793286
}
32803287

32813288
function deserializeBigIntLiteral(pos) {
3282-
let start,
3283-
end,
3289+
let start = deserializeU32(pos),
3290+
end = deserializeU32(pos + 4),
32843291
previousParent = parent,
32853292
node = (parent = {
32863293
__proto__: NodeProto,
32873294
type: "Literal",
32883295
value: null,
3289-
raw: deserializeOptionStr(pos + 32),
3296+
raw:
3297+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
3298+
? null
3299+
: sourceText.slice(start, end),
32903300
bigint: null,
3291-
start: (start = deserializeU32(pos)),
3292-
end: (end = deserializeU32(pos + 4)),
3301+
start,
3302+
end,
32933303
range: [start, end],
32943304
parent,
32953305
}),
@@ -3301,17 +3311,20 @@ function deserializeBigIntLiteral(pos) {
33013311
}
33023312

33033313
function deserializeRegExpLiteral(pos) {
3304-
let start,
3305-
end,
3314+
let start = deserializeU32(pos),
3315+
end = deserializeU32(pos + 4),
33063316
previousParent = parent,
33073317
node = (parent = {
33083318
__proto__: NodeProto,
33093319
type: "Literal",
33103320
value: null,
3311-
raw: deserializeOptionStr(pos + 48),
3321+
raw:
3322+
uint32[(pos + 48) >> 2] === 0 && uint32[(pos + 52) >> 2] === 0
3323+
? null
3324+
: sourceText.slice(start, end),
33123325
regex: null,
3313-
start: (start = deserializeU32(pos)),
3314-
end: (end = deserializeU32(pos + 4)),
3326+
start,
3327+
end,
33153328
range: [start, end],
33163329
parent,
33173330
}),
@@ -3820,14 +3833,18 @@ function deserializeJSXSpreadChild(pos) {
38203833
}
38213834

38223835
function deserializeJSXText(pos) {
3823-
let start, end;
3836+
let start = deserializeU32(pos),
3837+
end = deserializeU32(pos + 4);
38243838
return {
38253839
__proto__: NodeProto,
38263840
type: "JSXText",
38273841
value: deserializeStr(pos + 16),
3828-
raw: deserializeOptionStr(pos + 32),
3829-
start: (start = deserializeU32(pos)),
3830-
end: (end = deserializeU32(pos + 4)),
3842+
raw:
3843+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
3844+
? null
3845+
: sourceText.slice(start, end),
3846+
start,
3847+
end,
38313848
range: [start, end],
38323849
parent,
38333850
};

crates/oxc_ast/src/ast/jsx.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,5 +517,6 @@ pub struct JSXText<'a> {
517517
///
518518
/// `None` when this ast node is not constructed from the parser.
519519
#[content_eq(skip)]
520+
#[estree(from_span)]
520521
pub raw: Option<Str<'a>>,
521522
}

crates/oxc_ast/src/ast/literal.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub struct NumericLiteral<'a> {
6565
///
6666
/// `None` when this ast node is not constructed from the parser.
6767
#[content_eq(skip)]
68-
#[estree(json_safe)]
68+
#[estree(json_safe, from_span)]
6969
pub raw: Option<Str<'a>>,
7070
/// The base representation used by the literal in source code
7171
#[content_eq(skip)]
@@ -95,6 +95,7 @@ pub struct StringLiteral<'a> {
9595
///
9696
/// `None` when this ast node is not constructed from the parser.
9797
#[content_eq(skip)]
98+
#[estree(from_span)]
9899
pub raw: Option<Str<'a>>,
99100

100101
/// The string value contains lone surrogates.
@@ -122,7 +123,7 @@ pub struct BigIntLiteral<'a> {
122123
pub value: Str<'a>,
123124
/// The bigint as it appears in source code
124125
#[content_eq(skip)]
125-
#[estree(json_safe)]
126+
#[estree(json_safe, from_span)]
126127
pub raw: Option<Str<'a>>,
127128
/// The base representation used by the literal in source code
128129
#[content_eq(skip)]
@@ -153,6 +154,7 @@ pub struct RegExpLiteral<'a> {
153154
///
154155
/// `None` when this ast node is not constructed from the parser.
155156
#[content_eq(skip)]
157+
#[estree(from_span)]
156158
pub raw: Option<Str<'a>>,
157159
}
158160

napi/parser/src-js/generated/deserialize/js.js

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,22 +2314,32 @@ function deserializeNullLiteral(pos) {
23142314
}
23152315

23162316
function deserializeNumericLiteral(pos) {
2317+
let start = deserializeU32(pos),
2318+
end = deserializeU32(pos + 4);
23172319
return {
23182320
type: "Literal",
23192321
value: deserializeF64(pos + 32),
2320-
raw: deserializeOptionStr(pos + 16),
2321-
start: deserializeU32(pos),
2322-
end: deserializeU32(pos + 4),
2322+
raw:
2323+
uint32[(pos + 16) >> 2] === 0 && uint32[(pos + 20) >> 2] === 0
2324+
? null
2325+
: sourceText.slice(start, end),
2326+
start,
2327+
end,
23232328
};
23242329
}
23252330

23262331
function deserializeStringLiteral(pos) {
2327-
let node = {
2332+
let start = deserializeU32(pos),
2333+
end = deserializeU32(pos + 4),
2334+
node = {
23282335
type: "Literal",
23292336
value: null,
2330-
raw: deserializeOptionStr(pos + 32),
2331-
start: deserializeU32(pos),
2332-
end: deserializeU32(pos + 4),
2337+
raw:
2338+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
2339+
? null
2340+
: sourceText.slice(start, end),
2341+
start,
2342+
end,
23332343
},
23342344
value = deserializeStr(pos + 16);
23352345
deserializeBool(pos + 12) &&
@@ -2339,13 +2349,18 @@ function deserializeStringLiteral(pos) {
23392349
}
23402350

23412351
function deserializeBigIntLiteral(pos) {
2342-
let node = {
2352+
let start = deserializeU32(pos),
2353+
end = deserializeU32(pos + 4),
2354+
node = {
23432355
type: "Literal",
23442356
value: null,
2345-
raw: deserializeOptionStr(pos + 32),
2357+
raw:
2358+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
2359+
? null
2360+
: sourceText.slice(start, end),
23462361
bigint: null,
2347-
start: deserializeU32(pos),
2348-
end: deserializeU32(pos + 4),
2362+
start,
2363+
end,
23492364
},
23502365
bigint = deserializeStr(pos + 16);
23512366
node.value = BigInt(bigint);
@@ -2354,13 +2369,18 @@ function deserializeBigIntLiteral(pos) {
23542369
}
23552370

23562371
function deserializeRegExpLiteral(pos) {
2357-
let node = {
2372+
let start = deserializeU32(pos),
2373+
end = deserializeU32(pos + 4),
2374+
node = {
23582375
type: "Literal",
23592376
value: null,
2360-
raw: deserializeOptionStr(pos + 48),
2377+
raw:
2378+
uint32[(pos + 48) >> 2] === 0 && uint32[(pos + 52) >> 2] === 0
2379+
? null
2380+
: sourceText.slice(start, end),
23612381
regex: null,
2362-
start: deserializeU32(pos),
2363-
end: deserializeU32(pos + 4),
2382+
start,
2383+
end,
23642384
},
23652385
regex = deserializeRegExp(pos + 16),
23662386
value = null;
@@ -2767,12 +2787,17 @@ function deserializeJSXSpreadChild(pos) {
27672787
}
27682788

27692789
function deserializeJSXText(pos) {
2790+
let start = deserializeU32(pos),
2791+
end = deserializeU32(pos + 4);
27702792
return {
27712793
type: "JSXText",
27722794
value: deserializeStr(pos + 16),
2773-
raw: deserializeOptionStr(pos + 32),
2774-
start: deserializeU32(pos),
2775-
end: deserializeU32(pos + 4),
2795+
raw:
2796+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
2797+
? null
2798+
: sourceText.slice(start, end),
2799+
start,
2800+
end,
27762801
};
27772802
}
27782803

napi/parser/src-js/generated/deserialize/js_parent.js

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,24 +2597,34 @@ function deserializeNullLiteral(pos) {
25972597
}
25982598

25992599
function deserializeNumericLiteral(pos) {
2600+
let start = deserializeU32(pos),
2601+
end = deserializeU32(pos + 4);
26002602
return {
26012603
type: "Literal",
26022604
value: deserializeF64(pos + 32),
2603-
raw: deserializeOptionStr(pos + 16),
2604-
start: deserializeU32(pos),
2605-
end: deserializeU32(pos + 4),
2605+
raw:
2606+
uint32[(pos + 16) >> 2] === 0 && uint32[(pos + 20) >> 2] === 0
2607+
? null
2608+
: sourceText.slice(start, end),
2609+
start,
2610+
end,
26062611
parent,
26072612
};
26082613
}
26092614

26102615
function deserializeStringLiteral(pos) {
2611-
let previousParent = parent,
2616+
let start = deserializeU32(pos),
2617+
end = deserializeU32(pos + 4),
2618+
previousParent = parent,
26122619
node = (parent = {
26132620
type: "Literal",
26142621
value: null,
2615-
raw: deserializeOptionStr(pos + 32),
2616-
start: deserializeU32(pos),
2617-
end: deserializeU32(pos + 4),
2622+
raw:
2623+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
2624+
? null
2625+
: sourceText.slice(start, end),
2626+
start,
2627+
end,
26182628
parent,
26192629
}),
26202630
value = deserializeStr(pos + 16);
@@ -2626,14 +2636,19 @@ function deserializeStringLiteral(pos) {
26262636
}
26272637

26282638
function deserializeBigIntLiteral(pos) {
2629-
let previousParent = parent,
2639+
let start = deserializeU32(pos),
2640+
end = deserializeU32(pos + 4),
2641+
previousParent = parent,
26302642
node = (parent = {
26312643
type: "Literal",
26322644
value: null,
2633-
raw: deserializeOptionStr(pos + 32),
2645+
raw:
2646+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
2647+
? null
2648+
: sourceText.slice(start, end),
26342649
bigint: null,
2635-
start: deserializeU32(pos),
2636-
end: deserializeU32(pos + 4),
2650+
start,
2651+
end,
26372652
parent,
26382653
}),
26392654
bigint = deserializeStr(pos + 16);
@@ -2644,14 +2659,19 @@ function deserializeBigIntLiteral(pos) {
26442659
}
26452660

26462661
function deserializeRegExpLiteral(pos) {
2647-
let previousParent = parent,
2662+
let start = deserializeU32(pos),
2663+
end = deserializeU32(pos + 4),
2664+
previousParent = parent,
26482665
node = (parent = {
26492666
type: "Literal",
26502667
value: null,
2651-
raw: deserializeOptionStr(pos + 48),
2668+
raw:
2669+
uint32[(pos + 48) >> 2] === 0 && uint32[(pos + 52) >> 2] === 0
2670+
? null
2671+
: sourceText.slice(start, end),
26522672
regex: null,
2653-
start: deserializeU32(pos),
2654-
end: deserializeU32(pos + 4),
2673+
start,
2674+
end,
26552675
parent,
26562676
}),
26572677
regex = deserializeRegExp(pos + 16),
@@ -3100,12 +3120,17 @@ function deserializeJSXSpreadChild(pos) {
31003120
}
31013121

31023122
function deserializeJSXText(pos) {
3123+
let start = deserializeU32(pos),
3124+
end = deserializeU32(pos + 4);
31033125
return {
31043126
type: "JSXText",
31053127
value: deserializeStr(pos + 16),
3106-
raw: deserializeOptionStr(pos + 32),
3107-
start: deserializeU32(pos),
3108-
end: deserializeU32(pos + 4),
3128+
raw:
3129+
uint32[(pos + 32) >> 2] === 0 && uint32[(pos + 36) >> 2] === 0
3130+
? null
3131+
: sourceText.slice(start, end),
3132+
start,
3133+
end,
31093134
parent,
31103135
};
31113136
}

0 commit comments

Comments
 (0)