goscript 0.0.83 → 0.1.0
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/README.md +13 -1
- package/cmd/goscript/cmd_compile.go +70 -69
- package/cmd/goscript/cmd_compile_test.go +79 -0
- package/cmd/goscript/main.go +10 -5
- package/compiler/compile-request.go +218 -0
- package/compiler/compiler.go +16 -1336
- package/compiler/compliance_test.go +196 -0
- package/compiler/config.go +6 -13
- package/compiler/diagnostic.go +70 -0
- package/compiler/index.test.ts +28 -28
- package/compiler/index.ts +40 -72
- package/compiler/lowered-program.go +132 -0
- package/compiler/lowering.go +3576 -0
- package/compiler/override-registry.go +422 -0
- package/compiler/override-registry_test.go +207 -0
- package/compiler/package-graph.go +231 -0
- package/compiler/package-graph_test.go +281 -0
- package/compiler/result.go +13 -0
- package/compiler/runtime-contract.go +279 -0
- package/compiler/runtime-contract_test.go +90 -0
- package/compiler/semantic-model-types.go +110 -0
- package/compiler/semantic-model.go +922 -0
- package/compiler/semantic-model_test.go +416 -0
- package/compiler/service.go +133 -0
- package/compiler/skeleton_test.go +1145 -0
- package/compiler/typescript-emitter.go +663 -0
- package/compiler/wasm/compile.go +2 -3
- package/compiler/wasm/compile_test.go +29 -0
- package/compiler/wasm_api.go +10 -159
- package/dist/compiler/index.d.ts +1 -3
- package/dist/compiler/index.js +31 -55
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +13 -0
- package/dist/gs/builtin/builtin.js +27 -7
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +3 -3
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +86 -0
- package/dist/gs/builtin/hostio.js +266 -0
- package/dist/gs/builtin/hostio.js.map +1 -0
- package/dist/gs/builtin/index.d.ts +1 -0
- package/dist/gs/builtin/index.js +1 -0
- package/dist/gs/builtin/index.js.map +1 -1
- package/dist/gs/builtin/print.d.ts +8 -0
- package/dist/gs/builtin/print.js +111 -0
- package/dist/gs/builtin/print.js.map +1 -0
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +11 -0
- package/dist/gs/builtin/type.js +55 -1
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/rand/index.d.ts +5 -0
- package/dist/gs/crypto/rand/index.js +77 -0
- package/dist/gs/crypto/rand/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +160 -0
- package/dist/gs/encoding/json/index.js.map +1 -0
- package/dist/gs/fmt/fmt.js +2 -22
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +29 -0
- package/dist/gs/go/scanner/index.js +120 -0
- package/dist/gs/go/scanner/index.js.map +1 -0
- package/dist/gs/go/token/index.d.ts +31 -0
- package/dist/gs/go/token/index.js +82 -0
- package/dist/gs/go/token/index.js.map +1 -0
- package/dist/gs/internal/abi/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/readfile.js.map +1 -1
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +2 -4
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/rawconn_js.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/tempfile.gs.js +66 -9
- package/dist/gs/os/tempfile.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +2 -51
- package/dist/gs/os/types_js.gs.js +67 -105
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +2 -2
- package/dist/gs/reflect/index.js +1 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +2 -1
- package/dist/gs/reflect/type.js +85 -14
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/sort/sort.gs.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +1 -0
- package/dist/gs/sync/sync.js +12 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/go.mod +2 -2
- package/gs/builtin/builtin.ts +31 -6
- package/gs/builtin/hostio.test.ts +246 -0
- package/gs/builtin/hostio.ts +413 -0
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/print.test.ts +48 -0
- package/gs/builtin/print.ts +154 -0
- package/gs/builtin/runtime-contract.test.ts +230 -0
- package/gs/builtin/type.ts +84 -1
- package/gs/crypto/rand/index.test.ts +32 -0
- package/gs/crypto/rand/index.ts +90 -0
- package/gs/crypto/rand/meta.json +5 -0
- package/gs/encoding/json/index.test.ts +65 -0
- package/gs/encoding/json/index.ts +186 -0
- package/gs/fmt/fmt.test.ts +41 -30
- package/gs/fmt/fmt.ts +2 -22
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +23 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +3 -1
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
- package/gs/go/scanner/index.test.ts +50 -0
- package/gs/go/scanner/index.ts +157 -0
- package/gs/go/token/index.test.ts +21 -0
- package/gs/go/token/index.ts +120 -0
- package/gs/os/file_unix_js.test.ts +103 -0
- package/gs/os/meta.json +1 -2
- package/gs/os/tempfile.gs.test.ts +85 -0
- package/gs/os/tempfile.gs.ts +71 -11
- package/gs/os/types_js.gs.ts +74 -153
- package/gs/reflect/index.ts +1 -1
- package/gs/reflect/type.ts +106 -17
- package/gs/reflect/typefor.test.ts +75 -0
- package/gs/sync/sync.test.ts +24 -0
- package/gs/sync/sync.ts +12 -0
- package/package.json +13 -13
- package/compiler/analysis.go +0 -3475
- package/compiler/analysis_test.go +0 -338
- package/compiler/assignment.go +0 -580
- package/compiler/builtin_test.go +0 -92
- package/compiler/code-writer.go +0 -115
- package/compiler/compiler_test.go +0 -149
- package/compiler/composite-lit.go +0 -779
- package/compiler/config_test.go +0 -62
- package/compiler/constraint.go +0 -86
- package/compiler/decl.go +0 -801
- package/compiler/expr-call-async.go +0 -188
- package/compiler/expr-call-builtins.go +0 -208
- package/compiler/expr-call-helpers.go +0 -382
- package/compiler/expr-call-make.go +0 -318
- package/compiler/expr-call-type-conversion.go +0 -520
- package/compiler/expr-call.go +0 -413
- package/compiler/expr-selector.go +0 -343
- package/compiler/expr-star.go +0 -82
- package/compiler/expr-type.go +0 -442
- package/compiler/expr-value.go +0 -89
- package/compiler/expr.go +0 -773
- package/compiler/field.go +0 -183
- package/compiler/gs_dependencies_test.go +0 -298
- package/compiler/lit.go +0 -322
- package/compiler/output.go +0 -72
- package/compiler/primitive.go +0 -149
- package/compiler/protobuf.go +0 -697
- package/compiler/sanitize.go +0 -100
- package/compiler/spec-struct.go +0 -995
- package/compiler/spec-value.go +0 -540
- package/compiler/spec.go +0 -725
- package/compiler/stmt-assign.go +0 -664
- package/compiler/stmt-for.go +0 -266
- package/compiler/stmt-range.go +0 -475
- package/compiler/stmt-select.go +0 -262
- package/compiler/stmt-type-switch.go +0 -147
- package/compiler/stmt.go +0 -1308
- package/compiler/type-assert.go +0 -386
- package/compiler/type-info.go +0 -156
- package/compiler/type-utils.go +0 -207
- package/compiler/type.go +0 -892
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { basename, join } from 'node:path'
|
|
2
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
5
|
+
|
|
6
|
+
import { ErrUnimplemented } from './error.gs.js'
|
|
7
|
+
import { CreateTemp, MkdirTemp } from './tempfile.gs.js'
|
|
8
|
+
|
|
9
|
+
const tempRoots: string[] = []
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
vi.restoreAllMocks()
|
|
13
|
+
vi.unstubAllGlobals()
|
|
14
|
+
for (const root of tempRoots.splice(0)) {
|
|
15
|
+
rmSync(root, { force: true, recursive: true })
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
function makeTempRoot(): string {
|
|
20
|
+
const root = mkdtempSync(join(tmpdir(), 'goscript-os-temp-'))
|
|
21
|
+
tempRoots.push(root)
|
|
22
|
+
return root
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function stubRandomBytes(bytes: number[]): void {
|
|
26
|
+
vi.stubGlobal('crypto', {
|
|
27
|
+
getRandomValues: vi.fn((dst: Uint8Array) => {
|
|
28
|
+
for (let i = 0; i < dst.length; i++) {
|
|
29
|
+
dst[i] = bytes[i] ?? 0
|
|
30
|
+
}
|
|
31
|
+
return dst
|
|
32
|
+
}),
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function forbidMathRandom(): void {
|
|
37
|
+
vi.spyOn(Math, 'random').mockImplementation(() => {
|
|
38
|
+
throw new Error('os temp names must not use Math.random')
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe('os temp files', () => {
|
|
43
|
+
it('uses Web Crypto bytes for temp names', () => {
|
|
44
|
+
const root = makeTempRoot()
|
|
45
|
+
stubRandomBytes([0x78, 0x56, 0x34, 0x12])
|
|
46
|
+
forbidMathRandom()
|
|
47
|
+
|
|
48
|
+
const [dir, dirErr] = MkdirTemp(root, 'dir-*.tmp')
|
|
49
|
+
expect(dirErr).toBeNull()
|
|
50
|
+
expect(basename(dir)).toBe('dir-305419896.tmp')
|
|
51
|
+
expect(existsSync(dir)).toBe(true)
|
|
52
|
+
|
|
53
|
+
const [file, fileErr] = CreateTemp(root, 'file-*.tmp')
|
|
54
|
+
expect(fileErr).toBeNull()
|
|
55
|
+
expect(file).not.toBeNull()
|
|
56
|
+
expect(basename(file!.Name())).toBe('file-305419896.tmp')
|
|
57
|
+
expect(existsSync(file!.Name())).toBe(true)
|
|
58
|
+
file!.Close()
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('does not truncate an existing path after a random collision', () => {
|
|
62
|
+
const root = makeTempRoot()
|
|
63
|
+
const existing = join(root, 'file-305419896.tmp')
|
|
64
|
+
writeFileSync(existing, 'keep')
|
|
65
|
+
stubRandomBytes([0x78, 0x56, 0x34, 0x12])
|
|
66
|
+
forbidMathRandom()
|
|
67
|
+
|
|
68
|
+
const [file, err] = CreateTemp(root, 'file-*.tmp')
|
|
69
|
+
|
|
70
|
+
expect(file).toBeNull()
|
|
71
|
+
expect(err).not.toBeNull()
|
|
72
|
+
expect(readFileSync(existing, 'utf8')).toBe('keep')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('reports ErrUnimplemented without a secure random source', () => {
|
|
76
|
+
const root = makeTempRoot()
|
|
77
|
+
vi.stubGlobal('crypto', {})
|
|
78
|
+
forbidMathRandom()
|
|
79
|
+
|
|
80
|
+
const [dir, err] = MkdirTemp(root, 'dir-*')
|
|
81
|
+
|
|
82
|
+
expect(dir).toBe('')
|
|
83
|
+
expect(err).toBe(ErrUnimplemented)
|
|
84
|
+
})
|
|
85
|
+
})
|
package/gs/os/tempfile.gs.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as $ from "@goscript/builtin/index.js";
|
|
2
2
|
import { ErrUnimplemented } from "./error.gs.js";
|
|
3
3
|
import { TempDir } from "./file_constants_js.gs.js";
|
|
4
|
-
import {
|
|
5
|
-
import { File } from "./types_js.gs.js";
|
|
4
|
+
import { Mkdir } from "./file_js.gs.js";
|
|
5
|
+
import { createHostFile, File, getDeno, getNodeFS, newHostError } from "./types_js.gs.js";
|
|
6
6
|
|
|
7
7
|
export function joinPath(dir: string, file: string): string {
|
|
8
8
|
if (dir === "" || dir === ".") {
|
|
@@ -20,33 +20,93 @@ export function joinPath(dir: string, file: string): string {
|
|
|
20
20
|
return dir + "/" + file
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function nextTempPath(dir: string, pattern: string): string {
|
|
23
|
+
function nextTempPath(dir: string, pattern: string): [string, $.GoError] {
|
|
24
24
|
const baseDir = dir === "" ? TempDir() : dir
|
|
25
|
-
const suffix
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const [suffix, err] = nextRandom()
|
|
26
|
+
if (err !== null) {
|
|
27
|
+
return ["", err]
|
|
28
|
+
}
|
|
29
|
+
const star = pattern.lastIndexOf("*")
|
|
30
|
+
const name =
|
|
31
|
+
star >= 0
|
|
32
|
+
? pattern.slice(0, star) + suffix + pattern.slice(star + 1)
|
|
33
|
+
: pattern + suffix
|
|
34
|
+
return [joinPath(baseDir, name), null]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function nextRandom(): [string, $.GoError] {
|
|
38
|
+
const crypto = globalThis.crypto
|
|
39
|
+
if (!crypto || typeof crypto.getRandomValues !== "function") {
|
|
40
|
+
return ["", ErrUnimplemented]
|
|
41
|
+
}
|
|
42
|
+
const bytes = new Uint8Array(4)
|
|
43
|
+
crypto.getRandomValues(bytes)
|
|
44
|
+
const value =
|
|
45
|
+
bytes[0] |
|
|
46
|
+
(bytes[1] << 8) |
|
|
47
|
+
(bytes[2] << 16) |
|
|
48
|
+
(bytes[3] << 24)
|
|
49
|
+
return [(value >>> 0).toString(10), null]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function createTempFile(path: string): [File | null, $.GoError] {
|
|
53
|
+
const denoObj = getDeno()
|
|
54
|
+
if (denoObj?.openSync) {
|
|
55
|
+
try {
|
|
56
|
+
const handle = denoObj.openSync(path, {
|
|
57
|
+
createNew: true,
|
|
58
|
+
mode: 0o600,
|
|
59
|
+
read: true,
|
|
60
|
+
write: true,
|
|
61
|
+
})
|
|
62
|
+
return [createHostFile(path, handle?.rid ?? -1, handle), null]
|
|
63
|
+
} catch (err) {
|
|
64
|
+
return [null, newHostError(err)]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const nodeFS = getNodeFS()
|
|
69
|
+
if (nodeFS?.openSync) {
|
|
70
|
+
try {
|
|
71
|
+
return [createHostFile(path, nodeFS.openSync(path, "wx+", 0o600)), null]
|
|
72
|
+
} catch (err) {
|
|
73
|
+
return [null, newHostError(err)]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return [null, ErrUnimplemented]
|
|
28
78
|
}
|
|
29
79
|
|
|
30
80
|
export function CreateTemp(dir: string, pattern: string): [File | null, $.GoError] {
|
|
31
81
|
const template = pattern === "" ? "tmp-*" : pattern
|
|
82
|
+
let lastErr: $.GoError = ErrUnimplemented
|
|
32
83
|
for (let i = 0; i < 16; i++) {
|
|
33
|
-
const path = nextTempPath(dir, template)
|
|
34
|
-
|
|
84
|
+
const [path, randErr] = nextTempPath(dir, template)
|
|
85
|
+
if (randErr !== null) {
|
|
86
|
+
return [null, randErr]
|
|
87
|
+
}
|
|
88
|
+
const [file, err] = createTempFile(path)
|
|
35
89
|
if (err === null) {
|
|
36
90
|
return [file, null]
|
|
37
91
|
}
|
|
92
|
+
lastErr = err
|
|
38
93
|
}
|
|
39
|
-
return [null,
|
|
94
|
+
return [null, lastErr]
|
|
40
95
|
}
|
|
41
96
|
|
|
42
97
|
export function MkdirTemp(dir: string, pattern: string): [string, $.GoError] {
|
|
43
98
|
const template = pattern === "" ? "tmp-*" : pattern
|
|
99
|
+
let lastErr: $.GoError = ErrUnimplemented
|
|
44
100
|
for (let i = 0; i < 16; i++) {
|
|
45
|
-
const path = nextTempPath(dir, template)
|
|
101
|
+
const [path, randErr] = nextTempPath(dir, template)
|
|
102
|
+
if (randErr !== null) {
|
|
103
|
+
return ["", randErr]
|
|
104
|
+
}
|
|
46
105
|
const err = Mkdir(path, 0o700)
|
|
47
106
|
if (err === null) {
|
|
48
107
|
return [path, null]
|
|
49
108
|
}
|
|
109
|
+
lastErr = err
|
|
50
110
|
}
|
|
51
|
-
return ["",
|
|
111
|
+
return ["", lastErr]
|
|
52
112
|
}
|
package/gs/os/types_js.gs.ts
CHANGED
|
@@ -5,50 +5,16 @@ 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 {
|
|
9
|
+
DenoFileLike,
|
|
10
|
+
DenoStream,
|
|
11
|
+
getHostRuntime,
|
|
12
|
+
HostUnsupportedError,
|
|
13
|
+
NodeFSModule,
|
|
14
|
+
resetHostRuntimeForTests,
|
|
15
|
+
} from "@goscript/builtin/hostio.js"
|
|
8
16
|
import { newRawConn } from "./rawconn_js.gs.js"
|
|
9
17
|
|
|
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
18
|
export type HostStatLike = {
|
|
53
19
|
isDirectory(): boolean
|
|
54
20
|
isSymbolicLink?(): boolean
|
|
@@ -66,90 +32,24 @@ export function newHostError(err: unknown): $.GoError {
|
|
|
66
32
|
return { Error: () => message }
|
|
67
33
|
}
|
|
68
34
|
|
|
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
35
|
export function getNodeFS(): NodeFSModule | null {
|
|
80
|
-
|
|
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
|
|
36
|
+
return getHostRuntime().nodeFS
|
|
103
37
|
}
|
|
104
38
|
|
|
105
39
|
export function getDeno(): any | null {
|
|
106
|
-
return (
|
|
40
|
+
return getHostRuntime().deno
|
|
107
41
|
}
|
|
108
42
|
|
|
109
43
|
export function getPlatform(): string {
|
|
110
|
-
|
|
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"
|
|
44
|
+
return getHostRuntime().platform
|
|
121
45
|
}
|
|
122
46
|
|
|
123
47
|
export function getEnv(name: string): string {
|
|
124
|
-
|
|
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] ?? ""
|
|
48
|
+
return getHostRuntime().getEnv(name)
|
|
135
49
|
}
|
|
136
50
|
|
|
137
51
|
export function getDenoStream(fd: number): DenoStream | null {
|
|
138
|
-
|
|
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
|
-
}
|
|
52
|
+
return getHostRuntime().getStdioHandle(fd)
|
|
153
53
|
}
|
|
154
54
|
|
|
155
55
|
function readFD(fd: number, b: Uint8Array): [number, $.GoError] {
|
|
@@ -157,33 +57,18 @@ function readFD(fd: number, b: Uint8Array): [number, $.GoError] {
|
|
|
157
57
|
return [0, null]
|
|
158
58
|
}
|
|
159
59
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (n === null || n === 0) {
|
|
165
|
-
return [0, io.EOF]
|
|
166
|
-
}
|
|
167
|
-
return [n, null]
|
|
168
|
-
} catch (err) {
|
|
169
|
-
return [0, newHostError(err)]
|
|
60
|
+
try {
|
|
61
|
+
const n = getHostRuntime().readFD(fd, b)
|
|
62
|
+
if (n === null || n === 0) {
|
|
63
|
+
return [0, io.EOF]
|
|
170
64
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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)]
|
|
65
|
+
return [n, null]
|
|
66
|
+
} catch (err) {
|
|
67
|
+
if (err instanceof HostUnsupportedError) {
|
|
68
|
+
return [0, ErrUnimplemented]
|
|
183
69
|
}
|
|
70
|
+
return [0, newHostError(err)]
|
|
184
71
|
}
|
|
185
|
-
|
|
186
|
-
return [0, ErrUnimplemented]
|
|
187
72
|
}
|
|
188
73
|
|
|
189
74
|
function writeFD(fd: number, b: Uint8Array): [number, $.GoError] {
|
|
@@ -191,25 +76,51 @@ function writeFD(fd: number, b: Uint8Array): [number, $.GoError] {
|
|
|
191
76
|
return [0, null]
|
|
192
77
|
}
|
|
193
78
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return [0, newHostError(err)]
|
|
79
|
+
try {
|
|
80
|
+
return [getHostRuntime().writeFD(fd, b), null]
|
|
81
|
+
} catch (err) {
|
|
82
|
+
if (err instanceof HostUnsupportedError) {
|
|
83
|
+
return [0, ErrUnimplemented]
|
|
200
84
|
}
|
|
85
|
+
return [0, newHostError(err)]
|
|
201
86
|
}
|
|
87
|
+
}
|
|
202
88
|
|
|
203
|
-
|
|
204
|
-
if (
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
89
|
+
function readHandle(handle: DenoFileLike, b: Uint8Array): [number, $.GoError] {
|
|
90
|
+
if (typeof handle.readSync !== "function") {
|
|
91
|
+
return [0, ErrUnimplemented]
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const n = handle.readSync(b)
|
|
95
|
+
if (n === null || n === 0) {
|
|
96
|
+
return [0, io.EOF]
|
|
209
97
|
}
|
|
98
|
+
return [n, null]
|
|
99
|
+
} catch (err) {
|
|
100
|
+
return [0, newHostError(err)]
|
|
210
101
|
}
|
|
102
|
+
}
|
|
211
103
|
|
|
212
|
-
|
|
104
|
+
function writeHandle(handle: DenoFileLike, b: Uint8Array): [number, $.GoError] {
|
|
105
|
+
if (typeof handle.writeSync !== "function") {
|
|
106
|
+
return [0, ErrUnimplemented]
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
let offset = 0
|
|
110
|
+
while (offset < b.length) {
|
|
111
|
+
const n = handle.writeSync(b.subarray(offset))
|
|
112
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
113
|
+
throw new Error(`invalid write result: ${n}`)
|
|
114
|
+
}
|
|
115
|
+
if (n === 0) {
|
|
116
|
+
throw new Error("short write")
|
|
117
|
+
}
|
|
118
|
+
offset += n
|
|
119
|
+
}
|
|
120
|
+
return [b.length, null]
|
|
121
|
+
} catch (err) {
|
|
122
|
+
return [0, newHostError(err)]
|
|
123
|
+
}
|
|
213
124
|
}
|
|
214
125
|
|
|
215
126
|
class hostFileInfo {
|
|
@@ -281,11 +192,13 @@ export function createFileInfo(name: string, stat: HostStatLike): fs.FileInfo {
|
|
|
281
192
|
export function createHostFile(name: string, fd: number = -1, handle: DenoFileLike | null = null): File {
|
|
282
193
|
return new File({
|
|
283
194
|
fd,
|
|
284
|
-
file: new file({ handle, path: name }),
|
|
195
|
+
file: new file({ handle: handle ?? getHostRuntime().getStdioHandle(fd), path: name }),
|
|
285
196
|
name,
|
|
286
197
|
})
|
|
287
198
|
}
|
|
288
199
|
|
|
200
|
+
export { resetHostRuntimeForTests }
|
|
201
|
+
|
|
289
202
|
// Re-export essential types
|
|
290
203
|
export type Time = time.Time;
|
|
291
204
|
export type FileInfo = fs.FileInfo;
|
|
@@ -371,7 +284,11 @@ export class File {
|
|
|
371
284
|
return [0, null]
|
|
372
285
|
}
|
|
373
286
|
const buf = $.bytesToUint8Array(b)
|
|
374
|
-
const
|
|
287
|
+
const handle = this.file?.handle
|
|
288
|
+
const [n, err] =
|
|
289
|
+
handle && typeof handle.readSync === "function"
|
|
290
|
+
? readHandle(handle, buf)
|
|
291
|
+
: readFD(this.fd, buf)
|
|
375
292
|
if (!(b instanceof Uint8Array) && n > 0) {
|
|
376
293
|
$.copy(b, buf.subarray(0, n))
|
|
377
294
|
}
|
|
@@ -408,7 +325,11 @@ export class File {
|
|
|
408
325
|
if (b === null) {
|
|
409
326
|
return [0, null]
|
|
410
327
|
}
|
|
411
|
-
|
|
328
|
+
const buf = $.bytesToUint8Array(b)
|
|
329
|
+
const handle = this.file?.handle
|
|
330
|
+
return handle && typeof handle.writeSync === "function"
|
|
331
|
+
? writeHandle(handle, buf)
|
|
332
|
+
: writeFD(this.fd, buf)
|
|
412
333
|
}
|
|
413
334
|
|
|
414
335
|
public WriteAt(b: $.Bytes, off: number): [number, $.GoError] {
|
package/gs/reflect/index.ts
CHANGED
package/gs/reflect/type.ts
CHANGED
|
@@ -167,6 +167,7 @@ export const Func: Kind = 19
|
|
|
167
167
|
export const Interface: Kind = 20
|
|
168
168
|
export const Map: Kind = 21
|
|
169
169
|
export const Ptr: Kind = 22
|
|
170
|
+
export const Pointer: Kind = Ptr
|
|
170
171
|
export const Slice: Kind = 23
|
|
171
172
|
export const String: Kind = 24
|
|
172
173
|
export const Struct: Kind = 25
|
|
@@ -1945,22 +1946,7 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
1945
1946
|
typeInfo.params &&
|
|
1946
1947
|
typeInfo.results
|
|
1947
1948
|
) {
|
|
1948
|
-
|
|
1949
|
-
const paramTypes = typeInfo.params
|
|
1950
|
-
.map((p: any) => (typeof p === 'string' ? p : p.name || 'any'))
|
|
1951
|
-
.join(', ')
|
|
1952
|
-
const resultTypes = typeInfo.results.map((r: any) =>
|
|
1953
|
-
typeof r === 'string' ? r : r.name || 'any',
|
|
1954
|
-
)
|
|
1955
|
-
|
|
1956
|
-
let signature = `func(${paramTypes})`
|
|
1957
|
-
if (resultTypes.length === 1) {
|
|
1958
|
-
signature += ` ${resultTypes[0]}`
|
|
1959
|
-
} else if (resultTypes.length > 1) {
|
|
1960
|
-
signature += ` (${resultTypes.join(', ')})`
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
return new FunctionType(signature)
|
|
1949
|
+
return functionTypeFromInfo(typeInfo)
|
|
1964
1950
|
}
|
|
1965
1951
|
}
|
|
1966
1952
|
|
|
@@ -2180,10 +2166,113 @@ export function ChanOf(dir: ChanDir, t: Type): Type {
|
|
|
2180
2166
|
return new ChannelType(t, dir)
|
|
2181
2167
|
}
|
|
2182
2168
|
|
|
2183
|
-
export function TypeFor(): Type {
|
|
2169
|
+
export function TypeFor(typeArgs?: $.GenericTypeArgs): Type {
|
|
2170
|
+
const descriptor = typeArgs?.T
|
|
2171
|
+
if (descriptor?.type) {
|
|
2172
|
+
return typeFromTypeInfo(descriptor.type)
|
|
2173
|
+
}
|
|
2174
|
+
if (descriptor?.methods) {
|
|
2175
|
+
const methods = Object.keys(descriptor.methods)
|
|
2176
|
+
if (methods.length !== 0) {
|
|
2177
|
+
return new InterfaceType(
|
|
2178
|
+
`interface { ${methods.map((method) => method + '()').join('; ')} }`,
|
|
2179
|
+
)
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
if (descriptor?.zero) {
|
|
2183
|
+
return getTypeOf(descriptor.zero())
|
|
2184
|
+
}
|
|
2184
2185
|
return new InterfaceType('interface{}')
|
|
2185
2186
|
}
|
|
2186
2187
|
|
|
2188
|
+
function typeFromTypeInfo(info: $.TypeInfo | string): Type {
|
|
2189
|
+
if (typeof info === 'string') {
|
|
2190
|
+
const registered = builtinGetTypeByName(info)
|
|
2191
|
+
if (registered) {
|
|
2192
|
+
return typeFromTypeInfo(registered)
|
|
2193
|
+
}
|
|
2194
|
+
return StructType.createTypeFromFieldInfo(info)
|
|
2195
|
+
}
|
|
2196
|
+
switch (info.kind) {
|
|
2197
|
+
case $.TypeKind.Array:
|
|
2198
|
+
return new ArrayType(
|
|
2199
|
+
typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }),
|
|
2200
|
+
info.length,
|
|
2201
|
+
)
|
|
2202
|
+
case $.TypeKind.Channel:
|
|
2203
|
+
return new ChannelType(
|
|
2204
|
+
typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }),
|
|
2205
|
+
chanDirFromTypeInfo(info.direction),
|
|
2206
|
+
)
|
|
2207
|
+
case $.TypeKind.Function:
|
|
2208
|
+
return functionTypeFromInfo(info)
|
|
2209
|
+
case $.TypeKind.Interface:
|
|
2210
|
+
return interfaceTypeFromInfo(info)
|
|
2211
|
+
case $.TypeKind.Map:
|
|
2212
|
+
return new MapType(
|
|
2213
|
+
typeFromTypeInfo(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }),
|
|
2214
|
+
typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }),
|
|
2215
|
+
)
|
|
2216
|
+
case $.TypeKind.Pointer:
|
|
2217
|
+
return new PointerType(
|
|
2218
|
+
typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }),
|
|
2219
|
+
)
|
|
2220
|
+
default:
|
|
2221
|
+
return StructType.createTypeFromFieldInfo(info)
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
function functionTypeFromInfo(info: $.FunctionTypeInfo): Type {
|
|
2226
|
+
if (info.name) {
|
|
2227
|
+
return new FunctionType(info.name)
|
|
2228
|
+
}
|
|
2229
|
+
const params = info.params ?? []
|
|
2230
|
+
const paramTypes = params.map((param, index) => {
|
|
2231
|
+
const typeName = functionSignatureTypeName(param)
|
|
2232
|
+
if (!info.isVariadic || index !== params.length - 1) {
|
|
2233
|
+
return typeName
|
|
2234
|
+
}
|
|
2235
|
+
if (typeName.startsWith('[]')) {
|
|
2236
|
+
return '...' + typeName.slice(2)
|
|
2237
|
+
}
|
|
2238
|
+
return '...' + typeName
|
|
2239
|
+
})
|
|
2240
|
+
const resultTypes = (info.results ?? []).map(functionSignatureTypeName)
|
|
2241
|
+
let signature = `func(${paramTypes.join(', ')})`
|
|
2242
|
+
if (resultTypes.length === 1) {
|
|
2243
|
+
signature += ` ${resultTypes[0]}`
|
|
2244
|
+
}
|
|
2245
|
+
if (resultTypes.length > 1) {
|
|
2246
|
+
signature += ` (${resultTypes.join(', ')})`
|
|
2247
|
+
}
|
|
2248
|
+
return new FunctionType(signature)
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
function functionSignatureTypeName(info: $.TypeInfo | string): string {
|
|
2252
|
+
return typeFromTypeInfo(info).String()
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
function interfaceTypeFromInfo(info: $.InterfaceTypeInfo): Type {
|
|
2256
|
+
if (info.methods.length === 0) {
|
|
2257
|
+
return new InterfaceType('interface{}', info.name)
|
|
2258
|
+
}
|
|
2259
|
+
return new InterfaceType(
|
|
2260
|
+
`interface { ${info.methods.map((method) => method.name + '()').join('; ')} }`,
|
|
2261
|
+
info.name,
|
|
2262
|
+
)
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
function chanDirFromTypeInfo(direction?: 'send' | 'receive' | 'both'): ChanDir {
|
|
2266
|
+
switch (direction) {
|
|
2267
|
+
case 'send':
|
|
2268
|
+
return SendDir
|
|
2269
|
+
case 'receive':
|
|
2270
|
+
return RecvDir
|
|
2271
|
+
default:
|
|
2272
|
+
return BothDir
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2187
2276
|
/**
|
|
2188
2277
|
* getInterfaceTypeByName looks up a registered interface type by name
|
|
2189
2278
|
* and returns a Type for it. Returns an interface{} type if not found.
|