goscript 0.0.82 → 0.0.84

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.
Files changed (85) hide show
  1. package/dist/gs/builtin/builtin.js +4 -7
  2. package/dist/gs/builtin/builtin.js.map +1 -1
  3. package/dist/gs/builtin/hostio.d.ts +72 -0
  4. package/dist/gs/builtin/hostio.js +181 -0
  5. package/dist/gs/builtin/hostio.js.map +1 -0
  6. package/dist/gs/builtin/print.d.ts +8 -0
  7. package/dist/gs/builtin/print.js +111 -0
  8. package/dist/gs/builtin/print.js.map +1 -0
  9. package/dist/gs/fmt/fmt.js +2 -22
  10. package/dist/gs/fmt/fmt.js.map +1 -1
  11. package/dist/gs/os/dir.gs.js +41 -27
  12. package/dist/gs/os/dir.gs.js.map +1 -1
  13. package/dist/gs/os/exec.gs.js +1 -2
  14. package/dist/gs/os/exec.gs.js.map +1 -1
  15. package/dist/gs/os/exec_posix.gs.js +1 -1
  16. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  17. package/dist/gs/os/file_constants_js.gs.js +71 -7
  18. package/dist/gs/os/file_constants_js.gs.js.map +1 -1
  19. package/dist/gs/os/file_js.gs.js +168 -24
  20. package/dist/gs/os/file_js.gs.js.map +1 -1
  21. package/dist/gs/os/file_posix_js.gs.js +75 -11
  22. package/dist/gs/os/file_posix_js.gs.js.map +1 -1
  23. package/dist/gs/os/file_unix_js.gs.d.ts +3 -3
  24. package/dist/gs/os/file_unix_js.gs.js +218 -21
  25. package/dist/gs/os/file_unix_js.gs.js.map +1 -1
  26. package/dist/gs/os/getwd_js.gs.js +19 -6
  27. package/dist/gs/os/getwd_js.gs.js.map +1 -1
  28. package/dist/gs/os/path.gs.js +3 -3
  29. package/dist/gs/os/path.gs.js.map +1 -1
  30. package/dist/gs/os/pidfd_js.gs.js +0 -3
  31. package/dist/gs/os/pidfd_js.gs.js.map +1 -1
  32. package/dist/gs/os/proc.gs.js +6 -3
  33. package/dist/gs/os/proc.gs.js.map +1 -1
  34. package/dist/gs/os/proc_js.gs.js +10 -5
  35. package/dist/gs/os/proc_js.gs.js.map +1 -1
  36. package/dist/gs/os/rawconn_js.gs.d.ts +6 -3
  37. package/dist/gs/os/rawconn_js.gs.js +16 -10
  38. package/dist/gs/os/rawconn_js.gs.js.map +1 -1
  39. package/dist/gs/os/removeall_js.gs.js +2 -4
  40. package/dist/gs/os/removeall_js.gs.js.map +1 -1
  41. package/dist/gs/os/root_js.gs.d.ts +4 -1
  42. package/dist/gs/os/root_js.gs.js +90 -40
  43. package/dist/gs/os/root_js.gs.js.map +1 -1
  44. package/dist/gs/os/root_noopenat.gs.js +13 -16
  45. package/dist/gs/os/root_noopenat.gs.js.map +1 -1
  46. package/dist/gs/os/stat_js.gs.js +40 -4
  47. package/dist/gs/os/stat_js.gs.js.map +1 -1
  48. package/dist/gs/os/stat_unix_js.gs.d.ts +1 -1
  49. package/dist/gs/os/stat_unix_js.gs.js +5 -10
  50. package/dist/gs/os/stat_unix_js.gs.js.map +1 -1
  51. package/dist/gs/os/tempfile.gs.d.ts +1 -1
  52. package/dist/gs/os/tempfile.gs.js +24 -7
  53. package/dist/gs/os/tempfile.gs.js.map +1 -1
  54. package/dist/gs/os/types_js.gs.d.ts +30 -2
  55. package/dist/gs/os/types_js.gs.js +426 -23
  56. package/dist/gs/os/types_js.gs.js.map +1 -1
  57. package/gs/builtin/builtin.ts +4 -6
  58. package/gs/builtin/hostio.test.ts +69 -0
  59. package/gs/builtin/hostio.ts +298 -0
  60. package/gs/builtin/print.test.ts +48 -0
  61. package/gs/builtin/print.ts +154 -0
  62. package/gs/fmt/fmt.test.ts +41 -30
  63. package/gs/fmt/fmt.ts +2 -22
  64. package/gs/os/dir.gs.ts +40 -28
  65. package/gs/os/exec.gs.ts +2 -4
  66. package/gs/os/exec_posix.gs.ts +1 -2
  67. package/gs/os/file_constants_js.gs.ts +70 -8
  68. package/gs/os/file_js.gs.ts +156 -26
  69. package/gs/os/file_posix_js.gs.ts +69 -13
  70. package/gs/os/file_unix_js.gs.ts +212 -24
  71. package/gs/os/file_unix_js.test.ts +184 -0
  72. package/gs/os/getwd_js.gs.ts +18 -8
  73. package/gs/os/path.gs.ts +3 -4
  74. package/gs/os/pidfd_js.gs.ts +3 -8
  75. package/gs/os/proc.gs.ts +6 -4
  76. package/gs/os/proc_js.gs.ts +11 -8
  77. package/gs/os/rawconn_js.gs.ts +22 -14
  78. package/gs/os/removeall_js.gs.ts +3 -6
  79. package/gs/os/root_js.gs.ts +94 -42
  80. package/gs/os/root_noopenat.gs.ts +13 -20
  81. package/gs/os/stat_js.gs.ts +37 -6
  82. package/gs/os/stat_unix_js.gs.ts +6 -13
  83. package/gs/os/tempfile.gs.ts +27 -9
  84. package/gs/os/types_js.gs.ts +449 -26
  85. package/package.json +1 -1
@@ -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
- // JavaScript-specific implementations for Unix file operations
8
- // These functions stub Unix-specific operations that cannot be implemented in JavaScript
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
- // Device null path - stub for JavaScript
11
- export const DevNull = "/dev/null"
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
- // Stdin, Stdout, Stderr - stub implementations
14
- export const Stdin: File | null = null
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
- // NewFile creates a File from a file descriptor - stub implementation
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
- return null
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 [null, ErrUnimplemented]
209
+ return openFileNolog(name, O_RDONLY, 0)
51
210
  }
52
211
 
53
212
  export function tempDir(): string {
54
- return "/tmp"
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 null
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, kind: newFileKind, nonBlocking: boolean): File | null {
88
- return null
259
+ export function newFile(fd: number, name: string, _kind: newFileKind, _nonBlocking: boolean): File | null {
260
+ return NewFile(fd, name)
89
261
  }
90
262
 
91
- // Directory entry stubs
92
- export function newUnixDirent(parent: string, name: string, typ: number): [fs.DirEntry | null, $.GoError] {
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,184 @@
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
+ import { createHostFile, resetHostRuntimeForTests } from './types_js.gs.js'
8
+
9
+ const originalDeno = (globalThis as any).Deno
10
+ const originalProcess = (globalThis as any).process
11
+
12
+ afterEach(() => {
13
+ if (originalDeno === undefined) {
14
+ delete (globalThis as any).Deno
15
+ } else {
16
+ ;(globalThis as any).Deno = originalDeno
17
+ }
18
+
19
+ if (originalProcess === undefined) {
20
+ delete (globalThis as any).process
21
+ } else {
22
+ ;(globalThis as any).process = originalProcess
23
+ }
24
+
25
+ resetHostRuntimeForTests()
26
+ })
27
+
28
+ describe('os stdio', () => {
29
+ it('exports standard file descriptors', () => {
30
+ expect(Stdin).not.toBeNull()
31
+ expect(Stdout).not.toBeNull()
32
+ expect(Stderr).not.toBeNull()
33
+ expect(Stdin!.Fd()).toBe(0)
34
+ expect(Stdout!.Fd()).toBe(1)
35
+ expect(Stderr!.Fd()).toBe(2)
36
+ })
37
+
38
+ it('uses Deno sync stdio when available', () => {
39
+ const stdoutWriteSync = vi.fn((buffer: Uint8Array) => buffer.length)
40
+ const stdinReadSync = vi.fn((buffer: Uint8Array) => {
41
+ buffer.set([1, 2, 3], 0)
42
+ return 3
43
+ })
44
+
45
+ ;(globalThis as any).Deno = {
46
+ stderr: { writeSync: vi.fn((buffer: Uint8Array) => buffer.length) },
47
+ stdin: { readSync: stdinReadSync },
48
+ stdout: { writeSync: stdoutWriteSync },
49
+ }
50
+ delete (globalThis as any).process
51
+ resetHostRuntimeForTests()
52
+
53
+ const input = NewFile(0, 'stdin')
54
+ const output = NewFile(1, 'stdout')
55
+ const readBuf = new Uint8Array(4)
56
+
57
+ const [readN, readErr] = input!.Read(readBuf)
58
+ expect(readN).toBe(3)
59
+ expect(readErr).toBeNull()
60
+ expect(Array.from(readBuf.slice(0, 3))).toEqual([1, 2, 3])
61
+
62
+ const writeBuf = new Uint8Array([4, 5, 6])
63
+ const [writeN, writeErr] = output!.Write(writeBuf)
64
+ expect(writeN).toBe(3)
65
+ expect(writeErr).toBeNull()
66
+ expect(stdoutWriteSync).toHaveBeenCalledTimes(1)
67
+ expect(stdoutWriteSync).toHaveBeenCalledWith(writeBuf)
68
+ })
69
+
70
+ it('uses process builtin fs sync stdio when Deno is unavailable', () => {
71
+ const readSync = vi.fn(
72
+ (
73
+ _fd: number,
74
+ buffer: Uint8Array,
75
+ _offset?: number,
76
+ _length?: number,
77
+ _position?: number | null,
78
+ ) => {
79
+ buffer.set([7, 8], 0)
80
+ return 2
81
+ },
82
+ )
83
+ const writeSync = vi.fn(
84
+ (
85
+ _fd: number,
86
+ _buffer: Uint8Array,
87
+ _offset?: number,
88
+ length?: number,
89
+ _position?: number | null,
90
+ ) => length ?? 0,
91
+ )
92
+
93
+ delete (globalThis as any).Deno
94
+ ;(globalThis as any).process = {
95
+ getBuiltinModule: vi.fn(() => ({
96
+ readSync,
97
+ writeSync,
98
+ })),
99
+ }
100
+ resetHostRuntimeForTests()
101
+
102
+ const input = NewFile(0, 'stdin')
103
+ const output = NewFile(1, 'stdout')
104
+ const readBuf = new Uint8Array(2)
105
+
106
+ const [readN, readErr] = input!.Read(readBuf)
107
+ expect(readN).toBe(2)
108
+ expect(readErr).toBeNull()
109
+ expect(Array.from(readBuf)).toEqual([7, 8])
110
+
111
+ const writeBuf = new Uint8Array([9, 10, 11, 12])
112
+ const [writeN, writeErr] = output!.Write(writeBuf)
113
+ expect(writeN).toBe(4)
114
+ expect(writeErr).toBeNull()
115
+ expect(writeSync).toHaveBeenCalledTimes(1)
116
+ })
117
+
118
+ it('returns EOF on zero-byte reads and ErrClosed after Close', () => {
119
+ const stdinReadSync = vi.fn(() => 0)
120
+
121
+ ;(globalThis as any).Deno = {
122
+ stdin: { readSync: stdinReadSync },
123
+ }
124
+ delete (globalThis as any).process
125
+ resetHostRuntimeForTests()
126
+
127
+ const input = NewFile(0, 'stdin')!
128
+ const [readN, readErr] = input.Read(new Uint8Array(1))
129
+ expect(readN).toBe(0)
130
+ expect(readErr).toBe(io.EOF)
131
+
132
+ expect(input.Close()).toBeNull()
133
+ const [closedN, closedErr] = input.Read(new Uint8Array(1))
134
+ expect(closedN).toBe(0)
135
+ expect(closedErr).toBe(ErrClosed)
136
+ })
137
+
138
+ it('retries short writes until the full buffer is written', () => {
139
+ const writeSync = vi
140
+ .fn<(buffer: Uint8Array) => number>()
141
+ .mockImplementationOnce((_buffer: Uint8Array) => 2)
142
+ .mockImplementationOnce((buffer: Uint8Array) => buffer.length)
143
+
144
+ ;(globalThis as any).Deno = {
145
+ stdout: { writeSync },
146
+ }
147
+ delete (globalThis as any).process
148
+ resetHostRuntimeForTests()
149
+
150
+ const output = NewFile(1, 'stdout')!
151
+ const [writeN, writeErr] = output.Write(new Uint8Array([1, 2, 3, 4, 5]))
152
+ expect(writeN).toBe(5)
153
+ expect(writeErr).toBeNull()
154
+ expect(writeSync).toHaveBeenCalledTimes(2)
155
+ expect(Array.from(writeSync.mock.calls[1][0])).toEqual([3, 4, 5])
156
+ })
157
+
158
+ it('prefers direct handle read and write methods when available', () => {
159
+ const handle = {
160
+ readSync: vi.fn((buffer: Uint8Array) => {
161
+ buffer.set([11, 12, 13], 0)
162
+ return 3
163
+ }),
164
+ writeSync: vi
165
+ .fn<(buffer: Uint8Array) => number>()
166
+ .mockImplementationOnce((_buffer: Uint8Array) => 1)
167
+ .mockImplementationOnce((buffer: Uint8Array) => buffer.length),
168
+ }
169
+
170
+ const file = createHostFile('host-file', 99, handle)
171
+ const readBuf = new Uint8Array(4)
172
+
173
+ const [readN, readErr] = file.Read(readBuf)
174
+ expect(readN).toBe(3)
175
+ expect(readErr).toBeNull()
176
+ expect(Array.from(readBuf.slice(0, 3))).toEqual([11, 12, 13])
177
+
178
+ const [writeN, writeErr] = file.Write(new Uint8Array([21, 22, 23]))
179
+ expect(writeN).toBe(3)
180
+ expect(writeErr).toBeNull()
181
+ expect(handle.writeSync).toHaveBeenCalledTimes(2)
182
+ expect(Array.from(handle.writeSync.mock.calls[1][0])).toEqual([22, 23])
183
+ })
184
+ })
@@ -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 { ErrUnimplemented } from "./error.gs.js";
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 ErrUnimplemented
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 ErrUnimplemented
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
-
@@ -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-specific stubs for pidfd operations
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
- // Stub interface for process attributes
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 $.arrayToSlice<string>([])
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 - stub
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
+ }
@@ -1,15 +1,18 @@
1
1
  import * as $ from "@goscript/builtin/index.js";
2
- import { ErrUnimplemented } from "./error.gs.js";
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
- // In JavaScript environment, return empty args or process.argv equivalent
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
+ }