goscript 0.2.2 → 0.2.4
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/compiler/gotest/testdata/browserapi/browserapi_test.go +36 -0
- package/compiler/lowering.go +279 -16
- package/compiler/override-registry_test.go +175 -0
- package/compiler/protobuf-ts-binding.go +154 -6
- package/compiler/protobuf-ts-binding_test.go +7 -2
- package/compiler/runtime-contract.go +2 -0
- package/compiler/runtime-contract_test.go +1 -0
- package/compiler/semantic-model.go +16 -0
- package/compiler/semantic-model_test.go +38 -0
- package/compiler/skeleton_test.go +522 -17
- package/compiler/typescript-emitter.go +4 -0
- package/dist/gs/builtin/builtin.js +7 -9
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/defer.js +2 -2
- package/dist/gs/builtin/hostio.js +5 -5
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/map.js +2 -1
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +3 -0
- package/dist/gs/builtin/slice.js +39 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.js +49 -0
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/compress/gzip/index.d.ts +41 -0
- package/dist/gs/compress/gzip/index.js +235 -0
- package/dist/gs/compress/gzip/index.js.map +1 -0
- package/dist/gs/compress/zlib/index.js +5 -2
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/ecdh/index.js +27 -8
- package/dist/gs/crypto/ecdh/index.js.map +1 -1
- package/dist/gs/crypto/ed25519/index.js +3 -3
- package/dist/gs/crypto/ed25519/index.js.map +1 -1
- package/dist/gs/crypto/rand/index.js +6 -3
- package/dist/gs/crypto/rand/index.js.map +1 -1
- package/dist/gs/embed/index.js +9 -3
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +33 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.js +4 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/scrypt/index.d.ts +2 -0
- package/dist/gs/golang.org/x/crypto/scrypt/index.js +39 -0
- package/dist/gs/golang.org/x/crypto/scrypt/index.js.map +1 -0
- package/dist/gs/hash/fnv/index.js +13 -5
- package/dist/gs/hash/fnv/index.js.map +1 -1
- package/dist/gs/io/fs/glob.d.ts +3 -3
- package/dist/gs/io/fs/glob.js +9 -9
- package/dist/gs/io/fs/glob.js.map +1 -1
- package/dist/gs/io/fs/readdir.d.ts +2 -2
- package/dist/gs/io/fs/readdir.js +13 -74
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/readlink.d.ts +1 -1
- package/dist/gs/io/fs/readlink.js +2 -2
- package/dist/gs/io/fs/readlink.js.map +1 -1
- package/dist/gs/io/fs/stat.d.ts +4 -2
- package/dist/gs/io/fs/stat.js +12 -73
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.d.ts +2 -2
- package/dist/gs/io/fs/sub.js +11 -11
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/fs/walk.js +2 -2
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.js.map +1 -1
- package/dist/gs/mime/index.js +5 -2
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.js +6 -3
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +34 -18
- package/dist/gs/net/http/index.js +280 -63
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.d.ts +5 -5
- package/dist/gs/net/http/pprof/index.js +21 -21
- package/dist/gs/net/http/pprof/index.js.map +1 -1
- package/dist/gs/reflect/iter.js +1 -1
- package/dist/gs/reflect/iter.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +2 -0
- package/dist/gs/reflect/type.js +53 -21
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/runtime/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.js +2 -2
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +1 -1
- package/dist/gs/slices/slices.js +37 -4
- package/dist/gs/slices/slices.js.map +1 -1
- package/gs/builtin/builtin.ts +11 -14
- package/gs/builtin/defer.ts +2 -2
- package/gs/builtin/hostio.ts +5 -5
- package/gs/builtin/map.ts +4 -1
- package/gs/builtin/runtime-contract.test.ts +25 -0
- package/gs/builtin/slice.test.ts +14 -0
- package/gs/builtin/slice.ts +64 -0
- package/gs/builtin/type.ts +72 -0
- package/gs/bytes/bytes.test.ts +14 -13
- package/gs/compress/gzip/index.test.ts +86 -0
- package/gs/compress/gzip/index.ts +297 -0
- package/gs/compress/gzip/meta.json +6 -0
- package/gs/compress/gzip/parity.json +45 -0
- package/gs/compress/zlib/index.test.ts +19 -5
- package/gs/compress/zlib/index.ts +16 -7
- package/gs/context/context.test.ts +3 -1
- package/gs/crypto/ecdh/index.test.ts +6 -2
- package/gs/crypto/ecdh/index.ts +49 -12
- package/gs/crypto/ed25519/index.ts +20 -7
- package/gs/crypto/rand/index.ts +6 -3
- package/gs/embed/index.test.ts +4 -4
- package/gs/embed/index.ts +9 -3
- package/gs/fmt/fmt.test.ts +29 -4
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +126 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +46 -0
- package/gs/github.com/mr-tron/base58/base58/index.ts +9 -3
- package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +2 -8
- package/gs/golang.org/x/crypto/scrypt/index.test.ts +81 -0
- package/gs/golang.org/x/crypto/scrypt/index.ts +54 -0
- package/gs/golang.org/x/crypto/scrypt/meta.json +5 -0
- package/gs/hash/fnv/index.test.ts +1 -8
- package/gs/hash/fnv/index.ts +27 -10
- package/gs/io/fs/glob.ts +14 -11
- package/gs/io/fs/meta.json +5 -0
- package/gs/io/fs/readdir.test.ts +63 -2
- package/gs/io/fs/readdir.ts +33 -30
- package/gs/io/fs/readlink.test.ts +2 -2
- package/gs/io/fs/readlink.ts +5 -2
- package/gs/io/fs/stat.test.ts +79 -0
- package/gs/io/fs/stat.ts +24 -10
- package/gs/io/fs/sub.test.ts +93 -0
- package/gs/io/fs/sub.ts +13 -13
- package/gs/io/fs/walk.ts +2 -2
- package/gs/maps/iter.ts +9 -9
- package/gs/maps/maps.ts +4 -4
- package/gs/math/bits/index.test.ts +10 -1
- package/gs/mime/index.test.ts +33 -15
- package/gs/mime/index.ts +9 -2
- package/gs/net/http/httptest/index.test.ts +17 -3
- package/gs/net/http/httptest/index.ts +8 -3
- package/gs/net/http/index.test.ts +851 -124
- package/gs/net/http/index.ts +612 -146
- package/gs/net/http/meta.json +3 -1
- package/gs/net/http/pprof/index.test.ts +4 -4
- package/gs/net/http/pprof/index.ts +43 -22
- package/gs/os/file_unix_js.test.ts +22 -0
- package/gs/reflect/iter.ts +4 -2
- package/gs/reflect/map.test.ts +56 -1
- package/gs/reflect/type.ts +76 -37
- package/gs/runtime/pprof/index.test.ts +7 -1
- package/gs/runtime/pprof/index.ts +5 -1
- package/gs/runtime/runtime.test.ts +7 -0
- package/gs/runtime/runtime.ts +2 -4
- package/gs/runtime/trace/index.test.ts +9 -1
- package/gs/runtime/trace/index.ts +5 -1
- package/gs/slices/meta.json +3 -0
- package/gs/slices/slices.test.ts +59 -21
- package/gs/slices/slices.ts +61 -20
- package/gs/strconv/complex.test.ts +17 -3
- package/gs/sync/atomic/doc_64.test.ts +2 -9
- package/gs/sync/sync.test.ts +18 -8
- package/gs/syscall/js/index.test.ts +9 -4
- package/package.json +5 -4
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
4
|
+
import * as bytes from '@goscript/bytes/index.js'
|
|
5
|
+
import * as io from '@goscript/io/index.js'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
BestCompression,
|
|
9
|
+
BestSpeed,
|
|
10
|
+
DefaultCompression,
|
|
11
|
+
ErrHeader,
|
|
12
|
+
HuffmanOnly,
|
|
13
|
+
NewReader,
|
|
14
|
+
NewWriter,
|
|
15
|
+
NewWriterLevel,
|
|
16
|
+
NoCompression,
|
|
17
|
+
} from './index.js'
|
|
18
|
+
|
|
19
|
+
describe('compress/gzip override', () => {
|
|
20
|
+
test('exports flate compression level constants', () => {
|
|
21
|
+
expect(NoCompression).toBe(0)
|
|
22
|
+
expect(BestSpeed).toBe(1)
|
|
23
|
+
expect(BestCompression).toBe(9)
|
|
24
|
+
expect(DefaultCompression).toBe(-1)
|
|
25
|
+
expect(HuffmanOnly).toBe(-2)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('rejects invalid compression levels', () => {
|
|
29
|
+
const buf = $.markAsStructValue(new bytes.Buffer())
|
|
30
|
+
|
|
31
|
+
expect(NewWriterLevel(buf, HuffmanOnly)[1]).toBeNull()
|
|
32
|
+
expect(NewWriterLevel(buf, BestCompression)[1]).toBeNull()
|
|
33
|
+
expect(NewWriterLevel(buf, HuffmanOnly - 1)[1]?.Error()).toBe(
|
|
34
|
+
'gzip: invalid compression level: -3',
|
|
35
|
+
)
|
|
36
|
+
expect(NewWriterLevel(buf, BestCompression + 1)[1]?.Error()).toBe(
|
|
37
|
+
'gzip: invalid compression level: 10',
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('round trips bytes through writer and reader', async () => {
|
|
42
|
+
const input = $.stringToBytes('hello gzip world')
|
|
43
|
+
const buf = $.markAsStructValue(new bytes.Buffer())
|
|
44
|
+
const writer = NewWriter(buf)
|
|
45
|
+
|
|
46
|
+
const [written, writeErr] = writer.Write(input)
|
|
47
|
+
expect(writeErr).toBeNull()
|
|
48
|
+
expect(written).toBe(input.length)
|
|
49
|
+
expect(await writer.Close()).toBeNull()
|
|
50
|
+
|
|
51
|
+
const [reader, readerErr] = NewReader(bytes.NewReader(buf.Bytes()))
|
|
52
|
+
expect(readerErr).toBeNull()
|
|
53
|
+
expect(reader).not.toBeNull()
|
|
54
|
+
|
|
55
|
+
const [out, readErr] = await io.ReadAll(reader!)
|
|
56
|
+
expect(readErr).toBeNull()
|
|
57
|
+
expect($.bytesToString(out)).toBe('hello gzip world')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('reader reset accepts async generated readers', async () => {
|
|
61
|
+
const compressed = $.markAsStructValue(new bytes.Buffer())
|
|
62
|
+
const writer = NewWriter(compressed)
|
|
63
|
+
expect(writer.Write($.stringToBytes('async gzip source'))[1]).toBeNull()
|
|
64
|
+
expect(await writer.Close()).toBeNull()
|
|
65
|
+
|
|
66
|
+
const source = bytes.NewReader(compressed.Bytes())
|
|
67
|
+
const asyncReader = {
|
|
68
|
+
async Read(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
69
|
+
await Promise.resolve()
|
|
70
|
+
return source.Read(p)
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const [reader, readerErr] = NewReader(asyncReader as io.Reader)
|
|
75
|
+
expect(readerErr).toBeNull()
|
|
76
|
+
const [out, readErr] = await io.ReadAll(reader!)
|
|
77
|
+
expect(readErr).toBeNull()
|
|
78
|
+
expect($.bytesToString(out)).toBe('async gzip source')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('invalid gzip bytes return ErrHeader', () => {
|
|
82
|
+
const [reader, err] = NewReader(bytes.NewReader($.stringToBytes('plain')))
|
|
83
|
+
expect(reader).toBeNull()
|
|
84
|
+
expect(err).toBe(ErrHeader)
|
|
85
|
+
})
|
|
86
|
+
})
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as errors from '@goscript/errors/index.js'
|
|
3
|
+
import * as io from '@goscript/io/index.js'
|
|
4
|
+
|
|
5
|
+
type maybeAsyncWriter = {
|
|
6
|
+
Write(p: $.Bytes): [number, $.GoError] | Promise<[number, $.GoError]>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type compressionRuntime = {
|
|
10
|
+
gzipSync?: (data: Uint8Array, opts?: Record<string, unknown>) => Uint8Array
|
|
11
|
+
gunzipSync?: (data: Uint8Array) => Uint8Array
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const NoCompression = 0
|
|
15
|
+
export const BestSpeed = 1
|
|
16
|
+
export const BestCompression = 9
|
|
17
|
+
export const DefaultCompression = -1
|
|
18
|
+
export const HuffmanOnly = -2
|
|
19
|
+
|
|
20
|
+
export let ErrChecksum = errors.New('gzip: invalid checksum')
|
|
21
|
+
export let ErrHeader = errors.New('gzip: invalid header')
|
|
22
|
+
|
|
23
|
+
export function __goscript_set_ErrChecksum(value: $.GoError): void {
|
|
24
|
+
ErrChecksum = value
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function __goscript_set_ErrHeader(value: $.GoError): void {
|
|
28
|
+
ErrHeader = value
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class Header {
|
|
32
|
+
Comment = ''
|
|
33
|
+
Extra: $.Bytes = null
|
|
34
|
+
ModTime: any = null
|
|
35
|
+
Name = ''
|
|
36
|
+
OS = 255
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class Reader {
|
|
40
|
+
private data: Uint8Array = new Uint8Array(0)
|
|
41
|
+
private offset = 0
|
|
42
|
+
private pending: Promise<{ data: Uint8Array | null; err: $.GoError }> | null =
|
|
43
|
+
null
|
|
44
|
+
|
|
45
|
+
constructor(r?: io.Reader | null) {
|
|
46
|
+
if (r != null) {
|
|
47
|
+
this.Reset(r)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async Read(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
52
|
+
const pending = this.pending
|
|
53
|
+
if (pending != null) {
|
|
54
|
+
this.pending = null
|
|
55
|
+
const result = await pending
|
|
56
|
+
if (result.err != null) {
|
|
57
|
+
return [0, result.err]
|
|
58
|
+
}
|
|
59
|
+
this.data = result.data ?? new Uint8Array(0)
|
|
60
|
+
this.offset = 0
|
|
61
|
+
}
|
|
62
|
+
if (this.offset >= this.data.length) {
|
|
63
|
+
return [0, io.EOF]
|
|
64
|
+
}
|
|
65
|
+
const out = $.bytesToUint8Array(p)
|
|
66
|
+
const n = Math.min(out.length, this.data.length - this.offset)
|
|
67
|
+
out.set(this.data.subarray(this.offset, this.offset + n))
|
|
68
|
+
this.offset += n
|
|
69
|
+
return [n, null]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Close(): $.GoError {
|
|
73
|
+
return null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Reset(r: io.Reader | null): $.GoError {
|
|
77
|
+
if (r == null) {
|
|
78
|
+
return errors.New('gzip: nil reader')
|
|
79
|
+
}
|
|
80
|
+
const result = readGunzipped(r)
|
|
81
|
+
this.data = new Uint8Array(0)
|
|
82
|
+
this.offset = 0
|
|
83
|
+
if (result instanceof Promise) {
|
|
84
|
+
this.pending = result
|
|
85
|
+
return null
|
|
86
|
+
}
|
|
87
|
+
this.pending = null
|
|
88
|
+
if (result.err != null) {
|
|
89
|
+
return result.err
|
|
90
|
+
}
|
|
91
|
+
this.data = result.data ?? new Uint8Array(0)
|
|
92
|
+
return null
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export class Writer {
|
|
97
|
+
private chunks: Uint8Array[] = []
|
|
98
|
+
private closed = false
|
|
99
|
+
|
|
100
|
+
constructor(
|
|
101
|
+
private w: io.Writer | null,
|
|
102
|
+
private level = DefaultCompression,
|
|
103
|
+
) {}
|
|
104
|
+
|
|
105
|
+
Write(p: $.Bytes): [number, $.GoError] {
|
|
106
|
+
if (this.closed) {
|
|
107
|
+
return [0, errors.New('gzip: writer closed')]
|
|
108
|
+
}
|
|
109
|
+
const data = $.bytesToUint8Array(p)
|
|
110
|
+
this.chunks.push(data.slice())
|
|
111
|
+
return [data.length, null]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async Close(): Promise<$.GoError> {
|
|
115
|
+
if (this.closed) {
|
|
116
|
+
return null
|
|
117
|
+
}
|
|
118
|
+
this.closed = true
|
|
119
|
+
if (this.w == null) {
|
|
120
|
+
return errors.New('gzip: nil writer')
|
|
121
|
+
}
|
|
122
|
+
const compressed = await gzipBytes(concat(this.chunks), this.level)
|
|
123
|
+
const writer = $.pointerValue<maybeAsyncWriter>(this.w)
|
|
124
|
+
const [, err] = await writer.Write(compressed)
|
|
125
|
+
return err
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
Flush(): $.GoError {
|
|
129
|
+
return null
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
Reset(w: io.Writer | null): void {
|
|
133
|
+
this.w = w
|
|
134
|
+
this.chunks = []
|
|
135
|
+
this.closed = false
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function NewReader(
|
|
140
|
+
r: io.Reader | null,
|
|
141
|
+
): [io.ReadCloser | null, $.GoError] {
|
|
142
|
+
const reader = new Reader()
|
|
143
|
+
const err = reader.Reset(r)
|
|
144
|
+
if (err != null) {
|
|
145
|
+
return [null, err]
|
|
146
|
+
}
|
|
147
|
+
return [reader as any, null]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function NewWriter(w: io.Writer | null): Writer {
|
|
151
|
+
return new Writer(w)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function NewWriterLevel(
|
|
155
|
+
w: io.Writer | null,
|
|
156
|
+
level: number,
|
|
157
|
+
): [Writer | null, $.GoError] {
|
|
158
|
+
if (level < HuffmanOnly || level > BestCompression) {
|
|
159
|
+
return [null, errors.New(`gzip: invalid compression level: ${level}`)]
|
|
160
|
+
}
|
|
161
|
+
return [new Writer(w, level), null]
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function gzipBytes(data: Uint8Array, level: number): Promise<Uint8Array> {
|
|
165
|
+
const runtime = nodeCompressionRuntime()
|
|
166
|
+
if (runtime?.gzipSync != null) {
|
|
167
|
+
return runtime.gzipSync(data, { level })
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const CompressionStreamCtor = (globalThis as any).CompressionStream
|
|
171
|
+
if (typeof CompressionStreamCtor !== 'function') {
|
|
172
|
+
throw new Error('compress/gzip: CompressionStream unavailable')
|
|
173
|
+
}
|
|
174
|
+
return streamTransform(data, new CompressionStreamCtor('gzip'))
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function gunzipBytes(
|
|
178
|
+
data: Uint8Array,
|
|
179
|
+
): Uint8Array | Promise<Uint8Array> {
|
|
180
|
+
const runtime = nodeCompressionRuntime()
|
|
181
|
+
if (runtime?.gunzipSync != null) {
|
|
182
|
+
return runtime.gunzipSync(data)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const DecompressionStreamCtor = (globalThis as any).DecompressionStream
|
|
186
|
+
if (typeof DecompressionStreamCtor !== 'function') {
|
|
187
|
+
throw new Error('compress/gzip: DecompressionStream unavailable')
|
|
188
|
+
}
|
|
189
|
+
return streamTransform(data, new DecompressionStreamCtor('gzip'))
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function streamTransform(
|
|
193
|
+
data: Uint8Array,
|
|
194
|
+
stream: ReadableWritablePair<Uint8Array, Uint8Array>,
|
|
195
|
+
): Promise<Uint8Array> {
|
|
196
|
+
const body = new ArrayBuffer(data.length)
|
|
197
|
+
new Uint8Array(body).set(data)
|
|
198
|
+
const response = new Response(
|
|
199
|
+
new Blob([body]).stream().pipeThrough(stream as any),
|
|
200
|
+
)
|
|
201
|
+
return new Uint8Array(await response.arrayBuffer())
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function readGunzipped(
|
|
205
|
+
r: io.Reader,
|
|
206
|
+
):
|
|
207
|
+
| { data: Uint8Array | null; err: $.GoError }
|
|
208
|
+
| Promise<{ data: Uint8Array | null; err: $.GoError }> {
|
|
209
|
+
const chunks: Uint8Array[] = []
|
|
210
|
+
const buf = $.makeSlice<number>(1, undefined, 'byte')
|
|
211
|
+
while (true) {
|
|
212
|
+
const read = r.Read(buf)
|
|
213
|
+
if (read instanceof Promise) {
|
|
214
|
+
return readGunzippedAsync(read, r, buf, chunks)
|
|
215
|
+
}
|
|
216
|
+
const [n, err] = read
|
|
217
|
+
recordChunk(chunks, buf, n)
|
|
218
|
+
if (err != null) {
|
|
219
|
+
if (err === io.EOF) {
|
|
220
|
+
return inflateRecorded(chunks)
|
|
221
|
+
}
|
|
222
|
+
return { data: null, err }
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function readGunzippedAsync(
|
|
228
|
+
read: Promise<[number, $.GoError]>,
|
|
229
|
+
r: io.Reader,
|
|
230
|
+
buf: $.Bytes,
|
|
231
|
+
chunks: Uint8Array[],
|
|
232
|
+
): Promise<{ data: Uint8Array | null; err: $.GoError }> {
|
|
233
|
+
while (true) {
|
|
234
|
+
const [n, err] = await read
|
|
235
|
+
recordChunk(chunks, buf, n)
|
|
236
|
+
if (err != null) {
|
|
237
|
+
if (err === io.EOF) {
|
|
238
|
+
return inflateRecorded(chunks)
|
|
239
|
+
}
|
|
240
|
+
return { data: null, err }
|
|
241
|
+
}
|
|
242
|
+
read = r.Read(buf) as any
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function recordChunk(chunks: Uint8Array[], buf: $.Bytes, n: number): void {
|
|
247
|
+
if (n > 0) {
|
|
248
|
+
chunks.push($.bytesToUint8Array($.goSlice(buf, 0, n)).slice())
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function inflateRecorded(
|
|
253
|
+
chunks: Uint8Array[],
|
|
254
|
+
): { data: Uint8Array | null; err: $.GoError } | Promise<{
|
|
255
|
+
data: Uint8Array | null
|
|
256
|
+
err: $.GoError
|
|
257
|
+
}> {
|
|
258
|
+
try {
|
|
259
|
+
const inflated = gunzipBytes(concat(chunks))
|
|
260
|
+
if (inflated instanceof Promise) {
|
|
261
|
+
return inflated
|
|
262
|
+
.then((data) => ({ data, err: null }))
|
|
263
|
+
.catch(() => ({ data: null, err: ErrHeader }))
|
|
264
|
+
}
|
|
265
|
+
return { data: inflated, err: null }
|
|
266
|
+
} catch {
|
|
267
|
+
return { data: null, err: ErrHeader }
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function concat(chunks: Uint8Array[]): Uint8Array {
|
|
272
|
+
let length = 0
|
|
273
|
+
for (const chunk of chunks) {
|
|
274
|
+
length += chunk.length
|
|
275
|
+
}
|
|
276
|
+
const out = new Uint8Array(length)
|
|
277
|
+
let offset = 0
|
|
278
|
+
for (const chunk of chunks) {
|
|
279
|
+
out.set(chunk, offset)
|
|
280
|
+
offset += chunk.length
|
|
281
|
+
}
|
|
282
|
+
return out
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function nodeCompressionRuntime(): compressionRuntime | null {
|
|
286
|
+
const processObj = (globalThis as any).process
|
|
287
|
+
if (processObj && typeof processObj.getBuiltinModule === 'function') {
|
|
288
|
+
const mod = processObj.getBuiltinModule('zlib')
|
|
289
|
+
if (mod && typeof mod.gzipSync === 'function') {
|
|
290
|
+
return {
|
|
291
|
+
gzipSync: (data, opts) => new Uint8Array(mod.gzipSync(data, opts)),
|
|
292
|
+
gunzipSync: (data) => new Uint8Array(mod.gunzipSync(data)),
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return null
|
|
297
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"strict": true,
|
|
4
|
+
"symbols": {
|
|
5
|
+
"BestCompression": {
|
|
6
|
+
"status": "real"
|
|
7
|
+
},
|
|
8
|
+
"BestSpeed": {
|
|
9
|
+
"status": "real"
|
|
10
|
+
},
|
|
11
|
+
"DefaultCompression": {
|
|
12
|
+
"status": "real"
|
|
13
|
+
},
|
|
14
|
+
"ErrChecksum": {
|
|
15
|
+
"status": "real"
|
|
16
|
+
},
|
|
17
|
+
"ErrHeader": {
|
|
18
|
+
"status": "real"
|
|
19
|
+
},
|
|
20
|
+
"Header": {
|
|
21
|
+
"status": "real"
|
|
22
|
+
},
|
|
23
|
+
"HuffmanOnly": {
|
|
24
|
+
"status": "real"
|
|
25
|
+
},
|
|
26
|
+
"NewReader": {
|
|
27
|
+
"status": "real"
|
|
28
|
+
},
|
|
29
|
+
"NewWriter": {
|
|
30
|
+
"status": "real"
|
|
31
|
+
},
|
|
32
|
+
"NewWriterLevel": {
|
|
33
|
+
"status": "real"
|
|
34
|
+
},
|
|
35
|
+
"NoCompression": {
|
|
36
|
+
"status": "real"
|
|
37
|
+
},
|
|
38
|
+
"Reader": {
|
|
39
|
+
"status": "real"
|
|
40
|
+
},
|
|
41
|
+
"Writer": {
|
|
42
|
+
"status": "real"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -119,22 +119,36 @@ describe('compress/zlib override', () => {
|
|
|
119
119
|
test('writer and reader honor preset dictionaries', async () => {
|
|
120
120
|
const dict = $.stringToBytes('hello dictionary')
|
|
121
121
|
const compressed = $.markAsStructValue(new bytes.Buffer())
|
|
122
|
-
const [writer, writerErr] = NewWriterLevelDict(
|
|
122
|
+
const [writer, writerErr] = NewWriterLevelDict(
|
|
123
|
+
compressed,
|
|
124
|
+
DefaultCompression,
|
|
125
|
+
dict,
|
|
126
|
+
)
|
|
123
127
|
expect(writerErr).toBeNull()
|
|
124
|
-
expect(
|
|
128
|
+
expect(
|
|
129
|
+
writer!.Write($.stringToBytes('hello dictionary payload'))[1],
|
|
130
|
+
).toBeNull()
|
|
125
131
|
expect(await writer!.Close()).toBeNull()
|
|
126
132
|
|
|
127
|
-
const [missingDictReader, missingDictErr] = NewReader(
|
|
133
|
+
const [missingDictReader, missingDictErr] = NewReader(
|
|
134
|
+
bytes.NewReader(compressed.Bytes()),
|
|
135
|
+
)
|
|
128
136
|
expect(missingDictReader).toBeNull()
|
|
129
137
|
expect(missingDictErr).toBe(ErrDictionary)
|
|
130
138
|
|
|
131
|
-
const [reader, readerErr] = NewReaderDict(
|
|
139
|
+
const [reader, readerErr] = NewReaderDict(
|
|
140
|
+
bytes.NewReader(compressed.Bytes()),
|
|
141
|
+
dict,
|
|
142
|
+
)
|
|
132
143
|
expect(readerErr).toBeNull()
|
|
133
144
|
const [out, readErr] = await io.ReadAll(reader!)
|
|
134
145
|
expect(readErr).toBeNull()
|
|
135
146
|
expect($.bytesToString(out)).toBe('hello dictionary payload')
|
|
136
147
|
|
|
137
|
-
const [, wrongDictErr] = NewReaderDict(
|
|
148
|
+
const [, wrongDictErr] = NewReaderDict(
|
|
149
|
+
bytes.NewReader(compressed.Bytes()),
|
|
150
|
+
$.stringToBytes('wrong dictionary'),
|
|
151
|
+
)
|
|
138
152
|
expect(wrongDictErr).toBe(ErrDictionary)
|
|
139
153
|
|
|
140
154
|
const corrupt = Uint8Array.from(compressed.Bytes())
|
|
@@ -37,9 +37,8 @@ export function __goscript_set_ErrHeader(value: $.GoError): void {
|
|
|
37
37
|
class zlibReader implements Resetter {
|
|
38
38
|
private data: Uint8Array = new Uint8Array(0)
|
|
39
39
|
private offset = 0
|
|
40
|
-
private pending:
|
|
41
|
-
|
|
42
|
-
| null = null
|
|
40
|
+
private pending: Promise<{ data: Uint8Array | null; err: $.GoError }> | null =
|
|
41
|
+
null
|
|
43
42
|
|
|
44
43
|
constructor(data?: Uint8Array) {
|
|
45
44
|
if (data != null) {
|
|
@@ -180,7 +179,11 @@ export function NewReaderDict(
|
|
|
180
179
|
return [reader as any, null]
|
|
181
180
|
}
|
|
182
181
|
|
|
183
|
-
function deflate(
|
|
182
|
+
function deflate(
|
|
183
|
+
data: Uint8Array,
|
|
184
|
+
dict: $.Bytes | null,
|
|
185
|
+
level: number,
|
|
186
|
+
): Uint8Array {
|
|
184
187
|
const zlib = nodeZlib()
|
|
185
188
|
const opts: Record<string, unknown> = {}
|
|
186
189
|
if (dict != null && $.len(dict) > 0) {
|
|
@@ -197,7 +200,10 @@ function deflate(data: Uint8Array, dict: $.Bytes | null, level: number): Uint8Ar
|
|
|
197
200
|
|
|
198
201
|
function inflate(data: Uint8Array, dict: $.Bytes | null): Uint8Array {
|
|
199
202
|
const zlib = nodeZlib()
|
|
200
|
-
const opts =
|
|
203
|
+
const opts =
|
|
204
|
+
dict != null && $.len(dict) > 0 ?
|
|
205
|
+
{ dictionary: $.bytesToUint8Array(dict) }
|
|
206
|
+
: undefined
|
|
201
207
|
return new Uint8Array(zlib.inflateSync(data, opts))
|
|
202
208
|
}
|
|
203
209
|
|
|
@@ -302,11 +308,14 @@ function recordCompressedBytes(
|
|
|
302
308
|
}
|
|
303
309
|
|
|
304
310
|
function classifyInflateError(err: unknown): $.GoError {
|
|
305
|
-
const zerr = err instanceof Error ? err as nodeZlibError : null
|
|
311
|
+
const zerr = err instanceof Error ? (err as nodeZlibError) : null
|
|
306
312
|
if (zerr?.code === 'Z_NEED_DICT') {
|
|
307
313
|
return ErrDictionary
|
|
308
314
|
}
|
|
309
|
-
if (
|
|
315
|
+
if (
|
|
316
|
+
zerr?.code === 'Z_DATA_ERROR' &&
|
|
317
|
+
zerr.message.includes('incorrect data check')
|
|
318
|
+
) {
|
|
310
319
|
return ErrChecksum
|
|
311
320
|
}
|
|
312
321
|
return ErrHeader
|
|
@@ -35,9 +35,13 @@ describe('crypto/ecdh override', () => {
|
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
function hex(value: string): Uint8Array {
|
|
38
|
-
return new Uint8Array(
|
|
38
|
+
return new Uint8Array(
|
|
39
|
+
value.match(/../g)!.map((byte) => Number.parseInt(byte, 16)),
|
|
40
|
+
)
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
function toHex(value: Uint8Array | null): string {
|
|
42
|
-
return Array.from(value ?? [], (byte) =>
|
|
44
|
+
return Array.from(value ?? [], (byte) =>
|
|
45
|
+
byte.toString(16).padStart(2, '0'),
|
|
46
|
+
).join('')
|
|
43
47
|
}
|
package/gs/crypto/ecdh/index.ts
CHANGED
|
@@ -29,7 +29,9 @@ export class PublicKey {
|
|
|
29
29
|
|
|
30
30
|
public Equal(x: PublicKey | $.VarRef<PublicKey> | null): boolean {
|
|
31
31
|
const other = $.pointerValueOrNil(x)
|
|
32
|
-
return
|
|
32
|
+
return (
|
|
33
|
+
other instanceof PublicKey && bytesEqual(this.publicKey, other.publicKey)
|
|
34
|
+
)
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
|
|
@@ -54,17 +56,27 @@ export class PrivateKey {
|
|
|
54
56
|
return this.curve
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
public ECDH(
|
|
59
|
+
public ECDH(
|
|
60
|
+
remote: PublicKey | $.VarRef<PublicKey> | null,
|
|
61
|
+
): [$.Bytes, $.GoError] {
|
|
58
62
|
const remoteKey = $.pointerValueOrNil(remote)
|
|
59
63
|
if (remoteKey == null || remoteKey.curve !== this.curve) {
|
|
60
|
-
return [
|
|
64
|
+
return [
|
|
65
|
+
null,
|
|
66
|
+
$.newError(
|
|
67
|
+
'crypto/ecdh: private key and public key curves do not match',
|
|
68
|
+
),
|
|
69
|
+
]
|
|
61
70
|
}
|
|
62
71
|
return this.curve.ecdh(this, remoteKey)
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
public Equal(x: PrivateKey | $.VarRef<PrivateKey> | null): boolean {
|
|
66
75
|
const other = $.pointerValueOrNil(x)
|
|
67
|
-
return
|
|
76
|
+
return (
|
|
77
|
+
other instanceof PrivateKey &&
|
|
78
|
+
bytesEqual(this.privateKey, other.privateKey)
|
|
79
|
+
)
|
|
68
80
|
}
|
|
69
81
|
|
|
70
82
|
public Public(): PublicKey {
|
|
@@ -80,7 +92,9 @@ export class x25519Curve {
|
|
|
80
92
|
public GenerateKey(r: io.Reader | null): [PrivateKey | null, $.GoError] {
|
|
81
93
|
const key = new Uint8Array(x25519PrivateKeySize)
|
|
82
94
|
if (r != null) {
|
|
83
|
-
throw new Error(
|
|
95
|
+
throw new Error(
|
|
96
|
+
'crypto/ecdh: custom random readers are not implemented in GoScript',
|
|
97
|
+
)
|
|
84
98
|
}
|
|
85
99
|
globalThis.crypto.getRandomValues(key)
|
|
86
100
|
return this.NewPrivateKey(key)
|
|
@@ -113,10 +127,18 @@ export class x25519Curve {
|
|
|
113
127
|
return 'X25519'
|
|
114
128
|
}
|
|
115
129
|
|
|
116
|
-
public ecdh(
|
|
130
|
+
public ecdh(
|
|
131
|
+
local: PrivateKey | null,
|
|
132
|
+
remote: PublicKey | null,
|
|
133
|
+
): [$.Bytes, $.GoError] {
|
|
117
134
|
const out = scalarMult(local?.privateKey ?? null, remote?.publicKey ?? null)
|
|
118
135
|
if (isZero(out)) {
|
|
119
|
-
return [
|
|
136
|
+
return [
|
|
137
|
+
null,
|
|
138
|
+
$.newError(
|
|
139
|
+
'crypto/ecdh: bad X25519 remote ECDH input: low order point',
|
|
140
|
+
),
|
|
141
|
+
]
|
|
120
142
|
}
|
|
121
143
|
return [out, null]
|
|
122
144
|
}
|
|
@@ -132,23 +154,38 @@ export class unsupportedCurve {
|
|
|
132
154
|
constructor(private readonly name: string) {}
|
|
133
155
|
|
|
134
156
|
public GenerateKey(_r: io.Reader | null): [PrivateKey | null, $.GoError] {
|
|
135
|
-
return [
|
|
157
|
+
return [
|
|
158
|
+
null,
|
|
159
|
+
$.newError(`crypto/ecdh: ${this.name} is not implemented in GoScript`),
|
|
160
|
+
]
|
|
136
161
|
}
|
|
137
162
|
|
|
138
163
|
public NewPrivateKey(_key: $.Bytes): [PrivateKey | null, $.GoError] {
|
|
139
|
-
return [
|
|
164
|
+
return [
|
|
165
|
+
null,
|
|
166
|
+
$.newError(`crypto/ecdh: ${this.name} is not implemented in GoScript`),
|
|
167
|
+
]
|
|
140
168
|
}
|
|
141
169
|
|
|
142
170
|
public NewPublicKey(_key: $.Bytes): [PublicKey | null, $.GoError] {
|
|
143
|
-
return [
|
|
171
|
+
return [
|
|
172
|
+
null,
|
|
173
|
+
$.newError(`crypto/ecdh: ${this.name} is not implemented in GoScript`),
|
|
174
|
+
]
|
|
144
175
|
}
|
|
145
176
|
|
|
146
177
|
public String(): string {
|
|
147
178
|
return this.name
|
|
148
179
|
}
|
|
149
180
|
|
|
150
|
-
public ecdh(
|
|
151
|
-
|
|
181
|
+
public ecdh(
|
|
182
|
+
_local: PrivateKey | null,
|
|
183
|
+
_remote: PublicKey | null,
|
|
184
|
+
): [$.Bytes, $.GoError] {
|
|
185
|
+
return [
|
|
186
|
+
null,
|
|
187
|
+
$.newError(`crypto/ecdh: ${this.name} is not implemented in GoScript`),
|
|
188
|
+
]
|
|
152
189
|
}
|
|
153
190
|
}
|
|
154
191
|
|