Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6f782ba

Browse files
committed
refactor(linter/plugins): add parse function
1 parent99e6723 commit6f782ba

File tree

10 files changed

+380
-4
lines changed

10 files changed

+380
-4
lines changed

‎Cargo.lock‎

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎apps/oxlint/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ doctest = false
2828

2929
[dependencies]
3030
oxc_allocator = {workspace =true,features = ["fixed_size"] }
31+
oxc_ast_visit = {workspace =true,features = ["serialize"] }
3132
oxc_diagnostics = {workspace =true }
3233
oxc_language_server = {workspace =true,features = ["linter"] }
3334
oxc_linter = {workspace =true }
35+
oxc_parser = {workspace =true }
36+
oxc_semantic = {workspace =true }
3437
oxc_span = {workspace =true }
3538

3639
bpaf = {workspace =true,features = ["autocomplete","bright-color","derive"] }

‎apps/oxlint/src-js/bindings.d.ts‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
/* auto-generated by NAPI-RS */
22
/* eslint-disable */
3+
/**
4+
* Get offset within a `Uint8Array` which is aligned on `BUFFER_ALIGN`.
5+
*
6+
* Does not check that the offset is within bounds of `buffer`.
7+
* To ensure it always is, provide a `Uint8Array` of at least `BUFFER_SIZE + BUFFER_ALIGN` bytes.
8+
*/
9+
exportdeclarefunctiongetBufferOffset(buffer:Uint8Array):number
10+
311
/** JS callback to lint a file. */
412
exporttypeJsLintFileCb=
513
((arg0:string,arg1:number,arg2:Uint8Array|undefined|null,arg3:Array<number>,arg4:string)=>string)
@@ -19,3 +27,34 @@ export type JsLoadPluginCb =
1927
* Returns `true` if linting succeeded without errors, `false` otherwise.
2028
*/
2129
exportdeclarefunctionlint(args:Array<string>,loadPlugin:JsLoadPluginCb,lintFile:JsLintFileCb):Promise<boolean>
30+
31+
/**
32+
* Parse AST into provided `Uint8Array` buffer, synchronously.
33+
*
34+
* Source text must be written into the start of the buffer, and its length (in UTF-8 bytes)
35+
* provided as `source_len`.
36+
*
37+
* This function will parse the source, and write the AST into the buffer, starting at the end.
38+
*
39+
* It also writes to the very end of the buffer the offset of `Program` within the buffer.
40+
*
41+
* Caller can deserialize data from the buffer on JS side.
42+
*
43+
* # SAFETY
44+
*
45+
* Caller must ensure:
46+
* * Source text is written into start of the buffer.
47+
* * Source text's UTF-8 byte length is `source_len`.
48+
* * The 1st `source_len` bytes of the buffer comprises a valid UTF-8 string.
49+
*
50+
* If source text is originally a JS string on JS side, and converted to a buffer with
51+
* `Buffer.from(str)` or `new TextEncoder().encode(str)`, this guarantees it's valid UTF-8.
52+
*
53+
* # Panics
54+
*
55+
* Panics if source text is too long, or AST takes more memory than is available in the buffer.
56+
*/
57+
exportdeclarefunctionparseRawSync(filename:string,buffer:Uint8Array,sourceLen:number):void
58+
59+
/** Returns `true` if raw transfer is supported on this platform. */
60+
exportdeclarefunctionrawTransferSupported():boolean

‎apps/oxlint/src-js/bindings.js‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,5 +575,8 @@ if (!nativeBinding) {
575575
thrownewError(`Failed to load native binding`)
576576
}
577577

578-
const{ lint}=nativeBinding
578+
const{ getBufferOffset, lint, parseRawSync, rawTransferSupported}=nativeBinding
579+
export{getBufferOffset}
579580
export{lint}
581+
export{parseRawSync}
582+
export{rawTransferSupported}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import{
2+
getBufferOffset,
3+
rawTransferSupportedasrawTransferSupportedBinding,
4+
parseRawSync,
5+
}from"../bindings.js";
6+
import{debugAssert,debugAssertIsNonNull}from"../utils/asserts.js";
7+
import{buffers}from"../plugins/lint.js";
8+
import{BUFFER_SIZE,BUFFER_ALIGN,DATA_POINTER_POS_32}from"../generated/constants.js";
9+
10+
importtype{BufferWithArrays}from"../plugins/types.js";
11+
12+
// Size array buffer for raw transfer
13+
constARRAY_BUFFER_SIZE=BUFFER_SIZE+BUFFER_ALIGN;
14+
15+
// 1 GiB
16+
constONE_GIB=1<<30;
17+
18+
// Text encoder for encoding source text into buffer
19+
consttextEncoder=newTextEncoder();
20+
21+
// Buffer for raw transfer
22+
letbuffer:BufferWithArrays|null=null;
23+
24+
// Whether raw transfer is supported
25+
letrawTransferIsSupported:boolean|null=null;
26+
27+
/**
28+
* Parser source text into buffer.
29+
*@param path - Path of file to parse
30+
*@param sourceText - Source text to parse
31+
*@throws {Error} If raw transfer is not supported on this platform, or parsing failed
32+
*/
33+
exportfunctionparse(path:string,sourceText:string){
34+
if(!rawTransferSupported()){
35+
thrownewError(
36+
"`RuleTester` is not supported on 32-bit or big-endian systems, versions of NodeJS prior to v22.0.0, "+
37+
"versions of Deno prior to v2.0.0, or other runtimes",
38+
);
39+
}
40+
41+
// Initialize buffer, if not already
42+
if(buffer===null)initBuffer();
43+
debugAssertIsNonNull(buffer);
44+
45+
// Write source into start of buffer.
46+
// `TextEncoder` cannot write into a `Uint8Array` larger than 1 GiB,
47+
// so create a view into buffer of this size to write into.
48+
constsourceBuffer=newUint8Array(buffer.buffer,buffer.byteOffset,ONE_GIB);
49+
const{ read,written:sourceByteLen}=textEncoder.encodeInto(sourceText,sourceBuffer);
50+
if(read!==sourceText.length)thrownewError("Failed to write source text into buffer");
51+
52+
// Parse into buffer
53+
parseRawSync(path,buffer,sourceByteLen);
54+
55+
// Check parsing succeeded.
56+
// 0 is used as sentinel value to indicate parsing failed.
57+
// TODO: Get parsing error details from Rust to display nicely.
58+
constprogramOffset=buffer.uint32[DATA_POINTER_POS_32];
59+
if(programOffset===0)thrownewError("Parsing failed");
60+
}
61+
62+
/**
63+
* Create a `Uint8Array` which is 2 GiB in size, with its start aligned on 4 GiB.
64+
*
65+
* Store it in `buffer`, and also in `buffers` array, so it's accessible to `lintFileImpl` by passing `0`as `bufferId`.
66+
*
67+
* Achieve this by creating a 6 GiB `ArrayBuffer`, getting the offset within it that's aligned to 4 GiB,
68+
* chopping off that number of bytes from the start, and shortening to 2 GiB.
69+
*
70+
* It's always possible to obtain a 2 GiB slice aligned on 4 GiB within a 6 GiB buffer,
71+
* no matter how the 6 GiB buffer is aligned.
72+
*
73+
* Note: On systems with virtual memory, this only consumes 6 GiB of *virtual* memory.
74+
* It does not consume physical memory until data is actually written to the `Uint8Array`.
75+
* Physical memory consumed corresponds to the quantity of data actually written.
76+
*/
77+
exportfunctioninitBuffer(){
78+
// Create buffer
79+
constarrayBuffer=newArrayBuffer(ARRAY_BUFFER_SIZE);
80+
constoffset=getBufferOffset(newUint8Array(arrayBuffer));
81+
buffer=newUint8Array(arrayBuffer,offset,BUFFER_SIZE)asBufferWithArrays;
82+
buffer.uint32=newUint32Array(arrayBuffer,offset,BUFFER_SIZE/4);
83+
buffer.float64=newFloat64Array(arrayBuffer,offset,BUFFER_SIZE/8);
84+
85+
// Store in `buffers`, at index 0
86+
debugAssert(buffers.length===0);
87+
buffers.push(buffer);
88+
}
89+
90+
/**
91+
* Returns `true` if raw transfer is supported.
92+
*
93+
* Raw transfer is only supported on 64-bit little-endian systems,
94+
* and NodeJS >= v22.0.0 or Deno >= v2.0.0.
95+
*
96+
* Versions of NodeJS prior to v22.0.0 do not support creating an `ArrayBuffer` larger than 4 GiB.
97+
* Bun (as at v1.2.4) also does not support creating an `ArrayBuffer` larger than 4 GiB.
98+
* Support on Deno v1 is unknown and it's EOL, so treating Deno before v2.0.0 as unsupported.
99+
*
100+
* No easy way to determining pointer width (64 bit or 32 bit) in JS,
101+
* so call a function on Rust side to find out.
102+
*
103+
*@returns {boolean} - `true` if raw transfer is supported on this platform
104+
*/
105+
functionrawTransferSupported(){
106+
if(rawTransferIsSupported===null){
107+
rawTransferIsSupported=rawTransferRuntimeSupported()&&rawTransferSupportedBinding();
108+
}
109+
returnrawTransferIsSupported;
110+
}
111+
112+
declare global{
113+
varBun:unknown;
114+
varDeno:
115+
|{
116+
version:{
117+
deno:string;
118+
};
119+
}
120+
|undefined;
121+
}
122+
123+
// Checks copied from:
124+
// https://github.com/unjs/std-env/blob/ab15595debec9e9115a9c1d31bc7597a8e71dbfd/src/runtimes.ts
125+
// MIT license: https://github.com/unjs/std-env/blob/ab15595debec9e9115a9c1d31bc7597a8e71dbfd/LICENCE
126+
functionrawTransferRuntimeSupported(){
127+
letglobal;
128+
try{
129+
global=globalThis;
130+
}catch{
131+
returnfalse;
132+
}
133+
134+
constisBun=!!global.Bun||!!global.process?.versions?.bun;
135+
if(isBun)returnfalse;
136+
137+
constisDeno=!!global.Deno;
138+
if(isDeno){
139+
constmatch=Deno!.version?.deno?.match(/^(\d+)\./);
140+
return!!match&&+match[1]>=2;
141+
}
142+
143+
constisNode=global.process?.release?.name==="node";
144+
if(!isNode)returnfalse;
145+
146+
constmatch=process.version?.match(/^v(\d+)\./);
147+
return!!match&&+match[1]>=22;
148+
}

‎apps/oxlint/src-js/plugins/lint.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import type { AfterHook, BufferWithArrays } from "./types.ts";
2929
// All buffers sent from Rust are stored in this array, indexed by `bufferId` (also sent from Rust).
3030
// Buffers are only added to this array, never removed, so no buffers will be garbage collected
3131
// until the process exits.
32-
constbuffers:(BufferWithArrays|null)[]=[];
32+
exportconstbuffers:(BufferWithArrays|null)[]=[];
3333

3434
// Array of `after` hooks to run after traversal. This array reused for every file.
3535
constafterHooks:AfterHook[]=[];

‎apps/oxlint/src/js_plugins/mod.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
mod external_linter;
22
mod raw_fs;
33

4+
#[cfg(all(target_pointer_width ="64", target_endian ="little"))]
5+
pubmod parse;
6+
47
pubuse external_linter::create_external_linter;
58
pubuse raw_fs::RawTransferFileSystem;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp