goscript 0.1.4 → 0.2.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 +5 -2
- package/cmd/go_js_wasm_exec/main.go +201 -0
- package/cmd/go_js_wasm_exec/main_test.go +83 -0
- package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +7 -0
- package/cmd/goscript/cmd-test.go +14 -0
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/compiler/compile-request.go +12 -9
- package/compiler/compliance_test.go +0 -1
- package/compiler/config.go +2 -0
- package/compiler/gotest/request.go +28 -0
- package/compiler/gotest/runner.go +353 -27
- package/compiler/gotest/runner_test.go +273 -1
- package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
- package/compiler/gotest/testdata/browserapi/go.mod +3 -0
- package/compiler/lowered-program.go +24 -17
- package/compiler/lowering.go +392 -127
- package/compiler/lowering_bench_test.go +41 -27
- package/compiler/override-facts.go +15 -0
- package/compiler/override-parity-verifier.go +450 -0
- package/compiler/override-parity.go +122 -0
- package/compiler/override-registry_test.go +559 -0
- package/compiler/protobuf-ts-binding.go +514 -0
- package/compiler/protobuf-ts-binding_test.go +172 -0
- package/compiler/semantic-model-types.go +9 -4
- package/compiler/semantic-model.go +282 -70
- package/compiler/semantic-model_test.go +82 -1
- package/compiler/service.go +20 -1
- package/compiler/skeleton_test.go +62 -8
- package/compiler/typescript-emitter.go +128 -13
- package/dist/gs/builtin/slice.d.ts +2 -1
- package/dist/gs/builtin/slice.js +29 -4
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +13 -5
- package/dist/gs/builtin/type.js +153 -60
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +11 -0
- package/dist/gs/builtin/varRef.js +57 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +10 -3
- package/dist/gs/compress/zlib/index.js +50 -16
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +114 -0
- package/dist/gs/encoding/json/index.js +544 -36
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js +54 -30
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +2 -0
- package/dist/gs/go/scanner/index.js +29 -5
- package/dist/gs/go/scanner/index.js.map +1 -1
- package/dist/gs/go/token/index.js +22 -6
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/index.d.ts +6 -0
- package/dist/gs/hash/index.js +20 -0
- package/dist/gs/hash/index.js.map +1 -1
- package/dist/gs/internal/goarch/index.d.ts +43 -3
- package/dist/gs/internal/goarch/index.js +42 -10
- package/dist/gs/internal/goarch/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js +26 -14
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js +4 -2
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/sub.js +8 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.d.ts +2 -0
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +5 -0
- package/dist/gs/math/bits/index.js +16 -4
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.d.ts +16 -0
- package/dist/gs/mime/index.js +315 -6
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +12 -0
- package/dist/gs/net/http/httptest/index.js +85 -6
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +300 -5
- package/dist/gs/net/http/index.js +1598 -58
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +1 -1
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.d.ts +1 -0
- package/dist/gs/os/exec.gs.js +4 -8
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/index.d.ts +1 -1
- package/dist/gs/os/index.js +1 -1
- package/dist/gs/os/index.js.map +1 -1
- package/dist/gs/os/proc.gs.d.ts +4 -0
- package/dist/gs/os/proc.gs.js +12 -6
- package/dist/gs/os/proc.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js +1 -1
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/path.js +11 -7
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +5 -4
- package/dist/gs/reflect/index.js +4 -3
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +15 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +25 -6
- package/dist/gs/reflect/type.js +1418 -228
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +14 -6
- package/dist/gs/reflect/types.js +35 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +1 -0
- package/dist/gs/reflect/value.js +83 -41
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +4 -140
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +8 -2
- package/dist/gs/runtime/pprof/index.js +50 -30
- package/dist/gs/runtime/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.js +5 -4
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.js +5 -19
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/complex.gs.d.ts +3 -0
- package/dist/gs/strconv/complex.gs.js +148 -0
- package/dist/gs/strconv/complex.gs.js.map +1 -0
- package/dist/gs/strconv/index.d.ts +1 -0
- package/dist/gs/strconv/index.js +1 -0
- package/dist/gs/strconv/index.js.map +1 -1
- package/dist/gs/strings/builder.js +1 -1
- package/dist/gs/strings/reader.js +9 -5
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js +15 -7
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.d.ts +5 -0
- package/dist/gs/strings/strings.js +57 -5
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js +9 -9
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js +2 -2
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/syscall/env.js +22 -14
- package/dist/gs/syscall/env.js.map +1 -1
- package/dist/gs/testing/testing.js +55 -13
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.d.ts +24 -1
- package/dist/gs/time/time.js +43 -3
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unique/index.js +7 -1
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +3 -3
- package/go.sum +16 -0
- package/gs/builtin/runtime-contract.test.ts +218 -21
- package/gs/builtin/slice.ts +44 -4
- package/gs/builtin/type.ts +226 -59
- package/gs/builtin/varRef.ts +85 -2
- package/gs/bytes/buffer.gs.ts +1 -1
- package/gs/bytes/reader.gs.ts +1 -1
- package/gs/compress/zlib/index.test.ts +62 -1
- package/gs/compress/zlib/index.ts +53 -16
- package/gs/compress/zlib/parity.json +51 -0
- package/gs/encoding/json/index.test.ts +360 -6
- package/gs/encoding/json/index.ts +679 -38
- package/gs/encoding/json/parity.json +81 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
- package/gs/github.com/pkg/errors/errors.ts +54 -30
- package/gs/go/scanner/index.test.ts +39 -56
- package/gs/go/scanner/index.ts +33 -5
- package/gs/go/scanner/parity.json +27 -0
- package/gs/go/token/index.ts +22 -6
- package/gs/hash/index.test.ts +20 -33
- package/gs/hash/index.ts +28 -0
- package/gs/hash/parity.json +21 -0
- package/gs/internal/goarch/index.test.ts +32 -0
- package/gs/internal/goarch/index.ts +45 -13
- package/gs/internal/goarch/parity.json +144 -0
- package/gs/io/fs/fs.ts +26 -14
- package/gs/io/fs/readdir.ts +4 -4
- package/gs/io/fs/sub.ts +8 -1
- package/gs/io/io.ts +1 -0
- package/gs/io/parity.json +162 -0
- package/gs/math/bits/index.test.ts +14 -1
- package/gs/math/bits/index.ts +23 -4
- package/gs/math/bits/parity.json +156 -0
- package/gs/mime/index.test.ts +90 -0
- package/gs/mime/index.ts +369 -6
- package/gs/mime/parity.json +36 -0
- package/gs/net/http/httptest/index.test.ts +98 -2
- package/gs/net/http/httptest/index.ts +101 -6
- package/gs/net/http/httptest/parity.json +15 -0
- package/gs/net/http/index.test.ts +781 -12
- package/gs/net/http/index.ts +1860 -139
- package/gs/net/http/meta.json +16 -1
- package/gs/net/http/parity.json +193 -0
- package/gs/os/dir_unix.gs.ts +1 -1
- package/gs/os/error.gs.ts +1 -1
- package/gs/os/exec.gs.ts +4 -8
- package/gs/os/exec_posix.gs.ts +1 -1
- package/gs/os/index.test.ts +9 -0
- package/gs/os/index.ts +1 -0
- package/gs/os/parity.json +9 -0
- package/gs/os/proc.gs.ts +18 -5
- package/gs/os/proc.test.ts +26 -0
- package/gs/os/root_js.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +1 -1
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/path/path.ts +11 -7
- package/gs/reflect/field.test.ts +37 -15
- package/gs/reflect/function-types.test.ts +518 -22
- package/gs/reflect/index.ts +8 -6
- package/gs/reflect/map.ts +20 -0
- package/gs/reflect/meta.json +6 -4
- package/gs/reflect/parity.json +234 -0
- package/gs/reflect/sliceat.test.ts +156 -0
- package/gs/reflect/structof.test.ts +401 -0
- package/gs/reflect/type.ts +1897 -317
- package/gs/reflect/typefor.test.ts +510 -10
- package/gs/reflect/types.ts +43 -18
- package/gs/reflect/value.ts +105 -45
- package/gs/reflect/visiblefields.ts +5 -168
- package/gs/runtime/parity.json +24 -0
- package/gs/runtime/pprof/index.test.ts +29 -7
- package/gs/runtime/pprof/index.ts +56 -30
- package/gs/runtime/pprof/parity.json +27 -0
- package/gs/runtime/runtime.test.ts +3 -1
- package/gs/runtime/runtime.ts +4 -3
- package/gs/runtime/trace/index.test.ts +5 -3
- package/gs/runtime/trace/index.ts +8 -20
- package/gs/runtime/trace/parity.json +36 -0
- package/gs/strconv/atoi.gs.ts +1 -1
- package/gs/strconv/complex.gs.ts +174 -0
- package/gs/strconv/complex.test.ts +65 -0
- package/gs/strconv/index.ts +1 -0
- package/gs/strconv/parity.json +120 -0
- package/gs/strings/builder.ts +1 -1
- package/gs/strings/parity.json +186 -0
- package/gs/strings/reader.ts +9 -5
- package/gs/strings/replace.ts +15 -7
- package/gs/strings/strings.test.ts +22 -2
- package/gs/strings/strings.ts +64 -6
- package/gs/sync/atomic/type.gs.ts +9 -9
- package/gs/sync/atomic/value.gs.ts +2 -2
- package/gs/syscall/env.ts +29 -14
- package/gs/testing/testing.test.ts +67 -0
- package/gs/testing/testing.ts +87 -19
- package/gs/time/parity.json +225 -0
- package/gs/time/time.test.ts +20 -2
- package/gs/time/time.ts +49 -7
- package/gs/unique/index.ts +7 -1
- package/package.json +4 -2
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
- /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
package/gs/strings/reader.ts
CHANGED
|
@@ -434,11 +434,15 @@ export class Reader {
|
|
|
434
434
|
},
|
|
435
435
|
],
|
|
436
436
|
Reader,
|
|
437
|
-
|
|
438
|
-
s: { kind: $.TypeKind.Basic, name: 'string' },
|
|
439
|
-
i: { kind: $.TypeKind.Basic, name: 'number' },
|
|
440
|
-
|
|
441
|
-
|
|
437
|
+
[
|
|
438
|
+
{ name: 's', key: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
|
|
439
|
+
{ name: 'i', key: 'i', type: { kind: $.TypeKind.Basic, name: 'number' } },
|
|
440
|
+
{
|
|
441
|
+
name: 'prevRune',
|
|
442
|
+
key: 'prevRune',
|
|
443
|
+
type: { kind: $.TypeKind.Basic, name: 'number' },
|
|
444
|
+
},
|
|
445
|
+
],
|
|
442
446
|
)
|
|
443
447
|
}
|
|
444
448
|
|
package/gs/strings/replace.ts
CHANGED
|
@@ -205,14 +205,22 @@ export class Replacer {
|
|
|
205
205
|
},
|
|
206
206
|
],
|
|
207
207
|
Replacer,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
kind: $.TypeKind.
|
|
213
|
-
elemType: { kind: $.TypeKind.Basic, name: 'string' },
|
|
208
|
+
[
|
|
209
|
+
{
|
|
210
|
+
name: 'built',
|
|
211
|
+
key: 'built',
|
|
212
|
+
type: { kind: $.TypeKind.Basic, name: 'boolean' },
|
|
214
213
|
},
|
|
215
|
-
|
|
214
|
+
{ name: 'r', key: 'r', type: 'replacer' },
|
|
215
|
+
{
|
|
216
|
+
name: 'oldnew',
|
|
217
|
+
key: 'oldnew',
|
|
218
|
+
type: {
|
|
219
|
+
kind: $.TypeKind.Slice,
|
|
220
|
+
elemType: { kind: $.TypeKind.Basic, name: 'string' },
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
],
|
|
216
224
|
)
|
|
217
225
|
}
|
|
218
226
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import * as $ from '../builtin/index.js'
|
|
3
|
+
import * as unicode from '../unicode/unicode.js'
|
|
3
4
|
import {
|
|
4
5
|
Clone,
|
|
5
6
|
Compare,
|
|
@@ -36,8 +37,12 @@ import {
|
|
|
36
37
|
SplitN,
|
|
37
38
|
Title,
|
|
38
39
|
ToLower,
|
|
40
|
+
ToLowerSpecial,
|
|
39
41
|
ToTitle,
|
|
42
|
+
ToTitleSpecial,
|
|
40
43
|
ToUpper,
|
|
44
|
+
ToUpperSpecial,
|
|
45
|
+
ToValidUTF8,
|
|
41
46
|
Trim,
|
|
42
47
|
TrimFunc,
|
|
43
48
|
TrimLeft,
|
|
@@ -390,8 +395,8 @@ describe('strings', () => {
|
|
|
390
395
|
|
|
391
396
|
describe('ToTitle', () => {
|
|
392
397
|
it('should convert to title case', () => {
|
|
393
|
-
expect(ToTitle('hello world')).toBe('
|
|
394
|
-
expect(ToTitle('HELLO WORLD')).toBe('
|
|
398
|
+
expect(ToTitle('hello world')).toBe('HELLO WORLD')
|
|
399
|
+
expect(ToTitle('HELLO WORLD')).toBe('HELLO WORLD')
|
|
395
400
|
expect(ToTitle('')).toBe('')
|
|
396
401
|
})
|
|
397
402
|
})
|
|
@@ -404,6 +409,21 @@ describe('strings', () => {
|
|
|
404
409
|
})
|
|
405
410
|
})
|
|
406
411
|
|
|
412
|
+
describe('special casing and UTF-8 cleanup', () => {
|
|
413
|
+
it('should expose special-case string helpers', () => {
|
|
414
|
+
expect(ToUpperSpecial([], 'hello')).toBe('HELLO')
|
|
415
|
+
expect(ToLowerSpecial([], 'HELLO')).toBe('hello')
|
|
416
|
+
expect(ToTitleSpecial([], 'hello world')).toBe('HELLO WORLD')
|
|
417
|
+
expect(ToUpperSpecial(unicode.TurkishCase, 'iki')).toBe('İKİ')
|
|
418
|
+
expect(ToLowerSpecial(unicode.TurkishCase, 'Iİ')).toBe('ıi')
|
|
419
|
+
expect(ToTitleSpecial(unicode.TurkishCase, 'iki')).toBe('İKİ')
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
it('should preserve valid replacement runes', () => {
|
|
423
|
+
expect(ToValidUTF8('a\uFFFDb', '?')).toBe('a\uFFFDb')
|
|
424
|
+
})
|
|
425
|
+
})
|
|
426
|
+
|
|
407
427
|
describe('Trim', () => {
|
|
408
428
|
it('should trim cutset from both ends', () => {
|
|
409
429
|
expect(Trim('!hello!', '!')).toBe('hello')
|
package/gs/strings/strings.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as unicode from '@goscript/unicode/index.js'
|
|
2
3
|
|
|
3
4
|
// Count counts the number of non-overlapping instances of substr in s.
|
|
4
5
|
// If substr is an empty string, Count returns 1 + the number of Unicode code points in s.
|
|
@@ -355,14 +356,76 @@ export function ToUpper(s: string): string {
|
|
|
355
356
|
return s.toUpperCase()
|
|
356
357
|
}
|
|
357
358
|
|
|
359
|
+
export function ToUpperSpecial(c: unicode.SpecialCase, s: string): string {
|
|
360
|
+
if (isTurkishCase(c)) {
|
|
361
|
+
return mapTurkishCase(s, 'upper')
|
|
362
|
+
}
|
|
363
|
+
return ToUpper(s)
|
|
364
|
+
}
|
|
365
|
+
|
|
358
366
|
// ToLower returns s with all Unicode letters mapped to their lower case.
|
|
359
367
|
export function ToLower(s: string): string {
|
|
360
368
|
return s.toLowerCase()
|
|
361
369
|
}
|
|
362
370
|
|
|
371
|
+
export function ToLowerSpecial(c: unicode.SpecialCase, s: string): string {
|
|
372
|
+
if (isTurkishCase(c)) {
|
|
373
|
+
return mapTurkishCase(s, 'lower')
|
|
374
|
+
}
|
|
375
|
+
return ToLower(s)
|
|
376
|
+
}
|
|
377
|
+
|
|
363
378
|
// ToTitle returns a copy of the string s with all Unicode letters mapped to their Unicode title case.
|
|
364
379
|
export function ToTitle(s: string): string {
|
|
365
|
-
|
|
380
|
+
return s.toUpperCase()
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function ToTitleSpecial(c: unicode.SpecialCase, s: string): string {
|
|
384
|
+
if (isTurkishCase(c)) {
|
|
385
|
+
return mapTurkishCase(s, 'upper')
|
|
386
|
+
}
|
|
387
|
+
return ToTitle(s)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function isTurkishCase(c: unicode.SpecialCase): boolean {
|
|
391
|
+
return c === unicode.TurkishCase || c === unicode.AzeriCase
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function mapTurkishCase(s: string, mode: 'upper' | 'lower'): string {
|
|
395
|
+
let out = ''
|
|
396
|
+
for (const char of s) {
|
|
397
|
+
if (mode === 'upper') {
|
|
398
|
+
if (char === 'i') {
|
|
399
|
+
out += 'İ'
|
|
400
|
+
continue
|
|
401
|
+
}
|
|
402
|
+
if (char === 'ı') {
|
|
403
|
+
out += 'I'
|
|
404
|
+
continue
|
|
405
|
+
}
|
|
406
|
+
out += char.toUpperCase()
|
|
407
|
+
continue
|
|
408
|
+
}
|
|
409
|
+
if (char === 'I') {
|
|
410
|
+
out += 'ı'
|
|
411
|
+
continue
|
|
412
|
+
}
|
|
413
|
+
if (char === 'İ') {
|
|
414
|
+
out += 'i'
|
|
415
|
+
continue
|
|
416
|
+
}
|
|
417
|
+
out += char.toLowerCase()
|
|
418
|
+
}
|
|
419
|
+
return out
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export function ToValidUTF8(s: string, replacement: string): string {
|
|
423
|
+
void replacement
|
|
424
|
+
return s
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Title returns a copy of the string s with all Unicode letters that begin words mapped to their Unicode title case.
|
|
428
|
+
export function Title(s: string): string {
|
|
366
429
|
return s
|
|
367
430
|
.split(' ')
|
|
368
431
|
.map((word) =>
|
|
@@ -373,11 +436,6 @@ export function ToTitle(s: string): string {
|
|
|
373
436
|
.join(' ')
|
|
374
437
|
}
|
|
375
438
|
|
|
376
|
-
// Title returns a copy of the string s with all Unicode letters that begin words mapped to their Unicode title case.
|
|
377
|
-
export function Title(s: string): string {
|
|
378
|
-
return ToTitle(s)
|
|
379
|
-
}
|
|
380
|
-
|
|
381
439
|
// TrimSpace returns a slice of the string s, with all leading and trailing white space removed.
|
|
382
440
|
export function TrimSpace(s: string): string {
|
|
383
441
|
return s.trim()
|
|
@@ -62,7 +62,7 @@ export class Bool {
|
|
|
62
62
|
new Bool(),
|
|
63
63
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "boolean" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "boolean" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "boolean" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "boolean" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }],
|
|
64
64
|
Bool,
|
|
65
|
-
{"v": { kind: $.TypeKind.Basic, name: "number" }}
|
|
65
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -138,7 +138,7 @@ export class Pointer<T> {
|
|
|
138
138
|
new Pointer(),
|
|
139
139
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }], returns: [{ type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }, { name: "new", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }],
|
|
140
140
|
Pointer,
|
|
141
|
-
{"v": { kind: $.TypeKind.Basic, name: "Pointer" }}
|
|
141
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "Pointer" } }]
|
|
142
142
|
);
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -218,7 +218,7 @@ export class Int32 {
|
|
|
218
218
|
new Int32(),
|
|
219
219
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
|
|
220
220
|
Int32,
|
|
221
|
-
{"v": { kind: $.TypeKind.Basic, name: "number" }}
|
|
221
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
|
|
222
222
|
);
|
|
223
223
|
}
|
|
224
224
|
|
|
@@ -298,7 +298,7 @@ export class Int64 {
|
|
|
298
298
|
new Int64(),
|
|
299
299
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
|
|
300
300
|
Int64,
|
|
301
|
-
{"v": { kind: $.TypeKind.Basic, name: "number" }}
|
|
301
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
|
|
302
302
|
);
|
|
303
303
|
}
|
|
304
304
|
|
|
@@ -378,7 +378,7 @@ export class Uint32 {
|
|
|
378
378
|
new Uint32(),
|
|
379
379
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
|
|
380
380
|
Uint32,
|
|
381
|
-
{"v": { kind: $.TypeKind.Basic, name: "number" }}
|
|
381
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
|
|
382
382
|
);
|
|
383
383
|
}
|
|
384
384
|
|
|
@@ -458,7 +458,7 @@ export class Uint64 {
|
|
|
458
458
|
new Uint64(),
|
|
459
459
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
|
|
460
460
|
Uint64,
|
|
461
|
-
{"v": { kind: $.TypeKind.Basic, name: "number" }}
|
|
461
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
|
|
462
462
|
);
|
|
463
463
|
}
|
|
464
464
|
|
|
@@ -538,7 +538,7 @@ export class Uintptr {
|
|
|
538
538
|
new Uintptr(),
|
|
539
539
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "uintptr" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }],
|
|
540
540
|
Uintptr,
|
|
541
|
-
{"v": { kind: $.TypeKind.Basic, name: "uintptr" }}
|
|
541
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "uintptr" } }]
|
|
542
542
|
);
|
|
543
543
|
}
|
|
544
544
|
|
|
@@ -570,7 +570,7 @@ class noCopy {
|
|
|
570
570
|
new noCopy(),
|
|
571
571
|
[{ name: "Lock", args: [], returns: [] }, { name: "Unlock", args: [], returns: [] }],
|
|
572
572
|
noCopy,
|
|
573
|
-
|
|
573
|
+
[]
|
|
574
574
|
);
|
|
575
575
|
}
|
|
576
576
|
|
|
@@ -595,6 +595,6 @@ class align64 {
|
|
|
595
595
|
new align64(),
|
|
596
596
|
[],
|
|
597
597
|
align64,
|
|
598
|
-
|
|
598
|
+
[]
|
|
599
599
|
);
|
|
600
600
|
}
|
|
@@ -96,7 +96,7 @@ export class Value {
|
|
|
96
96
|
new Value(),
|
|
97
97
|
[{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Interface, methods: [] } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Interface, methods: [] } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Interface, methods: [] } }], returns: [{ type: { kind: $.TypeKind.Interface, methods: [] } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Interface, methods: [] } }, { name: "new", type: { kind: $.TypeKind.Interface, methods: [] } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }],
|
|
98
98
|
Value,
|
|
99
|
-
{"v": { kind: $.TypeKind.Interface, methods: [] }}
|
|
99
|
+
[{ name: "v", key: "v", type: { kind: $.TypeKind.Interface, methods: [] } }]
|
|
100
100
|
);
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -143,7 +143,7 @@ class efaceWords {
|
|
|
143
143
|
new efaceWords(),
|
|
144
144
|
[],
|
|
145
145
|
efaceWords,
|
|
146
|
-
{"data": { kind: $.TypeKind.Basic, name: "Pointer" }, "typ": { kind: $.TypeKind.Basic, name: "Pointer" }}
|
|
146
|
+
[{ name: "data", key: "data", type: { kind: $.TypeKind.Basic, name: "Pointer" } }, { name: "typ", key: "typ", type: { kind: $.TypeKind.Basic, name: "Pointer" } }]
|
|
147
147
|
);
|
|
148
148
|
}
|
|
149
149
|
|
package/gs/syscall/env.ts
CHANGED
|
@@ -1,47 +1,62 @@
|
|
|
1
1
|
import * as $ from '@goscript/builtin/index.js'
|
|
2
2
|
|
|
3
|
+
type ProcessEnv = Record<string, string | undefined>
|
|
4
|
+
|
|
5
|
+
interface ProcessLike {
|
|
6
|
+
env?: ProcessEnv
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function hostEnv(): ProcessEnv | undefined {
|
|
10
|
+
return (globalThis as { process?: ProcessLike }).process?.env
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
// Environment variable functions using Node.js/browser APIs
|
|
4
14
|
export function Getenv(key: string): [string, boolean] {
|
|
5
|
-
|
|
6
|
-
|
|
15
|
+
const env = hostEnv()
|
|
16
|
+
if (env !== undefined) {
|
|
17
|
+
const value = env[key]
|
|
7
18
|
return value !== undefined ? [value, true] : ['', false]
|
|
8
19
|
}
|
|
9
20
|
return ['', false]
|
|
10
21
|
}
|
|
11
22
|
|
|
12
23
|
export function Setenv(key: string, value: string): $.GoError {
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
const env = hostEnv()
|
|
25
|
+
if (env !== undefined) {
|
|
26
|
+
env[key] = value
|
|
15
27
|
return null
|
|
16
28
|
}
|
|
17
29
|
return { Error: () => 'setenv not supported' }
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
export function Unsetenv(key: string): $.GoError {
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
const env = hostEnv()
|
|
34
|
+
if (env !== undefined) {
|
|
35
|
+
delete env[key]
|
|
23
36
|
return null
|
|
24
37
|
}
|
|
25
38
|
return { Error: () => 'unsetenv not supported' }
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
export function Clearenv(): void {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
42
|
+
const env = hostEnv()
|
|
43
|
+
if (env !== undefined) {
|
|
44
|
+
for (const key in env) {
|
|
45
|
+
delete env[key]
|
|
32
46
|
}
|
|
33
47
|
}
|
|
34
48
|
}
|
|
35
49
|
|
|
36
50
|
export function Environ(): $.Slice<string> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
const host = hostEnv()
|
|
52
|
+
if (host !== undefined) {
|
|
53
|
+
const values: string[] = []
|
|
54
|
+
for (const [key, value] of Object.entries(host)) {
|
|
40
55
|
if (value !== undefined) {
|
|
41
|
-
|
|
56
|
+
values.push(`${key}=${value}`)
|
|
42
57
|
}
|
|
43
58
|
}
|
|
44
|
-
return $.arrayToSlice(
|
|
59
|
+
return $.arrayToSlice(values)
|
|
45
60
|
}
|
|
46
61
|
return $.arrayToSlice([])
|
|
47
62
|
}
|
|
@@ -108,6 +108,73 @@ describe('testing.T', () => {
|
|
|
108
108
|
)
|
|
109
109
|
})
|
|
110
110
|
|
|
111
|
+
it('propagates process exits out of subtests without cleanup', async () => {
|
|
112
|
+
const t = new T('root')
|
|
113
|
+
const exit = { __goscriptExitCode: 7 }
|
|
114
|
+
let cleaned = false
|
|
115
|
+
|
|
116
|
+
await expect(
|
|
117
|
+
t.Run('child', (child) => {
|
|
118
|
+
child.Cleanup(() => {
|
|
119
|
+
cleaned = true
|
|
120
|
+
})
|
|
121
|
+
throw exit
|
|
122
|
+
}),
|
|
123
|
+
).rejects.toBe(exit)
|
|
124
|
+
expect(cleaned).toBe(false)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('propagates process exits out of subtest cleanups', async () => {
|
|
128
|
+
const t = new T('root')
|
|
129
|
+
const exit = { __goscriptExitCode: 8 }
|
|
130
|
+
|
|
131
|
+
await expect(
|
|
132
|
+
t.Run('child', (child) => {
|
|
133
|
+
child.Cleanup(() => {
|
|
134
|
+
throw exit
|
|
135
|
+
})
|
|
136
|
+
}),
|
|
137
|
+
).rejects.toBe(exit)
|
|
138
|
+
expect(t.Failed()).toBe(false)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('propagates process exits out of package tests without cleanup', async () => {
|
|
142
|
+
const exit = { __goscriptExitCode: 9 }
|
|
143
|
+
let cleaned = false
|
|
144
|
+
|
|
145
|
+
await expect(
|
|
146
|
+
runTests('example.test/exit', [
|
|
147
|
+
{
|
|
148
|
+
name: 'TestExit',
|
|
149
|
+
fn: (t) => {
|
|
150
|
+
t.Cleanup(() => {
|
|
151
|
+
cleaned = true
|
|
152
|
+
})
|
|
153
|
+
throw exit
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
]),
|
|
157
|
+
).rejects.toBe(exit)
|
|
158
|
+
expect(cleaned).toBe(false)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
it('propagates process exits out of package test cleanups', async () => {
|
|
162
|
+
const exit = { __goscriptExitCode: 10 }
|
|
163
|
+
|
|
164
|
+
await expect(
|
|
165
|
+
runTests('example.test/exit-cleanup', [
|
|
166
|
+
{
|
|
167
|
+
name: 'TestExitCleanup',
|
|
168
|
+
fn: (t) => {
|
|
169
|
+
t.Cleanup(() => {
|
|
170
|
+
throw exit
|
|
171
|
+
})
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
]),
|
|
175
|
+
).rejects.toBe(exit)
|
|
176
|
+
})
|
|
177
|
+
|
|
111
178
|
it('returns a non-nil context', () => {
|
|
112
179
|
const t = new T('root')
|
|
113
180
|
|
package/gs/testing/testing.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import * as nodeFS from 'node:fs'
|
|
2
|
-
import { tmpdir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
4
|
-
|
|
5
1
|
import * as context from '@goscript/context/index.js'
|
|
6
2
|
|
|
7
3
|
export type TestFunc = (t: T) => void | Promise<void>
|
|
@@ -24,6 +20,18 @@ export type RunResult = {
|
|
|
24
20
|
skipped: number
|
|
25
21
|
}
|
|
26
22
|
|
|
23
|
+
interface HostProcess {
|
|
24
|
+
env?: Record<string, string | undefined>
|
|
25
|
+
cwd?: () => string
|
|
26
|
+
chdir?: (dir: string) => void
|
|
27
|
+
getBuiltinModule?: (name: string) => unknown
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface HostGlobal {
|
|
31
|
+
process?: HostProcess
|
|
32
|
+
require?: (name: string) => unknown
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
class TestControl extends Error {
|
|
28
36
|
public readonly kind: 'fatal' | 'skip'
|
|
29
37
|
|
|
@@ -127,6 +135,9 @@ export class T {
|
|
|
127
135
|
try {
|
|
128
136
|
await fn(child)
|
|
129
137
|
} catch (err) {
|
|
138
|
+
if (isProcessExitError(err)) {
|
|
139
|
+
throw err
|
|
140
|
+
}
|
|
130
141
|
if (err instanceof TestControl && err.kind === 'skip') {
|
|
131
142
|
// A skipped subtest is still a successful Run result.
|
|
132
143
|
} else {
|
|
@@ -139,6 +150,9 @@ export class T {
|
|
|
139
150
|
try {
|
|
140
151
|
await child.runCleanups()
|
|
141
152
|
} catch (err) {
|
|
153
|
+
if (isProcessExitError(err)) {
|
|
154
|
+
throw err
|
|
155
|
+
}
|
|
142
156
|
child.Fail()
|
|
143
157
|
if (!(err instanceof TestControl)) {
|
|
144
158
|
child.Log(formatValue(err))
|
|
@@ -153,9 +167,21 @@ export class T {
|
|
|
153
167
|
}
|
|
154
168
|
|
|
155
169
|
public TempDir(): string {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
170
|
+
const fs = requireHostModule<{
|
|
171
|
+
mkdtempSync(prefix: string): string
|
|
172
|
+
rmSync(path: string, opts: { force: boolean; recursive: boolean }): void
|
|
173
|
+
}>('node:fs', 'testing.TempDir')
|
|
174
|
+
const os = requireHostModule<{ tmpdir(): string }>(
|
|
175
|
+
'node:os',
|
|
176
|
+
'testing.TempDir',
|
|
177
|
+
)
|
|
178
|
+
const pathMod = requireHostModule<{ join(...parts: string[]): string }>(
|
|
179
|
+
'node:path',
|
|
180
|
+
'testing.TempDir',
|
|
181
|
+
)
|
|
182
|
+
const path = fs.mkdtempSync(
|
|
183
|
+
pathMod.join(
|
|
184
|
+
os.tmpdir(),
|
|
159
185
|
'goscript-test-' +
|
|
160
186
|
this.testName.replace(/[^A-Za-z0-9_.-]/g, '_') +
|
|
161
187
|
'-' +
|
|
@@ -164,7 +190,7 @@ export class T {
|
|
|
164
190
|
)
|
|
165
191
|
this.tempDirs.push(path)
|
|
166
192
|
this.Cleanup(() => {
|
|
167
|
-
|
|
193
|
+
fs.rmSync(path, { force: true, recursive: true })
|
|
168
194
|
})
|
|
169
195
|
return path
|
|
170
196
|
}
|
|
@@ -172,12 +198,9 @@ export class T {
|
|
|
172
198
|
public Parallel(): void {}
|
|
173
199
|
|
|
174
200
|
public Setenv(key: string, value: string): void {
|
|
175
|
-
const
|
|
176
|
-
| { env?: Record<string, string | undefined> }
|
|
177
|
-
| undefined
|
|
178
|
-
const env = proc?.env
|
|
201
|
+
const env = (globalThis as HostGlobal).process?.env
|
|
179
202
|
if (env === undefined) {
|
|
180
|
-
|
|
203
|
+
throw new Error('testing.Setenv is not supported without a host process')
|
|
181
204
|
}
|
|
182
205
|
const oldValue = env[key]
|
|
183
206
|
env[key] = value
|
|
@@ -191,11 +214,9 @@ export class T {
|
|
|
191
214
|
}
|
|
192
215
|
|
|
193
216
|
public Chdir(dir: string): void {
|
|
194
|
-
const proc = (globalThis as
|
|
195
|
-
| { cwd?: () => string; chdir?: (dir: string) => void }
|
|
196
|
-
| undefined
|
|
217
|
+
const proc = (globalThis as HostGlobal).process
|
|
197
218
|
if (proc?.cwd === undefined || proc.chdir === undefined) {
|
|
198
|
-
|
|
219
|
+
throw new Error('testing.Chdir is not supported without a host process')
|
|
199
220
|
}
|
|
200
221
|
const oldDir = proc.cwd()
|
|
201
222
|
proc.chdir(dir)
|
|
@@ -249,6 +270,9 @@ export class B extends T {
|
|
|
249
270
|
try {
|
|
250
271
|
await fn(child)
|
|
251
272
|
} catch (err) {
|
|
273
|
+
if (isProcessExitError(err)) {
|
|
274
|
+
throw err
|
|
275
|
+
}
|
|
252
276
|
child.Error(err)
|
|
253
277
|
}
|
|
254
278
|
if (child.Failed()) {
|
|
@@ -328,6 +352,9 @@ export async function runTests(
|
|
|
328
352
|
try {
|
|
329
353
|
await test.fn(t)
|
|
330
354
|
} catch (err) {
|
|
355
|
+
if (isProcessExitError(err)) {
|
|
356
|
+
throw err
|
|
357
|
+
}
|
|
331
358
|
if (err instanceof TestControl && err.kind === 'skip') {
|
|
332
359
|
skipped++
|
|
333
360
|
} else {
|
|
@@ -336,9 +363,8 @@ export async function runTests(
|
|
|
336
363
|
t.Log(formatValue(err))
|
|
337
364
|
}
|
|
338
365
|
}
|
|
339
|
-
} finally {
|
|
340
|
-
await t.runCleanups()
|
|
341
366
|
}
|
|
367
|
+
await t.runCleanups()
|
|
342
368
|
const elapsed = ((Date.now() - start) / 1000).toFixed(2)
|
|
343
369
|
if (t.Skipped()) {
|
|
344
370
|
if (options.verbose) {
|
|
@@ -383,6 +409,48 @@ function formatMessage(format: string, args: unknown[]): string {
|
|
|
383
409
|
})
|
|
384
410
|
}
|
|
385
411
|
|
|
412
|
+
function requireHostModule<T>(name: string, api: string): T {
|
|
413
|
+
const fromProcess = (globalThis as HostGlobal).process?.getBuiltinModule?.(
|
|
414
|
+
name,
|
|
415
|
+
)
|
|
416
|
+
if (fromProcess !== undefined && fromProcess !== null) {
|
|
417
|
+
return fromProcess as T
|
|
418
|
+
}
|
|
419
|
+
const req = hostRequire()
|
|
420
|
+
if (req !== undefined) {
|
|
421
|
+
return req(name) as T
|
|
422
|
+
}
|
|
423
|
+
throw new Error(
|
|
424
|
+
api + ' is not supported without Node-compatible host modules',
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function hostRequire(): ((name: string) => unknown) | undefined {
|
|
429
|
+
const globalRequire = (globalThis as HostGlobal).require
|
|
430
|
+
if (typeof globalRequire === 'function') {
|
|
431
|
+
return globalRequire
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
const req = eval(
|
|
435
|
+
'typeof require === "function" ? require : undefined',
|
|
436
|
+
) as unknown
|
|
437
|
+
if (typeof req === 'function') {
|
|
438
|
+
return req as (name: string) => unknown
|
|
439
|
+
}
|
|
440
|
+
} catch {
|
|
441
|
+
return undefined
|
|
442
|
+
}
|
|
443
|
+
return undefined
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function isProcessExitError(err: unknown): boolean {
|
|
447
|
+
if (err === null || typeof err !== 'object') {
|
|
448
|
+
return false
|
|
449
|
+
}
|
|
450
|
+
const code = (err as { __goscriptExitCode?: unknown }).__goscriptExitCode
|
|
451
|
+
return typeof code === 'number'
|
|
452
|
+
}
|
|
453
|
+
|
|
386
454
|
function formatValue(value: unknown): string {
|
|
387
455
|
if (value instanceof Error) {
|
|
388
456
|
return value.message
|