goscript 0.0.82 → 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.
Files changed (68) hide show
  1. package/dist/gs/os/dir.gs.js +41 -27
  2. package/dist/gs/os/dir.gs.js.map +1 -1
  3. package/dist/gs/os/exec.gs.js +1 -2
  4. package/dist/gs/os/exec.gs.js.map +1 -1
  5. package/dist/gs/os/exec_posix.gs.js +1 -1
  6. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  7. package/dist/gs/os/file_constants_js.gs.js +71 -7
  8. package/dist/gs/os/file_constants_js.gs.js.map +1 -1
  9. package/dist/gs/os/file_js.gs.js +168 -24
  10. package/dist/gs/os/file_js.gs.js.map +1 -1
  11. package/dist/gs/os/file_posix_js.gs.js +75 -11
  12. package/dist/gs/os/file_posix_js.gs.js.map +1 -1
  13. package/dist/gs/os/file_unix_js.gs.d.ts +3 -3
  14. package/dist/gs/os/file_unix_js.gs.js +218 -21
  15. package/dist/gs/os/file_unix_js.gs.js.map +1 -1
  16. package/dist/gs/os/getwd_js.gs.js +19 -6
  17. package/dist/gs/os/getwd_js.gs.js.map +1 -1
  18. package/dist/gs/os/path.gs.js +3 -3
  19. package/dist/gs/os/path.gs.js.map +1 -1
  20. package/dist/gs/os/pidfd_js.gs.js +0 -3
  21. package/dist/gs/os/pidfd_js.gs.js.map +1 -1
  22. package/dist/gs/os/proc.gs.js +6 -3
  23. package/dist/gs/os/proc.gs.js.map +1 -1
  24. package/dist/gs/os/proc_js.gs.js +10 -5
  25. package/dist/gs/os/proc_js.gs.js.map +1 -1
  26. package/dist/gs/os/rawconn_js.gs.d.ts +6 -3
  27. package/dist/gs/os/rawconn_js.gs.js +16 -10
  28. package/dist/gs/os/rawconn_js.gs.js.map +1 -1
  29. package/dist/gs/os/removeall_js.gs.js +2 -4
  30. package/dist/gs/os/removeall_js.gs.js.map +1 -1
  31. package/dist/gs/os/root_js.gs.d.ts +4 -1
  32. package/dist/gs/os/root_js.gs.js +90 -40
  33. package/dist/gs/os/root_js.gs.js.map +1 -1
  34. package/dist/gs/os/root_noopenat.gs.js +13 -16
  35. package/dist/gs/os/root_noopenat.gs.js.map +1 -1
  36. package/dist/gs/os/stat_js.gs.js +40 -4
  37. package/dist/gs/os/stat_js.gs.js.map +1 -1
  38. package/dist/gs/os/stat_unix_js.gs.d.ts +1 -1
  39. package/dist/gs/os/stat_unix_js.gs.js +5 -10
  40. package/dist/gs/os/stat_unix_js.gs.js.map +1 -1
  41. package/dist/gs/os/tempfile.gs.d.ts +1 -1
  42. package/dist/gs/os/tempfile.gs.js +24 -7
  43. package/dist/gs/os/tempfile.gs.js.map +1 -1
  44. package/dist/gs/os/types_js.gs.d.ts +78 -1
  45. package/dist/gs/os/types_js.gs.js +464 -23
  46. package/dist/gs/os/types_js.gs.js.map +1 -1
  47. package/gs/os/dir.gs.ts +40 -28
  48. package/gs/os/exec.gs.ts +2 -4
  49. package/gs/os/exec_posix.gs.ts +1 -2
  50. package/gs/os/file_constants_js.gs.ts +70 -8
  51. package/gs/os/file_js.gs.ts +156 -26
  52. package/gs/os/file_posix_js.gs.ts +69 -13
  53. package/gs/os/file_unix_js.gs.ts +212 -24
  54. package/gs/os/file_unix_js.test.ts +131 -0
  55. package/gs/os/getwd_js.gs.ts +18 -8
  56. package/gs/os/path.gs.ts +3 -4
  57. package/gs/os/pidfd_js.gs.ts +3 -8
  58. package/gs/os/proc.gs.ts +6 -4
  59. package/gs/os/proc_js.gs.ts +11 -8
  60. package/gs/os/rawconn_js.gs.ts +22 -14
  61. package/gs/os/removeall_js.gs.ts +3 -6
  62. package/gs/os/root_js.gs.ts +94 -42
  63. package/gs/os/root_noopenat.gs.ts +13 -20
  64. package/gs/os/stat_js.gs.ts +37 -6
  65. package/gs/os/stat_unix_js.gs.ts +6 -13
  66. package/gs/os/tempfile.gs.ts +27 -9
  67. package/gs/os/types_js.gs.ts +528 -26
  68. package/package.json +1 -1
@@ -1,10 +1,290 @@
1
1
  import * as $ from "@goscript/builtin/index.js";
2
- import { ErrUnimplemented } from "./error.gs.js";
2
+ import { ErrClosed, ErrInvalid, ErrUnimplemented } from "./error.gs.js";
3
3
 
4
4
  import * as fs from "@goscript/io/fs/index.js"
5
5
  import * as io from "@goscript/io/index.js"
6
6
  import * as time from "@goscript/time/index.js"
7
7
  import * as syscall from "@goscript/syscall/index.js"
8
+ import { newRawConn } from "./rawconn_js.gs.js"
9
+
10
+ export type NodeFSModule = {
11
+ readSync(fd: number, buffer: Uint8Array, offset?: number, length?: number, position?: number | null): number
12
+ writeSync(fd: number, buffer: Uint8Array, offset?: number, length?: number, position?: number | null): number
13
+ closeSync?(fd: number): void
14
+ fstatSync?(fd: number): HostStatLike
15
+ fsyncSync?(fd: number): void
16
+ ftruncateSync?(fd: number, len?: number): void
17
+ openSync?(path: string, flags: number | string, mode?: number): number
18
+ chmodSync?(path: string, mode: number): void
19
+ chownSync?(path: string, uid: number, gid: number): void
20
+ lchownSync?(path: string, uid: number, gid: number): void
21
+ linkSync?(existingPath: string, newPath: string): void
22
+ lstatSync?(path: string): HostStatLike
23
+ mkdirSync?(path: string, options?: number | { mode?: number, recursive?: boolean }): void
24
+ readFileSync?(path: string): Uint8Array
25
+ readdirSync?(path: string, options?: { withFileTypes?: boolean }): any[]
26
+ readlinkSync?(path: string): string
27
+ renameSync?(oldPath: string, newPath: string): void
28
+ rmSync?(path: string, options?: { force?: boolean, recursive?: boolean }): void
29
+ rmdirSync?(path: string): void
30
+ statSync?(path: string): HostStatLike
31
+ symlinkSync?(target: string, path: string): void
32
+ truncateSync?(path: string, len?: number): void
33
+ unlinkSync?(path: string): void
34
+ utimesSync?(path: string, atime: Date | number, mtime: Date | number): void
35
+ writeFileSync?(path: string, data: Uint8Array, options?: { mode?: number }): void
36
+ }
37
+
38
+ export type DenoStream = {
39
+ readSync?(buffer: Uint8Array): number | null
40
+ writeSync?(buffer: Uint8Array): number
41
+ }
42
+
43
+ export type DenoFileLike = DenoStream & {
44
+ close?(): void
45
+ rid?: number
46
+ seekSync?(offset: number, whence: number): number
47
+ syncSync?(): void
48
+ statSync?(): HostStatLike
49
+ truncateSync?(len?: number): void
50
+ }
51
+
52
+ export type HostStatLike = {
53
+ isDirectory(): boolean
54
+ isSymbolicLink?(): boolean
55
+ mode?: number
56
+ mtime?: Date | null
57
+ mtimeMs?: number
58
+ size?: number
59
+ }
60
+
61
+ export function newHostError(err: unknown): $.GoError {
62
+ const message =
63
+ err instanceof Error ? err.message
64
+ : typeof err === "string" ? err
65
+ : String(err)
66
+ return { Error: () => message }
67
+ }
68
+
69
+ export function getDynamicRequire(): ((specifier: string) => unknown) | null {
70
+ try {
71
+ return Function(
72
+ "return typeof require !== 'undefined' ? require : null",
73
+ )() as ((specifier: string) => unknown) | null
74
+ } catch {
75
+ return null
76
+ }
77
+ }
78
+
79
+ export function getNodeFS(): NodeFSModule | null {
80
+ const processObj = (globalThis as any).process
81
+ if (processObj && typeof processObj.getBuiltinModule === "function") {
82
+ const module = processObj.getBuiltinModule("fs")
83
+ if (module && typeof module.readSync === "function" && typeof module.writeSync === "function") {
84
+ return module as NodeFSModule
85
+ }
86
+ }
87
+
88
+ const requireFn = getDynamicRequire()
89
+ if (requireFn) {
90
+ for (const specifier of ["node:fs", "fs"]) {
91
+ try {
92
+ const module = requireFn(specifier) as NodeFSModule | null
93
+ if (module && typeof module.readSync === "function" && typeof module.writeSync === "function") {
94
+ return module
95
+ }
96
+ } catch {
97
+ // Try the next fallback.
98
+ }
99
+ }
100
+ }
101
+
102
+ return null
103
+ }
104
+
105
+ export function getDeno(): any | null {
106
+ return (globalThis as any).Deno ?? null
107
+ }
108
+
109
+ export function getPlatform(): string {
110
+ const denoObj = getDeno()
111
+ if (denoObj?.build?.os) {
112
+ return denoObj.build.os
113
+ }
114
+
115
+ const processObj = (globalThis as any).process
116
+ if (processObj?.platform) {
117
+ return processObj.platform
118
+ }
119
+
120
+ return "unknown"
121
+ }
122
+
123
+ export function getEnv(name: string): string {
124
+ const denoObj = getDeno()
125
+ if (denoObj?.env?.get) {
126
+ try {
127
+ return denoObj.env.get(name) ?? ""
128
+ } catch {
129
+ return ""
130
+ }
131
+ }
132
+
133
+ const processObj = (globalThis as any).process
134
+ return processObj?.env?.[name] ?? ""
135
+ }
136
+
137
+ export function getDenoStream(fd: number): DenoStream | null {
138
+ const denoObj = getDeno()
139
+ if (!denoObj) {
140
+ return null
141
+ }
142
+
143
+ switch (fd) {
144
+ case 0:
145
+ return denoObj.stdin ?? null
146
+ case 1:
147
+ return denoObj.stdout ?? null
148
+ case 2:
149
+ return denoObj.stderr ?? null
150
+ default:
151
+ return null
152
+ }
153
+ }
154
+
155
+ function readFD(fd: number, b: Uint8Array): [number, $.GoError] {
156
+ if (b.length === 0) {
157
+ return [0, null]
158
+ }
159
+
160
+ const denoStream = getDenoStream(fd)
161
+ if (denoStream && typeof denoStream.readSync === "function") {
162
+ try {
163
+ const n = denoStream.readSync(b)
164
+ if (n === null || n === 0) {
165
+ return [0, io.EOF]
166
+ }
167
+ return [n, null]
168
+ } catch (err) {
169
+ return [0, newHostError(err)]
170
+ }
171
+ }
172
+
173
+ const nodeFS = getNodeFS()
174
+ if (nodeFS) {
175
+ try {
176
+ const n = nodeFS.readSync(fd, b, 0, b.length, null)
177
+ if (n === 0) {
178
+ return [0, io.EOF]
179
+ }
180
+ return [n, null]
181
+ } catch (err) {
182
+ return [0, newHostError(err)]
183
+ }
184
+ }
185
+
186
+ return [0, ErrUnimplemented]
187
+ }
188
+
189
+ function writeFD(fd: number, b: Uint8Array): [number, $.GoError] {
190
+ if (b.length === 0) {
191
+ return [0, null]
192
+ }
193
+
194
+ const denoStream = getDenoStream(fd)
195
+ if (denoStream && typeof denoStream.writeSync === "function") {
196
+ try {
197
+ return [denoStream.writeSync(b), null]
198
+ } catch (err) {
199
+ return [0, newHostError(err)]
200
+ }
201
+ }
202
+
203
+ const nodeFS = getNodeFS()
204
+ if (nodeFS) {
205
+ try {
206
+ return [nodeFS.writeSync(fd, b, 0, b.length, null), null]
207
+ } catch (err) {
208
+ return [0, newHostError(err)]
209
+ }
210
+ }
211
+
212
+ return [0, ErrUnimplemented]
213
+ }
214
+
215
+ class hostFileInfo {
216
+ public name: string
217
+ public modTime: time.Time
218
+ public mode: fs.FileMode
219
+ public size: number
220
+ public sys: HostStatLike | null
221
+
222
+ constructor(init?: Partial<{modTime?: time.Time, mode?: fs.FileMode, name?: string, size?: number, sys?: HostStatLike | null}>) {
223
+ this.name = init?.name ?? ""
224
+ this.modTime = init?.modTime ?? time.Unix(0, 0)
225
+ this.mode = init?.mode ?? 0
226
+ this.size = init?.size ?? 0
227
+ this.sys = init?.sys ?? null
228
+ }
229
+
230
+ public IsDir(): boolean {
231
+ return fs.FileMode_IsDir(this.mode)
232
+ }
233
+
234
+ public ModTime(): time.Time {
235
+ return this.modTime
236
+ }
237
+
238
+ public Mode(): fs.FileMode {
239
+ return this.mode
240
+ }
241
+
242
+ public Name(): string {
243
+ return this.name
244
+ }
245
+
246
+ public Size(): number {
247
+ return this.size
248
+ }
249
+
250
+ public Sys(): HostStatLike | null {
251
+ return this.sys
252
+ }
253
+ }
254
+
255
+ export function createFileInfo(name: string, stat: HostStatLike): fs.FileInfo {
256
+ const normalizedName = name.replace(/\\/g, "/").split("/").filter((part) => part !== "").slice(-1)[0] ?? name
257
+ let mode = (stat.mode ?? 0) & fs.ModePerm
258
+ if (stat.isDirectory()) {
259
+ mode |= fs.ModeDir
260
+ }
261
+ if (stat.isSymbolicLink?.()) {
262
+ mode |= fs.ModeSymlink
263
+ }
264
+
265
+ let mtimeMs = 0
266
+ if (typeof stat.mtimeMs === "number") {
267
+ mtimeMs = stat.mtimeMs
268
+ } else if (stat.mtime instanceof Date) {
269
+ mtimeMs = stat.mtime.getTime()
270
+ }
271
+
272
+ return new hostFileInfo({
273
+ modTime: time.UnixMilli(mtimeMs),
274
+ mode,
275
+ name: normalizedName,
276
+ size: stat.size ?? 0,
277
+ sys: stat,
278
+ })
279
+ }
280
+
281
+ export function createHostFile(name: string, fd: number = -1, handle: DenoFileLike | null = null): File {
282
+ return new File({
283
+ fd,
284
+ file: new file({ handle, path: name }),
285
+ name,
286
+ })
287
+ }
8
288
 
9
289
  // Re-export essential types
10
290
  export type Time = time.Time;
@@ -25,30 +305,41 @@ export function Getpagesize(): number {
25
305
  return 4096
26
306
  }
27
307
 
28
- // Stub implementation of File for JavaScript environment
308
+ // File adapts host file descriptors and file handles to Go's os.File surface.
29
309
  export class File {
30
310
  public get file(): file | null {
31
- return null
311
+ return this._fields.file.value
32
312
  }
33
313
  public set file(value: file | null) {
34
- // No-op
314
+ this._fields.file.value = value
35
315
  }
36
316
 
317
+ public name: string
318
+ public closed: boolean
319
+ public fd: number
320
+
37
321
  public _fields: {
38
322
  file: $.VarRef<file | null>;
39
323
  }
40
324
 
41
- constructor(init?: Partial<{file?: file | null}>) {
325
+ constructor(init?: Partial<{closed?: boolean, fd?: number, file?: file | null, name?: string}>) {
326
+ this.name = init?.name ?? ""
327
+ this.closed = init?.closed ?? false
328
+ this.fd = init?.fd ?? -1
42
329
  this._fields = {
43
- file: $.varRef(null)
330
+ file: $.varRef(init?.file ?? null)
44
331
  }
45
332
  }
46
333
 
47
334
  public clone(): File {
48
- return new File()
335
+ return new File({
336
+ closed: this.closed,
337
+ fd: this.fd,
338
+ file: this.file,
339
+ name: this.name,
340
+ })
49
341
  }
50
342
 
51
- // All File methods return ErrUnimplemented in JavaScript environment
52
343
  public Readdir(n: number): [$.Slice<fs.FileInfo>, $.GoError] {
53
344
  return [null, ErrUnimplemented]
54
345
  }
@@ -66,42 +357,121 @@ export class File {
66
357
  }
67
358
 
68
359
  public Name(): string {
69
- return ""
360
+ return this.name
70
361
  }
71
362
 
72
363
  public Read(b: $.Bytes): [number, $.GoError] {
73
- return [0, ErrUnimplemented]
364
+ if (this.closed) {
365
+ return [0, ErrClosed]
366
+ }
367
+ if (this.fd < 0) {
368
+ return [0, ErrInvalid]
369
+ }
370
+ if (b === null) {
371
+ return [0, null]
372
+ }
373
+ const buf = $.bytesToUint8Array(b)
374
+ const [n, err] = readFD(this.fd, buf)
375
+ if (!(b instanceof Uint8Array) && n > 0) {
376
+ $.copy(b, buf.subarray(0, n))
377
+ }
378
+ return [n, err]
74
379
  }
75
380
 
76
381
  public ReadAt(b: $.Bytes, off: number): [number, $.GoError] {
77
- return [0, ErrUnimplemented]
382
+ const handle = this.file?.handle
383
+ if (!handle || typeof handle.seekSync !== "function" || b === null) {
384
+ return [0, ErrUnimplemented]
385
+ }
386
+ try {
387
+ handle.seekSync(off, io.SeekStart)
388
+ return this.Read(b)
389
+ } catch (err) {
390
+ return [0, newHostError(err)]
391
+ }
78
392
  }
79
393
 
80
394
  public ReadFrom(r: io.Reader): [number, $.GoError] {
81
- return [0, ErrUnimplemented]
395
+ if (this.closed) {
396
+ return [0, ErrClosed]
397
+ }
398
+ return io.Copy(this, r)
82
399
  }
83
400
 
84
401
  public Write(b: $.Bytes): [number, $.GoError] {
85
- return [0, ErrUnimplemented]
402
+ if (this.closed) {
403
+ return [0, ErrClosed]
404
+ }
405
+ if (this.fd < 0) {
406
+ return [0, ErrInvalid]
407
+ }
408
+ if (b === null) {
409
+ return [0, null]
410
+ }
411
+ return writeFD(this.fd, $.bytesToUint8Array(b))
86
412
  }
87
413
 
88
414
  public WriteAt(b: $.Bytes, off: number): [number, $.GoError] {
89
- return [0, ErrUnimplemented]
415
+ const handle = this.file?.handle
416
+ if (!handle || typeof handle.seekSync !== "function" || b === null) {
417
+ return [0, ErrUnimplemented]
418
+ }
419
+ try {
420
+ handle.seekSync(off, io.SeekStart)
421
+ return this.Write(b)
422
+ } catch (err) {
423
+ return [0, newHostError(err)]
424
+ }
90
425
  }
91
426
 
92
427
  public WriteTo(w: io.Writer): [number, $.GoError] {
93
- return [0, ErrUnimplemented]
428
+ if (this.closed) {
429
+ return [0, ErrClosed]
430
+ }
431
+ return io.Copy(w, this)
94
432
  }
95
433
 
96
434
  public Seek(offset: number, whence: number): [number, $.GoError] {
97
- return [0, ErrUnimplemented]
435
+ const handle = this.file?.handle
436
+ if (!handle || typeof handle.seekSync !== "function") {
437
+ return [0, ErrUnimplemented]
438
+ }
439
+ try {
440
+ return [handle.seekSync(offset, whence), null]
441
+ } catch (err) {
442
+ return [0, newHostError(err)]
443
+ }
98
444
  }
99
445
 
100
446
  public WriteString(s: string): [number, $.GoError] {
101
- return [0, ErrUnimplemented]
447
+ return this.Write($.stringToBytes(s))
102
448
  }
103
449
 
104
450
  public Chmod(mode: number): $.GoError {
451
+ if (this.closed) {
452
+ return ErrClosed
453
+ }
454
+ if (this.name === "") {
455
+ return ErrUnimplemented
456
+ }
457
+ const denoObj = getDeno()
458
+ if (denoObj?.chmodSync) {
459
+ try {
460
+ denoObj.chmodSync(this.name, mode)
461
+ return null
462
+ } catch (err) {
463
+ return newHostError(err)
464
+ }
465
+ }
466
+ const nodeFS = getNodeFS()
467
+ if (nodeFS?.chmodSync) {
468
+ try {
469
+ nodeFS.chmodSync(this.name, mode)
470
+ return null
471
+ } catch (err) {
472
+ return newHostError(err)
473
+ }
474
+ }
105
475
  return ErrUnimplemented
106
476
  }
107
477
 
@@ -118,40 +488,167 @@ export class File {
118
488
  }
119
489
 
120
490
  public SyscallConn(): [any, $.GoError] {
121
- return [null, ErrUnimplemented]
491
+ if (this.closed) {
492
+ return [null, ErrClosed]
493
+ }
494
+ if (this.fd < 0) {
495
+ return [null, ErrInvalid]
496
+ }
497
+ return [newRawConn(this), null]
122
498
  }
123
499
 
124
500
  public Close(): $.GoError {
125
- return ErrUnimplemented
501
+ if (this.closed) {
502
+ return ErrClosed
503
+ }
504
+ const handle = this.file?.handle
505
+ if (handle && typeof handle.close === "function") {
506
+ try {
507
+ handle.close()
508
+ } catch (err) {
509
+ return newHostError(err)
510
+ }
511
+ } else if (this.fd > 2) {
512
+ const nodeFS = getNodeFS()
513
+ if (nodeFS?.closeSync) {
514
+ try {
515
+ nodeFS.closeSync(this.fd)
516
+ } catch (err) {
517
+ return newHostError(err)
518
+ }
519
+ }
520
+ }
521
+ this.closed = true
522
+ return null
126
523
  }
127
524
 
128
525
  public Chown(uid: number, gid: number): $.GoError {
526
+ if (this.closed) {
527
+ return ErrClosed
528
+ }
529
+ if (this.name === "") {
530
+ return ErrUnimplemented
531
+ }
532
+ const denoObj = getDeno()
533
+ if (denoObj?.chownSync) {
534
+ try {
535
+ denoObj.chownSync(this.name, uid, gid)
536
+ return null
537
+ } catch (err) {
538
+ return newHostError(err)
539
+ }
540
+ }
541
+ const nodeFS = getNodeFS()
542
+ if (nodeFS?.chownSync) {
543
+ try {
544
+ nodeFS.chownSync(this.name, uid, gid)
545
+ return null
546
+ } catch (err) {
547
+ return newHostError(err)
548
+ }
549
+ }
129
550
  return ErrUnimplemented
130
551
  }
131
552
 
132
553
  public Truncate(size: number): $.GoError {
554
+ const handle = this.file?.handle
555
+ if (handle && typeof handle.truncateSync === "function") {
556
+ try {
557
+ handle.truncateSync(size)
558
+ return null
559
+ } catch (err) {
560
+ return newHostError(err)
561
+ }
562
+ }
563
+ const nodeFS = getNodeFS()
564
+ if (nodeFS?.ftruncateSync && this.fd >= 0) {
565
+ try {
566
+ nodeFS.ftruncateSync(this.fd, size)
567
+ return null
568
+ } catch (err) {
569
+ return newHostError(err)
570
+ }
571
+ }
133
572
  return ErrUnimplemented
134
573
  }
135
574
 
136
575
  public Sync(): $.GoError {
576
+ const handle = this.file?.handle
577
+ if (handle && typeof handle.syncSync === "function") {
578
+ try {
579
+ handle.syncSync()
580
+ return null
581
+ } catch (err) {
582
+ return newHostError(err)
583
+ }
584
+ }
585
+ const nodeFS = getNodeFS()
586
+ if (nodeFS?.fsyncSync && this.fd >= 0) {
587
+ try {
588
+ nodeFS.fsyncSync(this.fd)
589
+ return null
590
+ } catch (err) {
591
+ return newHostError(err)
592
+ }
593
+ }
137
594
  return ErrUnimplemented
138
595
  }
139
596
 
140
597
  public Chdir(): $.GoError {
598
+ const processObj = (globalThis as any).process
599
+ if (processObj?.chdir && this.name !== "") {
600
+ try {
601
+ processObj.chdir(this.name)
602
+ return null
603
+ } catch (err) {
604
+ return newHostError(err)
605
+ }
606
+ }
607
+ const denoObj = getDeno()
608
+ if (denoObj?.chdir && this.name !== "") {
609
+ try {
610
+ denoObj.chdir(this.name)
611
+ return null
612
+ } catch (err) {
613
+ return newHostError(err)
614
+ }
615
+ }
141
616
  return ErrUnimplemented
142
617
  }
143
618
 
144
619
  public Fd(): syscall.uintptr {
145
- return 0
620
+ return this.fd
146
621
  }
147
622
 
148
623
  public Stat(): [fs.FileInfo, $.GoError] {
624
+ const handle = this.file?.handle
625
+ if (handle && typeof handle.statSync === "function") {
626
+ try {
627
+ return [createFileInfo(this.name, handle.statSync()), null]
628
+ } catch (err) {
629
+ return [null, newHostError(err)]
630
+ }
631
+ }
632
+ const nodeFS = getNodeFS()
633
+ if (nodeFS?.fstatSync && this.fd >= 0) {
634
+ try {
635
+ return [createFileInfo(this.name, nodeFS.fstatSync(this.fd)), null]
636
+ } catch (err) {
637
+ return [null, newHostError(err)]
638
+ }
639
+ }
149
640
  return [null, ErrUnimplemented]
150
641
  }
151
642
 
152
643
  // Internal methods
153
644
  public checkValid(op: string): $.GoError {
154
- return ErrUnimplemented
645
+ if (this.closed) {
646
+ return ErrClosed
647
+ }
648
+ if (this.fd < 0) {
649
+ return ErrInvalid
650
+ }
651
+ return null
155
652
  }
156
653
 
157
654
  public wrapErr(op: string, err: $.GoError): $.GoError {
@@ -168,16 +665,21 @@ export class File {
168
665
  { name: "Close", args: [], returns: [{ type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }
169
666
  ],
170
667
  File,
171
- { "file": { kind: $.TypeKind.Pointer, elemType: "file" } }
668
+ { "file": { kind: $.TypeKind.Pointer, elemType: "file" }, "name": { kind: $.TypeKind.Basic, name: "string" }, "closed": { kind: $.TypeKind.Basic, name: "boolean" }, "fd": { kind: $.TypeKind.Basic, name: "number" } }
172
669
  );
173
670
  }
174
671
 
175
- // Stub file type for internal use
176
672
  class file {
177
- constructor() {}
673
+ public handle: DenoFileLike | null
674
+ public path: string
675
+
676
+ constructor(init?: Partial<{handle?: DenoFileLike | null, path?: string}>) {
677
+ this.handle = init?.handle ?? null
678
+ this.path = init?.path ?? ""
679
+ }
178
680
  }
179
681
 
180
- // Stub readdirMode type
682
+ // readdirMode mirrors the Go runtime helper enum.
181
683
  type readdirMode = number
182
684
 
183
685
  // File mode constants
@@ -223,4 +725,4 @@ export function FileMode_String(receiver: fs.FileMode): string {
223
725
 
224
726
  export function FileMode_Type(receiver: fs.FileMode): fs.FileMode {
225
727
  return fs.FileMode_Type(receiver)
226
- }
728
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goscript",
3
3
  "description": "Go to TypeScript transpiler",
4
- "version": "0.0.82",
4
+ "version": "0.0.83",
5
5
  "author": {
6
6
  "name": "Aperture Robotics LLC.",
7
7
  "email": "support@aperture.us",