Skip to content

Commit 58ba6d6

Browse files
lilnasyautofix-ci[bot]overlookmotel
authored
perf(linter/plugins): lazy deserialize comments array (#14637)
Part of #14564. Deserialize `program.comments` lazily upon first access, instead of eagerly, on assumption that most JS plugins won't access comments. `deserializeWith` cleans up the buffer once deserializing AST is complete, so we keep a local copy of the buffer in scope of the `comments` getter, and restore it when the getter is triggered. Buffers are reused, so the `if (localAstId !== astId)` check is required to make sure the AST in the buffer is same AST i.e. that the getter isn't accessed *after* the file has completed linting. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
1 parent 5858641 commit 58ba6d6

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Auto-generated code, DO NOT EDIT DIRECTLY!
22
// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`.
33

4-
let uint8, uint32, float64, sourceText, sourceIsAscii, sourceByteLen, parent = null, getLoc;
4+
let uint8, uint32, float64, sourceText, sourceIsAscii, sourceByteLen, astId = 0, parent = null, getLoc;
55

66
const textDecoder = new TextDecoder('utf-8', { ignoreBOM: true }),
77
decodeStr = textDecoder.decode.bind(textDecoder),
@@ -38,13 +38,35 @@ function deserializeWith(buffer, sourceTextInput, sourceByteLenInput, getLocInpu
3838

3939
function deserializeProgram(pos) {
4040
let end = deserializeU32(pos + 4),
41+
refUint32 = uint32,
42+
refUint8 = uint8,
43+
refSourceText = sourceText,
44+
localAstId = ++astId,
4145
program = parent = {
4246
__proto__: NodeProto,
4347
type: 'Program',
4448
body: null,
4549
sourceType: deserializeModuleKind(pos + 125),
4650
hashbang: null,
47-
comments: deserializeVecComment(pos + 24),
51+
get comments() {
52+
if (localAstId !== astId) throw Error('Comments are only accessible while linting the file');
53+
// Restore buffers
54+
uint32 = refUint32;
55+
uint8 = refUint8;
56+
sourceText = refSourceText;
57+
// Deserialize the comments
58+
let comments = deserializeVecComment(pos + 24);
59+
// Drop the references
60+
refUint32 =
61+
refUint8 =
62+
refSourceText =
63+
uint32 =
64+
uint8 =
65+
sourceText =
66+
void 0;
67+
Object.defineProperty(this, 'comments', { value: comments });
68+
return comments;
69+
},
4870
start: 0,
4971
end,
5072
range: [0, end],

crates/oxc_ast/src/serialize/mod.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,36 @@ impl Program<'_> {
124124
const start = IS_TS ? 0 : DESER[u32](POS_OFFSET.span.start),
125125
end = DESER[u32](POS_OFFSET.span.end);
126126
127+
128+
/* IF COMMENTS */
129+
// Buffers will be cleaned up after the main program is deserialized.
130+
// We hold references here in case the comments need to be later accessed.
131+
let refUint32 = uint32;
132+
let refUint8 = uint8;
133+
let refSourceText = sourceText;
134+
const localAstId = ++astId;
135+
/* END_IF */
136+
127137
const program = parent = {
128138
type: 'Program',
129139
body: null,
130140
sourceType: DESER[ModuleKind](POS_OFFSET.source_type.module_kind),
131141
hashbang: null,
132-
...(COMMENTS && { comments: DESER[Vec<Comment>](POS_OFFSET.comments) }),
142+
/* IF COMMENTS */
143+
get comments() {
144+
if (localAstId !== astId) throw new Error('Comments are only accessible while linting the file');
145+
// Restore buffers
146+
uint32 = refUint32;
147+
uint8 = refUint8;
148+
sourceText = refSourceText;
149+
// Deserialize the comments
150+
const comments = DESER[Vec<Comment>](POS_OFFSET.comments);
151+
// Drop the references
152+
refUint32 = refUint8 = refSourceText = uint32 = uint8 = sourceText = undefined;
153+
Object.defineProperty(this, 'comments', { value: comments });
154+
return comments;
155+
},
156+
/* END_IF */
133157
start,
134158
end,
135159
...(RANGE && { range: [start, end] }),

tasks/ast_tools/src/generators/raw_transfer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ fn generate_deserializers(
136136
let mut code = format!("
137137
let uint8, uint32, float64, sourceText, sourceIsAscii, sourceByteLen;
138138
139+
let astId = 0;
139140
let parent = null;
140141
let getLoc;
141142

0 commit comments

Comments
 (0)