goscript 0.0.83 → 0.1.0
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/README.md +13 -1
- package/cmd/goscript/cmd_compile.go +70 -69
- package/cmd/goscript/cmd_compile_test.go +79 -0
- package/cmd/goscript/main.go +10 -5
- package/compiler/compile-request.go +218 -0
- package/compiler/compiler.go +16 -1336
- package/compiler/compliance_test.go +196 -0
- package/compiler/config.go +6 -13
- package/compiler/diagnostic.go +70 -0
- package/compiler/index.test.ts +28 -28
- package/compiler/index.ts +40 -72
- package/compiler/lowered-program.go +132 -0
- package/compiler/lowering.go +3576 -0
- package/compiler/override-registry.go +422 -0
- package/compiler/override-registry_test.go +207 -0
- package/compiler/package-graph.go +231 -0
- package/compiler/package-graph_test.go +281 -0
- package/compiler/result.go +13 -0
- package/compiler/runtime-contract.go +279 -0
- package/compiler/runtime-contract_test.go +90 -0
- package/compiler/semantic-model-types.go +110 -0
- package/compiler/semantic-model.go +922 -0
- package/compiler/semantic-model_test.go +416 -0
- package/compiler/service.go +133 -0
- package/compiler/skeleton_test.go +1145 -0
- package/compiler/typescript-emitter.go +663 -0
- package/compiler/wasm/compile.go +2 -3
- package/compiler/wasm/compile_test.go +29 -0
- package/compiler/wasm_api.go +10 -159
- package/dist/compiler/index.d.ts +1 -3
- package/dist/compiler/index.js +31 -55
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +13 -0
- package/dist/gs/builtin/builtin.js +27 -7
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +3 -3
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +86 -0
- package/dist/gs/builtin/hostio.js +266 -0
- package/dist/gs/builtin/hostio.js.map +1 -0
- 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/print.d.ts +8 -0
- package/dist/gs/builtin/print.js +111 -0
- package/dist/gs/builtin/print.js.map +1 -0
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +11 -0
- package/dist/gs/builtin/type.js +55 -1
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/rand/index.d.ts +5 -0
- package/dist/gs/crypto/rand/index.js +77 -0
- package/dist/gs/crypto/rand/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +160 -0
- package/dist/gs/encoding/json/index.js.map +1 -0
- package/dist/gs/fmt/fmt.js +2 -22
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +29 -0
- package/dist/gs/go/scanner/index.js +120 -0
- package/dist/gs/go/scanner/index.js.map +1 -0
- package/dist/gs/go/token/index.d.ts +31 -0
- package/dist/gs/go/token/index.js +82 -0
- package/dist/gs/go/token/index.js.map +1 -0
- package/dist/gs/internal/abi/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/readfile.js.map +1 -1
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +2 -4
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/rawconn_js.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/tempfile.gs.js +66 -9
- package/dist/gs/os/tempfile.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +2 -51
- package/dist/gs/os/types_js.gs.js +67 -105
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +2 -2
- package/dist/gs/reflect/index.js +1 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +2 -1
- package/dist/gs/reflect/type.js +85 -14
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/sort/sort.gs.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +1 -0
- package/dist/gs/sync/sync.js +12 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/go.mod +2 -2
- package/gs/builtin/builtin.ts +31 -6
- package/gs/builtin/hostio.test.ts +246 -0
- package/gs/builtin/hostio.ts +413 -0
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/print.test.ts +48 -0
- package/gs/builtin/print.ts +154 -0
- package/gs/builtin/runtime-contract.test.ts +230 -0
- package/gs/builtin/type.ts +84 -1
- package/gs/crypto/rand/index.test.ts +32 -0
- package/gs/crypto/rand/index.ts +90 -0
- package/gs/crypto/rand/meta.json +5 -0
- package/gs/encoding/json/index.test.ts +65 -0
- package/gs/encoding/json/index.ts +186 -0
- package/gs/fmt/fmt.test.ts +41 -30
- package/gs/fmt/fmt.ts +2 -22
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +23 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +3 -1
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
- package/gs/go/scanner/index.test.ts +50 -0
- package/gs/go/scanner/index.ts +157 -0
- package/gs/go/token/index.test.ts +21 -0
- package/gs/go/token/index.ts +120 -0
- package/gs/os/file_unix_js.test.ts +103 -0
- package/gs/os/meta.json +1 -2
- package/gs/os/tempfile.gs.test.ts +85 -0
- package/gs/os/tempfile.gs.ts +71 -11
- package/gs/os/types_js.gs.ts +74 -153
- package/gs/reflect/index.ts +1 -1
- package/gs/reflect/type.ts +106 -17
- package/gs/reflect/typefor.test.ts +75 -0
- package/gs/sync/sync.test.ts +24 -0
- package/gs/sync/sync.ts +12 -0
- package/package.json +13 -13
- package/compiler/analysis.go +0 -3475
- package/compiler/analysis_test.go +0 -338
- package/compiler/assignment.go +0 -580
- package/compiler/builtin_test.go +0 -92
- package/compiler/code-writer.go +0 -115
- package/compiler/compiler_test.go +0 -149
- package/compiler/composite-lit.go +0 -779
- package/compiler/config_test.go +0 -62
- package/compiler/constraint.go +0 -86
- package/compiler/decl.go +0 -801
- package/compiler/expr-call-async.go +0 -188
- package/compiler/expr-call-builtins.go +0 -208
- package/compiler/expr-call-helpers.go +0 -382
- package/compiler/expr-call-make.go +0 -318
- package/compiler/expr-call-type-conversion.go +0 -520
- package/compiler/expr-call.go +0 -413
- package/compiler/expr-selector.go +0 -343
- package/compiler/expr-star.go +0 -82
- package/compiler/expr-type.go +0 -442
- package/compiler/expr-value.go +0 -89
- package/compiler/expr.go +0 -773
- package/compiler/field.go +0 -183
- package/compiler/gs_dependencies_test.go +0 -298
- package/compiler/lit.go +0 -322
- package/compiler/output.go +0 -72
- package/compiler/primitive.go +0 -149
- package/compiler/protobuf.go +0 -697
- package/compiler/sanitize.go +0 -100
- package/compiler/spec-struct.go +0 -995
- package/compiler/spec-value.go +0 -540
- package/compiler/spec.go +0 -725
- package/compiler/stmt-assign.go +0 -664
- package/compiler/stmt-for.go +0 -266
- package/compiler/stmt-range.go +0 -475
- package/compiler/stmt-select.go +0 -262
- package/compiler/stmt-type-switch.go +0 -147
- package/compiler/stmt.go +0 -1308
- package/compiler/type-assert.go +0 -386
- package/compiler/type-info.go +0 -156
- package/compiler/type-utils.go +0 -207
- package/compiler/type.go +0 -892
package/compiler/assignment.go
DELETED
|
@@ -1,580 +0,0 @@
|
|
|
1
|
-
package compiler
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"go/ast"
|
|
6
|
-
"go/token"
|
|
7
|
-
"go/types"
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
// writeAssignmentCore handles the central logic for translating Go assignment
|
|
11
|
-
// operations (LHS op RHS) into TypeScript. It's called by `WriteStmtAssign`
|
|
12
|
-
// and other functions that need to generate assignment code.
|
|
13
|
-
//
|
|
14
|
-
// Key behaviors:
|
|
15
|
-
// - Multi-variable assignment (e.g., `a, b = b, a`): Translates to TypeScript
|
|
16
|
-
// array destructuring: `[a_ts, b_ts] = [b_ts, a_ts]`. It correctly handles
|
|
17
|
-
// non-null assertions for array index expressions on both LHS and RHS if
|
|
18
|
-
// all expressions involved are index expressions (common in swaps).
|
|
19
|
-
// - Single-variable assignment to a map index (`myMap[key] = value`): Translates
|
|
20
|
-
// to `$.mapSet(myMap_ts, key_ts, value_ts)`.
|
|
21
|
-
// - Other single-variable assignments (`variable = value`):
|
|
22
|
-
// - The LHS expression is written (caller typically ensures `.value` is appended
|
|
23
|
-
// if assigning to a VarRefed variable's content).
|
|
24
|
-
// - The Go assignment token (`tok`, e.g., `=`, `+=`) is translated to its
|
|
25
|
-
// TypeScript equivalent using `TokenToTs`.
|
|
26
|
-
// - The RHS expression(s) are written. If `shouldApplyClone` indicates the RHS
|
|
27
|
-
// is a struct value, `.clone()` is appended to the translated RHS to emulate
|
|
28
|
-
// Go's value semantics for struct assignment.
|
|
29
|
-
// - Blank identifiers (`_`) on the LHS are handled by omitting them in TypeScript
|
|
30
|
-
// destructuring patterns or by skipping the assignment for single assignments.
|
|
31
|
-
//
|
|
32
|
-
// This function handles all assignment types including:
|
|
33
|
-
// - Pointer dereference assignments (*p = v)
|
|
34
|
-
// - Blank identifier assignments (_ = v)
|
|
35
|
-
func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Token, addDeclaration bool) error {
|
|
36
|
-
// Handle blank identifier (_) on the LHS for single assignments
|
|
37
|
-
if len(lhs) == 1 && len(rhs) == 1 {
|
|
38
|
-
if ident, ok := lhs[0].(*ast.Ident); ok && ident.Name == "_" {
|
|
39
|
-
return c.writeBlankIdentifierAssign(rhs[0])
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Handle the special case of "*p = val" or "*p += val" (assignment to dereferenced pointer)
|
|
43
|
-
if starExpr, ok := lhs[0].(*ast.StarExpr); ok {
|
|
44
|
-
return c.writePointerDerefAssign(starExpr, rhs[0], tok)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Handle variable referenced variables in declarations
|
|
48
|
-
if addDeclaration && tok == token.DEFINE {
|
|
49
|
-
if handled, err := c.writeVarRefShortDecl(lhs[0], rhs[0]); err != nil {
|
|
50
|
-
return err
|
|
51
|
-
} else if handled {
|
|
52
|
-
return nil
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
c.tsw.WriteLiterally("let ")
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Special case for multi-variable assignment to handle array element swaps
|
|
60
|
-
if len(lhs) > 1 && len(rhs) > 1 {
|
|
61
|
-
return c.writeMultiVarAssign(lhs, rhs, tok)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// --- Logic for assignments ---
|
|
65
|
-
isMapIndexLHS := false // Track if the first LHS is a map index
|
|
66
|
-
for i, l := range lhs {
|
|
67
|
-
if i != 0 {
|
|
68
|
-
c.tsw.WriteLiterally(", ")
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Handle map indexing assignment specially
|
|
72
|
-
// Note: We don't use WriteIndexExpr here because we need to use $.mapSet instead of .get
|
|
73
|
-
currentIsMapIndex := false
|
|
74
|
-
if indexExpr, ok := l.(*ast.IndexExpr); ok {
|
|
75
|
-
if tv, ok := c.pkg.TypesInfo.Types[indexExpr.X]; ok {
|
|
76
|
-
// Check if it's a concrete map type
|
|
77
|
-
if _, isMap := tv.Type.Underlying().(*types.Map); isMap {
|
|
78
|
-
currentIsMapIndex = true
|
|
79
|
-
if i == 0 {
|
|
80
|
-
isMapIndexLHS = true
|
|
81
|
-
}
|
|
82
|
-
// Use mapSet helper
|
|
83
|
-
c.tsw.WriteLiterally("$.mapSet(")
|
|
84
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil { // Map
|
|
85
|
-
return err
|
|
86
|
-
}
|
|
87
|
-
c.tsw.WriteLiterally(", ")
|
|
88
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil { // Key
|
|
89
|
-
return err
|
|
90
|
-
}
|
|
91
|
-
c.tsw.WriteLiterally(", ")
|
|
92
|
-
// Value will be added after operator and RHS
|
|
93
|
-
} else if typeParam, isTypeParam := tv.Type.(*types.TypeParam); isTypeParam {
|
|
94
|
-
// Check if the type parameter is constrained to be a map type
|
|
95
|
-
constraint := typeParam.Constraint()
|
|
96
|
-
if constraint != nil {
|
|
97
|
-
underlying := constraint.Underlying()
|
|
98
|
-
if iface, isInterface := underlying.(*types.Interface); isInterface {
|
|
99
|
-
if hasMapConstraint(iface) {
|
|
100
|
-
currentIsMapIndex = true
|
|
101
|
-
if i == 0 {
|
|
102
|
-
isMapIndexLHS = true
|
|
103
|
-
}
|
|
104
|
-
// Use mapSet helper for type parameter constrained to map
|
|
105
|
-
c.tsw.WriteLiterally("$.mapSet(")
|
|
106
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil { // Map
|
|
107
|
-
return err
|
|
108
|
-
}
|
|
109
|
-
c.tsw.WriteLiterally(", ")
|
|
110
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil { // Key
|
|
111
|
-
return err
|
|
112
|
-
}
|
|
113
|
-
c.tsw.WriteLiterally(", ")
|
|
114
|
-
// Value will be added after operator and RHS
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if !currentIsMapIndex {
|
|
123
|
-
// For single assignments, handle variable referenced variables specially
|
|
124
|
-
if len(lhs) == 1 && len(rhs) == 1 {
|
|
125
|
-
lhsExprIdent, lhsExprIsIdent := l.(*ast.Ident)
|
|
126
|
-
if lhsExprIsIdent {
|
|
127
|
-
// Determine if LHS is variable referenced
|
|
128
|
-
isLHSVarRefed := false
|
|
129
|
-
var lhsObj types.Object
|
|
130
|
-
// Get the types.Object from the identifier
|
|
131
|
-
lhsObj = c.objectOfIdent(lhsExprIdent)
|
|
132
|
-
|
|
133
|
-
// Check if this variable needs to be variable referenced
|
|
134
|
-
if lhsObj != nil && c.analysis.NeedsVarRef(lhsObj) {
|
|
135
|
-
isLHSVarRefed = true
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// prevent writing .value unless lhs is variable referenced
|
|
139
|
-
c.WriteIdent(lhsExprIdent, isLHSVarRefed)
|
|
140
|
-
continue
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Write the LHS expression normally
|
|
145
|
-
if err := c.WriteValueExpr(l); err != nil {
|
|
146
|
-
return err
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Check for integer division compound assignment (i /= n)
|
|
152
|
-
// Go's integer division truncates, but JavaScript's /= doesn't
|
|
153
|
-
// We need to convert `i /= n` to `i = Math.trunc(i / n)`
|
|
154
|
-
isIntegerDivisionAssign := false
|
|
155
|
-
if tok == token.QUO_ASSIGN && len(lhs) == 1 && len(rhs) == 1 {
|
|
156
|
-
if lhsType := c.pkg.TypesInfo.TypeOf(lhs[0]); lhsType != nil {
|
|
157
|
-
if basic, ok := lhsType.Underlying().(*types.Basic); ok {
|
|
158
|
-
if basic.Info()&types.IsInteger != 0 {
|
|
159
|
-
isIntegerDivisionAssign = true
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Only write the assignment operator for regular variables, not for map assignments handled by mapSet
|
|
166
|
-
if isMapIndexLHS && len(lhs) == 1 { // Only skip operator if it's a single map assignment
|
|
167
|
-
// Continue, we've already written part of the mapSet() function call
|
|
168
|
-
} else if isIntegerDivisionAssign {
|
|
169
|
-
// For integer division compound assignment, convert `i /= n` to `i = Math.trunc(i / n)`
|
|
170
|
-
c.tsw.WriteLiterally(" = Math.trunc(")
|
|
171
|
-
// Write LHS again as first operand of division
|
|
172
|
-
if err := c.WriteValueExpr(lhs[0]); err != nil {
|
|
173
|
-
return err
|
|
174
|
-
}
|
|
175
|
-
c.tsw.WriteLiterally(" / ")
|
|
176
|
-
// RHS will be written below, then we close the parenthesis
|
|
177
|
-
} else {
|
|
178
|
-
c.tsw.WriteLiterally(" ")
|
|
179
|
-
if err := c.writeAssignmentOperator(tok); err != nil {
|
|
180
|
-
return err
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Write RHS
|
|
185
|
-
for i, r := range rhs {
|
|
186
|
-
if i != 0 {
|
|
187
|
-
c.tsw.WriteLiterally(", ")
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Check if we need to access a variable referenced source value and apply clone
|
|
191
|
-
// For struct value assignments, we need to handle:
|
|
192
|
-
// 1. UnVarRefed source, unVarRefed target: source.clone()
|
|
193
|
-
// 2. Variable referenced source, unVarRefed target: source.value.clone()
|
|
194
|
-
// 3. UnVarRefed source, variable referenced target: $.varRef(source)
|
|
195
|
-
// 4. Variable referenced source, variable referenced target: source (straight assignment of the variable reference)
|
|
196
|
-
|
|
197
|
-
// Determine if RHS is a variable referenced variable (could be a struct or other variable)
|
|
198
|
-
needsVarRefedAccessRHS := false
|
|
199
|
-
var rhsObj types.Object
|
|
200
|
-
|
|
201
|
-
// Check if RHS is an identifier (variable name)
|
|
202
|
-
rhsIdent, rhsIsIdent := r.(*ast.Ident)
|
|
203
|
-
if rhsIsIdent {
|
|
204
|
-
rhsObj = c.objectOfIdent(rhsIdent)
|
|
205
|
-
|
|
206
|
-
// Important: For struct copying, we need to check if the variable itself is variable referenced
|
|
207
|
-
// Important: For struct copying, we need to check if the variable needs variable referenced access
|
|
208
|
-
// This is more comprehensive than just checking if it's variable referenced
|
|
209
|
-
if rhsObj != nil {
|
|
210
|
-
needsVarRefedAccessRHS = c.analysis.NeedsVarRefAccess(rhsObj)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Check for pointer-to-pointer assignment
|
|
215
|
-
if rhsIsIdent && rhsObj != nil && len(lhs) == 1 {
|
|
216
|
-
lhsType := c.pkg.TypesInfo.TypeOf(lhs[0])
|
|
217
|
-
rhsType := rhsObj.Type()
|
|
218
|
-
|
|
219
|
-
if lhsType != nil && rhsType != nil {
|
|
220
|
-
// Check if both LHS and RHS are pointer types
|
|
221
|
-
if _, lhsIsPtr := lhsType.(*types.Pointer); lhsIsPtr {
|
|
222
|
-
if _, rhsIsPtr := rhsType.(*types.Pointer); rhsIsPtr {
|
|
223
|
-
// This is pointer-to-pointer assignment
|
|
224
|
-
// The key question: is the RHS variable itself varref'd?
|
|
225
|
-
// - If RHS is varref'd (like pp1), use .value to get the actual pointer
|
|
226
|
-
// - If RHS is not varref'd (like p1), use the variable directly
|
|
227
|
-
|
|
228
|
-
if c.analysis.NeedsVarRef(rhsObj) {
|
|
229
|
-
// RHS variable is varref'd, so we need its .value to get the actual pointer
|
|
230
|
-
c.WriteIdent(rhsIdent, true) // Add .value access
|
|
231
|
-
} else {
|
|
232
|
-
// RHS variable is not varref'd, so it directly holds the pointer
|
|
233
|
-
c.WriteIdent(rhsIdent, false) // No .value access
|
|
234
|
-
}
|
|
235
|
-
continue
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Handle different cases for struct cloning
|
|
242
|
-
if shouldApplyClone(c.pkg, r) {
|
|
243
|
-
// When cloning for value assignment, mark the result as struct value
|
|
244
|
-
c.tsw.WriteLiterally("$.markAsStructValue(")
|
|
245
|
-
|
|
246
|
-
// Check if RHS is an async call - if so, wrap in parentheses so .clone() binds correctly
|
|
247
|
-
// Example: (await asyncFunc()).clone() instead of await asyncFunc().clone()
|
|
248
|
-
needsParensForAsync := false
|
|
249
|
-
if callExpr, isCall := r.(*ast.CallExpr); isCall && c.isCallExprAsync(callExpr) {
|
|
250
|
-
needsParensForAsync = true
|
|
251
|
-
c.tsw.WriteLiterally("(")
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// For other expressions, we need to handle variable referenced access differently
|
|
255
|
-
if _, isIdent := r.(*ast.Ident); isIdent {
|
|
256
|
-
// For identifiers, WriteValueExpr already adds .value if needed
|
|
257
|
-
if err := c.WriteValueExpr(r); err != nil {
|
|
258
|
-
return err
|
|
259
|
-
}
|
|
260
|
-
} else {
|
|
261
|
-
// For non-identifiers, write the expression and add .value if needed
|
|
262
|
-
if err := c.WriteValueExpr(r); err != nil {
|
|
263
|
-
return err
|
|
264
|
-
}
|
|
265
|
-
// Only add .value for non-identifiers that need variable referenced access
|
|
266
|
-
if needsVarRefedAccessRHS {
|
|
267
|
-
c.tsw.WriteLiterally(".value") // Access the variable referenced value
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if needsParensForAsync {
|
|
272
|
-
c.tsw.WriteLiterally(")")
|
|
273
|
-
}
|
|
274
|
-
c.tsw.WriteLiterally(".clone())") // Always add clone for struct values
|
|
275
|
-
} else {
|
|
276
|
-
// Check if this is a pointer variable assignment to an interface type
|
|
277
|
-
if rhsIsIdent && rhsObj != nil {
|
|
278
|
-
// Check if LHS is interface type and RHS is a pointer variable
|
|
279
|
-
if len(lhs) == 1 {
|
|
280
|
-
lhsType := c.pkg.TypesInfo.TypeOf(lhs[0])
|
|
281
|
-
rhsType := rhsObj.Type()
|
|
282
|
-
|
|
283
|
-
if lhsType != nil && rhsType != nil {
|
|
284
|
-
// Check if LHS is interface and RHS is pointer
|
|
285
|
-
if _, isInterface := lhsType.Underlying().(*types.Interface); isInterface {
|
|
286
|
-
if ptrType, isPtr := rhsType.(*types.Pointer); isPtr {
|
|
287
|
-
// This is pointer-to-interface assignment
|
|
288
|
-
// For pointer variables that point to varrefed values, write without .value
|
|
289
|
-
// We want to pass the VarRef object itself to the interface, not its .value
|
|
290
|
-
if c.analysis.NeedsVarRefAccess(rhsObj) {
|
|
291
|
-
// Write the pointer variable without .value access
|
|
292
|
-
c.WriteIdent(rhsIdent, false)
|
|
293
|
-
continue
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Check if this is a struct pointer for the element type
|
|
297
|
-
if _, isStruct := ptrType.Elem().Underlying().(*types.Struct); isStruct {
|
|
298
|
-
// Struct pointer to interface - might need special handling
|
|
299
|
-
// Continue to normal WriteValueExpr handling
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Non-struct case: write RHS normally
|
|
308
|
-
// Check if this is a primitive error type being assigned to an error interface
|
|
309
|
-
if c.writePrimitiveErrorWrapperForAssign(lhs, r, i) {
|
|
310
|
-
continue
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if err := c.WriteValueExpr(r); err != nil { // RHS is a non-struct value
|
|
314
|
-
return err
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Close the parenthesis for &^= transformation
|
|
320
|
-
if tok == token.AND_NOT_ASSIGN && !(isMapIndexLHS && len(lhs) == 1) {
|
|
321
|
-
c.tsw.WriteLiterally(")")
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Close the parenthesis for integer division compound assignment
|
|
325
|
-
if isIntegerDivisionAssign {
|
|
326
|
-
c.tsw.WriteLiterally(")")
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// If the LHS was a single map index, close the mapSet call
|
|
330
|
-
if isMapIndexLHS && len(lhs) == 1 {
|
|
331
|
-
c.tsw.WriteLiterally(")")
|
|
332
|
-
}
|
|
333
|
-
return nil
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// writePrimitiveErrorWrapperForAssign checks if an RHS value is a primitive type
|
|
337
|
-
// that implements the error interface being assigned to an error-typed LHS,
|
|
338
|
-
// and if so, wraps it with $.wrapPrimitiveError.
|
|
339
|
-
// Returns true if the wrapper was written, false otherwise.
|
|
340
|
-
func (c *GoToTSCompiler) writePrimitiveErrorWrapperForAssign(lhs []ast.Expr, rhs ast.Expr, rhsIndex int) bool {
|
|
341
|
-
// Only handle single assignments for now
|
|
342
|
-
if len(lhs) != 1 || rhsIndex != 0 {
|
|
343
|
-
return false
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Get the LHS type
|
|
347
|
-
lhsType := c.pkg.TypesInfo.TypeOf(lhs[0])
|
|
348
|
-
if lhsType == nil {
|
|
349
|
-
return false
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// Check if the LHS type is the error interface
|
|
353
|
-
if iface, ok := lhsType.Underlying().(*types.Interface); !ok || iface.String() != "interface{Error() string}" {
|
|
354
|
-
return false
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// Get the actual type of the RHS expression
|
|
358
|
-
rhsType := c.pkg.TypesInfo.TypeOf(rhs)
|
|
359
|
-
if rhsType == nil {
|
|
360
|
-
return false
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// Check if the RHS type is a wrapper type (named type with basic underlying type)
|
|
364
|
-
if !c.isWrapperType(rhsType) {
|
|
365
|
-
return false
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// Check if the RHS type has an Error() method
|
|
369
|
-
if !c.typeHasMethods(rhsType, "Error") {
|
|
370
|
-
return false
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Get the qualified type name for the Error function
|
|
374
|
-
typeName := c.getQualifiedTypeName(rhsType)
|
|
375
|
-
if typeName == "" {
|
|
376
|
-
return false
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Write: $.wrapPrimitiveError(value, TypeName_Error)
|
|
380
|
-
c.tsw.WriteLiterally("$.wrapPrimitiveError(")
|
|
381
|
-
if err := c.WriteValueExpr(rhs); err != nil {
|
|
382
|
-
return false
|
|
383
|
-
}
|
|
384
|
-
c.tsw.WriteLiterally(", ")
|
|
385
|
-
c.tsw.WriteLiterally(typeName)
|
|
386
|
-
c.tsw.WriteLiterally("_Error)")
|
|
387
|
-
|
|
388
|
-
return true
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// writeBlankIdentifierAssign handles assignment to blank identifier (_)
|
|
392
|
-
func (c *GoToTSCompiler) writeBlankIdentifierAssign(rhs ast.Expr) error {
|
|
393
|
-
c.tsw.WriteLiterally("/* _ = */ ")
|
|
394
|
-
return c.WriteValueExpr(rhs)
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// writePointerDerefAssign handles assignments to dereferenced pointers (*p = val)
|
|
398
|
-
func (c *GoToTSCompiler) writePointerDerefAssign(starExpr *ast.StarExpr, rhs ast.Expr, tok token.Token) error {
|
|
399
|
-
// Check if RHS is a struct - if so, use $.assignStruct() to copy fields
|
|
400
|
-
if shouldApplyClone(c.pkg, rhs) {
|
|
401
|
-
// For struct assignments, use $.assignStruct(target, source)
|
|
402
|
-
// This copies all fields from source to target
|
|
403
|
-
c.tsw.WriteLiterally("$.assignStruct(")
|
|
404
|
-
|
|
405
|
-
// Write the pointer as the target
|
|
406
|
-
if ident, ok := starExpr.X.(*ast.Ident); ok {
|
|
407
|
-
obj := c.objectOfIdent(ident)
|
|
408
|
-
if obj != nil && c.analysis.NeedsVarRef(obj) {
|
|
409
|
-
c.WriteIdent(ident, true)
|
|
410
|
-
} else {
|
|
411
|
-
c.WriteIdent(ident, false)
|
|
412
|
-
}
|
|
413
|
-
} else {
|
|
414
|
-
if err := c.WriteValueExpr(starExpr.X); err != nil {
|
|
415
|
-
return err
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
c.tsw.WriteLiterally("!, ")
|
|
419
|
-
|
|
420
|
-
// Write the RHS with clone as the source
|
|
421
|
-
c.tsw.WriteLiterally("$.markAsStructValue(")
|
|
422
|
-
if err := c.WriteValueExpr(rhs); err != nil {
|
|
423
|
-
return err
|
|
424
|
-
}
|
|
425
|
-
c.tsw.WriteLiterally(".clone()))")
|
|
426
|
-
return nil
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// For non-struct types, use the original p!.value = val approach
|
|
430
|
-
if ident, ok := starExpr.X.(*ast.Ident); ok {
|
|
431
|
-
obj := c.objectOfIdent(ident)
|
|
432
|
-
if obj != nil && c.analysis.NeedsVarRef(obj) {
|
|
433
|
-
c.WriteIdent(ident, true)
|
|
434
|
-
c.tsw.WriteLiterally("!.value")
|
|
435
|
-
} else {
|
|
436
|
-
c.WriteIdent(ident, false)
|
|
437
|
-
c.tsw.WriteLiterally("!.value")
|
|
438
|
-
}
|
|
439
|
-
} else {
|
|
440
|
-
if err := c.WriteValueExpr(starExpr.X); err != nil {
|
|
441
|
-
return err
|
|
442
|
-
}
|
|
443
|
-
c.tsw.WriteLiterally("!.value")
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Write assignment operator
|
|
447
|
-
if tok == token.AND_NOT_ASSIGN {
|
|
448
|
-
c.tsw.WriteLiterally(" &= ~(")
|
|
449
|
-
} else {
|
|
450
|
-
c.tsw.WriteLiterally(" ")
|
|
451
|
-
tokStr, ok := TokenToTs(tok)
|
|
452
|
-
if !ok {
|
|
453
|
-
return fmt.Errorf("unknown assignment token: %s", tok.String())
|
|
454
|
-
}
|
|
455
|
-
c.tsw.WriteLiterally(tokStr)
|
|
456
|
-
c.tsw.WriteLiterally(" ")
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Write RHS
|
|
460
|
-
if err := c.WriteValueExpr(rhs); err != nil {
|
|
461
|
-
return err
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if tok == token.AND_NOT_ASSIGN {
|
|
465
|
-
c.tsw.WriteLiterally(")")
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
return nil
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// writeVarRefShortDecl handles short declarations of varrefed variables
|
|
472
|
-
// Returns true if handled, false otherwise
|
|
473
|
-
func (c *GoToTSCompiler) writeVarRefShortDecl(lhs, rhs ast.Expr) (bool, error) {
|
|
474
|
-
ident, ok := lhs.(*ast.Ident)
|
|
475
|
-
if !ok {
|
|
476
|
-
return false, nil
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
obj := c.objectOfIdent(ident)
|
|
480
|
-
if obj == nil || !c.analysis.NeedsVarRef(obj) {
|
|
481
|
-
return false, nil
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
c.tsw.WriteLiterally("let ")
|
|
485
|
-
c.tsw.WriteLiterally(c.sanitizeIdentifier(ident.Name))
|
|
486
|
-
c.tsw.WriteLiterally(" = $.varRef(")
|
|
487
|
-
if err := c.WriteValueExpr(rhs); err != nil {
|
|
488
|
-
return false, err
|
|
489
|
-
}
|
|
490
|
-
c.tsw.WriteLiterally(")")
|
|
491
|
-
return true, nil
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// writeMultiVarAssign handles multi-variable assignments with array destructuring
|
|
495
|
-
func (c *GoToTSCompiler) writeMultiVarAssign(lhs, rhs []ast.Expr, tok token.Token) error {
|
|
496
|
-
// Check if all expressions are index expressions (for swap optimization)
|
|
497
|
-
allIndexExprs := true
|
|
498
|
-
for _, expr := range append(lhs, rhs...) {
|
|
499
|
-
if _, isIndexExpr := expr.(*ast.IndexExpr); !isIndexExpr {
|
|
500
|
-
allIndexExprs = false
|
|
501
|
-
break
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
// Add semicolon to prevent TypeScript parsing issues
|
|
506
|
-
if tok != token.DEFINE {
|
|
507
|
-
c.tsw.WriteLiterally(";")
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Write LHS array destructuring pattern
|
|
511
|
-
c.tsw.WriteLiterally("[")
|
|
512
|
-
for i, l := range lhs {
|
|
513
|
-
if i != 0 {
|
|
514
|
-
c.tsw.WriteLiterally(", ")
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
if ident, ok := l.(*ast.Ident); ok && ident.Name == "_" {
|
|
518
|
-
// Blank identifier - leave empty slot
|
|
519
|
-
} else if indexExpr, ok := l.(*ast.IndexExpr); ok && allIndexExprs {
|
|
520
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
521
|
-
return err
|
|
522
|
-
}
|
|
523
|
-
c.tsw.WriteLiterally("![")
|
|
524
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
525
|
-
return err
|
|
526
|
-
}
|
|
527
|
-
c.tsw.WriteLiterally("]")
|
|
528
|
-
} else {
|
|
529
|
-
if err := c.WriteValueExpr(l); err != nil {
|
|
530
|
-
return err
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// Write RHS array
|
|
536
|
-
c.tsw.WriteLiterally("] = [")
|
|
537
|
-
for i, r := range rhs {
|
|
538
|
-
if i != 0 {
|
|
539
|
-
c.tsw.WriteLiterally(", ")
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
if indexExpr, ok := r.(*ast.IndexExpr); ok && allIndexExprs {
|
|
543
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
544
|
-
return err
|
|
545
|
-
}
|
|
546
|
-
c.tsw.WriteLiterally("![")
|
|
547
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
548
|
-
return err
|
|
549
|
-
}
|
|
550
|
-
c.tsw.WriteLiterally("]")
|
|
551
|
-
} else if callExpr, isCallExpr := r.(*ast.CallExpr); isCallExpr {
|
|
552
|
-
if err := c.WriteCallExpr(callExpr); err != nil {
|
|
553
|
-
return err
|
|
554
|
-
}
|
|
555
|
-
} else {
|
|
556
|
-
if err := c.WriteValueExpr(r); err != nil {
|
|
557
|
-
return err
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
c.tsw.WriteLiterally("]")
|
|
562
|
-
|
|
563
|
-
return nil
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// writeAssignmentOperator writes the TypeScript assignment operator
|
|
567
|
-
func (c *GoToTSCompiler) writeAssignmentOperator(tok token.Token) error {
|
|
568
|
-
if tok == token.AND_NOT_ASSIGN {
|
|
569
|
-
c.tsw.WriteLiterally("&= ~(")
|
|
570
|
-
return nil
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
tokStr, ok := TokenToTs(tok)
|
|
574
|
-
if !ok {
|
|
575
|
-
return fmt.Errorf("unknown assignment token: %s", tok.String())
|
|
576
|
-
}
|
|
577
|
-
c.tsw.WriteLiterally(tokStr)
|
|
578
|
-
c.tsw.WriteLiterally(" ")
|
|
579
|
-
return nil
|
|
580
|
-
}
|
package/compiler/builtin_test.go
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
//go:build test_emit_builtin
|
|
2
|
-
|
|
3
|
-
package compiler
|
|
4
|
-
|
|
5
|
-
import (
|
|
6
|
-
"context"
|
|
7
|
-
"os"
|
|
8
|
-
"path/filepath"
|
|
9
|
-
"testing"
|
|
10
|
-
|
|
11
|
-
"github.com/sirupsen/logrus"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
func TestEmitBuiltinOption(t *testing.T) {
|
|
15
|
-
// Create a temporary directory for the test output
|
|
16
|
-
tempDir, err := os.MkdirTemp("", "goscript-test-emit-builtin")
|
|
17
|
-
if err != nil {
|
|
18
|
-
t.Fatalf("Failed to create temp dir: %v", err)
|
|
19
|
-
}
|
|
20
|
-
defer os.RemoveAll(tempDir)
|
|
21
|
-
|
|
22
|
-
// Setup logger
|
|
23
|
-
log := logrus.New()
|
|
24
|
-
log.SetLevel(logrus.DebugLevel)
|
|
25
|
-
le := logrus.NewEntry(log)
|
|
26
|
-
|
|
27
|
-
// Case 1: DisableEmitBuiltin = true (default behavior in tests tests)
|
|
28
|
-
t.Run("DisableEmitBuiltin=true", func(t *testing.T) {
|
|
29
|
-
outputDir := filepath.Join(tempDir, "disabled")
|
|
30
|
-
config := &Config{
|
|
31
|
-
OutputPath: outputDir,
|
|
32
|
-
AllDependencies: true,
|
|
33
|
-
DisableEmitBuiltin: true,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
compiler, err := NewCompiler(config, le, nil)
|
|
37
|
-
if err != nil {
|
|
38
|
-
t.Fatalf("Failed to create compiler: %v", err)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Compile a package that depends on builtin (time)
|
|
42
|
-
_, err = compiler.CompilePackages(context.Background(), "time")
|
|
43
|
-
if err != nil {
|
|
44
|
-
t.Fatalf("Compilation failed: %v", err)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Check that handwritten packages like unsafe aren't emitted when DisableEmitBuiltin=true
|
|
48
|
-
unsafePath := filepath.Join(outputDir, "@goscript/unsafe")
|
|
49
|
-
if _, err := os.Stat(unsafePath); !os.IsNotExist(err) {
|
|
50
|
-
t.Errorf("unsafe package was emitted when DisableEmitBuiltin=true")
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Also check for runtime package
|
|
54
|
-
runtimePath := filepath.Join(outputDir, "@goscript/runtime")
|
|
55
|
-
if _, err := os.Stat(runtimePath); !os.IsNotExist(err) {
|
|
56
|
-
t.Errorf("runtime package was emitted when DisableEmitBuiltin=true")
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// But time package should have been emitted
|
|
60
|
-
timePath := filepath.Join(outputDir, "@goscript/time")
|
|
61
|
-
if _, err := os.Stat(timePath); os.IsNotExist(err) {
|
|
62
|
-
t.Errorf("time package was not emitted")
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
// Case 2: DisableEmitBuiltin = false (new behavior for third-party projects)
|
|
67
|
-
t.Run("DisableEmitBuiltin=false", func(t *testing.T) {
|
|
68
|
-
outputDir := filepath.Join(tempDir, "enabled")
|
|
69
|
-
config := &Config{
|
|
70
|
-
OutputPath: outputDir,
|
|
71
|
-
AllDependencies: true,
|
|
72
|
-
DisableEmitBuiltin: false,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
compiler, err := NewCompiler(config, le, nil)
|
|
76
|
-
if err != nil {
|
|
77
|
-
t.Fatalf("Failed to create compiler: %v", err)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Compile a package that depends on builtin (time)
|
|
81
|
-
_, err = compiler.CompilePackages(context.Background(), "time")
|
|
82
|
-
if err != nil {
|
|
83
|
-
t.Fatalf("Compilation failed: %v", err)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Time package should also have been emitted
|
|
87
|
-
timePath := filepath.Join(outputDir, "@goscript/time")
|
|
88
|
-
if _, err := os.Stat(timePath); os.IsNotExist(err) {
|
|
89
|
-
t.Errorf("time package was not emitted")
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
}
|