goscript 0.0.75 → 0.0.77
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/cmd/goscript/main.js +48 -12
- package/compiler/analysis.go +100 -33
- package/compiler/analysis_test.go +2 -7
- package/compiler/assignment.go +34 -12
- package/compiler/code-writer.go +2 -2
- package/compiler/compiler.go +4 -4
- package/compiler/composite-lit.go +4 -6
- package/compiler/constraint.go +2 -4
- package/compiler/expr-call-async.go +4 -0
- package/compiler/expr-call-helpers.go +98 -8
- package/compiler/expr-call-make.go +4 -4
- package/compiler/expr-call.go +3 -0
- package/compiler/expr-type.go +42 -0
- package/compiler/gs_dependencies_test.go +3 -14
- package/compiler/index.ts +20 -5
- package/compiler/protobuf.go +21 -21
- package/compiler/spec-struct.go +22 -30
- package/compiler/spec.go +2 -2
- package/compiler/stmt-assign.go +2 -2
- package/compiler/type-info.go +20 -3
- package/compiler/type-utils.go +2 -4
- package/compiler/type.go +3 -4
- package/dist/compiler/index.js +13 -4
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +6 -0
- package/dist/gs/builtin/builtin.js +26 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.js +2 -3
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +1 -0
- package/dist/gs/builtin/type.js +8 -14
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.d.ts +1 -0
- package/dist/gs/bytes/buffer.gs.js +20 -0
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +5 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +10 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.d.ts +50 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js +221 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/index.js +2 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/index.js +2 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/runtime.d.ts +56 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/runtime.js +17 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/runtime.js.map +1 -0
- package/dist/gs/io/fs/format.js +2 -6
- package/dist/gs/io/fs/format.js.map +1 -1
- package/dist/gs/io/fs/glob.js +18 -23
- package/dist/gs/io/fs/glob.js.map +1 -1
- package/dist/gs/path/match.js +9 -22
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +1 -1
- package/dist/gs/reflect/index.js +1 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +1 -0
- package/dist/gs/reflect/type.js +52 -23
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/strings/iter.js +1 -1
- package/dist/gs/strings/iter.js.map +1 -1
- package/dist/gs/strings/reader.js +1 -1
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js +9 -20
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/time/time.js +2 -2
- package/dist/gs/time/time.js.map +1 -1
- package/go.mod +9 -10
- package/go.sum +20 -22
- package/gs/builtin/builtin.ts +29 -0
- package/gs/builtin/slice.ts +2 -2
- package/gs/builtin/type.ts +14 -14
- package/gs/bytes/buffer.gs.ts +21 -1
- package/gs/fmt/fmt.test.ts +1 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +14 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +238 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/index.ts +1 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +12 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/index.ts +1 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/meta.json +8 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/runtime.ts +94 -0
- package/gs/io/fs/format.ts +2 -5
- package/gs/io/fs/glob.ts +18 -21
- package/gs/path/match.ts +9 -22
- package/gs/reflect/index.ts +1 -0
- package/gs/reflect/type.ts +62 -25
- package/gs/strings/iter.ts +1 -1
- package/gs/strings/reader.ts +1 -1
- package/gs/strings/replace.ts +13 -18
- package/gs/time/time.ts +2 -2
- package/gs.go +8 -0
- package/package.json +20 -16
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// Package browser_runtime implements VmRuntime backed by the browser
|
|
2
|
+
// WebAssembly API. Pure TypeScript -- no syscall/js indirection.
|
|
3
|
+
|
|
4
|
+
import type * as vmruntime from '../runtime.js'
|
|
5
|
+
|
|
6
|
+
// Runtime implements VmRuntime using the browser WebAssembly API.
|
|
7
|
+
export class Runtime implements vmruntime.VmRuntime {
|
|
8
|
+
constructor() {}
|
|
9
|
+
|
|
10
|
+
// Compile calls WebAssembly.compile and returns a Module.
|
|
11
|
+
async Compile(
|
|
12
|
+
_ctx: any,
|
|
13
|
+
wasm: Uint8Array | number[],
|
|
14
|
+
): Promise<Module> {
|
|
15
|
+
const bytes = wasm instanceof Uint8Array ? wasm : new Uint8Array(wasm)
|
|
16
|
+
const compiled = await WebAssembly.compile(bytes.buffer as ArrayBuffer)
|
|
17
|
+
return new Module(compiled)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Close is a no-op for the browser runtime.
|
|
21
|
+
async Close(_ctx: any): Promise<null> {
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// New creates a new browser-backed VmRuntime.
|
|
27
|
+
export function New(): Runtime {
|
|
28
|
+
return new Runtime()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Module wraps a WebAssembly.Module.
|
|
32
|
+
export class Module implements vmruntime.VmModule {
|
|
33
|
+
constructor(private readonly wasmModule: WebAssembly.Module) {}
|
|
34
|
+
|
|
35
|
+
// Instantiate creates an instance with host functions wired as imports.
|
|
36
|
+
async Instantiate(
|
|
37
|
+
ctx: any,
|
|
38
|
+
config: vmruntime.VmModuleConfig,
|
|
39
|
+
): Promise<Instance> {
|
|
40
|
+
const imports = this.buildImports(ctx, config.HostFunctions)
|
|
41
|
+
const wasmInst = await WebAssembly.instantiate(this.wasmModule, imports)
|
|
42
|
+
const inst = new Instance(wasmInst)
|
|
43
|
+
// Patch the captured instance reference in host function closures.
|
|
44
|
+
if ((imports as any).__instRef) {
|
|
45
|
+
;(imports as any).__instRef.current = inst
|
|
46
|
+
}
|
|
47
|
+
return inst
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Close is a no-op.
|
|
51
|
+
async Close(_ctx: any): Promise<null> {
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// buildImports constructs the WebAssembly imports object.
|
|
56
|
+
private buildImports(
|
|
57
|
+
ctx: any,
|
|
58
|
+
hostFns: Map<string, vmruntime.HostFunction> | null,
|
|
59
|
+
): WebAssembly.Imports {
|
|
60
|
+
const imports: Record<string, Record<string, WebAssembly.ImportValue>> = {}
|
|
61
|
+
if (!hostFns) return imports
|
|
62
|
+
|
|
63
|
+
// Shared mutable ref -- patched after instantiation.
|
|
64
|
+
const instRef: { current: Instance | null } = { current: null }
|
|
65
|
+
|
|
66
|
+
hostFns.forEach((fn, key) => {
|
|
67
|
+
let modName = 'env'
|
|
68
|
+
let funcName = key
|
|
69
|
+
const dot = key.indexOf('.')
|
|
70
|
+
if (dot !== -1) {
|
|
71
|
+
modName = key.substring(0, dot)
|
|
72
|
+
funcName = key.substring(dot + 1)
|
|
73
|
+
}
|
|
74
|
+
if (!imports[modName]) imports[modName] = {}
|
|
75
|
+
|
|
76
|
+
imports[modName][funcName] = (...args: number[]) => {
|
|
77
|
+
const stack = new BigInt64Array(args.length)
|
|
78
|
+
for (let i = 0; i < args.length; i++) {
|
|
79
|
+
stack[i] = BigInt(args[i])
|
|
80
|
+
}
|
|
81
|
+
const u64Stack: number[] = args.map((a) => a >>> 0)
|
|
82
|
+
const err = fn(ctx, instRef.current, u64Stack)
|
|
83
|
+
if (err) throw err
|
|
84
|
+
// WASM i32 return: first stack element.
|
|
85
|
+
if (u64Stack.length > 0) return u64Stack[0]
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Stash the ref so Instantiate can patch it.
|
|
90
|
+
;(imports as any).__instRef = instRef
|
|
91
|
+
return imports
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Instance wraps a WebAssembly.Instance.
|
|
96
|
+
export class Instance implements vmruntime.VmInstance {
|
|
97
|
+
private readonly exports: WebAssembly.Exports
|
|
98
|
+
|
|
99
|
+
constructor(private readonly wasmInstance: WebAssembly.Instance) {
|
|
100
|
+
this.exports = wasmInstance.exports
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Call invokes an exported function by name.
|
|
104
|
+
async Call(
|
|
105
|
+
_ctx: any,
|
|
106
|
+
name: string,
|
|
107
|
+
...args: number[]
|
|
108
|
+
): Promise<number[] | null> {
|
|
109
|
+
const fn = this.exports[name]
|
|
110
|
+
if (typeof fn !== 'function') return null
|
|
111
|
+
const result = (fn as (...args: number[]) => unknown)(...args)
|
|
112
|
+
if (result === undefined) return null
|
|
113
|
+
return [result as number]
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Memory returns the instance's linear memory.
|
|
117
|
+
Memory(): BrowserMemory | null {
|
|
118
|
+
const mem = this.exports.memory
|
|
119
|
+
if (!(mem instanceof WebAssembly.Memory)) return null
|
|
120
|
+
return new BrowserMemory(mem)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ExportedFunction returns a callable reference.
|
|
124
|
+
ExportedFunction(name: string): BrowserFunction | null {
|
|
125
|
+
const fn = this.exports[name]
|
|
126
|
+
if (typeof fn !== 'function') return null
|
|
127
|
+
return new BrowserFunction(fn as (...args: number[]) => unknown)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ExportedGlobal returns a reference to an exported global.
|
|
131
|
+
ExportedGlobal(name: string): BrowserGlobal | null {
|
|
132
|
+
const g = this.exports[name]
|
|
133
|
+
if (!(g instanceof WebAssembly.Global)) return null
|
|
134
|
+
return new BrowserGlobal(g)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Close is a no-op.
|
|
138
|
+
async Close(_ctx: any): Promise<null> {
|
|
139
|
+
return null
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// BrowserFunction wraps a WebAssembly exported function.
|
|
144
|
+
export class BrowserFunction implements vmruntime.VmFunction {
|
|
145
|
+
constructor(private readonly fn: (...args: number[]) => unknown) {}
|
|
146
|
+
|
|
147
|
+
async Call(_ctx: any, ...args: number[]): Promise<number[] | null> {
|
|
148
|
+
const result = this.fn(...args)
|
|
149
|
+
if (result === undefined) return null
|
|
150
|
+
return [result as number]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// BrowserGlobal wraps a WebAssembly.Global.
|
|
155
|
+
export class BrowserGlobal implements vmruntime.VmGlobal {
|
|
156
|
+
constructor(private readonly global: WebAssembly.Global) {}
|
|
157
|
+
|
|
158
|
+
Get(): number {
|
|
159
|
+
return this.global.value as number
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Set(val: number): void {
|
|
163
|
+
this.global.value = val
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// BrowserMemory wraps WebAssembly.Memory with typed DataView access.
|
|
168
|
+
export class BrowserMemory implements vmruntime.VmMemory {
|
|
169
|
+
constructor(private readonly mem: WebAssembly.Memory) {}
|
|
170
|
+
|
|
171
|
+
private get buf(): ArrayBuffer {
|
|
172
|
+
return this.mem.buffer
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
Read(offset: number, length: number): [Uint8Array, boolean] {
|
|
176
|
+
if (offset + length > this.buf.byteLength) return [new Uint8Array(0), false]
|
|
177
|
+
return [new Uint8Array(this.buf, offset, length), true]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
ReadByteAt(offset: number): [number, boolean] {
|
|
181
|
+
if (offset >= this.buf.byteLength) return [0, false]
|
|
182
|
+
return [new Uint8Array(this.buf, offset, 1)[0], true]
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
ReadUint32Le(offset: number): [number, boolean] {
|
|
186
|
+
if (offset + 4 > this.buf.byteLength) return [0, false]
|
|
187
|
+
return [new DataView(this.buf).getUint32(offset, true), true]
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ReadUint64Le(offset: number): [bigint, boolean] {
|
|
191
|
+
if (offset + 8 > this.buf.byteLength) return [0n, false]
|
|
192
|
+
const dv = new DataView(this.buf)
|
|
193
|
+
const lo = BigInt(dv.getUint32(offset, true))
|
|
194
|
+
const hi = BigInt(dv.getUint32(offset + 4, true))
|
|
195
|
+
return [lo | (hi << 32n), true]
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
Write(offset: number, data: Uint8Array | number[]): boolean {
|
|
199
|
+
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data)
|
|
200
|
+
if (offset + bytes.length > this.buf.byteLength) return false
|
|
201
|
+
new Uint8Array(this.buf, offset, bytes.length).set(bytes)
|
|
202
|
+
return true
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
WriteByteAt(offset: number, val: number): boolean {
|
|
206
|
+
if (offset >= this.buf.byteLength) return false
|
|
207
|
+
new Uint8Array(this.buf, offset, 1)[0] = val
|
|
208
|
+
return true
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
WriteUint32Le(offset: number, val: number): boolean {
|
|
212
|
+
if (offset + 4 > this.buf.byteLength) return false
|
|
213
|
+
new DataView(this.buf).setUint32(offset, val, true)
|
|
214
|
+
return true
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
WriteUint64Le(offset: number, val: bigint | number): boolean {
|
|
218
|
+
if (offset + 8 > this.buf.byteLength) return false
|
|
219
|
+
const v = typeof val === 'bigint' ? val : BigInt(val)
|
|
220
|
+
const dv = new DataView(this.buf)
|
|
221
|
+
dv.setUint32(offset, Number(v & 0xffffffffn), true)
|
|
222
|
+
dv.setUint32(offset + 4, Number((v >> 32n) & 0xffffffffn), true)
|
|
223
|
+
return true
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
Size(): number {
|
|
227
|
+
return this.buf.byteLength
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
Grow(pages: number): [number, boolean] {
|
|
231
|
+
try {
|
|
232
|
+
const prev = this.mem.grow(pages)
|
|
233
|
+
return [prev, true]
|
|
234
|
+
} catch {
|
|
235
|
+
return [0, false]
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './browser.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './runtime.js'
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Package vmruntime defines abstract interfaces for WASM execution engines.
|
|
2
|
+
|
|
3
|
+
// VmRuntime abstracts the WASM execution engine.
|
|
4
|
+
export interface VmRuntime {
|
|
5
|
+
Compile(ctx: any, wasm: Uint8Array | number[]): Promise<VmModule>
|
|
6
|
+
Close(ctx: any): Promise<any>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// VmModule represents a compiled WASM module.
|
|
10
|
+
export interface VmModule {
|
|
11
|
+
Instantiate(ctx: any, config: VmModuleConfig): Promise<VmInstance>
|
|
12
|
+
Close(ctx: any): Promise<any>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// VmModuleConfig contains configuration for module instantiation.
|
|
16
|
+
export interface VmModuleConfig {
|
|
17
|
+
Name: string
|
|
18
|
+
Args: string[] | null
|
|
19
|
+
Env: string[] | null
|
|
20
|
+
Stdin: any
|
|
21
|
+
Stdout: any
|
|
22
|
+
Stderr: any
|
|
23
|
+
HostFunctions: Map<string, HostFunction> | null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// HostFunction is a host-provided function callable from WASM.
|
|
27
|
+
export type HostFunction = (
|
|
28
|
+
ctx: any,
|
|
29
|
+
inst: VmInstance | null,
|
|
30
|
+
stack: number[],
|
|
31
|
+
) => any
|
|
32
|
+
|
|
33
|
+
// VmInstance represents a running WASM module instance.
|
|
34
|
+
export interface VmInstance {
|
|
35
|
+
Call(ctx: any, name: string, ...args: number[]): Promise<number[] | null>
|
|
36
|
+
Memory(): VmMemory | null
|
|
37
|
+
ExportedFunction(name: string): VmFunction | null
|
|
38
|
+
ExportedGlobal(name: string): VmGlobal | null
|
|
39
|
+
Close(ctx: any): Promise<any>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// VmFunction represents an exported WASM function.
|
|
43
|
+
export interface VmFunction {
|
|
44
|
+
Call(ctx: any, ...args: number[]): Promise<number[] | null>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// VmGlobal represents an exported WASM global variable.
|
|
48
|
+
export interface VmGlobal {
|
|
49
|
+
Get(): number
|
|
50
|
+
Set(val: number): void
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// VmMemory abstracts access to WASM linear memory.
|
|
54
|
+
export interface VmMemory {
|
|
55
|
+
Read(offset: number, length: number): [Uint8Array | number[], boolean]
|
|
56
|
+
ReadByteAt(offset: number): [number, boolean]
|
|
57
|
+
ReadUint32Le(offset: number): [number, boolean]
|
|
58
|
+
ReadUint64Le(offset: number): [bigint | number, boolean]
|
|
59
|
+
Write(offset: number, data: Uint8Array | number[]): boolean
|
|
60
|
+
WriteByteAt(offset: number, val: number): boolean
|
|
61
|
+
WriteUint32Le(offset: number, val: number): boolean
|
|
62
|
+
WriteUint64Le(offset: number, val: bigint | number): boolean
|
|
63
|
+
Size(): number
|
|
64
|
+
Grow(pages: number): [number, boolean]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ExitError represents a clean process exit with a status code.
|
|
68
|
+
export class ExitError extends Error {
|
|
69
|
+
public Code: number
|
|
70
|
+
|
|
71
|
+
constructor(code: number) {
|
|
72
|
+
super('exit: ' + code)
|
|
73
|
+
this.Code = code
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ExitCode(): number {
|
|
77
|
+
return this.Code
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// NewExitError creates an ExitError with the given code.
|
|
82
|
+
export function NewExitError(code: number): ExitError {
|
|
83
|
+
return new ExitError(code)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Snapshotable is an optional extension for VmInstance.
|
|
87
|
+
export interface Snapshotable {
|
|
88
|
+
Snapshot(): Snapshot
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Snapshot represents a captured execution state.
|
|
92
|
+
export interface Snapshot {
|
|
93
|
+
Restore(returnValues: number[]): void
|
|
94
|
+
}
|
package/gs/io/fs/format.ts
CHANGED
|
@@ -16,12 +16,9 @@ export function FormatFileInfo(info: FileInfo): string {
|
|
|
16
16
|
b.push(' ')
|
|
17
17
|
|
|
18
18
|
let size = info!.Size()
|
|
19
|
-
|
|
20
|
-
if (size
|
|
21
|
-
usize = size as number
|
|
22
|
-
} else {
|
|
19
|
+
const usize = size >= 0 ? size : -size
|
|
20
|
+
if (size < 0) {
|
|
23
21
|
b.push('-')
|
|
24
|
-
usize = -size as number
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
b.push(usize.toString())
|
package/gs/io/fs/glob.ts
CHANGED
|
@@ -70,7 +70,6 @@ export function globWithLimit(
|
|
|
70
70
|
depth: number,
|
|
71
71
|
): [$.Slice<string>, $.GoError] {
|
|
72
72
|
let matches: $.Slice<string> = null
|
|
73
|
-
let err: $.GoError = null
|
|
74
73
|
{
|
|
75
74
|
// This limit is added to prevent stack exhaustion issues. See
|
|
76
75
|
// CVE-2022-30630.
|
|
@@ -87,15 +86,15 @@ export function globWithLimit(
|
|
|
87
86
|
|
|
88
87
|
// Check pattern is well-formed.
|
|
89
88
|
{
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
return [null,
|
|
89
|
+
const [, matchErr] = path.Match(pattern, '')
|
|
90
|
+
if (matchErr != null) {
|
|
91
|
+
return [null, matchErr]
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
if (!hasMeta(pattern)) {
|
|
96
95
|
{
|
|
97
|
-
|
|
98
|
-
if (
|
|
96
|
+
const [, statErr] = Stat(fsys, pattern)
|
|
97
|
+
if (statErr != null) {
|
|
99
98
|
return [null, null]
|
|
100
99
|
}
|
|
101
100
|
}
|
|
@@ -114,21 +113,21 @@ export function globWithLimit(
|
|
|
114
113
|
return [null, path.ErrBadPattern]
|
|
115
114
|
}
|
|
116
115
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return [null, err]
|
|
116
|
+
const [dirs, dirErr] = globWithLimit(fsys, dir, depth + 1)
|
|
117
|
+
if (dirErr != null) {
|
|
118
|
+
return [null, dirErr]
|
|
121
119
|
}
|
|
122
|
-
for (let _i = 0; _i < $.len(
|
|
123
|
-
const d =
|
|
120
|
+
for (let _i = 0; _i < $.len(dirs); _i++) {
|
|
121
|
+
const d = dirs![_i]
|
|
124
122
|
{
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
const [nextMatches, globErr] = glob(fsys, d, file, matches)
|
|
124
|
+
matches = nextMatches
|
|
125
|
+
if (globErr != null) {
|
|
126
|
+
return [matches, globErr]
|
|
128
127
|
}
|
|
129
128
|
}
|
|
130
129
|
}
|
|
131
|
-
return [matches,
|
|
130
|
+
return [matches, null]
|
|
132
131
|
}
|
|
133
132
|
}
|
|
134
133
|
|
|
@@ -155,15 +154,13 @@ export function glob(
|
|
|
155
154
|
pattern: string,
|
|
156
155
|
matches: $.Slice<string>,
|
|
157
156
|
): [$.Slice<string>, $.GoError] {
|
|
158
|
-
let m
|
|
159
|
-
let e: $.GoError = null
|
|
157
|
+
let m = matches
|
|
160
158
|
{
|
|
161
|
-
m = matches
|
|
162
159
|
let [infos, err] = ReadDir(fs, dir)
|
|
163
160
|
|
|
164
161
|
// ignore I/O error
|
|
165
162
|
if (err != null) {
|
|
166
|
-
return [m,
|
|
163
|
+
return [m, null]
|
|
167
164
|
}
|
|
168
165
|
|
|
169
166
|
for (let _i = 0; _i < $.len(infos); _i++) {
|
|
@@ -179,7 +176,7 @@ export function glob(
|
|
|
179
176
|
}
|
|
180
177
|
}
|
|
181
178
|
}
|
|
182
|
-
return [m,
|
|
179
|
+
return [m, null]
|
|
183
180
|
}
|
|
184
181
|
}
|
|
185
182
|
|
package/gs/path/match.ts
CHANGED
|
@@ -45,13 +45,7 @@ export function Match(pattern: string, name: string): [boolean, $.GoError] {
|
|
|
45
45
|
// Before returning false with no error,
|
|
46
46
|
// check that the remainder of the pattern is syntactically valid.
|
|
47
47
|
Pattern: for (; $.len(pattern) > 0; ) {
|
|
48
|
-
|
|
49
|
-
let chunk: string = ''
|
|
50
|
-
let rest: string = ''
|
|
51
|
-
let scanResult = scanChunk(pattern)
|
|
52
|
-
star = scanResult[0]
|
|
53
|
-
chunk = scanResult[1]
|
|
54
|
-
rest = scanResult[2]
|
|
48
|
+
const [star, chunk, rest] = scanChunk(pattern)
|
|
55
49
|
pattern = rest
|
|
56
50
|
|
|
57
51
|
// Trailing * matches rest of string unless it has a /.
|
|
@@ -104,13 +98,7 @@ export function Match(pattern: string, name: string): [boolean, $.GoError] {
|
|
|
104
98
|
// Before returning false with no error,
|
|
105
99
|
// check that the remainder of the pattern is syntactically valid.
|
|
106
100
|
for (; $.len(pattern) > 0; ) {
|
|
107
|
-
|
|
108
|
-
let chunk2: string = ''
|
|
109
|
-
let rest2: string = ''
|
|
110
|
-
let scanResult2 = scanChunk(pattern)
|
|
111
|
-
// star2 = scanResult2[0]
|
|
112
|
-
chunk2 = scanResult2[1]
|
|
113
|
-
rest2 = scanResult2[2]
|
|
101
|
+
const [, chunk2, rest2] = scanChunk(pattern)
|
|
114
102
|
pattern = rest2
|
|
115
103
|
{
|
|
116
104
|
let [, , err] = matchChunk(chunk2, '')
|
|
@@ -135,7 +123,7 @@ export function scanChunk(pattern: string): [boolean, string, string] {
|
|
|
135
123
|
star = true
|
|
136
124
|
}
|
|
137
125
|
let inrange = false
|
|
138
|
-
let i: number
|
|
126
|
+
let i: number
|
|
139
127
|
|
|
140
128
|
// error check handled in matchChunk: bad pattern.
|
|
141
129
|
Scan: for (i = 0; i < $.len(pattern); i++) {
|
|
@@ -174,7 +162,7 @@ export function matchChunk(
|
|
|
174
162
|
chunk: string,
|
|
175
163
|
s: string,
|
|
176
164
|
): [string, boolean, $.GoError] {
|
|
177
|
-
let err: $.GoError
|
|
165
|
+
let err: $.GoError
|
|
178
166
|
{
|
|
179
167
|
// failed records whether the match has failed.
|
|
180
168
|
// After the match fails, the loop continues on processing chunk,
|
|
@@ -200,10 +188,9 @@ export function matchChunk(
|
|
|
200
188
|
case 91: {
|
|
201
189
|
let r: number = 0
|
|
202
190
|
if (!failed) {
|
|
203
|
-
|
|
204
|
-
let decoded = utf8.DecodeRuneInString(s)
|
|
191
|
+
const decoded = utf8.DecodeRuneInString(s)
|
|
205
192
|
r = decoded[0]
|
|
206
|
-
n = decoded[1]
|
|
193
|
+
const n = decoded[1]
|
|
207
194
|
s = $.sliceString(s, n, undefined)
|
|
208
195
|
}
|
|
209
196
|
chunk = $.sliceString(chunk, 1, undefined)
|
|
@@ -223,10 +210,10 @@ export function matchChunk(
|
|
|
223
210
|
chunk = $.sliceString(chunk, 1, undefined)
|
|
224
211
|
break
|
|
225
212
|
}
|
|
226
|
-
let lo: number
|
|
227
|
-
let hi: number
|
|
213
|
+
let lo: number
|
|
214
|
+
let hi: number
|
|
228
215
|
{
|
|
229
|
-
|
|
216
|
+
const escResult = getEsc(chunk)
|
|
230
217
|
lo = escResult[0]
|
|
231
218
|
chunk = escResult[1]
|
|
232
219
|
err = escResult[2]
|
package/gs/reflect/index.ts
CHANGED
package/gs/reflect/type.ts
CHANGED
|
@@ -1492,7 +1492,10 @@ function typeImplementsInterface(
|
|
|
1492
1492
|
interfaceType: Type,
|
|
1493
1493
|
): boolean {
|
|
1494
1494
|
// Get the interface name and look it up in the type registry
|
|
1495
|
-
const interfaceName =
|
|
1495
|
+
const interfaceName =
|
|
1496
|
+
interfaceType instanceof InterfaceType ?
|
|
1497
|
+
interfaceType.registeredName() || interfaceType.String()
|
|
1498
|
+
: interfaceType.String()
|
|
1496
1499
|
const interfaceTypeInfo = builtinGetTypeByName(interfaceName)
|
|
1497
1500
|
|
|
1498
1501
|
if (!interfaceTypeInfo || !isInterfaceTypeInfo(interfaceTypeInfo)) {
|
|
@@ -1797,7 +1800,10 @@ class ChannelType implements Type {
|
|
|
1797
1800
|
|
|
1798
1801
|
// Interface type implementation
|
|
1799
1802
|
class InterfaceType implements Type {
|
|
1800
|
-
constructor(
|
|
1803
|
+
constructor(
|
|
1804
|
+
private _name: string = 'interface{}',
|
|
1805
|
+
private _registeredName?: string,
|
|
1806
|
+
) {}
|
|
1801
1807
|
|
|
1802
1808
|
public String(): string {
|
|
1803
1809
|
return this._name
|
|
@@ -1820,10 +1826,30 @@ class InterfaceType implements Type {
|
|
|
1820
1826
|
}
|
|
1821
1827
|
|
|
1822
1828
|
public PkgPath?(): string {
|
|
1829
|
+
if (
|
|
1830
|
+
this._name === 'interface{}' ||
|
|
1831
|
+
this._name.startsWith('interface {')
|
|
1832
|
+
) {
|
|
1833
|
+
return ''
|
|
1834
|
+
}
|
|
1835
|
+
const dotIndex = this._name.lastIndexOf('.')
|
|
1836
|
+
if (dotIndex > 0) {
|
|
1837
|
+
return this._name.substring(0, dotIndex)
|
|
1838
|
+
}
|
|
1823
1839
|
return ''
|
|
1824
1840
|
}
|
|
1825
1841
|
|
|
1826
1842
|
public Name(): string {
|
|
1843
|
+
if (
|
|
1844
|
+
this._name === 'interface{}' ||
|
|
1845
|
+
this._name.startsWith('interface {')
|
|
1846
|
+
) {
|
|
1847
|
+
return this._name
|
|
1848
|
+
}
|
|
1849
|
+
const dotIndex = this._name.lastIndexOf('.')
|
|
1850
|
+
if (dotIndex >= 0) {
|
|
1851
|
+
return this._name.substring(dotIndex + 1)
|
|
1852
|
+
}
|
|
1827
1853
|
return this._name
|
|
1828
1854
|
}
|
|
1829
1855
|
|
|
@@ -1868,6 +1894,10 @@ class InterfaceType implements Type {
|
|
|
1868
1894
|
public Bits(): number {
|
|
1869
1895
|
throw new Error('reflect: call of reflect.Type.Bits on interface Type')
|
|
1870
1896
|
}
|
|
1897
|
+
|
|
1898
|
+
public registeredName(): string | undefined {
|
|
1899
|
+
return this._registeredName
|
|
1900
|
+
}
|
|
1871
1901
|
}
|
|
1872
1902
|
|
|
1873
1903
|
function getTypeOf(value: ReflectValue): Type {
|
|
@@ -2161,30 +2191,37 @@ export function TypeFor(): Type {
|
|
|
2161
2191
|
export function getInterfaceTypeByName(name: string): Type {
|
|
2162
2192
|
const typeInfo = builtinGetTypeByName(name)
|
|
2163
2193
|
if (typeInfo && typeInfo.kind === TypeKind.Interface) {
|
|
2164
|
-
|
|
2194
|
+
return new InterfaceType(name, name)
|
|
2195
|
+
}
|
|
2196
|
+
return new InterfaceType('interface{}')
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
export function getInterfaceLiteralTypeByName(name: string): Type {
|
|
2200
|
+
const typeInfo = builtinGetTypeByName(name)
|
|
2201
|
+
if (typeInfo && typeInfo.kind === TypeKind.Interface) {
|
|
2165
2202
|
const methods = (typeInfo as any).methods || []
|
|
2166
|
-
if (methods.length
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
}
|
|
2183
|
-
|
|
2184
|
-
})
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
}
|
|
2203
|
+
if (methods.length === 0) {
|
|
2204
|
+
return new InterfaceType('interface{}', name)
|
|
2205
|
+
}
|
|
2206
|
+
const methodSigs = methods
|
|
2207
|
+
.map((m: any) => {
|
|
2208
|
+
const args =
|
|
2209
|
+
m.args
|
|
2210
|
+
?.map((a: any) => (typeof a === 'string' ? a : 'any'))
|
|
2211
|
+
.join(', ') || ''
|
|
2212
|
+
const returns = m.returns?.map((r: any) =>
|
|
2213
|
+
typeof r === 'string' ? r : 'any',
|
|
2214
|
+
)
|
|
2215
|
+
let returnSig = ''
|
|
2216
|
+
if (returns && returns.length === 1) {
|
|
2217
|
+
returnSig = ` ${returns[0]}`
|
|
2218
|
+
} else if (returns && returns.length > 1) {
|
|
2219
|
+
returnSig = ` (${returns.join(', ')})`
|
|
2220
|
+
}
|
|
2221
|
+
return `${m.name}(${args})${returnSig}`
|
|
2222
|
+
})
|
|
2223
|
+
.join('; ')
|
|
2224
|
+
return new InterfaceType(`interface { ${methodSigs} }`, name)
|
|
2188
2225
|
}
|
|
2189
2226
|
return new InterfaceType('interface{}')
|
|
2190
2227
|
}
|
package/gs/strings/iter.ts
CHANGED
|
@@ -25,7 +25,7 @@ const asciiSpace: { [key: number]: boolean } = {
|
|
|
25
25
|
export function Lines(s: string): iter.Seq<string> {
|
|
26
26
|
return (_yield: ((p0: string) => boolean) | null): void => {
|
|
27
27
|
for (; $.len(s) > 0; ) {
|
|
28
|
-
let line: string
|
|
28
|
+
let line: string
|
|
29
29
|
{
|
|
30
30
|
let i = IndexByte(s, 10)
|
|
31
31
|
if (i >= 0) {
|