Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions gs/builtin/panic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ export class RuntimeError extends Error {
Error(): string {
return this.message
}

// RuntimeError marks the value as a runtime.Error, as in Go.
RuntimeError(): void {}
}

/**
Expand Down
36 changes: 36 additions & 0 deletions gs/runtime/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,17 @@ export interface Error {
Error(): string | PromiseLike<string>
}

// Error is registered with the runtime type system, so type assertions to
// runtime.Error see its methods.
$.registerInterfaceType('runtime.Error', null, [
{
name: 'Error',
args: [],
returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
},
{ name: 'RuntimeError', args: [], returns: [] },
])

// TypeAssertionError represents a failed type assertion.
export class TypeAssertionError implements Error {
constructor(
Expand All @@ -424,6 +435,31 @@ export class TypeAssertionError implements Error {
}
}

// PanicNilError is the value of a panic called with a nil argument, as Go
// 1.21 and later panic with.
export class PanicNilError {
constructor(_init?: Partial<{}>) {}

public clone(): PanicNilError {
return new PanicNilError()
}

public Error(): string {
return 'runtime error: panic called with nil argument'
}

public RuntimeError(): void {}

// PanicNilError is registered with the runtime type system; the compiler
// gives its method signatures, for reflection.
static __typeInfo = $.registerStructType(
'runtime.PanicNilError',
new PanicNilError(),
[],
PanicNilError,
)
}

// PanicError represents a panic.
export class PanicError implements Error {
constructor(public readonly value: any) {}
Expand Down
8 changes: 0 additions & 8 deletions gs/runtime/stubs.gs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,6 @@ export function MutexProfile(..._args: any[]): any {
return $.notImplemented("runtime.MutexProfile")
}

export class PanicNilError {
[field: string]: any

constructor(..._args: any[]) {
$.notImplemented("runtime.PanicNilError")
}
}

export class Pinner {
[field: string]: any

Expand Down
2 changes: 2 additions & 0 deletions tests/tests/package_import_runtime/expected.log
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ Cleanup stopped
Finalizer ignored
locked goroutine ran
main unlocked
PanicNilError: runtime error: panic called with nil argument true
recovered runtime.Error: true
16 changes: 16 additions & 0 deletions tests/tests/package_import_runtime/package_import_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func main() {
println("Finalizer ignored")

lockOSThread()
panicNilError()
}

// callers reports frames of its own stack and names a function value.
Expand Down Expand Up @@ -124,3 +125,18 @@ func lockOSThread() {
runtime.UnlockOSThread()
println("main unlocked")
}

// panicNilError checks the value Go panics with for panic(nil).
func panicNilError() {
var err error = &runtime.PanicNilError{}
_, isRuntime := err.(runtime.Error)
println("PanicNilError:", err.Error(), isRuntime)

defer func() {
_, ok := recover().(runtime.Error)
println("recovered runtime.Error:", ok)
}()
var s []int
i := 5
_ = s[i]
}
31 changes: 31 additions & 0 deletions tests/tests/package_import_runtime/package_import_runtime.gs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export async function main(): globalThis.Promise<void> {
await $.println("Finalizer ignored")

await lockOSThread()
await panicNilError()
}

export async function callers(): globalThis.Promise<void> {
Expand Down Expand Up @@ -178,6 +179,29 @@ export async function lockOSThread(): globalThis.Promise<void> {
await $.println("main unlocked")
}

export async function panicNilError(): globalThis.Promise<void> {
const __defer = new $.AsyncDisposableStack()
try {
let err: $.GoError = $.interfaceValue<$.GoError>(new runtime.PanicNilError(), "*runtime.PanicNilError", __goscriptStatic2())
let [, isRuntime] = $.typeAssertTuple<runtime.Error | null>(err, "runtime.Error")
await $.println("PanicNilError:", (__goscriptAwait = (err !== null && (err as any).__isVarRef !== true && ((err as any).__goValue === undefined || (err as any).__goType?.charCodeAt(0) !== 42) ? (err as Exclude<$.GoError, null>) : $.pointerValue<Exclude<$.GoError, null>>(err)).Error(), __goscriptAwait instanceof Promise ? await __goscriptAwait : __goscriptAwait), isRuntime)

__defer.defer(async () => { await (async () => {
let [, ok] = $.typeAssertTuple<runtime.Error | null>($.recover(), "runtime.Error")
await $.println("recovered runtime.Error:", ok)
})() })
let s: $.Slice<number> = null! as $.Slice<number>
let i = 5
$.arrayIndex(s!, i)
await __defer.dispose()
} catch (e) {
await __defer.disposePanic(e)
if (!$.recovered(e)) {
throw e
}
}
}

var __goscriptStatic0$value: any
function __goscriptStatic0(): any {
return __goscriptStatic0$value ??= ({[$.genericTypeArgsMarker]: $.genericTypeArgsBrand, E: { type: /* @__PURE__ */ $.basicType("int"), zero: () => 0 }})
Expand All @@ -188,6 +212,13 @@ function __goscriptStatic1(): any {
return __goscriptStatic1$value ??= ([{Get: (receiver: any) => $.pointerValue(receiver).Get(__goscriptStatic0())}, [$.methodSignature("Get", [], [/* @__PURE__ */ $.basicType("int")], true, false)]])
}

var __goscriptStatic2$value: any
function __goscriptStatic2(): any {
return __goscriptStatic2$value ??= ($.overrideTypeMethods(/* @__PURE__ */ $.pointerType("runtime.PanicNilError"), "runtime.PanicNilError", () => [$.methodSignature("Error", [], [/* @__PURE__ */ $.basicType("string")], true), $.methodSignature("RuntimeError", [], [], true)]))
}

var __goscriptAwait: any

__goscriptInit0()

if ($.isMainScript(import.meta)) {
Expand Down
Loading