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
95 changes: 64 additions & 31 deletions gs/time/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1259,31 +1259,69 @@ export function Weekday_String(w: Weekday): string {
return WeekdayString(w)
}

// ParseError describes a problem parsing a time string.
export class ParseError extends Error {
public layout: string
public value: string
public layoutElem: string
public valueElem: string
public message: string
// ParseError describes a problem parsing a time string. It has the exported
// fields of Go's ParseError, so Go code can make one with a composite literal
// and match one with errors.As.
export class ParseError {
public Layout: string
public Value: string
public LayoutElem: string
public ValueElem: string
public Message: string

constructor(
layout: string,
value: string,
layoutElem: string,
valueElem: string,
message: string,
init?: Partial<{
Layout: string
Value: string
LayoutElem: string
ValueElem: string
Message: string
}>,
) {
super(message)
this.layout = layout
this.value = value
this.layoutElem = layoutElem
this.valueElem = valueElem
this.message = message
this.name = 'ParseError'
this.Layout = init?.Layout ?? ''
this.Value = init?.Value ?? ''
this.LayoutElem = init?.LayoutElem ?? ''
this.ValueElem = init?.ValueElem ?? ''
this.Message = init?.Message ?? ''
}

public clone(): ParseError {
return new ParseError(this)
}

// Error returns the string representation of a ParseError, as Go does.
public Error(): string {
if (this.Message === '') {
return (
'parsing time ' +
quoteParseValue(this.Value) +
' as ' +
quoteParseValue(this.Layout) +
': cannot parse ' +
quoteParseValue(this.ValueElem) +
' as ' +
quoteParseValue(this.LayoutElem)
)
}
return 'parsing time ' + quoteParseValue(this.Value) + this.Message
}

static __typeInfo: $.StructTypeInfo
}

// ParseError registers with the runtime type system, so that *ParseError
// implements error for type assertions and errors.As.
ParseError.__typeInfo = $.registerStructType(
'time.ParseError',
new ParseError(),
[{ name: 'Error', args: [], returns: [{ type: $.basicType('string') }] }],
ParseError,
() =>
['Layout', 'Value', 'LayoutElem', 'ValueElem', 'Message'].map((name, i) =>
$.structField(name, $.basicType('string'), [i], i * 16, true),
),
)

// Timer represents a single event timer. A Timer made without a duration is
// the zero Timer, which does not run until it is Reset.
export class Timer {
Expand Down Expand Up @@ -2185,18 +2223,13 @@ function newParseError(
valueElem: string,
message: string,
): $.GoError {
const text =
message === '' ?
'parsing time ' +
quoteParseValue(value) +
' as ' +
quoteParseValue(layout) +
': cannot parse ' +
quoteParseValue(valueElem) +
' as ' +
quoteParseValue(layoutElem)
: 'parsing time ' + quoteParseValue(value) + message
return $.toGoError(new ParseError(layout, value, layoutElem, valueElem, text))
return new ParseError({
Layout: layout,
Value: value,
LayoutElem: layoutElem,
ValueElem: valueElem,
Message: message,
})
}

function isLeap(year: number): boolean {
Expand Down
5 changes: 5 additions & 0 deletions tests/tests/package_import_time_parse_error/expected.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
as: true
fields: 2006-01-02 2024-13-01 : month out of range
error: parsing time "2024-13-01": month out of range
literal: parsing time "x" as "15:04": cannot parse "x" as "15"
message: parsing time "y": bad
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"errors"
"time"
)

func main() {
// A parse failure is a *time.ParseError that errors.As finds.
_, err := time.Parse("2006-01-02", "2024-13-01")
var pe *time.ParseError
println("as:", errors.As(err, &pe))
println("fields:", pe.Layout, pe.Value, pe.Message)
println("error:", err.Error())

// A composite literal sets the exported fields, and Error formats them.
lit := &time.ParseError{Layout: "15:04", Value: "x", LayoutElem: "15", ValueElem: "x"}
println("literal:", lit.Error())
lit = &time.ParseError{Value: "y", Message: ": bad"}
println("message:", lit.Error())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Generated file based on package_import_time_parse_error.go
// Updated when compliance tests are re-run, DO NOT EDIT!

import * as $ from "@goscript/builtin/index.js"
import * as errors from "@goscript/errors/index.js"
import * as time from "@goscript/time/index.js"

export async function main(): globalThis.Promise<void> {
// A parse failure is a *time.ParseError that errors.As finds.
let [, err] = time.Parse("2006-01-02", "2024-13-01")
let pe: $.VarRef<time.ParseError | $.VarRef<time.ParseError> | null> = $.varRef(null! as time.ParseError | $.VarRef<time.ParseError> | null)
await $.println("as:", errors.As($.pointerValueOrNil(err)!, $.interfaceValue(pe, "**time.ParseError", /* @__PURE__ */ $.pointerType(/* @__PURE__ */ $.pointerType("time.ParseError")))))
await $.println("fields:", $.pointerValue<time.ParseError>(pe.value).Layout, $.pointerValue<time.ParseError>(pe.value).Value, $.pointerValue<time.ParseError>(pe.value).Message)
await $.println("error:", (__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))

// A composite literal sets the exported fields, and Error formats them.
let lit: time.ParseError | $.VarRef<time.ParseError> | null = new time.ParseError({Layout: "15:04", Value: "x", LayoutElem: "15", ValueElem: "x"})
await $.println("literal:", (lit !== null && (lit as any).__isVarRef !== true && (lit as any).__goValue === undefined ? ((lit as any) as time.ParseError).Error() : time.ParseError.prototype.Error.call($.pointerValue<time.ParseError>(lit))))
lit = new time.ParseError({Value: "y", Message: ": bad"})
await $.println("message:", (lit !== null && (lit as any).__isVarRef !== true && (lit as any).__goValue === undefined ? ((lit as any) as time.ParseError).Error() : time.ParseError.prototype.Error.call($.pointerValue<time.ParseError>(lit))))
}

var __goscriptAwait: any

if ($.isMainScript(import.meta)) {
await main()
}
25 changes: 25 additions & 0 deletions tests/tests/package_import_time_parse_error/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"paths": {
"*": [
"./*"
],
"@go/github.com/s4wave/goscript/*": [
"../../../*"
],
"@goscript/*": [
"../../../tests/tests/package_import_time_parse_error/run/output/@goscript/*",
"../../../gs/*",
"../../../tests/deps/*"
],
"@goscript/github.com/s4wave/goscript/tests/tests/package_import_time_parse_error/*": [
"./*"
]
}
},
"extends": "../../../tests/tsconfig.base.json",
"include": [
"index.ts",
"package_import_time_parse_error.gs.ts"
]
}
Loading