goscript 0.2.0 → 0.2.2

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.
Files changed (75) hide show
  1. package/cmd/goscript-wasm/main.go +38 -6
  2. package/compiler/diagnostic.go +104 -12
  3. package/compiler/diagnostic_test.go +106 -0
  4. package/compiler/gotest/runner.go +99 -17
  5. package/compiler/gotest/runner_test.go +65 -0
  6. package/compiler/index.test.ts +23 -0
  7. package/compiler/lowered-program.go +9 -7
  8. package/compiler/lowering.go +361 -72
  9. package/compiler/lowering_bench_test.go +1 -0
  10. package/compiler/lowering_internal_test.go +18 -0
  11. package/compiler/protobuf-ts-binding.go +65 -12
  12. package/compiler/protobuf-ts-binding_test.go +339 -0
  13. package/compiler/runtime-contract.go +4 -0
  14. package/compiler/runtime-contract_test.go +2 -0
  15. package/compiler/service.go +1 -0
  16. package/compiler/skeleton_test.go +60 -3
  17. package/compiler/wasm/compile_test.go +37 -4
  18. package/compiler/wasm-api.go +57 -7
  19. package/dist/gs/builtin/hostio.js +6 -1
  20. package/dist/gs/builtin/hostio.js.map +1 -1
  21. package/dist/gs/builtin/slice.d.ts +11 -1
  22. package/dist/gs/builtin/slice.js +158 -2
  23. package/dist/gs/builtin/slice.js.map +1 -1
  24. package/dist/gs/crypto/aes/index.d.ts +15 -0
  25. package/dist/gs/crypto/aes/index.js +57 -0
  26. package/dist/gs/crypto/aes/index.js.map +1 -0
  27. package/dist/gs/crypto/cipher/index.d.ts +41 -0
  28. package/dist/gs/crypto/cipher/index.js +255 -0
  29. package/dist/gs/crypto/cipher/index.js.map +1 -0
  30. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -0
  31. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +30 -5
  32. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  33. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +1 -0
  34. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +17 -11
  35. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
  36. package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.d.ts +31 -0
  37. package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.js +117 -0
  38. package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.js.map +1 -0
  39. package/dist/gs/internal/byteorder/index.js +2 -2
  40. package/dist/gs/internal/byteorder/index.js.map +1 -1
  41. package/dist/gs/io/io.js +18 -2
  42. package/dist/gs/io/io.js.map +1 -1
  43. package/dist/gs/reflect/type.js +57 -0
  44. package/dist/gs/reflect/type.js.map +1 -1
  45. package/dist/gs/runtime/debug/index.js +2 -1
  46. package/dist/gs/runtime/debug/index.js.map +1 -1
  47. package/dist/gs/sync/atomic/doc_64.gs.js +7 -6
  48. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  49. package/go.mod +2 -2
  50. package/go.sum +2 -0
  51. package/gs/builtin/hostio.test.ts +22 -1
  52. package/gs/builtin/hostio.ts +6 -1
  53. package/gs/builtin/runtime-contract.test.ts +28 -0
  54. package/gs/builtin/slice.ts +225 -20
  55. package/gs/crypto/aes/index.test.ts +120 -0
  56. package/gs/crypto/aes/index.ts +76 -0
  57. package/gs/crypto/cipher/index.ts +345 -0
  58. package/gs/crypto/cipher/meta.json +6 -0
  59. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +162 -0
  60. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +41 -5
  61. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +18 -0
  62. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +17 -11
  63. package/gs/golang.org/x/crypto/chacha20poly1305/index.test.ts +91 -0
  64. package/gs/golang.org/x/crypto/chacha20poly1305/index.ts +245 -0
  65. package/gs/internal/byteorder/index.test.ts +2 -2
  66. package/gs/internal/byteorder/index.ts +2 -2
  67. package/gs/io/io.test.ts +56 -1
  68. package/gs/io/io.ts +19 -2
  69. package/gs/reflect/type.ts +64 -0
  70. package/gs/reflect/typefor.test.ts +21 -1
  71. package/gs/runtime/debug/index.test.ts +32 -4
  72. package/gs/runtime/debug/index.ts +5 -2
  73. package/gs/sync/atomic/doc_64.gs.ts +6 -7
  74. package/gs/sync/atomic/doc_64.test.ts +43 -0
  75. package/package.json +10 -3
@@ -3326,6 +3326,60 @@ function basicTypeFromName(name: string, typeName = ''): BasicType {
3326
3326
  }
3327
3327
  }
3328
3328
 
3329
+ function typeFromGoTypeName(typeName: string): Type | null {
3330
+ const trimmed = typeName.trim()
3331
+ if (trimmed === '') return null
3332
+
3333
+ if (trimmed.startsWith('<-chan ')) {
3334
+ return new ChannelType(typeFromGoTypeName(trimmed.slice(7)) ?? anyType(), RecvDir)
3335
+ }
3336
+ if (trimmed.startsWith('chan<- ')) {
3337
+ return new ChannelType(typeFromGoTypeName(trimmed.slice(7)) ?? anyType(), SendDir)
3338
+ }
3339
+ if (trimmed.startsWith('chan ')) {
3340
+ return new ChannelType(typeFromGoTypeName(trimmed.slice(5)) ?? anyType(), BothDir)
3341
+ }
3342
+ if (trimmed.startsWith('[]')) {
3343
+ return new SliceType(typeFromGoTypeName(trimmed.slice(2)) ?? anyType())
3344
+ }
3345
+ if (trimmed.startsWith('*')) {
3346
+ return new PointerType(typeFromGoTypeName(trimmed.slice(1)) ?? anyType())
3347
+ }
3348
+ if (trimmed === 'struct{}' || trimmed === 'struct {}') {
3349
+ return new StructType('', [], '', 'struct {}')
3350
+ }
3351
+ if (trimmed === 'interface{}' || trimmed === 'any') {
3352
+ return anyType()
3353
+ }
3354
+ if (trimmed === 'error') {
3355
+ return new InterfaceType('error', 'error')
3356
+ }
3357
+
3358
+ const registered = builtinGetTypeByName(trimmed)
3359
+ if (registered) {
3360
+ return typeFromTypeInfo(registered)
3361
+ }
3362
+
3363
+ const basic = basicTypeFromName(trimmed)
3364
+ if (basic.Kind() !== Invalid) {
3365
+ return basic
3366
+ }
3367
+
3368
+ return null
3369
+ }
3370
+
3371
+ function channelTypeFromGoTypeName(typeName: string): Type | null {
3372
+ const typ = typeFromGoTypeName(typeName)
3373
+ if (typ?.Kind() === Chan) {
3374
+ return typ
3375
+ }
3376
+ return null
3377
+ }
3378
+
3379
+ function anyType(): Type {
3380
+ return new BasicType(Interface, 'interface{}', 16)
3381
+ }
3382
+
3329
3383
  function structFieldsFromTypeInfo(
3330
3384
  ti: $.StructTypeInfo,
3331
3385
  seen = new Set<string>(),
@@ -3743,6 +3797,16 @@ function getTypeOf(value: ReflectValue): Type {
3743
3797
  )
3744
3798
  }
3745
3799
 
3800
+ if ('__goType' in value) {
3801
+ const goType = (value as { __goType?: unknown }).__goType
3802
+ if (typeof goType === 'string') {
3803
+ const channelType = channelTypeFromGoTypeName(goType)
3804
+ if (channelType) {
3805
+ return channelType
3806
+ }
3807
+ }
3808
+ }
3809
+
3746
3810
  if (
3747
3811
  'real' in value &&
3748
3812
  'imag' in value &&
@@ -1,5 +1,7 @@
1
1
  import { describe, it, expect } from 'vitest'
2
2
  import {
3
+ interfaceValue,
4
+ makeChannel,
3
5
  makeMap,
4
6
  mapGet,
5
7
  mapSet,
@@ -11,7 +13,9 @@ import {
11
13
  varRef,
12
14
  } from '../builtin/index.js'
13
15
  import { StructField } from './types.js'
16
+ import { SelectCase, SelectRecv } from './types.js'
14
17
  import {
18
+ Chan,
15
19
  Int,
16
20
  Ptr,
17
21
  Struct,
@@ -21,7 +25,7 @@ import {
21
25
  Uint64,
22
26
  ValueOf,
23
27
  } from './type.js'
24
- import { Indirect, New, Zero } from './value.js'
28
+ import { Indirect, New, Select, Zero } from './value.js'
25
29
 
26
30
  describe('TypeFor', () => {
27
31
  it('exposes StructField PkgPath and exported semantics', () => {
@@ -184,6 +188,22 @@ describe('TypeFor', () => {
184
188
  expect(target.value).toBe(15)
185
189
  })
186
190
 
191
+ it('preserves channel type metadata on interface boxes', () => {
192
+ const ch = makeChannel<{}>(0, {}, 'both')
193
+ const chanValue = ValueOf(interfaceValue(ch, '<-chan struct{}'))
194
+
195
+ expect(chanValue.Type().Kind()).toBe(Chan)
196
+ expect(chanValue.Type().String()).toBe('<-chan struct {}')
197
+ expect(chanValue.Type().Elem().Kind()).toBe(Struct)
198
+
199
+ const [chosen, recv, ok] = Select([
200
+ new SelectCase({ Dir: SelectRecv, Chan: chanValue }),
201
+ ])
202
+ expect(chosen).toBe(0)
203
+ expect(ok).toBe(true)
204
+ expect(recv.Type().String()).toBe('struct {}')
205
+ })
206
+
187
207
  it('formats literal interface methods from type metadata', () => {
188
208
  const ifaceType = TypeFor({
189
209
  T: {
@@ -1,6 +1,15 @@
1
1
  import { describe, expect, it, vi } from 'vitest'
2
2
 
3
- import { BuildInfo, BuildSetting, Module, PrintStack, ReadBuildInfo, Stack } from './index.js'
3
+ import { resetHostRuntimeForTests } from '@goscript/builtin/hostio.js'
4
+
5
+ import {
6
+ BuildInfo,
7
+ BuildSetting,
8
+ Module,
9
+ PrintStack,
10
+ ReadBuildInfo,
11
+ Stack,
12
+ } from './index.js'
4
13
 
5
14
  describe('runtime/debug override', () => {
6
15
  it('returns a stack trace as bytes', () => {
@@ -10,14 +19,33 @@ describe('runtime/debug override', () => {
10
19
  expect(new TextDecoder().decode(stack)).toContain('Error')
11
20
  })
12
21
 
13
- it('prints the current stack trace', () => {
22
+ it('prints the current stack trace through the browser-like stderr console fallback', () => {
23
+ const consoleLog = vi.spyOn(console, 'log').mockImplementation(() => {})
14
24
  const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
25
+ const originalDeno = (globalThis as any).Deno
26
+ const originalProcess = (globalThis as any).process
27
+ delete (globalThis as any).Deno
28
+ delete (globalThis as any).process
29
+ resetHostRuntimeForTests()
15
30
 
16
31
  try {
17
32
  PrintStack()
18
- expect(consoleError).toHaveBeenCalledTimes(1)
19
- expect(consoleError.mock.calls[0][0]).toContain('Error')
33
+ expect(consoleLog).toHaveBeenCalledTimes(1)
34
+ expect(consoleLog.mock.calls[0][0]).toContain('Error')
35
+ expect(consoleError).not.toHaveBeenCalled()
20
36
  } finally {
37
+ if (originalDeno === undefined) {
38
+ delete (globalThis as any).Deno
39
+ } else {
40
+ ;(globalThis as any).Deno = originalDeno
41
+ }
42
+ if (originalProcess === undefined) {
43
+ delete (globalThis as any).process
44
+ } else {
45
+ ;(globalThis as any).process = originalProcess
46
+ }
47
+ resetHostRuntimeForTests()
48
+ consoleLog.mockRestore()
21
49
  consoleError.mockRestore()
22
50
  }
23
51
  })
@@ -1,4 +1,5 @@
1
1
  import * as $ from '@goscript/builtin/index.js'
2
+ import { writeHostStderrText } from '@goscript/builtin/hostio.js'
2
3
 
3
4
  export class BuildSetting {
4
5
  public Key: string
@@ -10,7 +11,9 @@ export class BuildSetting {
10
11
  }
11
12
 
12
13
  public clone(): BuildSetting {
13
- return $.markAsStructValue(new BuildSetting({ Key: this.Key, Value: this.Value }))
14
+ return $.markAsStructValue(
15
+ new BuildSetting({ Key: this.Key, Value: this.Value }),
16
+ )
14
17
  }
15
18
  }
16
19
 
@@ -88,7 +91,7 @@ export function Stack(): Uint8Array {
88
91
  }
89
92
 
90
93
  export function PrintStack(): void {
91
- console.error(new TextDecoder().decode(Stack()))
94
+ writeHostStderrText(new TextDecoder().decode(Stack()))
92
95
  }
93
96
 
94
97
  export function ReadBuildInfo(): [BuildInfo | null, boolean] {
@@ -59,7 +59,7 @@ export function CompareAndSwapUint64(addr: $.VarRef<number> | null, old: number,
59
59
  //go:noescape
60
60
  export function AddInt64(addr: $.VarRef<number> | null, delta: number): number {
61
61
  if (!addr) return 0;
62
- addr.value = addr.value + delta;
62
+ addr.value = $.int64Add(addr.value, delta);
63
63
  return addr.value;
64
64
  }
65
65
 
@@ -72,7 +72,7 @@ export function AddInt64(addr: $.VarRef<number> | null, delta: number): number {
72
72
  //go:noescape
73
73
  export function AddUint64(addr: $.VarRef<number> | null, delta: number): number {
74
74
  if (!addr) return 0;
75
- addr.value = addr.value + delta;
75
+ addr.value = $.uint64Add(addr.value, delta);
76
76
  return addr.value;
77
77
  }
78
78
 
@@ -84,7 +84,7 @@ export function AddUint64(addr: $.VarRef<number> | null, delta: number): number
84
84
  export function AndInt64(addr: $.VarRef<number> | null, mask: number): number {
85
85
  if (!addr) return 0;
86
86
  let old = addr.value;
87
- addr.value = addr.value & mask;
87
+ addr.value = $.int64And(addr.value, mask);
88
88
  return old;
89
89
  }
90
90
 
@@ -96,7 +96,7 @@ export function AndInt64(addr: $.VarRef<number> | null, mask: number): number {
96
96
  export function AndUint64(addr: $.VarRef<number> | null, mask: number): number {
97
97
  if (!addr) return 0;
98
98
  let old = addr.value;
99
- addr.value = addr.value & mask;
99
+ addr.value = $.uint64And(addr.value, mask);
100
100
  return old;
101
101
  }
102
102
 
@@ -108,7 +108,7 @@ export function AndUint64(addr: $.VarRef<number> | null, mask: number): number {
108
108
  export function OrInt64(addr: $.VarRef<number> | null, mask: number): number {
109
109
  if (!addr) return 0;
110
110
  let old = addr.value;
111
- addr.value = addr.value | mask;
111
+ addr.value = $.int64Or(addr.value, mask);
112
112
  return old;
113
113
  }
114
114
 
@@ -120,7 +120,7 @@ export function OrInt64(addr: $.VarRef<number> | null, mask: number): number {
120
120
  export function OrUint64(addr: $.VarRef<number> | null, mask: number): number {
121
121
  if (!addr) return 0;
122
122
  let old = addr.value;
123
- addr.value = addr.value | mask;
123
+ addr.value = $.uint64Or(addr.value, mask);
124
124
  return old;
125
125
  }
126
126
 
@@ -165,4 +165,3 @@ export function StoreUint64(addr: $.VarRef<number> | null, val: number): void {
165
165
  addr.value = val;
166
166
  }
167
167
  }
168
-
@@ -0,0 +1,43 @@
1
+ import { describe, expect, test } from 'vitest'
2
+
3
+ import * as $ from '../../builtin/index.js'
4
+ import {
5
+ AddInt64,
6
+ AddUint64,
7
+ AndUint64,
8
+ OrUint64,
9
+ } from './doc_64.gs.js'
10
+
11
+ function asBigInt(value: number): bigint {
12
+ return typeof value === 'bigint' ? value : BigInt(value)
13
+ }
14
+
15
+ describe('sync/atomic 64-bit operations', () => {
16
+ test('adds uint64 values without mixing number and bigint arithmetic', () => {
17
+ const value = $.varRef($.uint('18446744073709551614', 64))
18
+
19
+ expect(AddUint64(value, $.uint(2, 64))).toBe(0)
20
+ expect(value.value).toBe(0)
21
+ })
22
+
23
+ test('preserves high uint64 bits for bitwise operations', () => {
24
+ const value = $.varRef($.uint('9223372036854775808', 64))
25
+
26
+ expect(asBigInt(OrUint64(value, $.uint(1, 64)))).toBe(
27
+ 9223372036854775808n,
28
+ )
29
+ expect(asBigInt(value.value)).toBe(9223372036854775809n)
30
+
31
+ expect(asBigInt(AndUint64(value, $.uint('18446744073709551614', 64)))).toBe(
32
+ 9223372036854775809n,
33
+ )
34
+ expect(asBigInt(value.value)).toBe(9223372036854775808n)
35
+ })
36
+
37
+ test('adds int64 values without number coercion', () => {
38
+ const value = $.varRef($.int('9223372036854775807', 64))
39
+
40
+ expect(AddInt64(value, 1)).toBe(-9223372036854775808)
41
+ expect(value.value).toBe(-9223372036854775808)
42
+ })
43
+ })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goscript",
3
3
  "description": "Go to TypeScript transpiler",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "author": {
6
6
  "name": "Aperture Robotics LLC.",
7
7
  "email": "support@aperture.us",
@@ -94,7 +94,7 @@
94
94
  "./{src,builtin,example}/**/(*.ts|*.tsx|*.html|*.css|*.scss)": "prettier --config .prettierrc.yaml --write"
95
95
  },
96
96
  "devDependencies": {
97
- "@aptre/protobuf-es-lite": "^1.0.2",
97
+ "@aptre/protobuf-es-lite": "1.1.0",
98
98
  "@eslint/js": "^10.0.0",
99
99
  "@types/node": "^25.5.2",
100
100
  "@typescript-eslint/eslint-plugin": "^8.58.0",
@@ -108,12 +108,19 @@
108
108
  "husky": "^9.1.7",
109
109
  "lint-staged": "^17.0.0",
110
110
  "prettier": "^3.8.1",
111
- "starpc": "0.49.16",
111
+ "starpc": "0.49.17",
112
112
  "typescript": "^6.0.0",
113
113
  "typescript-eslint": "^8.58.0",
114
114
  "vitest": "^4.1.2"
115
115
  },
116
116
  "dependencies": {
117
+ "@noble/ciphers": "2.2.0",
117
118
  "globals": "^17.4.0"
119
+ },
120
+ "resolutions": {
121
+ "@aptre/protobuf-es-lite": "1.1.0"
122
+ },
123
+ "overrides": {
124
+ "@aptre/protobuf-es-lite": "1.1.0"
118
125
  }
119
126
  }