goscript 0.0.81 → 0.0.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/gs/builtin/type.js +1 -1
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/os/dir.gs.js +41 -27
- package/dist/gs/os/dir.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.js +1 -2
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/file_constants_js.gs.js +71 -7
- package/dist/gs/os/file_constants_js.gs.js.map +1 -1
- package/dist/gs/os/file_js.gs.js +168 -24
- package/dist/gs/os/file_js.gs.js.map +1 -1
- package/dist/gs/os/file_posix_js.gs.js +75 -11
- package/dist/gs/os/file_posix_js.gs.js.map +1 -1
- package/dist/gs/os/file_unix_js.gs.d.ts +3 -3
- package/dist/gs/os/file_unix_js.gs.js +218 -21
- package/dist/gs/os/file_unix_js.gs.js.map +1 -1
- package/dist/gs/os/getwd_js.gs.js +19 -6
- package/dist/gs/os/getwd_js.gs.js.map +1 -1
- package/dist/gs/os/path.gs.js +3 -3
- package/dist/gs/os/path.gs.js.map +1 -1
- package/dist/gs/os/pidfd_js.gs.js +0 -3
- package/dist/gs/os/pidfd_js.gs.js.map +1 -1
- package/dist/gs/os/proc.gs.js +6 -3
- package/dist/gs/os/proc.gs.js.map +1 -1
- package/dist/gs/os/proc_js.gs.js +10 -5
- package/dist/gs/os/proc_js.gs.js.map +1 -1
- package/dist/gs/os/rawconn_js.gs.d.ts +6 -3
- package/dist/gs/os/rawconn_js.gs.js +16 -10
- package/dist/gs/os/rawconn_js.gs.js.map +1 -1
- package/dist/gs/os/removeall_js.gs.js +2 -4
- package/dist/gs/os/removeall_js.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.d.ts +4 -1
- package/dist/gs/os/root_js.gs.js +90 -40
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/root_noopenat.gs.js +13 -16
- package/dist/gs/os/root_noopenat.gs.js.map +1 -1
- package/dist/gs/os/stat_js.gs.js +40 -4
- package/dist/gs/os/stat_js.gs.js.map +1 -1
- package/dist/gs/os/stat_unix_js.gs.d.ts +1 -1
- package/dist/gs/os/stat_unix_js.gs.js +5 -10
- package/dist/gs/os/stat_unix_js.gs.js.map +1 -1
- package/dist/gs/os/tempfile.gs.d.ts +1 -1
- package/dist/gs/os/tempfile.gs.js +24 -7
- package/dist/gs/os/tempfile.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +78 -1
- package/dist/gs/os/types_js.gs.js +464 -23
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/go.mod +2 -0
- package/gs/builtin/type.ts +1 -1
- package/gs/os/dir.gs.ts +40 -28
- package/gs/os/exec.gs.ts +2 -4
- package/gs/os/exec_posix.gs.ts +1 -2
- package/gs/os/file_constants_js.gs.ts +70 -8
- package/gs/os/file_js.gs.ts +156 -26
- package/gs/os/file_posix_js.gs.ts +69 -13
- package/gs/os/file_unix_js.gs.ts +212 -24
- package/gs/os/file_unix_js.test.ts +131 -0
- package/gs/os/getwd_js.gs.ts +18 -8
- package/gs/os/path.gs.ts +3 -4
- package/gs/os/pidfd_js.gs.ts +3 -8
- package/gs/os/proc.gs.ts +6 -4
- package/gs/os/proc_js.gs.ts +11 -8
- package/gs/os/rawconn_js.gs.ts +22 -14
- package/gs/os/removeall_js.gs.ts +3 -6
- package/gs/os/root_js.gs.ts +94 -42
- package/gs/os/root_noopenat.gs.ts +13 -20
- package/gs/os/stat_js.gs.ts +37 -6
- package/gs/os/stat_unix_js.gs.ts +6 -13
- package/gs/os/tempfile.gs.ts +27 -9
- package/gs/os/types_js.gs.ts +528 -26
- package/package.json +1 -1
package/gs/os/file_unix_js.gs.ts
CHANGED
|
@@ -1,64 +1,238 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
2
|
import { ErrUnimplemented } from "./error.gs.js";
|
|
3
|
-
import { File } from "./types_js.gs.js";
|
|
3
|
+
import { createFileInfo, createHostFile, File, getDeno, getEnv, getNodeFS, getPlatform, newHostError } from "./types_js.gs.js";
|
|
4
|
+
import { O_APPEND, O_CREATE, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY } from "./file_constants_js.gs.js";
|
|
5
|
+
import { FileInfoToDirEntry } from "@goscript/io/fs/readdir.js"
|
|
4
6
|
|
|
5
7
|
import * as fs from "@goscript/io/fs/index.js"
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
function getDevNullPath(): string {
|
|
10
|
+
return getPlatform() === "win32" ? "NUL" : "/dev/null"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getTempDirPath(): string {
|
|
14
|
+
for (const key of ["TMPDIR", "TEMP", "TMP"]) {
|
|
15
|
+
const value = getEnv(key)
|
|
16
|
+
if (value !== "") {
|
|
17
|
+
return value
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return getPlatform() === "win32" ? "." : "/tmp"
|
|
21
|
+
}
|
|
9
22
|
|
|
10
|
-
|
|
11
|
-
|
|
23
|
+
function openOptionsFromFlags(flag: number): {
|
|
24
|
+
append: boolean
|
|
25
|
+
create: boolean
|
|
26
|
+
createNew: boolean
|
|
27
|
+
read: boolean
|
|
28
|
+
truncate: boolean
|
|
29
|
+
write: boolean
|
|
30
|
+
} {
|
|
31
|
+
const readWrite = (flag & O_RDWR) !== 0
|
|
32
|
+
const writeOnly = !readWrite && (flag & O_WRONLY) !== 0
|
|
33
|
+
const write = readWrite || writeOnly
|
|
34
|
+
const read = readWrite || !writeOnly
|
|
35
|
+
return {
|
|
36
|
+
append: (flag & O_APPEND) !== 0,
|
|
37
|
+
create: (flag & O_CREATE) !== 0,
|
|
38
|
+
createNew: (flag & O_CREATE) !== 0 && (flag & O_EXCL) !== 0,
|
|
39
|
+
read,
|
|
40
|
+
truncate: (flag & O_TRUNC) !== 0,
|
|
41
|
+
write,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
12
44
|
|
|
13
|
-
//
|
|
14
|
-
export const
|
|
15
|
-
export const Stdout: File | null = null
|
|
16
|
-
export const Stderr: File | null = null
|
|
45
|
+
// Device null path for the host platform.
|
|
46
|
+
export const DevNull = getDevNullPath()
|
|
17
47
|
|
|
18
|
-
|
|
48
|
+
const standardInputFD = 0
|
|
49
|
+
const standardOutputFD = 1
|
|
50
|
+
const standardErrorFD = 2
|
|
51
|
+
|
|
52
|
+
// Stdin, Stdout, and Stderr expose the host process standard streams.
|
|
53
|
+
export const Stdin: File | null = NewFile(standardInputFD, "/dev/stdin")
|
|
54
|
+
export const Stdout: File | null = NewFile(standardOutputFD, "/dev/stdout")
|
|
55
|
+
export const Stderr: File | null = NewFile(standardErrorFD, "/dev/stderr")
|
|
56
|
+
|
|
57
|
+
// NewFile creates a File from a file descriptor.
|
|
19
58
|
export function NewFile(fd: number, name: string): File | null {
|
|
20
|
-
|
|
59
|
+
if (!Number.isInteger(fd) || fd < 0) {
|
|
60
|
+
return null
|
|
61
|
+
}
|
|
62
|
+
return createHostFile(name, fd)
|
|
21
63
|
}
|
|
22
64
|
|
|
23
|
-
// File operations that need to be stubbed
|
|
24
65
|
export function Remove(name: string): $.GoError {
|
|
66
|
+
const denoObj = getDeno()
|
|
67
|
+
if (denoObj?.removeSync) {
|
|
68
|
+
try {
|
|
69
|
+
denoObj.removeSync(name)
|
|
70
|
+
return null
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return newHostError(err)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const nodeFS = getNodeFS()
|
|
76
|
+
if (nodeFS?.rmSync) {
|
|
77
|
+
try {
|
|
78
|
+
nodeFS.rmSync(name)
|
|
79
|
+
return null
|
|
80
|
+
} catch (err) {
|
|
81
|
+
return newHostError(err)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (nodeFS?.unlinkSync) {
|
|
85
|
+
try {
|
|
86
|
+
nodeFS.unlinkSync(name)
|
|
87
|
+
return null
|
|
88
|
+
} catch (err) {
|
|
89
|
+
return newHostError(err)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
25
92
|
return ErrUnimplemented
|
|
26
93
|
}
|
|
27
94
|
|
|
28
95
|
export function Link(oldname: string, newname: string): $.GoError {
|
|
96
|
+
const denoObj = getDeno()
|
|
97
|
+
if (denoObj?.linkSync) {
|
|
98
|
+
try {
|
|
99
|
+
denoObj.linkSync(oldname, newname)
|
|
100
|
+
return null
|
|
101
|
+
} catch (err) {
|
|
102
|
+
return newHostError(err)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const nodeFS = getNodeFS()
|
|
106
|
+
if (nodeFS?.linkSync) {
|
|
107
|
+
try {
|
|
108
|
+
nodeFS.linkSync(oldname, newname)
|
|
109
|
+
return null
|
|
110
|
+
} catch (err) {
|
|
111
|
+
return newHostError(err)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
29
114
|
return ErrUnimplemented
|
|
30
115
|
}
|
|
31
116
|
|
|
32
117
|
export function Symlink(oldname: string, newname: string): $.GoError {
|
|
118
|
+
const denoObj = getDeno()
|
|
119
|
+
if (denoObj?.symlinkSync) {
|
|
120
|
+
try {
|
|
121
|
+
denoObj.symlinkSync(oldname, newname)
|
|
122
|
+
return null
|
|
123
|
+
} catch (err) {
|
|
124
|
+
return newHostError(err)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const nodeFS = getNodeFS()
|
|
128
|
+
if (nodeFS?.symlinkSync) {
|
|
129
|
+
try {
|
|
130
|
+
nodeFS.symlinkSync(oldname, newname)
|
|
131
|
+
return null
|
|
132
|
+
} catch (err) {
|
|
133
|
+
return newHostError(err)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
33
136
|
return ErrUnimplemented
|
|
34
137
|
}
|
|
35
138
|
|
|
36
139
|
export function Truncate(name: string, size: number): $.GoError {
|
|
140
|
+
const denoObj = getDeno()
|
|
141
|
+
if (denoObj?.truncateSync) {
|
|
142
|
+
try {
|
|
143
|
+
denoObj.truncateSync(name, size)
|
|
144
|
+
return null
|
|
145
|
+
} catch (err) {
|
|
146
|
+
return newHostError(err)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const nodeFS = getNodeFS()
|
|
150
|
+
if (nodeFS?.truncateSync) {
|
|
151
|
+
try {
|
|
152
|
+
nodeFS.truncateSync(name, size)
|
|
153
|
+
return null
|
|
154
|
+
} catch (err) {
|
|
155
|
+
return newHostError(err)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
37
158
|
return ErrUnimplemented
|
|
38
159
|
}
|
|
39
160
|
|
|
40
|
-
// Internal stub functions that may be referenced by other files
|
|
41
161
|
export function rename(oldname: string, newname: string): $.GoError {
|
|
162
|
+
const denoObj = getDeno()
|
|
163
|
+
if (denoObj?.renameSync) {
|
|
164
|
+
try {
|
|
165
|
+
denoObj.renameSync(oldname, newname)
|
|
166
|
+
return null
|
|
167
|
+
} catch (err) {
|
|
168
|
+
return newHostError(err)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const nodeFS = getNodeFS()
|
|
172
|
+
if (nodeFS?.renameSync) {
|
|
173
|
+
try {
|
|
174
|
+
nodeFS.renameSync(oldname, newname)
|
|
175
|
+
return null
|
|
176
|
+
} catch (err) {
|
|
177
|
+
return newHostError(err)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
42
180
|
return ErrUnimplemented
|
|
43
181
|
}
|
|
44
182
|
|
|
45
183
|
export function openFileNolog(name: string, flag: number, perm: number): [File | null, $.GoError] {
|
|
184
|
+
const denoObj = getDeno()
|
|
185
|
+
if (denoObj?.openSync) {
|
|
186
|
+
try {
|
|
187
|
+
const handle = denoObj.openSync(name, {
|
|
188
|
+
...openOptionsFromFlags(flag),
|
|
189
|
+
mode: perm,
|
|
190
|
+
})
|
|
191
|
+
return [createHostFile(name, handle?.rid ?? -1, handle), null]
|
|
192
|
+
} catch (err) {
|
|
193
|
+
return [null, newHostError(err)]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const nodeFS = getNodeFS()
|
|
197
|
+
if (nodeFS?.openSync) {
|
|
198
|
+
try {
|
|
199
|
+
const fd = nodeFS.openSync(name, flag, perm)
|
|
200
|
+
return [createHostFile(name, fd), null]
|
|
201
|
+
} catch (err) {
|
|
202
|
+
return [null, newHostError(err)]
|
|
203
|
+
}
|
|
204
|
+
}
|
|
46
205
|
return [null, ErrUnimplemented]
|
|
47
206
|
}
|
|
48
207
|
|
|
49
208
|
export function openDirNolog(name: string): [File | null, $.GoError] {
|
|
50
|
-
return
|
|
209
|
+
return openFileNolog(name, O_RDONLY, 0)
|
|
51
210
|
}
|
|
52
211
|
|
|
53
212
|
export function tempDir(): string {
|
|
54
|
-
return
|
|
213
|
+
return getTempDirPath()
|
|
55
214
|
}
|
|
56
215
|
|
|
57
216
|
export function readlink(name: string): [string, $.GoError] {
|
|
217
|
+
const denoObj = getDeno()
|
|
218
|
+
if (denoObj?.readLinkSync) {
|
|
219
|
+
try {
|
|
220
|
+
return [denoObj.readLinkSync(name), null]
|
|
221
|
+
} catch (err) {
|
|
222
|
+
return ["", newHostError(err)]
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const nodeFS = getNodeFS()
|
|
226
|
+
if (nodeFS?.readlinkSync) {
|
|
227
|
+
try {
|
|
228
|
+
return [nodeFS.readlinkSync(name), null]
|
|
229
|
+
} catch (err) {
|
|
230
|
+
return ["", newHostError(err)]
|
|
231
|
+
}
|
|
232
|
+
}
|
|
58
233
|
return ["", ErrUnimplemented]
|
|
59
234
|
}
|
|
60
235
|
|
|
61
|
-
// File class methods that need to be stubbed for unix compatibility
|
|
62
236
|
export function fixLongPath(path: string): string {
|
|
63
237
|
return path
|
|
64
238
|
}
|
|
@@ -71,24 +245,38 @@ export function epipecheck(file: File | null, e: $.GoError): void {
|
|
|
71
245
|
// No-op in JavaScript
|
|
72
246
|
}
|
|
73
247
|
|
|
74
|
-
// dirInfo stub for compatibility
|
|
75
248
|
export interface dirInfo {
|
|
76
249
|
close(): void
|
|
77
250
|
}
|
|
78
251
|
|
|
79
|
-
// Network file creation stub
|
|
80
252
|
export function net_newUnixFile(fd: number, name: string): File | null {
|
|
81
|
-
return
|
|
253
|
+
return NewFile(fd, name)
|
|
82
254
|
}
|
|
83
255
|
|
|
84
256
|
// File kind enum for compatibility
|
|
85
257
|
export type newFileKind = number
|
|
86
258
|
|
|
87
|
-
export function newFile(fd: number, name: string,
|
|
88
|
-
return
|
|
259
|
+
export function newFile(fd: number, name: string, _kind: newFileKind, _nonBlocking: boolean): File | null {
|
|
260
|
+
return NewFile(fd, name)
|
|
89
261
|
}
|
|
90
262
|
|
|
91
|
-
|
|
92
|
-
|
|
263
|
+
export function newUnixDirent(parent: string, name: string, _typ: number): [fs.DirEntry | null, $.GoError] {
|
|
264
|
+
const fullName = parent === "" || parent === "." ? name : parent.replace(/\/+$/, "") + "/" + name
|
|
265
|
+
const denoObj = getDeno()
|
|
266
|
+
if (denoObj?.lstatSync) {
|
|
267
|
+
try {
|
|
268
|
+
return [FileInfoToDirEntry(createFileInfo(name, denoObj.lstatSync(fullName))), null]
|
|
269
|
+
} catch (err) {
|
|
270
|
+
return [null, newHostError(err)]
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const nodeFS = getNodeFS()
|
|
274
|
+
if (nodeFS?.lstatSync) {
|
|
275
|
+
try {
|
|
276
|
+
return [FileInfoToDirEntry(createFileInfo(name, nodeFS.lstatSync(fullName))), null]
|
|
277
|
+
} catch (err) {
|
|
278
|
+
return [null, newHostError(err)]
|
|
279
|
+
}
|
|
280
|
+
}
|
|
93
281
|
return [null, ErrUnimplemented]
|
|
94
|
-
}
|
|
282
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import * as io from '@goscript/io/index.js'
|
|
4
|
+
|
|
5
|
+
import { NewFile, Stderr, Stdin, Stdout } from './file_unix_js.gs.js'
|
|
6
|
+
import { ErrClosed } from './error.gs.js'
|
|
7
|
+
|
|
8
|
+
const originalDeno = (globalThis as any).Deno
|
|
9
|
+
const originalProcess = (globalThis as any).process
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
if (originalDeno === undefined) {
|
|
13
|
+
delete (globalThis as any).Deno
|
|
14
|
+
} else {
|
|
15
|
+
;(globalThis as any).Deno = originalDeno
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (originalProcess === undefined) {
|
|
19
|
+
delete (globalThis as any).process
|
|
20
|
+
} else {
|
|
21
|
+
;(globalThis as any).process = originalProcess
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('os stdio', () => {
|
|
26
|
+
it('exports standard file descriptors', () => {
|
|
27
|
+
expect(Stdin).not.toBeNull()
|
|
28
|
+
expect(Stdout).not.toBeNull()
|
|
29
|
+
expect(Stderr).not.toBeNull()
|
|
30
|
+
expect(Stdin!.Fd()).toBe(0)
|
|
31
|
+
expect(Stdout!.Fd()).toBe(1)
|
|
32
|
+
expect(Stderr!.Fd()).toBe(2)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('uses Deno sync stdio when available', () => {
|
|
36
|
+
const stdoutWriteSync = vi.fn((buffer: Uint8Array) => buffer.length)
|
|
37
|
+
const stdinReadSync = vi.fn((buffer: Uint8Array) => {
|
|
38
|
+
buffer.set([1, 2, 3], 0)
|
|
39
|
+
return 3
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
;(globalThis as any).Deno = {
|
|
43
|
+
stderr: { writeSync: vi.fn((buffer: Uint8Array) => buffer.length) },
|
|
44
|
+
stdin: { readSync: stdinReadSync },
|
|
45
|
+
stdout: { writeSync: stdoutWriteSync },
|
|
46
|
+
}
|
|
47
|
+
delete (globalThis as any).process
|
|
48
|
+
|
|
49
|
+
const input = NewFile(0, 'stdin')
|
|
50
|
+
const output = NewFile(1, 'stdout')
|
|
51
|
+
const readBuf = new Uint8Array(4)
|
|
52
|
+
|
|
53
|
+
const [readN, readErr] = input!.Read(readBuf)
|
|
54
|
+
expect(readN).toBe(3)
|
|
55
|
+
expect(readErr).toBeNull()
|
|
56
|
+
expect(Array.from(readBuf.slice(0, 3))).toEqual([1, 2, 3])
|
|
57
|
+
|
|
58
|
+
const writeBuf = new Uint8Array([4, 5, 6])
|
|
59
|
+
const [writeN, writeErr] = output!.Write(writeBuf)
|
|
60
|
+
expect(writeN).toBe(3)
|
|
61
|
+
expect(writeErr).toBeNull()
|
|
62
|
+
expect(stdoutWriteSync).toHaveBeenCalledTimes(1)
|
|
63
|
+
expect(stdoutWriteSync).toHaveBeenCalledWith(writeBuf)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('uses process builtin fs sync stdio when Deno is unavailable', () => {
|
|
67
|
+
const readSync = vi.fn(
|
|
68
|
+
(
|
|
69
|
+
_fd: number,
|
|
70
|
+
buffer: Uint8Array,
|
|
71
|
+
_offset?: number,
|
|
72
|
+
_length?: number,
|
|
73
|
+
_position?: number | null,
|
|
74
|
+
) => {
|
|
75
|
+
buffer.set([7, 8], 0)
|
|
76
|
+
return 2
|
|
77
|
+
},
|
|
78
|
+
)
|
|
79
|
+
const writeSync = vi.fn(
|
|
80
|
+
(
|
|
81
|
+
_fd: number,
|
|
82
|
+
_buffer: Uint8Array,
|
|
83
|
+
_offset?: number,
|
|
84
|
+
length?: number,
|
|
85
|
+
_position?: number | null,
|
|
86
|
+
) => length ?? 0,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
delete (globalThis as any).Deno
|
|
90
|
+
;(globalThis as any).process = {
|
|
91
|
+
getBuiltinModule: vi.fn(() => ({
|
|
92
|
+
readSync,
|
|
93
|
+
writeSync,
|
|
94
|
+
})),
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const input = NewFile(0, 'stdin')
|
|
98
|
+
const output = NewFile(1, 'stdout')
|
|
99
|
+
const readBuf = new Uint8Array(2)
|
|
100
|
+
|
|
101
|
+
const [readN, readErr] = input!.Read(readBuf)
|
|
102
|
+
expect(readN).toBe(2)
|
|
103
|
+
expect(readErr).toBeNull()
|
|
104
|
+
expect(Array.from(readBuf)).toEqual([7, 8])
|
|
105
|
+
|
|
106
|
+
const writeBuf = new Uint8Array([9, 10, 11, 12])
|
|
107
|
+
const [writeN, writeErr] = output!.Write(writeBuf)
|
|
108
|
+
expect(writeN).toBe(4)
|
|
109
|
+
expect(writeErr).toBeNull()
|
|
110
|
+
expect(writeSync).toHaveBeenCalledTimes(1)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('returns EOF on zero-byte reads and ErrClosed after Close', () => {
|
|
114
|
+
const stdinReadSync = vi.fn(() => 0)
|
|
115
|
+
|
|
116
|
+
;(globalThis as any).Deno = {
|
|
117
|
+
stdin: { readSync: stdinReadSync },
|
|
118
|
+
}
|
|
119
|
+
delete (globalThis as any).process
|
|
120
|
+
|
|
121
|
+
const input = NewFile(0, 'stdin')!
|
|
122
|
+
const [readN, readErr] = input.Read(new Uint8Array(1))
|
|
123
|
+
expect(readN).toBe(0)
|
|
124
|
+
expect(readErr).toBe(io.EOF)
|
|
125
|
+
|
|
126
|
+
expect(input.Close()).toBeNull()
|
|
127
|
+
const [closedN, closedErr] = input.Read(new Uint8Array(1))
|
|
128
|
+
expect(closedN).toBe(0)
|
|
129
|
+
expect(closedErr).toBe(ErrClosed)
|
|
130
|
+
})
|
|
131
|
+
})
|
package/gs/os/getwd_js.gs.ts
CHANGED
|
@@ -1,28 +1,38 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
|
+
import { getDeno } from "./types_js.gs.js";
|
|
2
3
|
|
|
3
4
|
import * as fs from "@goscript/io/fs/index.js"
|
|
4
5
|
|
|
5
|
-
// JavaScript-specific implementation of Getwd
|
|
6
|
-
// Working directories are not a concept in JavaScript environments
|
|
7
|
-
// Store working directory in a global variable
|
|
8
|
-
|
|
9
|
-
// Global working directory variable, defaults to test directory
|
|
10
6
|
let currentWorkingDir: string = "/"
|
|
11
7
|
|
|
12
8
|
export function Getwd(): [string, $.GoError] {
|
|
9
|
+
const denoObj = getDeno()
|
|
10
|
+
if (denoObj?.cwd) {
|
|
11
|
+
try {
|
|
12
|
+
return [denoObj.cwd(), null]
|
|
13
|
+
} catch {
|
|
14
|
+
// Fall back to the tracked working directory below.
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const processObj = (globalThis as any).process
|
|
18
|
+
if (processObj?.cwd) {
|
|
19
|
+
try {
|
|
20
|
+
return [processObj.cwd(), null]
|
|
21
|
+
} catch {
|
|
22
|
+
// Fall back to the tracked working directory below.
|
|
23
|
+
}
|
|
24
|
+
}
|
|
13
25
|
return [currentWorkingDir, null]
|
|
14
26
|
}
|
|
15
27
|
|
|
16
|
-
// Set the working directory (for internal use)
|
|
17
28
|
export function setWorkingDir(dir: string): void {
|
|
18
29
|
currentWorkingDir = dir
|
|
19
30
|
}
|
|
20
31
|
|
|
21
|
-
// Additional functions that may be imported by other files
|
|
22
32
|
export function statNolog(name: string): [fs.FileInfo | null, $.GoError] {
|
|
23
33
|
return [null, fs.ErrNotExist]
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
export function lstatNolog(name: string): [fs.FileInfo | null, $.GoError] {
|
|
27
37
|
return [null, fs.ErrNotExist]
|
|
28
|
-
}
|
|
38
|
+
}
|
package/gs/os/path.gs.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { MkdirAll as mkdirAllPath, RemoveAll as removeAllPath } from "./file_js.gs.js";
|
|
3
3
|
import { IsPathSeparator } from "./path_unix.gs.js";
|
|
4
4
|
|
|
5
5
|
// MkdirAll creates a directory named path,
|
|
@@ -10,7 +10,7 @@ import { IsPathSeparator } from "./path_unix.gs.js";
|
|
|
10
10
|
// If path is already a directory, MkdirAll does nothing
|
|
11
11
|
// and returns nil.
|
|
12
12
|
export function MkdirAll(path: string, perm: number): $.GoError {
|
|
13
|
-
return
|
|
13
|
+
return mkdirAllPath(path, perm)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
// RemoveAll removes path and any children it contains.
|
|
@@ -19,7 +19,7 @@ export function MkdirAll(path: string, perm: number): $.GoError {
|
|
|
19
19
|
// returns nil (no error).
|
|
20
20
|
// If there is an error, it will be of type [*PathError].
|
|
21
21
|
export function RemoveAll(path: string): $.GoError {
|
|
22
|
-
return
|
|
22
|
+
return removeAllPath(path)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// endsWithDot reports whether the final component of path is ".".
|
|
@@ -32,4 +32,3 @@ export function endsWithDot(path: string): boolean {
|
|
|
32
32
|
}
|
|
33
33
|
return false
|
|
34
34
|
}
|
|
35
|
-
|
package/gs/os/pidfd_js.gs.ts
CHANGED
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
2
|
import { ErrUnimplemented } from "./error.gs.js";
|
|
3
3
|
|
|
4
|
-
// JavaScript
|
|
5
|
-
// These operations are Linux-specific and not available in JavaScript
|
|
4
|
+
// JavaScript runtimes do not expose Linux pidfd operations.
|
|
6
5
|
|
|
7
|
-
// SysProcAttr stub for compatibility
|
|
8
6
|
export interface SysProcAttr {
|
|
9
|
-
//
|
|
7
|
+
// Process attributes are not modeled for JavaScript pidfd support.
|
|
10
8
|
}
|
|
11
9
|
|
|
12
|
-
// ensurePidfd ensures pidfd support - stub implementation
|
|
13
10
|
export function ensurePidfd(sysAttr: SysProcAttr | null): [SysProcAttr | null, boolean] {
|
|
14
11
|
return [null, false]
|
|
15
12
|
}
|
|
16
13
|
|
|
17
|
-
// getPidfd gets a process file descriptor - stub implementation
|
|
18
14
|
export function getPidfd(_: SysProcAttr | null, _usePidfd: boolean): [number, boolean] {
|
|
19
15
|
return [0, false]
|
|
20
16
|
}
|
|
21
17
|
|
|
22
|
-
// pidfdFind finds a process by pidfd - stub implementation
|
|
23
18
|
export function pidfdFind(_: number): [number, $.GoError] {
|
|
24
19
|
return [0, ErrUnimplemented]
|
|
25
|
-
}
|
|
20
|
+
}
|
package/gs/os/proc.gs.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
2
|
import { NewSyscallError, ErrUnimplemented } from "./error.gs.js";
|
|
3
|
+
import { runtime_args as hostRuntimeArgs, runtime_beforeExit as hostRuntimeBeforeExit } from "./proc_js.gs.js";
|
|
3
4
|
|
|
4
5
|
import * as runtime from "@goscript/runtime/index.js"
|
|
5
6
|
|
|
@@ -13,7 +14,7 @@ export function init(): void {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export function runtime_args(): $.Slice<string> {
|
|
16
|
-
return
|
|
17
|
+
return hostRuntimeArgs()
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
// Getuid returns the numeric user id of the caller.
|
|
@@ -59,7 +60,7 @@ export function Getgroups(): [$.Slice<number>, $.GoError] {
|
|
|
59
60
|
// For portability, the status code should be in the range [0, 125].
|
|
60
61
|
export function Exit(code: number): void {
|
|
61
62
|
|
|
62
|
-
// Testlog functionality not available in JavaScript
|
|
63
|
+
// Testlog functionality is not available in JavaScript.
|
|
63
64
|
// if (code == 0 && testlog.PanicOnExit0()) {
|
|
64
65
|
// $.panic("unexpected call to os.Exit(0) during test")
|
|
65
66
|
// }
|
|
@@ -80,5 +81,6 @@ export function Exit(code: number): void {
|
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
export function runtime_beforeExit(exitCode: number): void {
|
|
84
|
-
|
|
84
|
+
export function runtime_beforeExit(exitCode: number): void {
|
|
85
|
+
hostRuntimeBeforeExit(exitCode)
|
|
86
|
+
}
|
package/gs/os/proc_js.gs.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getDeno } from "./types_js.gs.js";
|
|
3
3
|
|
|
4
|
-
// JavaScript-specific process functions
|
|
5
|
-
|
|
6
|
-
// runtime_args returns command line arguments (stub for JS)
|
|
7
4
|
export function runtime_args(): $.Slice<string> {
|
|
8
|
-
|
|
5
|
+
const denoObj = getDeno()
|
|
6
|
+
if (Array.isArray(denoObj?.args)) {
|
|
7
|
+
return $.arrayToSlice<string>(denoObj.args)
|
|
8
|
+
}
|
|
9
|
+
const processObj = (globalThis as any).process
|
|
10
|
+
if (Array.isArray(processObj?.argv)) {
|
|
11
|
+
return $.arrayToSlice<string>(processObj.argv.slice(2))
|
|
12
|
+
}
|
|
9
13
|
return $.arrayToSlice<string>([])
|
|
10
14
|
}
|
|
11
15
|
|
|
12
|
-
// runtime_beforeExit is called before exit (stub for JS)
|
|
13
16
|
export function runtime_beforeExit(exitCode: number): void {
|
|
14
|
-
// No-op in JavaScript
|
|
15
|
-
}
|
|
17
|
+
// No-op in JavaScript.
|
|
18
|
+
}
|
package/gs/os/rawconn_js.gs.ts
CHANGED
|
@@ -1,30 +1,38 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
|
-
import {
|
|
3
|
-
import { File } from "./types_js.gs.js";
|
|
2
|
+
import { ErrInvalid } from "./error.gs.js";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
type rawConnFile = {
|
|
5
|
+
fd: number
|
|
6
|
+
}
|
|
7
7
|
|
|
8
8
|
export class rawConn {
|
|
9
|
-
constructor(private file:
|
|
9
|
+
constructor(private file: rawConnFile | null) {}
|
|
10
10
|
|
|
11
|
-
// Control calls fn with the file descriptor - stub implementation
|
|
12
11
|
public Control(f: ((fd: number) => void) | null): $.GoError {
|
|
13
|
-
|
|
12
|
+
if (!this.file || this.file.fd < 0) {
|
|
13
|
+
return ErrInvalid
|
|
14
|
+
}
|
|
15
|
+
f?.(this.file.fd)
|
|
16
|
+
return null
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
// Read calls fn when the file descriptor is ready for reading - stub implementation
|
|
17
19
|
public Read(f: ((fd: number) => boolean) | null): $.GoError {
|
|
18
|
-
|
|
20
|
+
if (!this.file || this.file.fd < 0) {
|
|
21
|
+
return ErrInvalid
|
|
22
|
+
}
|
|
23
|
+
f?.(this.file.fd)
|
|
24
|
+
return null
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
// Write calls fn when the file descriptor is ready for writing - stub implementation
|
|
22
27
|
public Write(f: ((fd: number) => boolean) | null): $.GoError {
|
|
23
|
-
|
|
28
|
+
if (!this.file || this.file.fd < 0) {
|
|
29
|
+
return ErrInvalid
|
|
30
|
+
}
|
|
31
|
+
f?.(this.file.fd)
|
|
32
|
+
return null
|
|
24
33
|
}
|
|
25
34
|
}
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
export function newRawConn(file: File | null): rawConn {
|
|
36
|
+
export function newRawConn(file: rawConnFile | null): rawConn {
|
|
29
37
|
return new rawConn(file)
|
|
30
|
-
}
|
|
38
|
+
}
|
package/gs/os/removeall_js.gs.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
// JavaScript-specific stub for removeall operations
|
|
5
|
-
// These operations cannot be implemented in JavaScript environments
|
|
2
|
+
import { RemoveAll as removeAllPath } from "./file_js.gs.js";
|
|
6
3
|
|
|
7
4
|
export function RemoveAll(path: string): $.GoError {
|
|
8
|
-
return
|
|
9
|
-
}
|
|
5
|
+
return removeAllPath(path)
|
|
6
|
+
}
|