goscript 0.0.44 → 0.0.47
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 +198 -504
- package/compiler/analysis.go +98 -0
- package/compiler/compiler.go +20 -70
- package/compiler/decl.go +63 -40
- package/compiler/expr-call-async.go +101 -0
- package/compiler/expr-call-builtins.go +133 -0
- package/compiler/expr-call-helpers.go +138 -0
- package/compiler/expr-call-make.go +568 -0
- package/compiler/expr-call-type-conversion.go +424 -0
- package/compiler/expr-call.go +59 -1305
- package/compiler/expr.go +126 -4
- package/compiler/spec-struct.go +50 -30
- package/compiler/spec.go +69 -112
- package/compiler/type.go +51 -0
- package/dist/gs/builtin/builtin.d.ts +3 -1
- package/dist/gs/builtin/builtin.js +6 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/errors.js +1 -1
- package/dist/gs/builtin/slice.js +2 -1
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/io/fs/fs.d.ts +12 -1
- package/dist/gs/io/fs/fs.js +106 -30
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +1 -3
- package/dist/gs/os/types_js.gs.js +2 -1
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +2 -2
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/filepath/path.d.ts +1 -1
- package/dist/gs/path/filepath/path.js +1 -1
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/time/time.js +11 -3
- package/dist/gs/time/time.js.map +1 -1
- package/gs/builtin/builtin.ts +8 -3
- package/gs/builtin/errors.ts +2 -2
- package/gs/builtin/slice.ts +24 -8
- package/gs/fmt/fmt.ts +12 -3
- package/gs/fmt/index.ts +1 -1
- package/gs/io/fs/fs.ts +100 -31
- package/gs/io/fs/godoc.txt +370 -17
- package/gs/os/types_js.gs.ts +2 -2
- package/gs/os/types_unix.gs.ts +2 -2
- package/gs/path/filepath/path.test.ts +2 -2
- package/gs/path/filepath/path.ts +3 -10
- package/gs/reflect/value.ts +10 -2
- package/gs/time/time.ts +52 -17
- package/package.json +1 -1
package/gs/io/fs/godoc.txt
CHANGED
|
@@ -6,30 +6,383 @@ provided by the host operating system but also by other packages.
|
|
|
6
6
|
See the testing/fstest package for support with testing implementations of file
|
|
7
7
|
systems.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
VARIABLES
|
|
10
|
+
|
|
11
|
+
var (
|
|
12
|
+
ErrInvalid = errInvalid() // "invalid argument"
|
|
13
|
+
ErrPermission = errPermission() // "permission denied"
|
|
14
|
+
ErrExist = errExist() // "file already exists"
|
|
15
|
+
ErrNotExist = errNotExist() // "file does not exist"
|
|
16
|
+
ErrClosed = errClosed() // "file already closed"
|
|
17
|
+
)
|
|
18
|
+
Generic file system errors. Errors returned by file systems can be tested
|
|
19
|
+
against these errors using errors.Is.
|
|
20
|
+
|
|
10
21
|
var SkipAll = errors.New("skip everything and stop the walk")
|
|
22
|
+
SkipAll is used as a return value from WalkDirFunc to indicate that all
|
|
23
|
+
remaining files and directories are to be skipped. It is not returned as an
|
|
24
|
+
error by any function.
|
|
25
|
+
|
|
11
26
|
var SkipDir = errors.New("skip this directory")
|
|
27
|
+
SkipDir is used as a return value from WalkDirFunc to indicate that the
|
|
28
|
+
directory named in the call is to be skipped. It is not returned as an error
|
|
29
|
+
by any function.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
FUNCTIONS
|
|
33
|
+
|
|
12
34
|
func FormatDirEntry(dir DirEntry) string
|
|
35
|
+
FormatDirEntry returns a formatted version of dir for human readability.
|
|
36
|
+
Implementations of DirEntry can call this from a String method. The outputs
|
|
37
|
+
for a directory named subdir and a file named hello.go are:
|
|
38
|
+
|
|
39
|
+
d subdir/
|
|
40
|
+
- hello.go
|
|
41
|
+
|
|
13
42
|
func FormatFileInfo(info FileInfo) string
|
|
43
|
+
FormatFileInfo returns a formatted version of info for human readability.
|
|
44
|
+
Implementations of FileInfo can call this from a String method. The output
|
|
45
|
+
for a file named "hello.go", 100 bytes, mode 0o644, created January 1,
|
|
46
|
+
1970 at noon is
|
|
47
|
+
|
|
48
|
+
-rw-r--r-- 100 1970-01-01 12:00:00 hello.go
|
|
49
|
+
|
|
14
50
|
func Glob(fsys FS, pattern string) (matches []string, err error)
|
|
51
|
+
Glob returns the names of all files matching pattern or nil if there is
|
|
52
|
+
no matching file. The syntax of patterns is the same as in path.Match.
|
|
53
|
+
The pattern may describe hierarchical names such as usr/*/bin/ed.
|
|
54
|
+
|
|
55
|
+
Glob ignores file system errors such as I/O errors reading directories.
|
|
56
|
+
The only possible returned error is path.ErrBadPattern, reporting that the
|
|
57
|
+
pattern is malformed.
|
|
58
|
+
|
|
59
|
+
If fs implements GlobFS, Glob calls fs.Glob. Otherwise, Glob uses ReadDir to
|
|
60
|
+
traverse the directory tree and look for matches for the pattern.
|
|
61
|
+
|
|
15
62
|
func ReadFile(fsys FS, name string) ([]byte, error)
|
|
63
|
+
ReadFile reads the named file from the file system fs and returns its
|
|
64
|
+
contents. A successful call returns a nil error, not io.EOF. (Because
|
|
65
|
+
ReadFile reads the whole file, the expected EOF from the final Read is not
|
|
66
|
+
treated as an error to be reported.)
|
|
67
|
+
|
|
68
|
+
If fs implements ReadFileFS, ReadFile calls fs.ReadFile. Otherwise ReadFile
|
|
69
|
+
calls fs.Open and uses Read and Close on the returned File.
|
|
70
|
+
|
|
16
71
|
func ValidPath(name string) bool
|
|
72
|
+
ValidPath reports whether the given path name is valid for use in a call to
|
|
73
|
+
Open.
|
|
74
|
+
|
|
75
|
+
Path names passed to open are UTF-8-encoded, unrooted, slash-separated
|
|
76
|
+
sequences of path elements, like “x/y/z”. Path names must not contain an
|
|
77
|
+
element that is “.” or “..” or the empty string, except for the special case
|
|
78
|
+
that the name "." may be used for the root directory. Paths must not start
|
|
79
|
+
or end with a slash: “/x” and “x/” are invalid.
|
|
80
|
+
|
|
81
|
+
Note that paths are slash-separated on all systems, even Windows.
|
|
82
|
+
Paths containing other characters such as backslash and colon are
|
|
83
|
+
accepted as valid, but those characters must never be interpreted by an FS
|
|
84
|
+
implementation as path element separators.
|
|
85
|
+
|
|
17
86
|
func WalkDir(fsys FS, root string, fn WalkDirFunc) error
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
87
|
+
WalkDir walks the file tree rooted at root, calling fn for each file or
|
|
88
|
+
directory in the tree, including root.
|
|
89
|
+
|
|
90
|
+
All errors that arise visiting files and directories are filtered by fn:
|
|
91
|
+
see the fs.WalkDirFunc documentation for details.
|
|
92
|
+
|
|
93
|
+
The files are walked in lexical order, which makes the output deterministic
|
|
94
|
+
but requires WalkDir to read an entire directory into memory before
|
|
95
|
+
proceeding to walk that directory.
|
|
96
|
+
|
|
97
|
+
WalkDir does not follow symbolic links found in directories, but if root
|
|
98
|
+
itself is a symbolic link, its target will be walked.
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
TYPES
|
|
102
|
+
|
|
103
|
+
type DirEntry interface {
|
|
104
|
+
// Name returns the name of the file (or subdirectory) described by the entry.
|
|
105
|
+
// This name is only the final element of the path (the base name), not the entire path.
|
|
106
|
+
// For example, Name would return "hello.go" not "home/gopher/hello.go".
|
|
107
|
+
Name() string
|
|
108
|
+
|
|
109
|
+
// IsDir reports whether the entry describes a directory.
|
|
110
|
+
IsDir() bool
|
|
111
|
+
|
|
112
|
+
// Type returns the type bits for the entry.
|
|
113
|
+
// The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method.
|
|
114
|
+
Type() FileMode
|
|
115
|
+
|
|
116
|
+
// Info returns the FileInfo for the file or subdirectory described by the entry.
|
|
117
|
+
// The returned FileInfo may be from the time of the original directory read
|
|
118
|
+
// or from the time of the call to Info. If the file has been removed or renamed
|
|
119
|
+
// since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist).
|
|
120
|
+
// If the entry denotes a symbolic link, Info reports the information about the link itself,
|
|
121
|
+
// not the link's target.
|
|
122
|
+
Info() (FileInfo, error)
|
|
123
|
+
}
|
|
124
|
+
A DirEntry is an entry read from a directory (using the ReadDir function or
|
|
125
|
+
a ReadDirFile's ReadDir method).
|
|
126
|
+
|
|
127
|
+
func FileInfoToDirEntry(info FileInfo) DirEntry
|
|
128
|
+
FileInfoToDirEntry returns a DirEntry that returns information from info.
|
|
129
|
+
If info is nil, FileInfoToDirEntry returns nil.
|
|
130
|
+
|
|
131
|
+
func ReadDir(fsys FS, name string) ([]DirEntry, error)
|
|
132
|
+
ReadDir reads the named directory and returns a list of directory entries
|
|
133
|
+
sorted by filename.
|
|
134
|
+
|
|
135
|
+
If fs implements ReadDirFS, ReadDir calls fs.ReadDir. Otherwise ReadDir
|
|
136
|
+
calls fs.Open and uses ReadDir and Close on the returned file.
|
|
137
|
+
|
|
138
|
+
type FS interface {
|
|
139
|
+
// Open opens the named file.
|
|
140
|
+
// [File.Close] must be called to release any associated resources.
|
|
141
|
+
//
|
|
142
|
+
// When Open returns an error, it should be of type *PathError
|
|
143
|
+
// with the Op field set to "open", the Path field set to name,
|
|
144
|
+
// and the Err field describing the problem.
|
|
145
|
+
//
|
|
146
|
+
// Open should reject attempts to open names that do not satisfy
|
|
147
|
+
// ValidPath(name), returning a *PathError with Err set to
|
|
148
|
+
// ErrInvalid or ErrNotExist.
|
|
149
|
+
Open(name string) (File, error)
|
|
150
|
+
}
|
|
151
|
+
An FS provides access to a hierarchical file system.
|
|
152
|
+
|
|
153
|
+
The FS interface is the minimum implementation required of the file system.
|
|
154
|
+
A file system may implement additional interfaces, such as ReadFileFS,
|
|
155
|
+
to provide additional or optimized functionality.
|
|
156
|
+
|
|
157
|
+
testing/fstest.TestFS may be used to test implementations of an FS for
|
|
158
|
+
correctness.
|
|
159
|
+
|
|
160
|
+
func Sub(fsys FS, dir string) (FS, error)
|
|
161
|
+
Sub returns an FS corresponding to the subtree rooted at fsys's dir.
|
|
162
|
+
|
|
163
|
+
If dir is ".", Sub returns fsys unchanged. Otherwise, if fs implements
|
|
164
|
+
SubFS, Sub returns fsys.Sub(dir). Otherwise, Sub returns a new FS
|
|
165
|
+
implementation sub that, in effect, implements sub.Open(name) as
|
|
166
|
+
fsys.Open(path.Join(dir, name)). The implementation also translates calls to
|
|
167
|
+
ReadDir, ReadFile, and Glob appropriately.
|
|
168
|
+
|
|
169
|
+
Note that Sub(os.DirFS("/"), "prefix") is equivalent to os.DirFS("/prefix")
|
|
170
|
+
and that neither of them guarantees to avoid operating system accesses
|
|
171
|
+
outside "/prefix", because the implementation of os.DirFS does not check for
|
|
172
|
+
symbolic links inside "/prefix" that point to other directories. That is,
|
|
173
|
+
os.DirFS is not a general substitute for a chroot-style security mechanism,
|
|
174
|
+
and Sub does not change that fact.
|
|
175
|
+
|
|
176
|
+
type File interface {
|
|
177
|
+
Stat() (FileInfo, error)
|
|
178
|
+
Read([]byte) (int, error)
|
|
179
|
+
Close() error
|
|
180
|
+
}
|
|
181
|
+
A File provides access to a single file. The File interface is the minimum
|
|
182
|
+
implementation required of the file. Directory files should also implement
|
|
183
|
+
ReadDirFile. A file may implement io.ReaderAt or io.Seeker as optimizations.
|
|
184
|
+
|
|
185
|
+
type FileInfo interface {
|
|
186
|
+
Name() string // base name of the file
|
|
187
|
+
Size() int64 // length in bytes for regular files; system-dependent for others
|
|
188
|
+
Mode() FileMode // file mode bits
|
|
189
|
+
ModTime() time.Time // modification time
|
|
190
|
+
IsDir() bool // abbreviation for Mode().IsDir()
|
|
191
|
+
Sys() any // underlying data source (can return nil)
|
|
192
|
+
}
|
|
193
|
+
A FileInfo describes a file and is returned by Stat.
|
|
194
|
+
|
|
195
|
+
func Stat(fsys FS, name string) (FileInfo, error)
|
|
196
|
+
Stat returns a FileInfo describing the named file from the file system.
|
|
197
|
+
|
|
198
|
+
If fs implements StatFS, Stat calls fs.Stat. Otherwise, Stat opens the File
|
|
199
|
+
to stat it.
|
|
200
|
+
|
|
26
201
|
type FileMode uint32
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
202
|
+
A FileMode represents a file's mode and permission bits. The bits have the
|
|
203
|
+
same definition on all systems, so that information about files can be moved
|
|
204
|
+
from one system to another portably. Not all bits apply to all systems.
|
|
205
|
+
The only required bit is ModeDir for directories.
|
|
206
|
+
|
|
207
|
+
const (
|
|
208
|
+
// The single letters are the abbreviations
|
|
209
|
+
// used by the String method's formatting.
|
|
210
|
+
ModeDir FileMode = 1 << (32 - 1 - iota) // d: is a directory
|
|
211
|
+
ModeAppend // a: append-only
|
|
212
|
+
ModeExclusive // l: exclusive use
|
|
213
|
+
ModeTemporary // T: temporary file; Plan 9 only
|
|
214
|
+
ModeSymlink // L: symbolic link
|
|
215
|
+
ModeDevice // D: device file
|
|
216
|
+
ModeNamedPipe // p: named pipe (FIFO)
|
|
217
|
+
ModeSocket // S: Unix domain socket
|
|
218
|
+
ModeSetuid // u: setuid
|
|
219
|
+
ModeSetgid // g: setgid
|
|
220
|
+
ModeCharDevice // c: Unix character device, when ModeDevice is set
|
|
221
|
+
ModeSticky // t: sticky
|
|
222
|
+
ModeIrregular // ?: non-regular file; nothing else is known about this file
|
|
223
|
+
|
|
224
|
+
// Mask for the type bits. For regular files, none will be set.
|
|
225
|
+
ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular
|
|
226
|
+
|
|
227
|
+
ModePerm FileMode = 0777 // Unix permission bits
|
|
228
|
+
)
|
|
229
|
+
The defined file mode bits are the most significant bits of the FileMode.
|
|
230
|
+
The nine least-significant bits are the standard Unix rwxrwxrwx permissions.
|
|
231
|
+
The values of these bits should be considered part of the public API and may
|
|
232
|
+
be used in wire protocols or disk representations: they must not be changed,
|
|
233
|
+
although new bits might be added.
|
|
234
|
+
|
|
235
|
+
func (m FileMode) IsDir() bool
|
|
236
|
+
IsDir reports whether m describes a directory. That is, it tests for the
|
|
237
|
+
ModeDir bit being set in m.
|
|
238
|
+
|
|
239
|
+
func (m FileMode) IsRegular() bool
|
|
240
|
+
IsRegular reports whether m describes a regular file. That is, it tests that
|
|
241
|
+
no mode type bits are set.
|
|
242
|
+
|
|
243
|
+
func (m FileMode) Perm() FileMode
|
|
244
|
+
Perm returns the Unix permission bits in m (m & ModePerm).
|
|
245
|
+
|
|
246
|
+
func (m FileMode) String() string
|
|
247
|
+
|
|
248
|
+
func (m FileMode) Type() FileMode
|
|
249
|
+
Type returns type bits in m (m & ModeType).
|
|
250
|
+
|
|
251
|
+
type GlobFS interface {
|
|
252
|
+
FS
|
|
253
|
+
|
|
254
|
+
// Glob returns the names of all files matching pattern,
|
|
255
|
+
// providing an implementation of the top-level
|
|
256
|
+
// Glob function.
|
|
257
|
+
Glob(pattern string) ([]string, error)
|
|
258
|
+
}
|
|
259
|
+
A GlobFS is a file system with a Glob method.
|
|
260
|
+
|
|
261
|
+
type PathError struct {
|
|
262
|
+
Op string
|
|
263
|
+
Path string
|
|
264
|
+
Err error
|
|
265
|
+
}
|
|
266
|
+
PathError records an error and the operation and file path that caused it.
|
|
267
|
+
|
|
268
|
+
func (e *PathError) Error() string
|
|
269
|
+
|
|
270
|
+
func (e *PathError) Timeout() bool
|
|
271
|
+
Timeout reports whether this error represents a timeout.
|
|
272
|
+
|
|
273
|
+
func (e *PathError) Unwrap() error
|
|
274
|
+
|
|
275
|
+
type ReadDirFS interface {
|
|
276
|
+
FS
|
|
277
|
+
|
|
278
|
+
// ReadDir reads the named directory
|
|
279
|
+
// and returns a list of directory entries sorted by filename.
|
|
280
|
+
ReadDir(name string) ([]DirEntry, error)
|
|
281
|
+
}
|
|
282
|
+
ReadDirFS is the interface implemented by a file system that provides an
|
|
283
|
+
optimized implementation of ReadDir.
|
|
284
|
+
|
|
285
|
+
type ReadDirFile interface {
|
|
286
|
+
File
|
|
287
|
+
|
|
288
|
+
// ReadDir reads the contents of the directory and returns
|
|
289
|
+
// a slice of up to n DirEntry values in directory order.
|
|
290
|
+
// Subsequent calls on the same file will yield further DirEntry values.
|
|
291
|
+
//
|
|
292
|
+
// If n > 0, ReadDir returns at most n DirEntry structures.
|
|
293
|
+
// In this case, if ReadDir returns an empty slice, it will return
|
|
294
|
+
// a non-nil error explaining why.
|
|
295
|
+
// At the end of a directory, the error is io.EOF.
|
|
296
|
+
// (ReadDir must return io.EOF itself, not an error wrapping io.EOF.)
|
|
297
|
+
//
|
|
298
|
+
// If n <= 0, ReadDir returns all the DirEntry values from the directory
|
|
299
|
+
// in a single slice. In this case, if ReadDir succeeds (reads all the way
|
|
300
|
+
// to the end of the directory), it returns the slice and a nil error.
|
|
301
|
+
// If it encounters an error before the end of the directory,
|
|
302
|
+
// ReadDir returns the DirEntry list read until that point and a non-nil error.
|
|
303
|
+
ReadDir(n int) ([]DirEntry, error)
|
|
304
|
+
}
|
|
305
|
+
A ReadDirFile is a directory file whose entries can be read with the
|
|
306
|
+
ReadDir method. Every directory file should implement this interface. (It
|
|
307
|
+
is permissible for any file to implement this interface, but if so ReadDir
|
|
308
|
+
should return an error for non-directories.)
|
|
309
|
+
|
|
310
|
+
type ReadFileFS interface {
|
|
311
|
+
FS
|
|
312
|
+
|
|
313
|
+
// ReadFile reads the named file and returns its contents.
|
|
314
|
+
// A successful call returns a nil error, not io.EOF.
|
|
315
|
+
// (Because ReadFile reads the whole file, the expected EOF
|
|
316
|
+
// from the final Read is not treated as an error to be reported.)
|
|
317
|
+
//
|
|
318
|
+
// The caller is permitted to modify the returned byte slice.
|
|
319
|
+
// This method should return a copy of the underlying data.
|
|
320
|
+
ReadFile(name string) ([]byte, error)
|
|
321
|
+
}
|
|
322
|
+
ReadFileFS is the interface implemented by a file system that provides an
|
|
323
|
+
optimized implementation of ReadFile.
|
|
324
|
+
|
|
325
|
+
type StatFS interface {
|
|
326
|
+
FS
|
|
327
|
+
|
|
328
|
+
// Stat returns a FileInfo describing the file.
|
|
329
|
+
// If there is an error, it should be of type *PathError.
|
|
330
|
+
Stat(name string) (FileInfo, error)
|
|
331
|
+
}
|
|
332
|
+
A StatFS is a file system with a Stat method.
|
|
333
|
+
|
|
334
|
+
type SubFS interface {
|
|
335
|
+
FS
|
|
336
|
+
|
|
337
|
+
// Sub returns an FS corresponding to the subtree rooted at dir.
|
|
338
|
+
Sub(dir string) (FS, error)
|
|
339
|
+
}
|
|
340
|
+
A SubFS is a file system with a Sub method.
|
|
341
|
+
|
|
35
342
|
type WalkDirFunc func(path string, d DirEntry, err error) error
|
|
343
|
+
WalkDirFunc is the type of the function called by WalkDir to visit each file
|
|
344
|
+
or directory.
|
|
345
|
+
|
|
346
|
+
The path argument contains the argument to WalkDir as a prefix. That is,
|
|
347
|
+
if WalkDir is called with root argument "dir" and finds a file named "a" in
|
|
348
|
+
that directory, the walk function will be called with argument "dir/a".
|
|
349
|
+
|
|
350
|
+
The d argument is the DirEntry for the named path.
|
|
351
|
+
|
|
352
|
+
The error result returned by the function controls how WalkDir continues.
|
|
353
|
+
If the function returns the special value SkipDir, WalkDir skips the current
|
|
354
|
+
directory (path if d.IsDir() is true, otherwise path's parent directory). If
|
|
355
|
+
the function returns the special value SkipAll, WalkDir skips all remaining
|
|
356
|
+
files and directories. Otherwise, if the function returns a non-nil error,
|
|
357
|
+
WalkDir stops entirely and returns that error.
|
|
358
|
+
|
|
359
|
+
The err argument reports an error related to path, signaling that WalkDir
|
|
360
|
+
will not walk into that directory. The function can decide how to handle
|
|
361
|
+
that error; as described earlier, returning the error will cause WalkDir to
|
|
362
|
+
stop walking the entire tree.
|
|
363
|
+
|
|
364
|
+
WalkDir calls the function with a non-nil err argument in two cases.
|
|
365
|
+
|
|
366
|
+
First, if the initial Stat on the root directory fails, WalkDir calls the
|
|
367
|
+
function with path set to root, d set to nil, and err set to the error from
|
|
368
|
+
fs.Stat.
|
|
369
|
+
|
|
370
|
+
Second, if a directory's ReadDir method (see ReadDirFile) fails, WalkDir
|
|
371
|
+
calls the function with path set to the directory's path, d set to an
|
|
372
|
+
DirEntry describing the directory, and err set to the error from ReadDir.
|
|
373
|
+
In this second case, the function is called twice with the path of the
|
|
374
|
+
directory: the first call is before the directory read is attempted and has
|
|
375
|
+
err set to nil, giving the function a chance to return SkipDir or SkipAll
|
|
376
|
+
and avoid the ReadDir entirely. The second call is after a failed ReadDir
|
|
377
|
+
and reports the error from ReadDir. (If ReadDir succeeds, there is no second
|
|
378
|
+
call.)
|
|
379
|
+
|
|
380
|
+
The differences between WalkDirFunc compared to path/filepath.WalkFunc are:
|
|
381
|
+
|
|
382
|
+
- The second argument has type DirEntry instead of FileInfo.
|
|
383
|
+
- The function is called before reading a directory, to allow SkipDir
|
|
384
|
+
or SkipAll to bypass the directory read entirely or skip all remaining
|
|
385
|
+
files and directories respectively.
|
|
386
|
+
- If a directory read fails, the function is called a second time for that
|
|
387
|
+
directory to report the error.
|
|
388
|
+
|
package/gs/os/types_js.gs.ts
CHANGED
|
@@ -9,13 +9,13 @@ import * as syscall from "@goscript/syscall/index.js"
|
|
|
9
9
|
// Re-export essential types
|
|
10
10
|
export type Time = time.Time;
|
|
11
11
|
export type FileInfo = fs.FileInfo;
|
|
12
|
-
export
|
|
12
|
+
export { FileMode } from "@goscript/io/fs/index.js";
|
|
13
13
|
export type DirEntry = fs.DirEntry;
|
|
14
14
|
|
|
15
15
|
// Export runtime values for ES module compatibility
|
|
16
16
|
export const Time = null as any;
|
|
17
17
|
export const FileInfo = null as any;
|
|
18
|
-
|
|
18
|
+
// FileMode is now a class, so we re-export it directly from fs
|
|
19
19
|
export const DirEntry = null as any;
|
|
20
20
|
|
|
21
21
|
// Getpagesize returns the underlying system's memory page size.
|
package/gs/os/types_unix.gs.ts
CHANGED
|
@@ -54,7 +54,7 @@ class fileStat {
|
|
|
54
54
|
this._fields = {
|
|
55
55
|
name: $.varRef(init?.name ?? ""),
|
|
56
56
|
size: $.varRef(init?.size ?? 0),
|
|
57
|
-
mode: $.varRef(init?.mode ?? 0),
|
|
57
|
+
mode: $.varRef(init?.mode ?? new fs.FileMode(0)),
|
|
58
58
|
modTime: $.varRef(init?.modTime?.clone() ?? time.Now()),
|
|
59
59
|
sys: $.varRef(init?.sys?.clone() ?? new syscall.Stat_t())
|
|
60
60
|
}
|
|
@@ -79,7 +79,7 @@ class fileStat {
|
|
|
79
79
|
|
|
80
80
|
public IsDir(): boolean {
|
|
81
81
|
const fileStat = this
|
|
82
|
-
return (fileStat!.Mode() & fs.ModeDir) !== 0
|
|
82
|
+
return (fileStat!.Mode().valueOf() & fs.ModeDir.valueOf()) !== 0
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
public Size(): number {
|
|
@@ -203,8 +203,8 @@ describe('path/filepath - Path manipulation functions', () => {
|
|
|
203
203
|
|
|
204
204
|
describe('Constants', () => {
|
|
205
205
|
it('should have correct separator constants', () => {
|
|
206
|
-
expect(Separator).toBe(
|
|
207
|
-
expect(ListSeparator).toBe(
|
|
206
|
+
expect(Separator).toBe(47)
|
|
207
|
+
expect(ListSeparator).toBe(58)
|
|
208
208
|
})
|
|
209
209
|
})
|
|
210
210
|
})
|
package/gs/path/filepath/path.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Package filepath implements utility routines for manipulating filename paths
|
|
2
2
|
// in a way compatible with the target operating system-defined file paths.
|
|
3
|
-
import * as $ from
|
|
3
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
4
4
|
|
|
5
5
|
// Path separator constants
|
|
6
6
|
export const Separator = $.stringToRune('/')
|
|
@@ -272,10 +272,7 @@ export function Abs(path: string): [string, $.GoError] {
|
|
|
272
272
|
return ['/' + Clean(path), null]
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
export function Rel(
|
|
276
|
-
basepath: string,
|
|
277
|
-
targpath: string,
|
|
278
|
-
): [string, $.GoError] {
|
|
275
|
+
export function Rel(basepath: string, targpath: string): [string, $.GoError] {
|
|
279
276
|
// Simplified implementation - in reality this is much more complex
|
|
280
277
|
const base = Clean(basepath)
|
|
281
278
|
const targ = Clean(targpath)
|
|
@@ -307,11 +304,7 @@ export function Glob(_pattern: string): [string[], $.GoError] {
|
|
|
307
304
|
// prefix; that is, if Walk is called with "dir" and finds a file "a"
|
|
308
305
|
// in that directory, the walk function will be called with argument
|
|
309
306
|
// "dir/a". The info argument is the fs.FileInfo for the named path.
|
|
310
|
-
export type WalkFunc = (
|
|
311
|
-
path: string,
|
|
312
|
-
info: any,
|
|
313
|
-
err: $.GoError,
|
|
314
|
-
) => $.GoError
|
|
307
|
+
export type WalkFunc = (path: string, info: any, err: $.GoError) => $.GoError
|
|
315
308
|
|
|
316
309
|
export function Walk(root: string, walkFn: WalkFunc): $.GoError {
|
|
317
310
|
// No filesystem support, just call the function with the root
|
package/gs/reflect/value.ts
CHANGED
|
@@ -210,11 +210,19 @@ export function MakeChan(typ: Type, buffer: number): Value {
|
|
|
210
210
|
export function Select(cases: $.Slice<SelectCase>): [number, Value, boolean] {
|
|
211
211
|
// Extract the backing array from the GoScript slice
|
|
212
212
|
let selectCases: SelectCase[] = []
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
if (cases && typeof cases === 'object') {
|
|
215
215
|
if ('__meta__' in cases) {
|
|
216
216
|
// This is a GoScript SliceProxy, extract the backing array
|
|
217
|
-
const meta = (
|
|
217
|
+
const meta = (
|
|
218
|
+
cases as {
|
|
219
|
+
__meta__?: {
|
|
220
|
+
backing?: SelectCase[]
|
|
221
|
+
offset?: number
|
|
222
|
+
length?: number
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
).__meta__
|
|
218
226
|
if (meta && meta.backing) {
|
|
219
227
|
const offset = meta.offset ?? 0
|
|
220
228
|
const length = meta.length ?? meta.backing.length
|
package/gs/time/time.ts
CHANGED
|
@@ -34,7 +34,9 @@ export class Time {
|
|
|
34
34
|
|
|
35
35
|
// UnixMicro returns t as a Unix time, the number of microseconds elapsed since January 1, 1970 UTC
|
|
36
36
|
public UnixMicro(): number {
|
|
37
|
-
return
|
|
37
|
+
return (
|
|
38
|
+
Math.floor(this._date.getTime() * 1000) + Math.floor(this._nsec / 1000)
|
|
39
|
+
)
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
// UnixNano returns t as a Unix time, the number of nanoseconds elapsed since January 1, 1970 UTC
|
|
@@ -656,7 +658,15 @@ export enum Weekday {
|
|
|
656
658
|
|
|
657
659
|
// WeekdayString returns the string representation of a Weekday
|
|
658
660
|
export function WeekdayString(w: Weekday): string {
|
|
659
|
-
const names = [
|
|
661
|
+
const names = [
|
|
662
|
+
'Sunday',
|
|
663
|
+
'Monday',
|
|
664
|
+
'Tuesday',
|
|
665
|
+
'Wednesday',
|
|
666
|
+
'Thursday',
|
|
667
|
+
'Friday',
|
|
668
|
+
'Saturday',
|
|
669
|
+
]
|
|
660
670
|
return names[w] || 'Unknown'
|
|
661
671
|
}
|
|
662
672
|
|
|
@@ -712,7 +722,7 @@ export class Timer {
|
|
|
712
722
|
this._duration = duration
|
|
713
723
|
this._callback = callback
|
|
714
724
|
const ms = duration.valueOf() / 1000000 // Convert nanoseconds to milliseconds
|
|
715
|
-
|
|
725
|
+
|
|
716
726
|
if (callback) {
|
|
717
727
|
this._timeout = setTimeout(callback, ms)
|
|
718
728
|
} else {
|
|
@@ -775,10 +785,10 @@ export class Ticker {
|
|
|
775
785
|
}
|
|
776
786
|
|
|
777
787
|
// Channel returns an async iterator that yields time values
|
|
778
|
-
public async*
|
|
788
|
+
public async *Channel(): AsyncIterableIterator<Time> {
|
|
779
789
|
const ms = this._duration.valueOf() / 1000000
|
|
780
790
|
while (!this._stopped) {
|
|
781
|
-
await new Promise(resolve => setTimeout(resolve, ms))
|
|
791
|
+
await new Promise((resolve) => setTimeout(resolve, ms))
|
|
782
792
|
if (!this._stopped) {
|
|
783
793
|
yield Now()
|
|
784
794
|
}
|
|
@@ -925,15 +935,15 @@ export function UnixNano(nsec: number): Time {
|
|
|
925
935
|
export function ParseDuration(s: string): Duration {
|
|
926
936
|
const regex = /^([+-]?)(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h)$/
|
|
927
937
|
const match = s.match(regex)
|
|
928
|
-
|
|
938
|
+
|
|
929
939
|
if (!match) {
|
|
930
940
|
throw new Error(`time: invalid duration "${s}"`)
|
|
931
941
|
}
|
|
932
|
-
|
|
942
|
+
|
|
933
943
|
const [, sign, valueStr, unit] = match
|
|
934
944
|
let value = parseFloat(valueStr)
|
|
935
945
|
if (sign === '-') value = -value
|
|
936
|
-
|
|
946
|
+
|
|
937
947
|
let nanoseconds: number
|
|
938
948
|
switch (unit) {
|
|
939
949
|
case 'ns':
|
|
@@ -958,7 +968,7 @@ export function ParseDuration(s: string): Duration {
|
|
|
958
968
|
default:
|
|
959
969
|
throw new Error(`time: unknown unit "${unit}" in duration "${s}"`)
|
|
960
970
|
}
|
|
961
|
-
|
|
971
|
+
|
|
962
972
|
return new Duration(Math.floor(nanoseconds))
|
|
963
973
|
}
|
|
964
974
|
|
|
@@ -968,31 +978,53 @@ export function Parse(layout: string, value: string): Time {
|
|
|
968
978
|
}
|
|
969
979
|
|
|
970
980
|
// ParseInLocation is like Parse but differs in two important ways
|
|
971
|
-
export function ParseInLocation(
|
|
981
|
+
export function ParseInLocation(
|
|
982
|
+
layout: string,
|
|
983
|
+
value: string,
|
|
984
|
+
loc: Location,
|
|
985
|
+
): Time {
|
|
972
986
|
// This is a simplified implementation
|
|
973
987
|
// A full implementation would need to parse according to the layout format
|
|
974
|
-
|
|
988
|
+
|
|
975
989
|
// Handle common layouts
|
|
976
990
|
if (layout === RFC3339 || layout === '2006-01-02T15:04:05Z07:00') {
|
|
977
991
|
const date = new globalThis.Date(value)
|
|
978
992
|
if (isNaN(date.getTime())) {
|
|
979
|
-
throw new ParseError(
|
|
993
|
+
throw new ParseError(
|
|
994
|
+
layout,
|
|
995
|
+
value,
|
|
996
|
+
'',
|
|
997
|
+
'',
|
|
998
|
+
`parsing time "${value}" as "${layout}": cannot parse`,
|
|
999
|
+
)
|
|
980
1000
|
}
|
|
981
1001
|
return new Time(date, 0, undefined, loc)
|
|
982
1002
|
}
|
|
983
|
-
|
|
1003
|
+
|
|
984
1004
|
if (layout === DateTime || layout === '2006-01-02 15:04:05') {
|
|
985
1005
|
const date = new globalThis.Date(value)
|
|
986
1006
|
if (isNaN(date.getTime())) {
|
|
987
|
-
throw new ParseError(
|
|
1007
|
+
throw new ParseError(
|
|
1008
|
+
layout,
|
|
1009
|
+
value,
|
|
1010
|
+
'',
|
|
1011
|
+
'',
|
|
1012
|
+
`parsing time "${value}" as "${layout}": cannot parse`,
|
|
1013
|
+
)
|
|
988
1014
|
}
|
|
989
1015
|
return new Time(date, 0, undefined, loc)
|
|
990
1016
|
}
|
|
991
|
-
|
|
1017
|
+
|
|
992
1018
|
// Fallback to standard Date parsing
|
|
993
1019
|
const date = new globalThis.Date(value)
|
|
994
1020
|
if (isNaN(date.getTime())) {
|
|
995
|
-
throw new ParseError(
|
|
1021
|
+
throw new ParseError(
|
|
1022
|
+
layout,
|
|
1023
|
+
value,
|
|
1024
|
+
'',
|
|
1025
|
+
'',
|
|
1026
|
+
`parsing time "${value}" as "${layout}": cannot parse`,
|
|
1027
|
+
)
|
|
996
1028
|
}
|
|
997
1029
|
return new Time(date, 0, undefined, loc)
|
|
998
1030
|
}
|
|
@@ -1039,7 +1071,10 @@ export function LoadLocation(name: string): Location {
|
|
|
1039
1071
|
|
|
1040
1072
|
// LoadLocationFromTZData returns a Location with the given name
|
|
1041
1073
|
// This is a simplified implementation
|
|
1042
|
-
export function LoadLocationFromTZData(
|
|
1074
|
+
export function LoadLocationFromTZData(
|
|
1075
|
+
name: string,
|
|
1076
|
+
_data: Uint8Array,
|
|
1077
|
+
): Location {
|
|
1043
1078
|
// In a real implementation, this would parse the timezone data
|
|
1044
1079
|
return new Location(name)
|
|
1045
1080
|
}
|