goscript 0.0.28 → 0.0.30

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 (74) hide show
  1. package/compiler/analysis.go +41 -2
  2. package/compiler/compiler.go +8 -1
  3. package/compiler/expr-call.go +87 -15
  4. package/compiler/expr-selector.go +100 -0
  5. package/compiler/spec-value.go +79 -8
  6. package/compiler/spec.go +236 -0
  7. package/dist/gs/builtin/builtin.d.ts +1 -0
  8. package/dist/gs/builtin/builtin.js +11 -0
  9. package/dist/gs/builtin/builtin.js.map +1 -1
  10. package/dist/gs/internal/oserror/errors.d.ts +6 -0
  11. package/dist/gs/internal/oserror/errors.js +7 -0
  12. package/dist/gs/internal/oserror/errors.js.map +1 -0
  13. package/dist/gs/internal/oserror/index.d.ts +1 -0
  14. package/dist/gs/internal/oserror/index.js +2 -0
  15. package/dist/gs/internal/oserror/index.js.map +1 -0
  16. package/dist/gs/io/fs/format.d.ts +3 -0
  17. package/dist/gs/io/fs/format.js +56 -0
  18. package/dist/gs/io/fs/format.js.map +1 -0
  19. package/dist/gs/io/fs/fs.d.ts +79 -0
  20. package/dist/gs/io/fs/fs.js +200 -0
  21. package/dist/gs/io/fs/fs.js.map +1 -0
  22. package/dist/gs/io/fs/glob.d.ts +10 -0
  23. package/dist/gs/io/fs/glob.js +141 -0
  24. package/dist/gs/io/fs/glob.js.map +1 -0
  25. package/dist/gs/io/fs/index.d.ts +8 -0
  26. package/dist/gs/io/fs/index.js +9 -0
  27. package/dist/gs/io/fs/index.js.map +1 -0
  28. package/dist/gs/io/fs/readdir.d.ts +7 -0
  29. package/dist/gs/io/fs/readdir.js +152 -0
  30. package/dist/gs/io/fs/readdir.js.map +1 -0
  31. package/dist/gs/io/fs/readfile.d.ts +6 -0
  32. package/dist/gs/io/fs/readfile.js +118 -0
  33. package/dist/gs/io/fs/readfile.js.map +1 -0
  34. package/dist/gs/io/fs/stat.d.ts +6 -0
  35. package/dist/gs/io/fs/stat.js +87 -0
  36. package/dist/gs/io/fs/stat.js.map +1 -0
  37. package/dist/gs/io/fs/sub.d.ts +6 -0
  38. package/dist/gs/io/fs/sub.js +172 -0
  39. package/dist/gs/io/fs/sub.js.map +1 -0
  40. package/dist/gs/io/fs/walk.d.ts +7 -0
  41. package/dist/gs/io/fs/walk.js +76 -0
  42. package/dist/gs/io/fs/walk.js.map +1 -0
  43. package/dist/gs/path/index.d.ts +2 -0
  44. package/dist/gs/path/index.js +3 -0
  45. package/dist/gs/path/index.js.map +1 -0
  46. package/dist/gs/path/match.d.ts +6 -0
  47. package/dist/gs/path/match.js +281 -0
  48. package/dist/gs/path/match.js.map +1 -0
  49. package/dist/gs/path/path.d.ts +7 -0
  50. package/dist/gs/path/path.js +256 -0
  51. package/dist/gs/path/path.js.map +1 -0
  52. package/dist/gs/time/time.d.ts +11 -2
  53. package/dist/gs/time/time.js +337 -12
  54. package/dist/gs/time/time.js.map +1 -1
  55. package/gs/builtin/builtin.ts +13 -0
  56. package/gs/internal/oserror/errors.ts +14 -0
  57. package/gs/internal/oserror/index.ts +1 -0
  58. package/gs/io/fs/format.ts +65 -0
  59. package/gs/io/fs/fs.ts +359 -0
  60. package/gs/io/fs/glob.ts +167 -0
  61. package/gs/io/fs/godoc.txt +35 -0
  62. package/gs/io/fs/index.ts +8 -0
  63. package/gs/io/fs/readdir.ts +126 -0
  64. package/gs/io/fs/readfile.ts +77 -0
  65. package/gs/io/fs/stat.ts +38 -0
  66. package/gs/io/fs/sub.ts +208 -0
  67. package/gs/io/fs/walk.ts +89 -0
  68. package/gs/path/index.ts +2 -0
  69. package/gs/path/match.ts +307 -0
  70. package/gs/path/path.ts +301 -0
  71. package/gs/strings/reader.test.ts +0 -1
  72. package/gs/time/time.ts +325 -12
  73. package/package.json +1 -1
  74. package/gs/time/godoc.md +0 -116
@@ -0,0 +1,77 @@
1
+ import * as $ from "@goscript/builtin/builtin.js";
2
+ import { FS } from "./fs.js";
3
+
4
+ import * as io from "@goscript/io/index.js"
5
+
6
+ export type ReadFileFS = null | {
7
+ // ReadFile reads the named file and returns its contents.
8
+ // A successful call returns a nil error, not io.EOF.
9
+ // (Because ReadFile reads the whole file, the expected EOF
10
+ // from the final Read is not treated as an error to be reported.)
11
+ //
12
+ // The caller is permitted to modify the returned byte slice.
13
+ // This method should return a copy of the underlying data.
14
+ ReadFile(name: string): [Uint8Array, $.GoError]
15
+ } & FS
16
+
17
+ $.registerInterfaceType(
18
+ 'ReadFileFS',
19
+ null, // Zero value for interface is null
20
+ [{ name: "ReadFile", args: [{ name: "name", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "number" } } }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }]
21
+ );
22
+
23
+ // ReadFile reads the named file from the file system fs and returns its contents.
24
+ // A successful call returns a nil error, not [io.EOF].
25
+ // (Because ReadFile reads the whole file, the expected EOF
26
+ // from the final Read is not treated as an error to be reported.)
27
+ //
28
+ // If fs implements [ReadFileFS], ReadFile calls fs.ReadFile.
29
+ // Otherwise ReadFile calls fs.Open and uses Read and Close
30
+ // on the returned [File].
31
+ export function ReadFile(fsys: FS, name: string): [Uint8Array, $.GoError] {
32
+ using __defer = new $.DisposableStack();
33
+ {
34
+ let { value: fsysTyped, ok: ok } = $.typeAssert<ReadFileFS>(fsys, 'ReadFileFS')
35
+ if (ok) {
36
+ return fsysTyped!.ReadFile(name)
37
+ }
38
+ }
39
+
40
+ let [file, err] = fsys!.Open(name)
41
+ if (err != null) {
42
+ return [new Uint8Array(0), err]
43
+ }
44
+ __defer.defer(() => {
45
+ file!.Close()
46
+ });
47
+
48
+ let size: number = 0
49
+ {
50
+ let [info, err] = file!.Stat()
51
+ if (err == null) {
52
+ let size64 = info!.Size()
53
+ if (((size64 as number) as number) == size64) {
54
+ size = (size64 as number)
55
+ }
56
+ }
57
+ }
58
+
59
+ let data = new Uint8Array(0)
60
+ for (; ; ) {
61
+ if ($.len(data) >= $.cap(data)) {
62
+ // Grow the array by creating a new larger one
63
+ let newData = new Uint8Array($.len(data) * 2 + 1)
64
+ newData.set(data)
65
+ data = newData
66
+ }
67
+ let [n, err] = file!.Read(data.subarray($.len(data), $.cap(data)))
68
+ data = data.subarray(0, $.len(data) + n)
69
+ if (err != null) {
70
+ if (err == io.EOF) {
71
+ err = null
72
+ }
73
+ return [data, err]
74
+ }
75
+ }
76
+ }
77
+
@@ -0,0 +1,38 @@
1
+ import * as $ from "@goscript/builtin/builtin.js";
2
+ import { FS, FileInfo } from "./fs.js";
3
+
4
+ export type StatFS = null | {
5
+ // Stat returns a FileInfo describing the file.
6
+ // If there is an error, it should be of type *PathError.
7
+ Stat(name: string): [FileInfo, $.GoError]
8
+ } & FS
9
+
10
+ $.registerInterfaceType(
11
+ 'StatFS',
12
+ null, // Zero value for interface is null
13
+ [{ name: "Stat", args: [{ name: "name", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: "FileInfo" }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }]
14
+ );
15
+
16
+ // Stat returns a [FileInfo] describing the named file from the file system.
17
+ //
18
+ // If fs implements [StatFS], Stat calls fs.Stat.
19
+ // Otherwise, Stat opens the [File] to stat it.
20
+ export function Stat(fsys: FS, name: string): [FileInfo, $.GoError] {
21
+ using __defer = new $.DisposableStack();
22
+ {
23
+ let { value: fsysTyped, ok: ok } = $.typeAssert<StatFS>(fsys, 'StatFS')
24
+ if (ok) {
25
+ return fsysTyped!.Stat(name)
26
+ }
27
+ }
28
+
29
+ let [file, err] = fsys!.Open(name)
30
+ if (err != null) {
31
+ return [null, err]
32
+ }
33
+ __defer.defer(() => {
34
+ file!.Close()
35
+ });
36
+ return file!.Stat()
37
+ }
38
+
@@ -0,0 +1,208 @@
1
+ import * as $ from "@goscript/builtin/builtin.js";
2
+ import { ValidPath, FS, PathError, ErrInvalid, File, DirEntry } from "./fs.js";
3
+ import { ReadDir } from "./readdir.js";
4
+ import { ReadFile } from "./readfile.js";
5
+ import { Glob } from "./glob.js";
6
+
7
+ import * as errors from "@goscript/errors/index.js"
8
+
9
+ import * as path from "@goscript/path/index.js"
10
+
11
+ export type SubFS = null | {
12
+ // Sub returns an FS corresponding to the subtree rooted at dir.
13
+ Sub(dir: string): [FS, $.GoError]
14
+ } & FS
15
+
16
+ $.registerInterfaceType(
17
+ 'SubFS',
18
+ null, // Zero value for interface is null
19
+ [{ name: "Sub", args: [{ name: "dir", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: "FS" }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }]
20
+ );
21
+
22
+ // Sub returns an [FS] corresponding to the subtree rooted at fsys's dir.
23
+ //
24
+ // If dir is ".", Sub returns fsys unchanged.
25
+ // Otherwise, if fs implements [SubFS], Sub returns fsys.Sub(dir).
26
+ // Otherwise, Sub returns a new [FS] implementation sub that,
27
+ // in effect, implements sub.Open(name) as fsys.Open(path.Join(dir, name)).
28
+ // The implementation also translates calls to ReadDir, ReadFile, and Glob appropriately.
29
+ //
30
+ // Note that Sub(os.DirFS("/"), "prefix") is equivalent to os.DirFS("/prefix")
31
+ // and that neither of them guarantees to avoid operating system
32
+ // accesses outside "/prefix", because the implementation of [os.DirFS]
33
+ // does not check for symbolic links inside "/prefix" that point to
34
+ // other directories. That is, [os.DirFS] is not a general substitute for a
35
+ // chroot-style security mechanism, and Sub does not change that fact.
36
+ export function Sub(fsys: FS, dir: string): [FS, $.GoError] {
37
+ if (!ValidPath(dir)) {
38
+ return [null, new PathError({Err: ErrInvalid, Op: "sub", Path: dir})]
39
+ }
40
+ if (dir == ".") {
41
+ return [fsys, null]
42
+ }
43
+ {
44
+ let { value: fsysTyped, ok: ok } = $.typeAssert<SubFS>(fsys, 'SubFS')
45
+ if (ok) {
46
+ return fsysTyped!.Sub(dir)
47
+ }
48
+ }
49
+ return [new subFS({}), null]
50
+ }
51
+
52
+ class subFS {
53
+ public get fsys(): FS {
54
+ return this._fields.fsys.value
55
+ }
56
+ public set fsys(value: FS) {
57
+ this._fields.fsys.value = value
58
+ }
59
+
60
+ public get dir(): string {
61
+ return this._fields.dir.value
62
+ }
63
+ public set dir(value: string) {
64
+ this._fields.dir.value = value
65
+ }
66
+
67
+ public _fields: {
68
+ fsys: $.VarRef<FS>;
69
+ dir: $.VarRef<string>;
70
+ }
71
+
72
+ constructor(init?: Partial<{dir?: string, fsys?: FS}>) {
73
+ this._fields = {
74
+ fsys: $.varRef(init?.fsys ?? null),
75
+ dir: $.varRef(init?.dir ?? "")
76
+ }
77
+ }
78
+
79
+ public clone(): subFS {
80
+ const cloned = new subFS()
81
+ cloned._fields = {
82
+ fsys: $.varRef(this._fields.fsys.value),
83
+ dir: $.varRef(this._fields.dir.value)
84
+ }
85
+ return cloned
86
+ }
87
+
88
+ // fullName maps name to the fully-qualified name dir/name.
89
+ public fullName(op: string, name: string): [string, $.GoError] {
90
+ const f = this
91
+ if (!ValidPath(name)) {
92
+ return ["", new PathError({Err: ErrInvalid, Op: op, Path: name})]
93
+ }
94
+ return [path.Join(f!.dir, name), null]
95
+ }
96
+
97
+ // shorten maps name, which should start with f.dir, back to the suffix after f.dir.
98
+ public shorten(name: string): [string, boolean] {
99
+ const f = this
100
+ if (name == f!.dir) {
101
+ return [".", true]
102
+ }
103
+ if ($.len(name) >= $.len(f!.dir) + 2 && $.indexString(name, $.len(f!.dir)) == 47 && $.sliceString(name, undefined, $.len(f!.dir)) == f!.dir) {
104
+ return [$.sliceString(name, $.len(f!.dir) + 1, undefined), true]
105
+ }
106
+ return ["", false]
107
+ }
108
+
109
+ // fixErr shortens any reported names in PathErrors by stripping f.dir.
110
+ public fixErr(err: $.GoError): $.GoError {
111
+ const f = this
112
+ {
113
+ let { value: e, ok: ok } = $.typeAssert<PathError | null>(err, {kind: $.TypeKind.Pointer, elemType: 'PathError'})
114
+ if (ok) {
115
+ {
116
+ let [short, ok] = f!.shorten(e!.Path)
117
+ if (ok) {
118
+ e!.Path = short
119
+ }
120
+ }
121
+ }
122
+ }
123
+ return err
124
+ }
125
+
126
+ public Open(name: string): [File, $.GoError] {
127
+ const f = this
128
+ let [full, err] = f!.fullName("open", name)
129
+ if (err != null) {
130
+ return [null, err]
131
+ }
132
+ let file: File
133
+ [file, err] = f!.fsys!.Open(full)
134
+ return [file, f!.fixErr(err)]
135
+ }
136
+
137
+ public ReadDir(name: string): [$.Slice<DirEntry>, $.GoError] {
138
+ const f = this
139
+ let [full, err] = f!.fullName("read", name)
140
+ if (err != null) {
141
+ return [null, err]
142
+ }
143
+ let dir: $.Slice<DirEntry>
144
+ [dir, err] = ReadDir(f!.fsys, full)
145
+ return [dir, f!.fixErr(err)]
146
+ }
147
+
148
+ public ReadFile(name: string): [Uint8Array, $.GoError] {
149
+ const f = this
150
+ let [full, err] = f!.fullName("read", name)
151
+ if (err != null) {
152
+ return [new Uint8Array(0), err]
153
+ }
154
+ let data: Uint8Array
155
+ [data, err] = ReadFile(f!.fsys, full)
156
+ return [data, f!.fixErr(err)]
157
+ }
158
+
159
+ public Glob(pattern: string): [$.Slice<string>, $.GoError] {
160
+ const f = this
161
+ {
162
+ let [, err] = path.Match(pattern, "")
163
+ if (err != null) {
164
+ return [null, err]
165
+ }
166
+ }
167
+ if (pattern == ".") {
168
+ return [$.arrayToSlice<string>(["."]), null]
169
+ }
170
+ let full = f!.dir + "/" + pattern
171
+ let [list, err] = Glob(f!.fsys, full)
172
+ for (let i = 0; i < $.len(list); i++) {
173
+ const name = list![i]
174
+ {
175
+ let [shortName, ok] = f!.shorten(name)
176
+
177
+ // can't use fmt in this package
178
+ if (!ok) {
179
+ return [null, errors.New("invalid result from inner fsys Glob: " + shortName + " not in " + f!.dir)]
180
+ }
181
+ list![i] = shortName
182
+ }
183
+ }
184
+ return [list, f!.fixErr(err)]
185
+ }
186
+
187
+ public Sub(dir: string): [FS, $.GoError] {
188
+ const f = this
189
+ if (dir == ".") {
190
+ return [f, null]
191
+ }
192
+ let [full, err] = f!.fullName("sub", dir)
193
+ if (err != null) {
194
+ return [null, err]
195
+ }
196
+ return [new subFS({}), null]
197
+ }
198
+
199
+ // Register this type with the runtime type system
200
+ static __typeInfo = $.registerStructType(
201
+ 'subFS',
202
+ new subFS(),
203
+ [{ name: "fullName", args: [{ name: "op", type: { kind: $.TypeKind.Basic, name: "string" } }, { name: "name", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "string" } }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }, { name: "shorten", args: [{ name: "name", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "string" } }, { type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "fixErr", args: [{ name: "err", type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }], returns: [{ type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }, { name: "Open", args: [{ name: "name", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: "File" }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }, { name: "ReadDir", args: [{ name: "name", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: { kind: $.TypeKind.Slice, elemType: "DirEntry" } }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }, { name: "ReadFile", args: [{ name: "name", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "number" } } }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }, { name: "Glob", args: [{ name: "pattern", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: { kind: $.TypeKind.Slice, elemType: { kind: $.TypeKind.Basic, name: "string" } } }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }, { name: "Sub", args: [{ name: "dir", type: { kind: $.TypeKind.Basic, name: "string" } }], returns: [{ type: "FS" }, { type: { kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] } }] }],
204
+ subFS,
205
+ {"fsys": "FS", "dir": { kind: $.TypeKind.Basic, name: "string" }}
206
+ );
207
+ }
208
+
@@ -0,0 +1,89 @@
1
+ import * as $ from "@goscript/builtin/builtin.js";
2
+ import { FileInfoToDirEntry, ReadDir } from "./readdir.js";
3
+ import { Stat } from "./stat.js";
4
+ import { FS, DirEntry } from "./fs.js";
5
+
6
+ import * as errors from "@goscript/errors/index.js"
7
+
8
+ import * as path from "@goscript/path/index.js"
9
+
10
+ export let SkipDir: $.GoError = errors.New("skip this directory")
11
+
12
+ export let SkipAll: $.GoError = errors.New("skip everything and stop the walk")
13
+
14
+ export type WalkDirFunc = ((path: string, d: DirEntry, err: $.GoError) => $.GoError) | null;
15
+
16
+ // walkDir recursively descends path, calling walkDirFn.
17
+ export function walkDir(fsys: FS, name: string, d: DirEntry, walkDirFn: WalkDirFunc): $.GoError {
18
+
19
+ // Successfully skipped directory.
20
+ {
21
+ let err = walkDirFn!(name, d, null)
22
+ if (err != null || !d!.IsDir()) {
23
+
24
+ // Successfully skipped directory.
25
+ if (err == SkipDir && d!.IsDir()) {
26
+ // Successfully skipped directory.
27
+ err = null
28
+ }
29
+ return err
30
+ }
31
+ }
32
+
33
+ let [dirs, err] = ReadDir(fsys, name)
34
+
35
+ // Second call, to report ReadDir error.
36
+ if (err != null) {
37
+ // Second call, to report ReadDir error.
38
+ err = walkDirFn!(name, d, err)
39
+ if (err != null) {
40
+ if (err == SkipDir && d!.IsDir()) {
41
+ err = null
42
+ }
43
+ return err
44
+ }
45
+ }
46
+
47
+ for (let _i = 0; _i < $.len(dirs); _i++) {
48
+ const d1 = dirs![_i]
49
+ {
50
+ let name1 = path.Join(name, d1!.Name())
51
+ {
52
+ let err = walkDir(fsys, name1, d1, walkDirFn)
53
+ if (err != null) {
54
+ if (err == SkipDir) {
55
+ break
56
+ }
57
+ return err
58
+ }
59
+ }
60
+ }
61
+ }
62
+ return null
63
+ }
64
+
65
+ // WalkDir walks the file tree rooted at root, calling fn for each file or
66
+ // directory in the tree, including root.
67
+ //
68
+ // All errors that arise visiting files and directories are filtered by fn:
69
+ // see the [fs.WalkDirFunc] documentation for details.
70
+ //
71
+ // The files are walked in lexical order, which makes the output deterministic
72
+ // but requires WalkDir to read an entire directory into memory before proceeding
73
+ // to walk that directory.
74
+ //
75
+ // WalkDir does not follow symbolic links found in directories,
76
+ // but if root itself is a symbolic link, its target will be walked.
77
+ export function WalkDir(fsys: FS, root: string, fn: WalkDirFunc): $.GoError {
78
+ let [info, err] = Stat(fsys, root)
79
+ if (err != null) {
80
+ err = fn!(root, null, err)
81
+ } else {
82
+ err = walkDir(fsys, root, FileInfoToDirEntry(info), fn)
83
+ }
84
+ if (err == SkipDir || err == SkipAll) {
85
+ return null
86
+ }
87
+ return err
88
+ }
89
+
@@ -0,0 +1,2 @@
1
+ export { ErrBadPattern, Match } from "./match.js"
2
+ export { Base, Clean, Dir, Ext, IsAbs, Join, Split } from "./path.js"