gofront 1.6.0 → 1.6.1

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 (68) hide show
  1. package/package.json +1 -1
  2. package/src/backend/js/expressions.js +238 -109
  3. package/src/backend/js/index.js +38 -1
  4. package/src/backend/js/runtime.js +953 -53
  5. package/src/backend/js/statements.js +55 -67
  6. package/src/backend/js/stdlib/base64.js +12 -0
  7. package/src/backend/js/stdlib/binary.js +102 -0
  8. package/src/backend/js/stdlib/bits.js +15 -1
  9. package/src/backend/js/stdlib/builder.js +28 -9
  10. package/src/backend/js/stdlib/bytes.js +75 -18
  11. package/src/backend/js/stdlib/errors.js +20 -1
  12. package/src/backend/js/stdlib/fmt.js +70 -13
  13. package/src/backend/js/stdlib/hex.js +17 -0
  14. package/src/backend/js/stdlib/html.js +1 -1
  15. package/src/backend/js/stdlib/index.js +16 -0
  16. package/src/backend/js/stdlib/io.js +105 -3
  17. package/src/backend/js/stdlib/math.js +13 -1
  18. package/src/backend/js/stdlib/path.js +18 -4
  19. package/src/backend/js/stdlib/rand.js +10 -5
  20. package/src/backend/js/stdlib/sha256.js +12 -0
  21. package/src/backend/js/stdlib/slices.js +52 -26
  22. package/src/backend/js/stdlib/strconv.js +21 -5
  23. package/src/backend/js/stdlib/strings.js +148 -15
  24. package/src/backend/js/stdlib/sync.js +13 -0
  25. package/src/backend/js/stdlib/time.js +90 -19
  26. package/src/backend/js/stdlib/unicode.js +2 -2
  27. package/src/backend/wasm/boundary.js +1207 -41
  28. package/src/backend/wasm/const-fold.js +205 -0
  29. package/src/backend/wasm/emit-builtins.js +203 -76
  30. package/src/backend/wasm/emit-exprs.js +464 -276
  31. package/src/backend/wasm/emit-maps.js +144 -8
  32. package/src/backend/wasm/emit-stdlib.js +12 -3005
  33. package/src/backend/wasm/emit-stmts.js +264 -270
  34. package/src/backend/wasm/emit.js +115 -87
  35. package/src/backend/wasm/encode.js +55 -29
  36. package/src/backend/wasm/index.js +1001 -32
  37. package/src/backend/wasm/optimize.js +13 -4
  38. package/src/backend/wasm/stdlib/bytes.js +5039 -0
  39. package/src/backend/wasm/stdlib/core.js +8903 -0
  40. package/src/backend/wasm/stdlib/index.js +40 -0
  41. package/src/backend/wasm/stdlib/io.js +2161 -0
  42. package/src/backend/wasm/stdlib/packages.js +2400 -0
  43. package/src/backend/wasm/stdlib/pure.js +720 -0
  44. package/src/backend/wasm/stdlib/time.js +1200 -0
  45. package/src/backend/wasm/types.js +153 -1
  46. package/src/cli-core.js +1 -1
  47. package/src/compiler.js +18 -4
  48. package/src/dts-parser.js +79 -126
  49. package/src/index.js +2 -6
  50. package/src/lexer.js +80 -29
  51. package/src/lower/boxing.js +1 -2
  52. package/src/lower/captures.js +2 -6
  53. package/src/lower/ownership.js +30 -9
  54. package/src/minifier.js +20 -68
  55. package/src/parser/declarations.js +3 -6
  56. package/src/parser/expressions.js +3 -8
  57. package/src/parser/index.js +18 -3
  58. package/src/parser/statements.js +25 -38
  59. package/src/parser/types.js +1 -2
  60. package/src/resolver.js +2 -27
  61. package/src/templ-lexer.js +29 -63
  62. package/src/templ-parser.js +22 -45
  63. package/src/typechecker/assignability.js +81 -13
  64. package/src/typechecker/expressions.js +102 -2
  65. package/src/typechecker/resolve.js +36 -6
  66. package/src/typechecker/stdlib/core.js +280 -89
  67. package/src/typechecker/stdlib/extended.js +453 -1
  68. package/src/typechecker/types.js +344 -6
@@ -5,7 +5,7 @@
5
5
  // Parsers return [value, msg|null] from the shared __strconv_* helpers
6
6
  // (runtime.js); the message becomes a Go error value.
7
7
  const parsed = (call, toValue = "r[0]") =>
8
- `((r) => [${toValue}, r[1] === null ? null : __error(r[1])])(${call})`;
8
+ `((r) => [${toValue}, r[1] === null ? null : __error(r[1], r[1].includes("invalid syntax") ? __strconv_err_syntax : r[1].includes("value out of range") ? __strconv_err_range : null)])(${call})`;
9
9
 
10
10
  const STRCONV_DISPATCH = {
11
11
  Itoa: (a) => `String(${a[0]})`,
@@ -25,17 +25,28 @@ const STRCONV_DISPATCH = {
25
25
  ParseBool: (a) => parsed(`__strconv_parse_bool(${a[0]})`),
26
26
  Quote: (a) => `JSON.stringify(${a[0]})`,
27
27
  Unquote: (a) =>
28
- `((s) => { try { const v = JSON.parse(s); return [v, null]; } catch(e) { return ["", __error("invalid syntax")]; } })(${a[0]})`,
28
+ `((s) => { if (typeof s === "string" && s.startsWith("\`") && s.endsWith("\`") && s.length >= 2) { if (s.slice(1, -1).includes("\`")) return ["", __strconv_err_syntax]; return [s.slice(1, -1), null]; } try { const v = JSON.parse(s); if (typeof v !== "string") throw 0; return [v, null]; } catch(e) { return ["", __strconv_err_syntax]; } })(${a[0]})`,
29
29
  AppendInt: (a) =>
30
- `[...(${a[0]}), ...new TextEncoder().encode((${a[1]}).toString(${a[2]}))]`,
30
+ `((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, (${a[1]}).toString(${a[2]}))`,
31
+ AppendUint: (a) =>
32
+ `((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, (BigInt.asUintN(64, BigInt(${a[1]}))).toString(${a[2]}))`,
33
+ AppendBool: (a) =>
34
+ `((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, String(${a[1]}))`,
31
35
  AppendFloat: (a) =>
32
- `[...(${a[0]}), ...new TextEncoder().encode(${a[1]}.toFixed(${a[3]} < 0 ? 6 : ${a[3]}))]`,
36
+ `((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, __strconv_format_float(${a[1]}, typeof (${a[2]}) === "string" ? (${a[2]}).charCodeAt(0) : (${a[2]}), ${a[3]}))`,
37
+ FormatUint: (a) => `(BigInt.asUintN(64, BigInt(${a[0]}))).toString(${a[1]})`,
38
+ ParseUint: (a) =>
39
+ parsed(
40
+ `__strconv_parse_uint(${a[0]}, ${a[1]}, ${a[2] ?? 64})`,
41
+ "Number(r[0])",
42
+ ),
33
43
  };
34
44
 
35
45
  const USES_ERROR = new Set([
36
46
  "Atoi",
37
47
  "ParseFloat",
38
48
  "ParseInt",
49
+ "ParseUint",
39
50
  "ParseBool",
40
51
  "Unquote",
41
52
  ]);
@@ -43,15 +54,20 @@ const USES_STRCONV = new Set([
43
54
  "Atoi",
44
55
  "ParseFloat",
45
56
  "ParseInt",
57
+ "ParseUint",
46
58
  "ParseBool",
47
59
  "FormatFloat",
60
+ "AppendFloat",
48
61
  ]);
49
62
 
50
63
  /** @type {ThisType<CodeGen>} */
51
64
  export const strconvMethods = {
52
65
  _genStrconv(fn, a) {
53
66
  const gen = STRCONV_DISPATCH[fn];
54
- if (gen && USES_ERROR.has(fn)) this.useHelper("error");
67
+ if (gen && USES_ERROR.has(fn)) {
68
+ this.useHelper("error");
69
+ this.useHelper("strconvError");
70
+ }
55
71
  if (gen && USES_STRCONV.has(fn)) this.useHelper("strconv");
56
72
  return gen ? gen(a()) : undefined;
57
73
  },
@@ -27,27 +27,81 @@ const STRINGS_DISPATCH = {
27
27
  : `((str, o, nw, cnt) => { if (cnt < 0) return str.replaceAll(o, nw); let r = ""; let i = 0; for (; cnt > 0; cnt--) { const j = str.indexOf(o, i); if (j < 0) break; r += str.slice(i, j) + nw; i = j + o.length; if (o.length === 0) { if (i >= str.length) break; r += str[i]; i++; } } return r + str.slice(i); })(${s}, ${s2}, ${s3}, ${n})`,
28
28
  ReplaceAll: ([s, s2, s3]) => `${s}.replaceAll(${s2}, ${s3})`,
29
29
  Trim: ([s, s2]) =>
30
- `${s}.replace(new RegExp(\`^[\${${s2}}]+|[\${${s2}}]+$\`, "g"), "")`,
30
+ `((str, cut) => { const cs = new Set(cut); let i = 0, j = str.length; while (i < j && cs.has(str[i])) i++; while (j > i && cs.has(str[j - 1])) j--; return str.slice(i, j); })(${s}, ${s2})`,
31
31
  TrimPrefix: ([s, s2]) =>
32
32
  `((s, pre) => s.startsWith(pre) ? s.slice(pre.length) : s)(${s}, ${s2})`,
33
33
  TrimSuffix: ([s, s2]) =>
34
34
  `((s, suf) => !suf.length || !s.endsWith(suf) ? s : s.slice(0, -suf.length))(${s}, ${s2})`,
35
- TrimLeft: ([s, s2]) => `${s}.replace(new RegExp(\`^[\${${s2}}]+\`), "")`,
36
- TrimRight: ([s, s2]) => `${s}.replace(new RegExp(\`[\${${s2}}]+$\`), "")`,
35
+ TrimLeft: ([s, s2]) =>
36
+ `((str, cut) => { const cs = new Set(cut); let i = 0; while (i < str.length && cs.has(str[i])) i++; return str.slice(i); })(${s}, ${s2})`,
37
+ TrimRight: ([s, s2]) =>
38
+ `((str, cut) => { const cs = new Set(cut); let j = str.length; while (j > 0 && cs.has(str[j - 1])) j--; return str.slice(0, j); })(${s}, ${s2})`,
37
39
  EqualFold: ([s, s2]) => `${s}.toLowerCase() === ${s2}.toLowerCase()`,
38
40
  Fields: ([s]) => `(${s}).trim() === '' ? [] : (${s}).trim().split(/\\s+/)`,
41
+ FieldsFunc: ([s, f]) =>
42
+ `((s, fn) => { const res = []; const runes = Array.from(s ?? ""); let cur = ""; for (const ch of runes) { const cp = ch.codePointAt(0); if (fn(cp)) { if (cur.length > 0) { res.push(cur); cur = ""; } } else { cur += ch; } } if (cur.length > 0) res.push(cur); return res; })(${s}, ${f})`,
39
43
  Cut: ([s, s2]) =>
40
44
  `((s, sep) => { const i = s.indexOf(sep); return i < 0 ? [s, "", false] : [s.slice(0, i), s.slice(i + sep.length), true]; })(${s}, ${s2})`,
41
45
  CutPrefix: ([s, s2]) =>
42
- `(${s}).startsWith(${s2}) ? [(${s}).slice((${s2}).length), true] : [${s}, false]`,
46
+ `((str, pre) => str.startsWith(pre) ? [str.slice(pre.length), true] : [str, false])(${s}, ${s2})`,
43
47
  CutSuffix: ([s, s2]) =>
44
- `(${s}).endsWith(${s2}) ? [(${s}).slice(0, -(${s2}).length), true] : [${s}, false]`,
48
+ `((str, suf) => { if (suf === "") return [str, true]; return str.endsWith(suf) ? [str.slice(0, -suf.length), true] : [str, false]; })(${s}, ${s2})`,
45
49
  SplitN: ([s, s2, s3]) =>
46
- `((s, sep, n) => { if (n === 0) return []; if (n < 0) return s.split(sep); const r = []; let cur = s; for (let i = 1; i < n && cur.length; i++) { const j = cur.indexOf(sep); if (j < 0) break; r.push(cur.slice(0, j)); cur = cur.slice(j + sep.length); } r.push(cur); return r; })(${s}, ${s2}, ${s3})`,
50
+ `((s, sep, n) => {
51
+ if (n === 0) return null;
52
+ if (n < 0) return sep === "" ? [...s] : s.split(sep);
53
+ if (sep === "") {
54
+ const chars = [...s];
55
+ if (chars.length <= n) return chars;
56
+ const r = chars.slice(0, n - 1);
57
+ r.push(chars.slice(n - 1).join(""));
58
+ return r;
59
+ }
60
+ const r = [];
61
+ let cur = s;
62
+ for (let i = 1; i < n && cur.length; i++) {
63
+ const j = cur.indexOf(sep);
64
+ if (j < 0) break;
65
+ r.push(cur.slice(0, j));
66
+ cur = cur.slice(j + sep.length);
67
+ }
68
+ r.push(cur);
69
+ return r;
70
+ })(${s}, ${s2}, ${s3})`,
47
71
  SplitAfter: ([s, s2]) =>
48
- `((s, sep) => { if (sep === "") return [...s]; const r = []; let cur = s; while (cur.length) { const j = cur.indexOf(sep); if (j < 0) { r.push(cur); break; } r.push(cur.slice(0, j + sep.length)); cur = cur.slice(j + sep.length); } return r; })(${s}, ${s2})`,
72
+ `((s, sep) => {
73
+ if (sep === "") return [...s];
74
+ const r = [];
75
+ let cur = s;
76
+ while (true) {
77
+ const j = cur.indexOf(sep);
78
+ if (j < 0) { r.push(cur); break; }
79
+ r.push(cur.slice(0, j + sep.length));
80
+ cur = cur.slice(j + sep.length);
81
+ }
82
+ return r;
83
+ })(${s}, ${s2})`,
49
84
  SplitAfterN: ([s, s2, s3]) =>
50
- `((s, sep, n) => { if (n === 0) return []; if (n < 0 || sep === "") return ((s, sep) => { if (sep === "") return [...s]; const r = []; let cur = s; while (cur.length) { const j = cur.indexOf(sep); if (j < 0) { r.push(cur); break; } r.push(cur.slice(0, j + sep.length)); cur = cur.slice(j + sep.length); } return r; })(s, sep); const r = []; let cur = s; for (let i = 1; i < n && cur.length; i++) { const j = cur.indexOf(sep); if (j < 0) break; r.push(cur.slice(0, j + sep.length)); cur = cur.slice(j + sep.length); } r.push(cur); return r; })(${s}, ${s2}, ${s3})`,
85
+ `((s, sep, n) => {
86
+ if (n === 0) return null;
87
+ if (sep === "") {
88
+ const chars = [...s];
89
+ if (n < 0 || chars.length <= n) return chars;
90
+ const r = chars.slice(0, n - 1);
91
+ r.push(chars.slice(n - 1).join(""));
92
+ return r;
93
+ }
94
+ const r = [];
95
+ let cur = s;
96
+ for (let i = 1; (n < 0 || i < n) && cur.length; i++) {
97
+ const j = cur.indexOf(sep);
98
+ if (j < 0) break;
99
+ r.push(cur.slice(0, j + sep.length));
100
+ cur = cur.slice(j + sep.length);
101
+ }
102
+ r.push(cur);
103
+ return r;
104
+ })(${s}, ${s2}, ${s3})`,
51
105
  IndexAny: ([s, s2]) =>
52
106
  `((s, chars) => { let m = -1; for (const c of chars) { const i = s.indexOf(c); if (i >= 0 && (m < 0 || i < m)) m = i; } return m; })(${s}, ${s2})`,
53
107
  LastIndexAny: ([s, s2]) =>
@@ -58,27 +112,106 @@ const STRINGS_DISPATCH = {
58
112
  IndexByte: ([s, s2]) => `(${s}).indexOf(String.fromCharCode(${s2}))`,
59
113
  LastIndexByte: ([s, s2]) => `(${s}).lastIndexOf(String.fromCharCode(${s2}))`,
60
114
  Map: ([s, s2]) =>
61
- `[...(${s2})].map(c => String.fromCodePoint((${s})(c.codePointAt(0)))).join("")`,
115
+ `((f, s) => { let out = ""; for (const c of s) { const r = f(c.codePointAt(0)); if (r >= 0) out += String.fromCodePoint(r); } return out; })(${s}, ${s2})`,
62
116
  Title: ([s]) => `(${s}).replace(/\\b\\w/g, c => c.toUpperCase())`,
63
117
  TrimFunc: ([s, s2]) =>
64
- `((s, f) => { let l = 0, r = s.length; while (l < r && f(s.codePointAt(l))) l++; while (r > l && f(s.codePointAt(r - 1))) r--; return s.slice(l, r); })(${s}, ${s2})`,
118
+ `((s, f) => {
119
+ let l = 0, r = s.length;
120
+ while (l < r) {
121
+ const cp = s.codePointAt(l);
122
+ if (!f(cp)) break;
123
+ l += cp > 0xFFFF ? 2 : 1;
124
+ }
125
+ while (r > l) {
126
+ let cp, step;
127
+ if (r > 1 && s.charCodeAt(r - 1) >= 0xDC00 && s.charCodeAt(r - 1) <= 0xDFFF &&
128
+ s.charCodeAt(r - 2) >= 0xD800 && s.charCodeAt(r - 2) <= 0xDBFF) {
129
+ cp = s.codePointAt(r - 2);
130
+ step = 2;
131
+ } else {
132
+ cp = s.codePointAt(r - 1);
133
+ step = 1;
134
+ }
135
+ if (!f(cp)) break;
136
+ r -= step;
137
+ }
138
+ return s.slice(l, r);
139
+ })(${s}, ${s2})`,
65
140
  TrimLeftFunc: ([s, s2]) =>
66
- `((s, f) => { let l = 0; while (l < s.length && f(s.codePointAt(l))) l++; return s.slice(l); })(${s}, ${s2})`,
141
+ `((s, f) => {
142
+ let l = 0;
143
+ while (l < s.length) {
144
+ const cp = s.codePointAt(l);
145
+ if (!f(cp)) break;
146
+ l += cp > 0xFFFF ? 2 : 1;
147
+ }
148
+ return s.slice(l);
149
+ })(${s}, ${s2})`,
67
150
  TrimRightFunc: ([s, s2]) =>
68
- `((s, f) => { let r = s.length; while (r > 0 && f(s.codePointAt(r - 1))) r--; return s.slice(0, r); })(${s}, ${s2})`,
151
+ `((s, f) => {
152
+ let r = s.length;
153
+ while (r > 0) {
154
+ let cp, step;
155
+ if (r > 1 && s.charCodeAt(r - 1) >= 0xDC00 && s.charCodeAt(r - 1) <= 0xDFFF &&
156
+ s.charCodeAt(r - 2) >= 0xD800 && s.charCodeAt(r - 2) <= 0xDBFF) {
157
+ cp = s.codePointAt(r - 2);
158
+ step = 2;
159
+ } else {
160
+ cp = s.codePointAt(r - 1);
161
+ step = 1;
162
+ }
163
+ if (!f(cp)) break;
164
+ r -= step;
165
+ }
166
+ return s.slice(0, r);
167
+ })(${s}, ${s2})`,
69
168
  IndexFunc: ([s, s2]) =>
70
169
  `((s, f) => { for (let i = 0; i < s.length; i++) { const cp = s.codePointAt(i); if (f(cp)) return i; if (cp > 0xFFFF) i++; } return -1; })(${s}, ${s2})`,
71
170
  LastIndexFunc: ([s, s2]) =>
72
- `((s, f) => { for (let i = s.length - 1; i >= 0; i--) { const cp = s.codePointAt(i); if (f(cp)) return i; } return -1; })(${s}, ${s2})`,
171
+ `((s, f) => { for (let i = s.length - 1; i >= 0; i--) { let cp = s.codePointAt(i); if (i > 0 && s.charCodeAt(i) >= 0xDC00 && s.charCodeAt(i) <= 0xDFFF && s.charCodeAt(i - 1) >= 0xD800 && s.charCodeAt(i - 1) <= 0xDBFF) { cp = s.codePointAt(i - 1); i--; } if (f(cp)) return i; } return -1; })(${s}, ${s2})`,
73
172
  NewReader: ([s]) =>
74
- `{_src: ${s}, _pos: 0, Read(p) { const n = Math.min(p.length, this._src.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._src.charCodeAt(this._pos + i); this._pos += n; return [n, n === 0 ? "EOF" : null]; }, Len() { return this._src.length - this._pos; }, Reset(s) { this._src = s; this._pos = 0; }}`,
173
+ `((s) => ({ _bytes: new TextEncoder().encode(s), _pos: 0, Read(p) { if (this._pos >= this._bytes.length) return [0, __io_eof]; const n = Math.min(p.length, this._bytes.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._bytes[this._pos + i]; this._pos += n; return [n, null]; }, Len() { return Math.max(0, this._bytes.length - this._pos); }, Reset(s2) { this._bytes = new TextEncoder().encode(s2); this._pos = 0; } }))(${s})`,
75
174
  NewReplacer: (args) =>
76
- `((...pairs) => { const p = []; for (let i = 0; i < pairs.length; i += 2) p.push([pairs[i], pairs[i+1]]); return { _p: p, Replace(s) { let r = s; for (const [o, n] of this._p) r = r.split(o).join(n); return r; } }; })(${args.join(", ")})`,
175
+ `((...pairs) => {
176
+ const p = [];
177
+ for (let i = 0; i < pairs.length; i += 2) {
178
+ if (pairs[i] !== undefined && pairs[i+1] !== undefined) {
179
+ p.push([pairs[i], pairs[i+1]]);
180
+ }
181
+ }
182
+ return {
183
+ _p: p,
184
+ Replace(s) {
185
+ s = s ?? "";
186
+ if (!this._p || this._p.length === 0 || s === "") return s;
187
+ let out = "";
188
+ let i = 0;
189
+ while (i < s.length) {
190
+ let matched = false;
191
+ for (let k = 0; k < this._p.length; k++) {
192
+ const [oldStr, newStr] = this._p[k];
193
+ if (oldStr.length > 0 && s.startsWith(oldStr, i)) {
194
+ out += newStr;
195
+ i += oldStr.length;
196
+ matched = true;
197
+ break;
198
+ }
199
+ }
200
+ if (!matched) {
201
+ out += s[i];
202
+ i++;
203
+ }
204
+ }
205
+ return out;
206
+ }
207
+ };
208
+ })(${args.join(", ")})`,
77
209
  };
78
210
 
79
211
  /** @type {ThisType<CodeGen>} */
80
212
  export const stringsMethods = {
81
213
  _genStrings(fn, a) {
214
+ if (fn === "NewReader") this.useHelper("ioEOF");
82
215
  const args = a();
83
216
  const [s, s2] = args;
84
217
  if (STRINGS_M1[fn]) return `${s}.${STRINGS_M1[fn]}()`;
@@ -0,0 +1,13 @@
1
+ // src/backend/js/stdlib/sync.js
2
+ // CodeGen for Go sync package.
3
+
4
+ export const syncMethods = {
5
+ _genSync(fn) {
6
+ this.useHelper("sync");
7
+ if (fn === "Once") return "__sync_once()";
8
+ if (fn === "Mutex") return "__sync_mutex()";
9
+ if (fn === "RWMutex") return "__sync_rwmutex()";
10
+ if (fn === "WaitGroup") return "__sync_waitgroup()";
11
+ return undefined;
12
+ },
13
+ };
@@ -3,29 +3,77 @@
3
3
  /** @typedef {import('../index.js').CodeGen} CodeGen */
4
4
 
5
5
  const TIME_METHOD_DISPATCH = {
6
- Year: (r) => `${r}._d.getFullYear()`,
7
- Month: (r) => `${r}._d.getMonth() + 1`,
8
- Day: (r) => `${r}._d.getDate()`,
9
- Hour: (r) => `${r}._d.getHours()`,
10
- Minute: (r) => `${r}._d.getMinutes()`,
11
- Second: (r) => `${r}._d.getSeconds()`,
12
- Weekday: (r) => `${r}._d.getDay()`,
6
+ Year: (r) =>
7
+ `(${r}._offset === 0 ? ${r}._d.getUTCFullYear() : ${r}._d.getFullYear())`,
8
+ Month: (r) =>
9
+ `(${r}._offset === 0 ? ${r}._d.getUTCMonth() + 1 : ${r}._d.getMonth() + 1)`,
10
+ Day: (r) => `(${r}._offset === 0 ? ${r}._d.getUTCDate() : ${r}._d.getDate())`,
11
+ Hour: (r) =>
12
+ `(${r}._offset === 0 ? ${r}._d.getUTCHours() : ${r}._d.getHours())`,
13
+ Minute: (r) =>
14
+ `(${r}._offset === 0 ? ${r}._d.getUTCMinutes() : ${r}._d.getMinutes())`,
15
+ Second: (r) =>
16
+ `(${r}._offset === 0 ? ${r}._d.getUTCSeconds() : ${r}._d.getSeconds())`,
17
+ Weekday: (r) =>
18
+ `(${r}._offset === 0 ? ${r}._d.getUTCDay() : ${r}._d.getDay())`,
13
19
  Unix: (r) => `Math.floor(${r}._d.getTime() / 1000)`,
14
20
  UnixMilli: (r) => `${r}._d.getTime()`,
15
- Add: (r, a) => `{_d: new Date(${r}._d.getTime() + (${a[0]}))}`,
16
- Sub: (r, a) => `${r}._d.getTime() - (${a[0]})._d.getTime()`,
17
- Before: (r, a) => `${r}._d < (${a[0]})._d`,
18
- After: (r, a) => `${r}._d > (${a[0]})._d`,
19
- Equal: (r, a) => `${r}._d.getTime() === (${a[0]})._d.getTime()`,
21
+ Add: (r, a) =>
22
+ `{_d: new Date(${r}._d.getTime() + Math.round(Number(${a[0]}) / 1000000))}`,
23
+ Sub: (r, a) =>
24
+ `Math.round((${r}._d.getTime() - (${a[0]})._d.getTime()) * 1000000)`,
25
+ Before: (r, a) => `(${r}._d < (${a[0]})._d)`,
26
+ After: (r, a) => `(${r}._d > (${a[0]})._d)`,
27
+ Equal: (r, a) => `(${r}._d.getTime() === (${a[0]})._d.getTime())`,
28
+ IsZero: (r) =>
29
+ `(!${r} || !${r}._d || ${r}._isZero === true || ${r}._d.getTime() === -62135596800000 || (${r}._d.getUTCFullYear() <= 1 && ${r}._d.getUTCMonth() === 0 && ${r}._d.getUTCDate() === 1 && ${r}._d.getUTCHours() === 0 && ${r}._d.getUTCMinutes() === 0 && ${r}._d.getUTCSeconds() === 0 && ${r}._d.getUTCMilliseconds() === 0))`,
30
+ UnixNano: (r) => `(${r}?._d ? Math.round(${r}._d.getTime() * 1000000) : 0)`,
31
+ Nanosecond: (r) =>
32
+ `(${r}?._d ? (${r}._offset === 0 ? ${r}._d.getUTCMilliseconds() : ${r}._d.getMilliseconds()) * 1000000 : 0)`,
33
+ UTC: (r) => `({_d: ${r}?._d ?? new Date(0), _offset: 0})`,
34
+ Local: (r) => `({_d: ${r}?._d ?? new Date(0)})`,
35
+ AddDate: (r, a) =>
36
+ `({_d: new Date(${r}._d.getFullYear() + Number(${a[0]}), ${r}._d.getMonth() + Number(${a[1]}), ${r}._d.getDate() + Number(${a[2]}))})`,
37
+ Truncate: (r, a) =>
38
+ `({_d: new Date(Math.floor(${r}._d.getTime() / (Number(${a[0]}) / 1000000)) * (Number(${a[0]}) / 1000000))})`,
39
+ Round: (r, a) =>
40
+ `({_d: new Date(Math.round(${r}._d.getTime() / (Number(${a[0]}) / 1000000)) * (Number(${a[0]}) / 1000000))})`,
41
+ Date: (r) =>
42
+ `[${r}._offset === 0 ? ${r}._d.getUTCFullYear() : ${r}._d.getFullYear(), ${r}._offset === 0 ? ${r}._d.getUTCMonth() + 1 : ${r}._d.getMonth() + 1, ${r}._offset === 0 ? ${r}._d.getUTCDate() : ${r}._d.getDate()]`,
43
+ Clock: (r) =>
44
+ `[${r}._offset === 0 ? ${r}._d.getUTCHours() : ${r}._d.getHours(), ${r}._offset === 0 ? ${r}._d.getUTCMinutes() : ${r}._d.getMinutes(), ${r}._offset === 0 ? ${r}._d.getUTCSeconds() : ${r}._d.getSeconds()]`,
45
+ YearDay: (r) =>
46
+ `Math.floor((${r}._d - new Date(${r}._d.getFullYear(), 0, 0)) / 86400000)`,
47
+ Compare: (r, a) =>
48
+ `(${r}._d.getTime() < (${a[0]})._d.getTime() ? -1 : (${r}._d.getTime() > (${a[0]})._d.getTime() ? 1 : 0))`,
49
+ In: (r) => `${r}`,
50
+ Location: () => `null`,
51
+ Zone: (r) =>
52
+ `[${r}._offset === 0 ? "UTC" : "LOCAL", ${r}._offset === 0 ? 0 : -${r}._d.getTimezoneOffset() * 60]`,
53
+ };
54
+
55
+ const DURATION_METHOD_DISPATCH = {
56
+ Nanoseconds: (r) => `${r}`,
57
+ Microseconds: (r) => `Math.trunc(Number(${r}) / 1000)`,
58
+ Milliseconds: (r) => `Math.trunc(Number(${r}) / 1000000)`,
59
+ Seconds: (r) => `(Number(${r}) / 1000000000)`,
60
+ Minutes: (r) => `(Number(${r}) / 60000000000)`,
61
+ Hours: (r) => `(Number(${r}) / 3600000000000)`,
62
+ String: (r) => `__durationString(${r})`,
20
63
  };
21
64
 
22
65
  const TIME_DISPATCH = {
23
- Now: () => "{_d: new Date()}",
24
- Since: (a) => `(Date.now() - (${a[0]})._d.getTime())`,
66
+ Now: () =>
67
+ '(typeof globalThis.__GOFRONT_CLOCK === "function" ? {_d: new Date(globalThis.__GOFRONT_CLOCK())} : {_d: new Date()})',
68
+ Since: (a) =>
69
+ `(Math.round(((typeof globalThis.__GOFRONT_CLOCK === "function" ? globalThis.__GOFRONT_CLOCK() : Date.now()) - (${a[0]})._d.getTime()) * 1000000))`,
25
70
  Sleep: (a) => `await new Promise(r => setTimeout(r, ${a[0]} / 1000000))`,
26
- Unix: (a) => `{_d: new Date((${a[0]}) * 1000)}`,
71
+ Unix: (a) =>
72
+ `{_d: new Date(Number(${a[0]}) * 1000 + Math.round(Number(${a[1] || 0}) / 1000000))}`,
73
+ UnixMicro: (a) => `{_d: new Date(Math.round(Number(${a[0]}) / 1000))}`,
74
+ UnixMilli: (a) => `{_d: new Date(Number(${a[0]}))}`,
27
75
  Date: (a) =>
28
- `{_d: new Date(${a[0]}, ${a[1]} - 1, ${a[2]}, ${a[3]}, ${a[4]}, ${a[5]})}`,
76
+ `{_d: new Date(${a[0]}, ${a[1]} - 1, ${a[2]}, ${a[3]}, ${a[4]}, ${a[5]}, Math.round(Number(${a[6] || 0}) / 1000000))}`,
29
77
  };
30
78
 
31
79
  /** @type {ThisType<CodeGen>} */
@@ -36,21 +84,44 @@ export const timeMethods = {
36
84
  const args = expr.args.map((a) => this.genExpr(a));
37
85
  if (method === "Format") {
38
86
  this.useHelper("timeFmt");
39
- return `__timeFmt(${recvJs}._d, ${args[0]})`;
87
+ return `__timeFmt(${recvJs}, ${args[0]})`;
40
88
  }
41
89
  if (method === "String") {
42
90
  this.useHelper("timeFmt");
43
- return `__timeFmt(${recvJs}._d, "2006-01-02T15:04:05Z07:00")`;
91
+ return `__timeFmt(${recvJs}, "2006-01-02 15:04:05.999999999 -0700 MST")`;
44
92
  }
45
93
  const gen = TIME_METHOD_DISPATCH[method];
46
94
  return gen ? gen(recvJs, args) : undefined;
47
95
  },
48
96
 
49
- _genTime(fn, a) {
97
+ _genDurationMethodCall(method, expr) {
98
+ const recv = expr.func.expr;
99
+ const recvJs = this.genExpr(recv);
100
+ if (method === "String") {
101
+ this.useHelper("duration");
102
+ }
103
+ const gen = DURATION_METHOD_DISPATCH[method];
104
+ return gen ? gen(recvJs) : undefined;
105
+ },
106
+
107
+ _genTime(fn, a, expr) {
50
108
  if (fn === "Parse") {
51
109
  this.useHelper("timeParse");
52
110
  return `__timeParse(${a()[0]}, ${a()[1]})`;
53
111
  }
112
+ if (fn === "Date") {
113
+ const args = a();
114
+ const locArg = expr?.args?.[7];
115
+ const isUtc =
116
+ (locArg?.kind === "SelectorExpr" &&
117
+ (locArg.sel?.name === "UTC" || locArg.field === "UTC")) ||
118
+ (locArg?.kind === "Ident" && locArg.name === "UTC") ||
119
+ args[7] === '"UTC"';
120
+ if (isUtc) {
121
+ return `{_d: new Date(Date.UTC(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]}, Math.round(Number(${args[6] || 0}) / 1000000))), _offset: 0}`;
122
+ }
123
+ return `{_d: new Date(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]}, Math.round(Number(${args[6] || 0}) / 1000000))}`;
124
+ }
54
125
  const gen = TIME_DISPATCH[fn];
55
126
  return gen ? gen(a()) : undefined;
56
127
  },
@@ -11,8 +11,8 @@ export const unicodeMethods = {
11
11
  IsLetter: `/\\p{L}/u.test(${cp})`,
12
12
  IsDigit: `/\\p{Nd}/u.test(${cp})`,
13
13
  IsSpace: `/\\s/.test(${cp})`,
14
- IsUpper: `((__c) => __c === __c.toUpperCase() && /\\p{L}/u.test(__c))(${cp})`,
15
- IsLower: `((__c) => __c === __c.toLowerCase() && /\\p{L}/u.test(__c))(${cp})`,
14
+ IsUpper: `/\\p{Lu}/u.test(${cp})`,
15
+ IsLower: `/\\p{Ll}/u.test(${cp})`,
16
16
  IsPunct: `/\\p{P}/u.test(${cp})`,
17
17
  IsControl: `/\\p{Cc}/u.test(${cp})`,
18
18
  IsPrint: `!/\\p{Cc}/u.test(${cp})`,