goscript 0.2.6 → 0.2.7
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/cmd-compile.go +7 -0
- package/cmd/goscript/cmd_compile_test.go +83 -0
- package/compiler/compile-request.go +3 -0
- package/compiler/compiler-cache.go +828 -0
- package/compiler/compiler-cache_test.go +705 -0
- package/compiler/config.go +2 -0
- package/compiler/index.test.ts +26 -1
- package/compiler/index.ts +5 -0
- package/compiler/lowered-program.go +31 -20
- package/compiler/lowering.go +349 -93
- package/compiler/lowering_bench_test.go +1 -0
- package/compiler/override-facts.go +309 -8
- package/compiler/override-parity-verifier.go +45 -1
- package/compiler/override-parity-verifier_test.go +100 -0
- package/compiler/override-registry_test.go +1 -0
- package/compiler/package-graph.go +40 -12
- package/compiler/package-graph_test.go +29 -0
- package/compiler/runtime-contract.go +8 -0
- package/compiler/service.go +98 -11
- package/compiler/skeleton_test.go +110 -14
- package/compiler/typescript-emitter.go +120 -23
- package/dist/compiler/index.d.ts +2 -0
- package/dist/compiler/index.js +3 -0
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +24 -33
- package/dist/gs/builtin/builtin.js +54 -61
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +1 -0
- package/dist/gs/builtin/hostio.js +1 -1
- package/dist/gs/builtin/hostio.js.map +1 -1
- 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/panic.d.ts +18 -0
- package/dist/gs/builtin/panic.js +98 -0
- package/dist/gs/builtin/panic.js.map +1 -0
- package/dist/gs/builtin/slice.d.ts +10 -0
- package/dist/gs/builtin/slice.js +110 -53
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.js +15 -3
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +1 -1
- package/dist/gs/builtin/varRef.js +3 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.js +51 -38
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.d.ts +1 -1
- package/dist/gs/bytes/reader.gs.js +6 -7
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/cmp/index.d.ts +1 -1
- package/dist/gs/cmp/index.js +43 -10
- package/dist/gs/cmp/index.js.map +1 -1
- package/dist/gs/context/context.d.ts +2 -2
- package/dist/gs/context/context.js +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/embed/index.js +1 -1
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/encoding/binary/index.js +201 -8
- package/dist/gs/encoding/binary/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +5 -0
- package/dist/gs/encoding/json/index.js +388 -25
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.js +17 -24
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.js +129 -35
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -1
- package/dist/gs/internal/bytealg/index.js +43 -8
- package/dist/gs/internal/bytealg/index.js.map +1 -1
- package/dist/gs/internal/byteorder/index.d.ts +2 -2
- package/dist/gs/internal/byteorder/index.js +2 -2
- package/dist/gs/internal/byteorder/index.js.map +1 -1
- package/dist/gs/io/fs/format.js +2 -2
- package/dist/gs/io/fs/format.js.map +1 -1
- package/dist/gs/io/fs/fs.d.ts +1 -1
- package/dist/gs/io/fs/fs.js +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/io.d.ts +21 -21
- package/dist/gs/io/io.js +49 -50
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.js +26 -8
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/math/copysign.gs.js +10 -17
- package/dist/gs/math/copysign.gs.js.map +1 -1
- package/dist/gs/math/pow.gs.js +5 -0
- package/dist/gs/math/pow.gs.js.map +1 -1
- package/dist/gs/math/signbit.gs.js +6 -2
- package/dist/gs/math/signbit.gs.js.map +1 -1
- package/dist/gs/mime/index.js +1 -0
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +6 -6
- package/dist/gs/net/http/index.js +507 -43
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/stat.gs.d.ts +2 -2
- package/dist/gs/os/types.gs.d.ts +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.d.ts +1 -1
- package/dist/gs/os/types_js.gs.js +7 -7
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.d.ts +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/os/zero_copy_posix.gs.d.ts +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js +8 -4
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.js +216 -42
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/path/match.js +6 -3
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +5 -4
- package/dist/gs/reflect/type.js +29 -11
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/slices/slices.js +11 -11
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/strconv/atof.gs.js +156 -43
- package/dist/gs/strconv/atof.gs.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.d.ts +3 -2
- package/dist/gs/strconv/atoi.gs.js +86 -67
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/ftoa.gs.js +73 -3
- package/dist/gs/strconv/ftoa.gs.js.map +1 -1
- package/dist/gs/strconv/itoa.gs.d.ts +4 -4
- package/dist/gs/strconv/itoa.gs.js +5 -4
- package/dist/gs/strconv/itoa.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.d.ts +1 -1
- package/dist/gs/strconv/quote.gs.js +311 -103
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +8 -8
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/strings.js +87 -61
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/doc_64.gs.d.ts +14 -14
- package/dist/gs/sync/atomic/doc_64.gs.js +10 -10
- package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.d.ts +22 -22
- package/dist/gs/sync/atomic/type.gs.js +4 -4
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/sync.js +50 -12
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +6 -6
- package/dist/gs/syscall/fs.js +1 -1
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/time/time.d.ts +18 -18
- package/dist/gs/time/time.js +58 -55
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/tables.d.ts +11 -0
- package/dist/gs/unicode/tables.js +635 -0
- package/dist/gs/unicode/tables.js.map +1 -0
- package/dist/gs/unicode/unicode.d.ts +58 -38
- package/dist/gs/unicode/unicode.js +362 -278
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/go.sum +13 -0
- package/gs/builtin/builtin.ts +83 -93
- package/gs/builtin/hostio.ts +1 -1
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/panic.test.ts +189 -0
- package/gs/builtin/panic.ts +107 -0
- package/gs/builtin/runtime-contract.test.ts +5 -5
- package/gs/builtin/slice.test.ts +23 -0
- package/gs/builtin/slice.ts +133 -95
- package/gs/builtin/type.ts +16 -3
- package/gs/builtin/varRef.ts +4 -2
- package/gs/builtin/wide-int.test.ts +41 -0
- package/gs/bytes/bytes.gs.ts +54 -41
- package/gs/bytes/bytes.test.ts +18 -1
- package/gs/bytes/reader.gs.ts +7 -8
- package/gs/cmp/index.test.ts +55 -0
- package/gs/cmp/index.ts +45 -9
- package/gs/context/context.ts +3 -3
- package/gs/embed/index.ts +2 -2
- package/gs/encoding/binary/index.test.ts +104 -0
- package/gs/encoding/binary/index.ts +259 -11
- package/gs/encoding/json/index.test.ts +107 -0
- package/gs/encoding/json/index.ts +400 -29
- package/gs/errors/errors.test.ts +44 -1
- package/gs/errors/errors.ts +15 -31
- package/gs/fmt/fmt.test.ts +70 -2
- package/gs/fmt/fmt.ts +128 -34
- package/gs/golang.org/x/crypto/cryptobyte/index.ts +1 -1
- package/gs/internal/bytealg/index.test.ts +26 -1
- package/gs/internal/bytealg/index.ts +44 -8
- package/gs/internal/byteorder/index.ts +6 -4
- package/gs/io/fs/format.ts +2 -2
- package/gs/io/fs/fs.ts +2 -2
- package/gs/io/fs/stat.test.ts +2 -2
- package/gs/io/fs/sub.test.ts +2 -2
- package/gs/io/fs/walk.test.ts +2 -2
- package/gs/io/io.test.ts +47 -5
- package/gs/io/io.ts +73 -73
- package/gs/io/limit.test.ts +103 -0
- package/gs/math/bits/index.test.ts +128 -0
- package/gs/math/bits/index.ts +26 -8
- package/gs/math/copysign.gs.test.ts +3 -1
- package/gs/math/copysign.gs.ts +10 -22
- package/gs/math/pow.gs.test.ts +4 -5
- package/gs/math/pow.gs.ts +5 -0
- package/gs/math/signbit.gs.test.ts +2 -1
- package/gs/math/signbit.gs.ts +6 -3
- package/gs/mime/index.ts +1 -0
- package/gs/net/http/index.test.ts +683 -2
- package/gs/net/http/index.ts +598 -57
- package/gs/net/http/meta.json +3 -0
- package/gs/os/stat.gs.ts +2 -2
- package/gs/os/types.gs.ts +2 -2
- package/gs/os/types_js.gs.ts +9 -9
- package/gs/os/types_unix.gs.ts +2 -2
- package/gs/os/zero_copy_posix.gs.ts +2 -2
- package/gs/path/filepath/match.test.ts +16 -0
- package/gs/path/filepath/match.ts +8 -4
- package/gs/path/filepath/path.test.ts +91 -9
- package/gs/path/filepath/path.ts +223 -49
- package/gs/path/match.test.ts +32 -0
- package/gs/path/match.ts +6 -3
- package/gs/reflect/deepequal.test.ts +1 -1
- package/gs/reflect/field.test.ts +1 -1
- package/gs/reflect/function-types.test.ts +6 -6
- package/gs/reflect/sliceat.test.ts +13 -13
- package/gs/reflect/structof.test.ts +4 -4
- package/gs/reflect/type.ts +34 -14
- package/gs/reflect/typefor.test.ts +5 -5
- package/gs/runtime/pprof/index.test.ts +20 -0
- package/gs/runtime/trace/index.test.ts +3 -0
- package/gs/slices/slices.test.ts +31 -0
- package/gs/slices/slices.ts +11 -11
- package/gs/strconv/append.test.ts +99 -0
- package/gs/strconv/atof.gs.ts +156 -42
- package/gs/strconv/atof.test.ts +45 -0
- package/gs/strconv/atoi.gs.ts +87 -69
- package/gs/strconv/atoi.test.ts +49 -0
- package/gs/strconv/ftoa.gs.ts +85 -10
- package/gs/strconv/ftoa.test.ts +43 -0
- package/gs/strconv/itoa.gs.ts +10 -9
- package/gs/strconv/quote.gs.ts +335 -108
- package/gs/strconv/quote.test.ts +111 -0
- package/gs/strings/reader.test.ts +10 -10
- package/gs/strings/reader.ts +9 -9
- package/gs/strings/strings.test.ts +18 -5
- package/gs/strings/strings.ts +81 -68
- package/gs/sync/atomic/doc_64.gs.ts +24 -24
- package/gs/sync/atomic/doc_64.test.ts +5 -5
- package/gs/sync/atomic/type.gs.ts +28 -28
- package/gs/sync/sync.test.ts +109 -1
- package/gs/sync/sync.ts +46 -12
- package/gs/syscall/fs.ts +8 -8
- package/gs/syscall/net.test.ts +1 -1
- package/gs/time/parse.test.ts +45 -0
- package/gs/time/time.test.ts +46 -23
- package/gs/time/time.ts +69 -66
- package/gs/unicode/gen.go +198 -0
- package/gs/unicode/tables.ts +646 -0
- package/gs/unicode/unicode.test.ts +69 -0
- package/gs/unicode/unicode.ts +396 -312
- package/package.json +1 -1
- package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +0 -20
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js +0 -134
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +0 -30
- package/gs/github.com/aperturerobotics/util/conc/index.ts +0 -172
- package/gs/github.com/aperturerobotics/util/conc/meta.json +0 -9
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ErrBadPattern, Match } from './index.js'
|
|
2
|
+
import { describe, expect, test } from 'vitest'
|
|
3
|
+
|
|
4
|
+
describe('path.Match', () => {
|
|
5
|
+
test('star consumes the run up to but not including a slash', () => {
|
|
6
|
+
// Go: path.Match("*/c", "a/c") => (true, nil). The star matches "a" and
|
|
7
|
+
// the literal "/c" matches the remainder.
|
|
8
|
+
expect(Match('*/c', 'a/c')).toEqual([true, null])
|
|
9
|
+
// Go: a star still cannot cross a slash.
|
|
10
|
+
expect(Match('*c', 'a/c')).toEqual([false, null])
|
|
11
|
+
// Go: path.Match("a*b", "axxb") => (true, nil).
|
|
12
|
+
expect(Match('a*b', 'axxb')).toEqual([true, null])
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('unterminated character class reports ErrBadPattern', () => {
|
|
16
|
+
// Go: an escape that consumes the last rune of the class returns
|
|
17
|
+
// ErrBadPattern rather than indexing past the end of the chunk.
|
|
18
|
+
const [ok, err] = Match('[a', 'x')
|
|
19
|
+
expect(ok).toBe(false)
|
|
20
|
+
expect(err).toBe(ErrBadPattern)
|
|
21
|
+
|
|
22
|
+
const [ok2, err2] = Match('[', 'a')
|
|
23
|
+
expect(ok2).toBe(false)
|
|
24
|
+
expect(err2).toBe(ErrBadPattern)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('well-formed character class still matches', () => {
|
|
28
|
+
// Go: path.Match("[a-c]", "b") => (true, nil).
|
|
29
|
+
expect(Match('[a-c]', 'b')).toEqual([true, null])
|
|
30
|
+
expect(Match('[^a-c]', 'b')).toEqual([false, null])
|
|
31
|
+
})
|
|
32
|
+
})
|
package/gs/path/match.ts
CHANGED
|
@@ -78,7 +78,7 @@ export function Match(pattern: string, name: string): [boolean, $.GoError] {
|
|
|
78
78
|
for (let i = 0; i < $.len(name) && $.indexString(name, i) != 47; i++) {
|
|
79
79
|
let [t, ok, err] = matchChunk(
|
|
80
80
|
chunk,
|
|
81
|
-
$.sliceString(name, i, undefined),
|
|
81
|
+
$.sliceString(name, i + 1, undefined),
|
|
82
82
|
)
|
|
83
83
|
|
|
84
84
|
// if we're the last chunk, make sure we exhausted the name
|
|
@@ -300,8 +300,11 @@ export function getEsc(chunk: string): [number, string, $.GoError] {
|
|
|
300
300
|
return [0, '', ErrBadPattern]
|
|
301
301
|
}
|
|
302
302
|
chunk = $.sliceString(chunk, n, undefined)
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
// An escape that consumes the last rune of the class leaves no terminator,
|
|
304
|
+
// so the pattern is malformed (Go reports ErrBadPattern instead of indexing
|
|
305
|
+
// past the end of the chunk).
|
|
306
|
+
if ($.len(chunk) == 0) {
|
|
307
|
+
return [r, chunk, ErrBadPattern]
|
|
305
308
|
}
|
|
306
309
|
return [r, chunk, null]
|
|
307
310
|
}
|
package/gs/reflect/field.test.ts
CHANGED
|
@@ -63,7 +63,7 @@ describe('reflect struct field access', () => {
|
|
|
63
63
|
ValueOf(person)
|
|
64
64
|
.FieldByIndex(arrayToSlice([1]))
|
|
65
65
|
.Int(),
|
|
66
|
-
).toBe(
|
|
66
|
+
).toBe(3n)
|
|
67
67
|
expect(ValueOf(person).FieldByName('Missing').IsValid()).toBe(false)
|
|
68
68
|
|
|
69
69
|
const stringMethod = ValueOf(person).MethodByName('String')
|
|
@@ -358,7 +358,7 @@ describe('Function Type Detection', () => {
|
|
|
358
358
|
})
|
|
359
359
|
const tupleResult = asArray(await ValueOf(tupleFunc).Call(arrayToSlice([])))
|
|
360
360
|
expect(tupleResult).toHaveLength(2)
|
|
361
|
-
expect(tupleResult[0].Int()).toBe(
|
|
361
|
+
expect(tupleResult[0].Int()).toBe(1n)
|
|
362
362
|
expect(tupleResult[1].String()).toBe('ok')
|
|
363
363
|
|
|
364
364
|
const sliceFunc = functionValue(() => [1, 2], {
|
|
@@ -384,7 +384,7 @@ describe('Function Type Detection', () => {
|
|
|
384
384
|
await ValueOf(namedResultFunc).Call(arrayToSlice([])),
|
|
385
385
|
)
|
|
386
386
|
expect(namedResult[0].Type().String()).toBe('main.MyInt')
|
|
387
|
-
expect(namedResult[0].Int()).toBe(
|
|
387
|
+
expect(namedResult[0].Int()).toBe(7n)
|
|
388
388
|
|
|
389
389
|
const badTupleFunc = functionValue(() => [1], {
|
|
390
390
|
kind: TypeKind.Function,
|
|
@@ -459,7 +459,7 @@ describe('Function Type Detection', () => {
|
|
|
459
459
|
)()
|
|
460
460
|
expect(tuple).toEqual([3, true])
|
|
461
461
|
const reflectedTuple = asArray(await tupleValue.Call(arrayToSlice([])))
|
|
462
|
-
expect(reflectedTuple[0].Int()).toBe(
|
|
462
|
+
expect(reflectedTuple[0].Int()).toBe(3n)
|
|
463
463
|
expect(reflectedTuple[1].Bool()).toBe(true)
|
|
464
464
|
|
|
465
465
|
const zeroType = FuncOf(arrayToSlice([]), arrayToSlice([]), false)
|
|
@@ -481,7 +481,7 @@ describe('Function Type Detection', () => {
|
|
|
481
481
|
const variadicValue = MakeFunc(variadicType, (args) => {
|
|
482
482
|
const values = asArray(args)
|
|
483
483
|
expect(values).toHaveLength(2)
|
|
484
|
-
return arrayToSlice([ValueOf(values[0].Int() + values[1].Len())])
|
|
484
|
+
return arrayToSlice([ValueOf(Number(values[0].Int()) + values[1].Len())])
|
|
485
485
|
})
|
|
486
486
|
const variadic = variadicValue.Interface() as (
|
|
487
487
|
prefix: number,
|
|
@@ -493,13 +493,13 @@ describe('Function Type Detection', () => {
|
|
|
493
493
|
arrayToSlice([ValueOf(10), ValueOf('a'), ValueOf('b')]),
|
|
494
494
|
),
|
|
495
495
|
)
|
|
496
|
-
expect(reflectedVariadic[0].Int()).toBe(
|
|
496
|
+
expect(reflectedVariadic[0].Int()).toBe(12n)
|
|
497
497
|
const reflectedSliceCall = asArray(
|
|
498
498
|
await variadicValue.CallSlice(
|
|
499
499
|
arrayToSlice([ValueOf(10), ValueOf(arrayToSlice(['a', 'b', 'c']))]),
|
|
500
500
|
),
|
|
501
501
|
)
|
|
502
|
-
expect(reflectedSliceCall[0].Int()).toBe(
|
|
502
|
+
expect(reflectedSliceCall[0].Int()).toBe(13n)
|
|
503
503
|
|
|
504
504
|
const badResult = MakeFunc(unaryType, () => arrayToSlice([]))
|
|
505
505
|
await expect(
|
|
@@ -19,18 +19,18 @@ describe('reflect owned pointer handles', () => {
|
|
|
19
19
|
const values = [1, 2, 3]
|
|
20
20
|
const element = ValueOf(values).Index(1)
|
|
21
21
|
|
|
22
|
-
element.SetInt(
|
|
22
|
+
element.SetInt(8n)
|
|
23
23
|
expect(values).toEqual([1, 8, 3])
|
|
24
24
|
|
|
25
25
|
const address = element.UnsafeAddr()
|
|
26
26
|
expect($.isOwnedPointerHandle(address)).toBe(true)
|
|
27
27
|
|
|
28
28
|
const pointer = NewAt(element.Type(), address as any)
|
|
29
|
-
pointer.Elem().SetInt(
|
|
29
|
+
pointer.Elem().SetInt(11n)
|
|
30
30
|
expect(values).toEqual([1, 11, 3])
|
|
31
31
|
|
|
32
32
|
const refPointer = NewAt(element.Type(), $.indexRef(values, 1) as any)
|
|
33
|
-
refPointer.Elem().SetInt(
|
|
33
|
+
refPointer.Elem().SetInt(14n)
|
|
34
34
|
expect(values).toEqual([1, 14, 3])
|
|
35
35
|
})
|
|
36
36
|
|
|
@@ -38,14 +38,14 @@ describe('reflect owned pointer handles', () => {
|
|
|
38
38
|
const bytes = new Uint8Array([4, 5, 6])
|
|
39
39
|
const element = ValueOf(bytes).Index(1)
|
|
40
40
|
|
|
41
|
-
element.SetUint(
|
|
41
|
+
element.SetUint(9n)
|
|
42
42
|
expect(Array.from(bytes)).toEqual([4, 9, 6])
|
|
43
43
|
|
|
44
44
|
const address = element.UnsafeAddr()
|
|
45
45
|
expect($.isOwnedPointerHandle(address)).toBe(true)
|
|
46
46
|
|
|
47
47
|
const pointer = NewAt(element.Type(), address as any)
|
|
48
|
-
pointer.Elem().SetUint(
|
|
48
|
+
pointer.Elem().SetUint(12n)
|
|
49
49
|
expect(Array.from(bytes)).toEqual([4, 12, 6])
|
|
50
50
|
})
|
|
51
51
|
|
|
@@ -54,14 +54,14 @@ describe('reflect owned pointer handles', () => {
|
|
|
54
54
|
const arrayValue = new Value(values, ArrayOf(2, TypeOf(0)))
|
|
55
55
|
const element = arrayValue.Index(0)
|
|
56
56
|
|
|
57
|
-
element.SetInt(
|
|
57
|
+
element.SetInt(7n)
|
|
58
58
|
expect(values).toEqual([7, 2])
|
|
59
59
|
|
|
60
60
|
const address = element.UnsafeAddr()
|
|
61
61
|
expect($.isOwnedPointerHandle(address)).toBe(true)
|
|
62
62
|
|
|
63
63
|
const pointer = NewAt(element.Type(), address as any)
|
|
64
|
-
pointer.Elem().SetInt(
|
|
64
|
+
pointer.Elem().SetInt(13n)
|
|
65
65
|
expect(values).toEqual([13, 2])
|
|
66
66
|
})
|
|
67
67
|
|
|
@@ -71,13 +71,13 @@ describe('reflect owned pointer handles', () => {
|
|
|
71
71
|
|
|
72
72
|
NewAt(intType, local as any)
|
|
73
73
|
.Elem()
|
|
74
|
-
.SetInt(
|
|
74
|
+
.SetInt(4n)
|
|
75
75
|
expect(local.value).toBe(4)
|
|
76
76
|
|
|
77
77
|
const target = { count: 2 }
|
|
78
78
|
NewAt(intType, $.fieldRef(target, 'count') as any)
|
|
79
79
|
.Elem()
|
|
80
|
-
.SetInt(
|
|
80
|
+
.SetInt(5n)
|
|
81
81
|
expect(target.count).toBe(5)
|
|
82
82
|
|
|
83
83
|
expect(() => SliceAt(intType, local as any, 1)).toThrow(
|
|
@@ -107,8 +107,8 @@ describe('reflect owned pointer handles', () => {
|
|
|
107
107
|
expect(slice.Cap()).toBe(2)
|
|
108
108
|
expect(slice.Pointer()).toBe($.indexAddress(values, 1))
|
|
109
109
|
|
|
110
|
-
slice.Index(0).SetInt(
|
|
111
|
-
slice.Index(1).SetInt(
|
|
110
|
+
slice.Index(0).SetInt(21n)
|
|
111
|
+
slice.Index(1).SetInt(31n)
|
|
112
112
|
expect(values).toEqual([10, 21, 31, 40])
|
|
113
113
|
})
|
|
114
114
|
|
|
@@ -123,8 +123,8 @@ describe('reflect owned pointer handles', () => {
|
|
|
123
123
|
expect(slice.Cap()).toBe(2)
|
|
124
124
|
expect(slice.Pointer()).toBe($.indexAddress(bytes, 1))
|
|
125
125
|
|
|
126
|
-
slice.Index(0).SetUint(
|
|
127
|
-
slice.Index(1).SetUint(
|
|
126
|
+
slice.Index(0).SetUint(7n)
|
|
127
|
+
slice.Index(1).SetUint(8n)
|
|
128
128
|
expect(Array.from(bytes)).toEqual([1, 7, 8, 4])
|
|
129
129
|
})
|
|
130
130
|
|
|
@@ -41,7 +41,7 @@ describe('StructOf', () => {
|
|
|
41
41
|
|
|
42
42
|
const value = New(typ).Elem()
|
|
43
43
|
value.Field(0).SetString('Ada')
|
|
44
|
-
value.FieldByName('Count').SetInt(
|
|
44
|
+
value.FieldByName('Count').SetInt(3n)
|
|
45
45
|
|
|
46
46
|
const [data, err] = Marshal(value.Interface())
|
|
47
47
|
expect(err).toBeNull()
|
|
@@ -51,7 +51,7 @@ describe('StructOf', () => {
|
|
|
51
51
|
expect(TypeOf(clone).String()).toBe(typ.String())
|
|
52
52
|
expect(clone.Name).toBe('Ada')
|
|
53
53
|
expect(clone.Count).toBe(3)
|
|
54
|
-
value.FieldByName('Count').SetInt(
|
|
54
|
+
value.FieldByName('Count').SetInt(4n)
|
|
55
55
|
expect(clone.Count).toBe(3)
|
|
56
56
|
})
|
|
57
57
|
|
|
@@ -348,9 +348,9 @@ describe('StructOf', () => {
|
|
|
348
348
|
])
|
|
349
349
|
|
|
350
350
|
const value = New(outer).Elem()
|
|
351
|
-
value.FieldByIndex($.arrayToSlice([0, 0])).SetInt(
|
|
351
|
+
value.FieldByIndex($.arrayToSlice([0, 0])).SetInt(7n)
|
|
352
352
|
value.FieldByName('Label').SetString('seven')
|
|
353
|
-
expect(value.FieldByName('ID').Int()).toBe(
|
|
353
|
+
expect(value.FieldByName('ID').Int()).toBe(7n)
|
|
354
354
|
expect(value.FieldByIndex($.arrayToSlice([0, 1])).String()).toBe('seven')
|
|
355
355
|
})
|
|
356
356
|
|
package/gs/reflect/type.ts
CHANGED
|
@@ -587,9 +587,24 @@ export class Value {
|
|
|
587
587
|
}
|
|
588
588
|
|
|
589
589
|
// Methods required by godoc.txt and used throughout the codebase
|
|
590
|
-
|
|
590
|
+
|
|
591
|
+
// integerValue reads the underlying value as a bigint regardless of whether it
|
|
592
|
+
// is stored as a number (int8..int32/uint8..uint32) or a bigint (int64/uint64).
|
|
593
|
+
private integerValue(): bigint | null {
|
|
594
|
+
if (typeof this._value === 'bigint') {
|
|
595
|
+
return this._value
|
|
596
|
+
}
|
|
591
597
|
const value = this.numericValue()
|
|
592
598
|
if (value !== null && Number.isInteger(value)) {
|
|
599
|
+
return BigInt(value)
|
|
600
|
+
}
|
|
601
|
+
return null
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Int returns v's underlying value as an int64, matching reflect.Value.Int.
|
|
605
|
+
public Int(): bigint {
|
|
606
|
+
const value = this.integerValue()
|
|
607
|
+
if (value !== null) {
|
|
593
608
|
return value
|
|
594
609
|
}
|
|
595
610
|
throw new Error(
|
|
@@ -599,9 +614,10 @@ export class Value {
|
|
|
599
614
|
)
|
|
600
615
|
}
|
|
601
616
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
617
|
+
// Uint returns v's underlying value as a uint64, matching reflect.Value.Uint.
|
|
618
|
+
public Uint(): bigint {
|
|
619
|
+
const value = this.integerValue()
|
|
620
|
+
if (value !== null && value >= 0n) {
|
|
605
621
|
return value
|
|
606
622
|
}
|
|
607
623
|
throw new Error(
|
|
@@ -1159,8 +1175,9 @@ export class Value {
|
|
|
1159
1175
|
}
|
|
1160
1176
|
}
|
|
1161
1177
|
|
|
1162
|
-
// SetInt sets v's underlying value to x
|
|
1163
|
-
|
|
1178
|
+
// SetInt sets v's underlying value to x. x is an int64 (bigint); the stored
|
|
1179
|
+
// value uses the field's representation: bigint for Int64, number otherwise.
|
|
1180
|
+
public SetInt(x: bigint): void {
|
|
1164
1181
|
if (!this.CanSet()) {
|
|
1165
1182
|
throw new Error(
|
|
1166
1183
|
'reflect: call of reflect.Value.SetInt on unaddressable value',
|
|
@@ -1172,17 +1189,19 @@ export class Value {
|
|
|
1172
1189
|
'reflect: call of reflect.Value.SetInt on ' + k + ' Value',
|
|
1173
1190
|
)
|
|
1174
1191
|
}
|
|
1175
|
-
|
|
1192
|
+
const stored: number | bigint = k === Int64 ? x : Number(x)
|
|
1193
|
+
this._value = stored
|
|
1176
1194
|
if (this._parentVarRef) {
|
|
1177
|
-
this._parentVarRef.value =
|
|
1195
|
+
this._parentVarRef.value = stored
|
|
1178
1196
|
}
|
|
1179
1197
|
if (this._parentStruct && this._fieldName) {
|
|
1180
|
-
this._parentStruct[this._fieldName] =
|
|
1198
|
+
this._parentStruct[this._fieldName] = stored
|
|
1181
1199
|
}
|
|
1182
1200
|
}
|
|
1183
1201
|
|
|
1184
|
-
// SetUint sets v's underlying value to x
|
|
1185
|
-
|
|
1202
|
+
// SetUint sets v's underlying value to x. x is a uint64 (bigint); the stored
|
|
1203
|
+
// value uses the field's representation: bigint for Uint64, number otherwise.
|
|
1204
|
+
public SetUint(x: bigint): void {
|
|
1186
1205
|
if (!this.CanSet()) {
|
|
1187
1206
|
throw new Error(
|
|
1188
1207
|
'reflect: call of reflect.Value.SetUint on unaddressable value',
|
|
@@ -1201,12 +1220,13 @@ export class Value {
|
|
|
1201
1220
|
'reflect: call of reflect.Value.SetUint on ' + k + ' Value',
|
|
1202
1221
|
)
|
|
1203
1222
|
}
|
|
1204
|
-
|
|
1223
|
+
const stored: number | bigint = k === Uint64 ? x : Number(x)
|
|
1224
|
+
this._value = stored
|
|
1205
1225
|
if (this._parentVarRef) {
|
|
1206
|
-
this._parentVarRef.value =
|
|
1226
|
+
this._parentVarRef.value = stored
|
|
1207
1227
|
}
|
|
1208
1228
|
if (this._parentStruct && this._fieldName) {
|
|
1209
|
-
this._parentStruct[this._fieldName] =
|
|
1229
|
+
this._parentStruct[this._fieldName] = stored
|
|
1210
1230
|
}
|
|
1211
1231
|
}
|
|
1212
1232
|
|
|
@@ -184,8 +184,8 @@ describe('TypeFor', () => {
|
|
|
184
184
|
|
|
185
185
|
const elem = ValueOf(boxed).Elem()
|
|
186
186
|
expect(elem.Kind()).toBe(Uint64)
|
|
187
|
-
elem.SetUint(
|
|
188
|
-
expect(target.value).toBe(
|
|
187
|
+
elem.SetUint(15n)
|
|
188
|
+
expect(target.value).toBe(15n)
|
|
189
189
|
})
|
|
190
190
|
|
|
191
191
|
it('preserves channel type metadata on interface boxes', () => {
|
|
@@ -680,9 +680,9 @@ describe('TypeFor', () => {
|
|
|
680
680
|
const pointer = New(TypeOf(0))
|
|
681
681
|
const value = Indirect(pointer)
|
|
682
682
|
|
|
683
|
-
expect(value.Int()).toBe(
|
|
684
|
-
value.SetInt(
|
|
685
|
-
expect(pointer.Elem().Int()).toBe(
|
|
683
|
+
expect(value.Int()).toBe(0n)
|
|
684
|
+
value.SetInt(7n)
|
|
685
|
+
expect(pointer.Elem().Int()).toBe(7n)
|
|
686
686
|
})
|
|
687
687
|
|
|
688
688
|
it('interns runtime type descriptors for reflect.Type map keys', () => {
|
|
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
|
|
|
3
3
|
import {
|
|
4
4
|
Lookup,
|
|
5
5
|
NewProfile,
|
|
6
|
+
Profiles,
|
|
6
7
|
StartCPUProfile,
|
|
7
8
|
StopCPUProfile,
|
|
8
9
|
WriteHeapProfile,
|
|
@@ -61,4 +62,23 @@ describe('runtime/pprof override', () => {
|
|
|
61
62
|
'pprof: NewProfile name already in use: goscript.test',
|
|
62
63
|
)
|
|
63
64
|
})
|
|
65
|
+
|
|
66
|
+
it('lists built-in and custom profiles', () => {
|
|
67
|
+
const custom =
|
|
68
|
+
Lookup('goscript.profiles') ?? NewProfile('goscript.profiles')
|
|
69
|
+
const profiles = Array.from(Profiles() ?? [])
|
|
70
|
+
const names = profiles.map((profile) => profile?.Name())
|
|
71
|
+
|
|
72
|
+
expect(names).toEqual(
|
|
73
|
+
expect.arrayContaining([
|
|
74
|
+
'allocs',
|
|
75
|
+
'block',
|
|
76
|
+
'goroutine',
|
|
77
|
+
'heap',
|
|
78
|
+
'mutex',
|
|
79
|
+
'threadcreate',
|
|
80
|
+
custom.Name(),
|
|
81
|
+
]),
|
|
82
|
+
)
|
|
83
|
+
})
|
|
64
84
|
})
|
|
@@ -5,6 +5,7 @@ import * as context from '@goscript/context/index.js'
|
|
|
5
5
|
import {
|
|
6
6
|
IsEnabled,
|
|
7
7
|
Log,
|
|
8
|
+
Logf,
|
|
8
9
|
NewTask,
|
|
9
10
|
Start,
|
|
10
11
|
StartRegion,
|
|
@@ -109,6 +110,7 @@ describe('runtime/trace override', () => {
|
|
|
109
110
|
const [ctx, task] = NewTask(context.Background(), 'proof-task')
|
|
110
111
|
WithRegion(ctx, 'proof-region', () => {
|
|
111
112
|
Log(ctx, 'proof-key', 'proof-value')
|
|
113
|
+
Logf(ctx, 'proof-format', 'value=%s count=%d', 'ok', 3)
|
|
112
114
|
})
|
|
113
115
|
task.End()
|
|
114
116
|
|
|
@@ -126,6 +128,7 @@ describe('runtime/trace override', () => {
|
|
|
126
128
|
expect(text).toContain('proof-task')
|
|
127
129
|
expect(text).toContain('proof-region')
|
|
128
130
|
expect(text).toContain('proof-value')
|
|
131
|
+
expect(text).toContain('value=ok count=3')
|
|
129
132
|
})
|
|
130
133
|
|
|
131
134
|
it('splits a large capture into batches under the size limit', () => {
|
package/gs/slices/slices.test.ts
CHANGED
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
CompareFunc,
|
|
14
14
|
Concat,
|
|
15
15
|
DeleteFunc,
|
|
16
|
+
Equal,
|
|
16
17
|
EqualFunc,
|
|
18
|
+
Index,
|
|
17
19
|
IndexFunc,
|
|
18
20
|
IsSorted,
|
|
19
21
|
IsSortedFunc,
|
|
@@ -27,6 +29,35 @@ import {
|
|
|
27
29
|
SortStableFunc,
|
|
28
30
|
} from './slices.js'
|
|
29
31
|
|
|
32
|
+
describe('slices Go comparable equality and lower-bound search', () => {
|
|
33
|
+
// Go compares comparable elements (arrays/structs) by value with ==, and
|
|
34
|
+
// BinarySearch returns the earliest index for duplicate targets.
|
|
35
|
+
it('Compact removes adjacent equal-by-value array elements', () => {
|
|
36
|
+
expect(Array.from(Compact($.arrayToSlice([[1], [1], [2]])) ?? [])).toEqual([
|
|
37
|
+
[1],
|
|
38
|
+
[2],
|
|
39
|
+
])
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('Equal compares array elements by value', () => {
|
|
43
|
+
expect(Equal($.arrayToSlice([[1, 2]]), $.arrayToSlice([[1, 2]]))).toBe(true)
|
|
44
|
+
expect(Equal($.arrayToSlice([[1, 2]]), $.arrayToSlice([[1, 3]]))).toBe(
|
|
45
|
+
false,
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('Index finds an equal-by-value array element', () => {
|
|
50
|
+
expect(Index($.arrayToSlice([[1], [2], [3]]), [2])).toBe(1)
|
|
51
|
+
expect(Index($.arrayToSlice([[1], [2]]), [9])).toBe(-1)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('BinarySearch returns the first index of a duplicate target', () => {
|
|
55
|
+
expect(BinarySearch($.arrayToSlice([1, 2, 2, 2, 3]), 2)).toEqual([1, true])
|
|
56
|
+
expect(BinarySearch($.arrayToSlice([1, 2, 2, 2, 3]), 4)).toEqual([5, false])
|
|
57
|
+
expect(BinarySearch($.arrayToSlice([1, 3, 5]), 0)).toEqual([0, false])
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
30
61
|
describe('slices.SortFunc', () => {
|
|
31
62
|
it('awaits async comparison callbacks', async () => {
|
|
32
63
|
const values = $.arrayToSlice([3, 1, 2])
|
package/gs/slices/slices.ts
CHANGED
|
@@ -381,7 +381,7 @@ export function Compact<T>(s: $.Slice<T>): $.Slice<T> {
|
|
|
381
381
|
}
|
|
382
382
|
let w = 1
|
|
383
383
|
for (let i = 1; i < $.len(s); i++) {
|
|
384
|
-
if ((s as any)[i]
|
|
384
|
+
if (!$.comparableEqual((s as any)[i], (s as any)[i - 1])) {
|
|
385
385
|
;(s as any)[w] = (s as any)[i]
|
|
386
386
|
w++
|
|
387
387
|
}
|
|
@@ -432,7 +432,7 @@ export function Equal<T>(s1: $.Slice<T>, s2: $.Slice<T>): boolean {
|
|
|
432
432
|
return false
|
|
433
433
|
}
|
|
434
434
|
for (let i = 0; i < len1; i++) {
|
|
435
|
-
if ((s1 as any)[i]
|
|
435
|
+
if (!$.comparableEqual((s1 as any)[i], (s2 as any)[i])) {
|
|
436
436
|
return false
|
|
437
437
|
}
|
|
438
438
|
}
|
|
@@ -461,7 +461,7 @@ export function EqualFunc<T, U>(
|
|
|
461
461
|
|
|
462
462
|
export function Index<T>(s: $.Slice<T>, v: T): number {
|
|
463
463
|
for (let i = 0; i < $.len(s); i++) {
|
|
464
|
-
if ((s as any)[i]
|
|
464
|
+
if ($.comparableEqual((s as any)[i], v)) {
|
|
465
465
|
return i
|
|
466
466
|
}
|
|
467
467
|
}
|
|
@@ -688,23 +688,23 @@ export function BinarySearchFunc<E, T>(
|
|
|
688
688
|
if (cmp == null) {
|
|
689
689
|
throw new Error('slices.BinarySearchFunc: nil comparison function')
|
|
690
690
|
}
|
|
691
|
+
const n = $.len(x)
|
|
691
692
|
let left = 0
|
|
692
|
-
let right =
|
|
693
|
+
let right = n
|
|
693
694
|
|
|
695
|
+
// Lower-bound search: narrow to the earliest index not less than target so
|
|
696
|
+
// duplicate targets return the first match, matching Go's BinarySearchFunc.
|
|
694
697
|
while (left < right) {
|
|
695
698
|
const mid = Math.floor((left + right) / 2)
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
if (result < 0) {
|
|
699
|
+
if (syncNumber(cmp((x as any)[mid] as E, target)) < 0) {
|
|
699
700
|
left = mid + 1
|
|
700
|
-
} else if (result > 0) {
|
|
701
|
-
right = mid
|
|
702
701
|
} else {
|
|
703
|
-
|
|
702
|
+
right = mid
|
|
704
703
|
}
|
|
705
704
|
}
|
|
706
705
|
|
|
707
|
-
|
|
706
|
+
const found = left < n && syncNumber(cmp((x as any)[left] as E, target)) === 0
|
|
707
|
+
return [left, found]
|
|
708
708
|
}
|
|
709
709
|
|
|
710
710
|
function syncNumber(value: SyncCallbackResult<number>): number {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
4
|
+
|
|
5
|
+
import { AppendBool } from './atob.gs.js'
|
|
6
|
+
import { AppendFloat } from './ftoa.gs.js'
|
|
7
|
+
import { AppendInt, AppendUint, FormatUint } from './itoa.gs.js'
|
|
8
|
+
import {
|
|
9
|
+
AppendQuote,
|
|
10
|
+
AppendQuoteRune,
|
|
11
|
+
AppendQuoteRuneToASCII,
|
|
12
|
+
AppendQuoteRuneToGraphic,
|
|
13
|
+
AppendQuoteToASCII,
|
|
14
|
+
AppendQuoteToGraphic,
|
|
15
|
+
IsGraphic,
|
|
16
|
+
IsPrint,
|
|
17
|
+
QuoteRuneToASCII,
|
|
18
|
+
QuoteRuneToGraphic,
|
|
19
|
+
QuotedPrefix,
|
|
20
|
+
QuoteToGraphic,
|
|
21
|
+
} from './quote.gs.js'
|
|
22
|
+
|
|
23
|
+
// Expected outputs are the literal results Go's strconv produces (go1.26.4).
|
|
24
|
+
function appended(dst: $.Bytes): string {
|
|
25
|
+
return $.bytesToString(dst)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function prefix(s: string): $.Bytes {
|
|
29
|
+
return $.stringToBytes(s)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('strconv append/format coverage (Go semantics)', () => {
|
|
33
|
+
it('FormatUint renders in the requested base', () => {
|
|
34
|
+
expect(FormatUint(255, 16)).toBe('ff')
|
|
35
|
+
expect(FormatUint(10, 2)).toBe('1010')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('AppendInt/AppendUint extend the destination buffer', () => {
|
|
39
|
+
expect(appended(AppendInt(prefix('x='), -42, 10))).toBe('x=-42')
|
|
40
|
+
expect(appended(AppendUint(prefix('x='), 255, 16))).toBe('x=ff')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('AppendBool appends true/false', () => {
|
|
44
|
+
expect(appended(AppendBool(prefix('b='), true))).toBe('b=true')
|
|
45
|
+
expect(appended(AppendBool(prefix('b='), false))).toBe('b=false')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('AppendFloat formats with the given verb and precision', () => {
|
|
49
|
+
expect(appended(AppendFloat(prefix('f='), 3.14159, 0x66, 2, 64))).toBe(
|
|
50
|
+
'f=3.14',
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('AppendQuote escapes like Quote', () => {
|
|
55
|
+
expect(appended(AppendQuote(prefix('q='), 'a\tb'))).toBe('q="a\\tb"')
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('AppendQuoteToASCII escapes non-ASCII to \\u', () => {
|
|
59
|
+
expect(appended(AppendQuoteToASCII(prefix(''), 'héllo'))).toBe(
|
|
60
|
+
'"h\\u00e9llo"',
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('AppendQuoteToGraphic keeps graphic Unicode in place', () => {
|
|
65
|
+
expect(appended(AppendQuoteToGraphic(prefix(''), '背'))).toBe('"背"')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('AppendQuoteRune* quote a single rune', () => {
|
|
69
|
+
expect(appended(AppendQuoteRune(prefix(''), 0x41))).toBe("'A'")
|
|
70
|
+
expect(appended(AppendQuoteRuneToASCII(prefix(''), 0x4e16))).toBe(
|
|
71
|
+
"'\\u4e16'",
|
|
72
|
+
)
|
|
73
|
+
expect(appended(AppendQuoteRuneToGraphic(prefix(''), 0x4e16))).toBe("'世'")
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('QuoteToGraphic and QuoteRune variants match Go', () => {
|
|
77
|
+
expect(QuoteToGraphic('背\t')).toBe('"背\\t"')
|
|
78
|
+
expect(QuoteRuneToASCII(0x4e16)).toBe("'\\u4e16'")
|
|
79
|
+
expect(QuoteRuneToGraphic(0x4e16)).toBe("'世'")
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('IsPrint and IsGraphic match Go predicates', () => {
|
|
83
|
+
expect(IsPrint(0x41)).toBe(true)
|
|
84
|
+
expect(IsPrint(0x09)).toBe(false)
|
|
85
|
+
expect(IsPrint(0x07)).toBe(false)
|
|
86
|
+
expect(IsGraphic(0x41)).toBe(true)
|
|
87
|
+
expect(IsGraphic(0x20)).toBe(true)
|
|
88
|
+
expect(IsGraphic(0x09)).toBe(false)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('QuotedPrefix returns the leading quoted literal or a syntax error', () => {
|
|
92
|
+
const [p, err] = QuotedPrefix('"abc" tail')
|
|
93
|
+
expect(p).toBe('"abc"')
|
|
94
|
+
expect(err).toBeNull()
|
|
95
|
+
const [p2, err2] = QuotedPrefix('nope')
|
|
96
|
+
expect(p2).toBe('')
|
|
97
|
+
expect(err2).not.toBeNull()
|
|
98
|
+
})
|
|
99
|
+
})
|