@spyglassmc/core 0.4.45 → 0.4.46

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/lib/common/Dev.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { bigintJsonNumberReplacer } from './index.js';
1
2
  export var Dev;
2
3
  (function (Dev) {
3
4
  function assertDefined(value) {
@@ -68,12 +69,12 @@ export var Dev;
68
69
  if (value && typeof value === 'object') {
69
70
  try {
70
71
  const seen = new Set();
71
- return JSON.stringify(value, (_k, v) => {
72
+ return JSON.stringify(value, (k, v) => {
72
73
  if (v && typeof v === 'object') {
73
74
  return seen.has(v) ? '[Circular]' : (seen.add(v), v);
74
75
  }
75
76
  else {
76
- return v;
77
+ return bigintJsonNumberReplacer(k, v);
77
78
  }
78
79
  });
79
80
  }
@@ -1,5 +1,6 @@
1
1
  export * from './Dev.js';
2
2
  export * from './externals/index.js';
3
+ export * from './json.js';
3
4
  export * from './Logger.js';
4
5
  export * from './Operations.js';
5
6
  export * from './ReadonlyProxy.js';
@@ -1,5 +1,6 @@
1
1
  export * from './Dev.js';
2
2
  export * from './externals/index.js';
3
+ export * from './json.js';
3
4
  export * from './Logger.js';
4
5
  export * from './Operations.js';
5
6
  export * from './ReadonlyProxy.js';
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Json replacer that writes bigints as a json string of the form `"$$type:bigint;$$value:91"`.
3
+ * Intended to be used with `bigintJsonLosslessReviver`
4
+ * @param _key The key at which the value lives
5
+ * @param value The value to encode
6
+ * @returns Replaced value
7
+ */
8
+ export declare function bigintJsonLosslessReplacer(_key: string, value: any): any;
9
+ /**
10
+ * Json reviver that revives bigints encoded by `bigintJsonLosslessReplacer`
11
+ * @param _key
12
+ * @param value
13
+ * @returns
14
+ */
15
+ export declare function bigintJsonLosslessReviver(_key: string, value: any): any;
16
+ /**
17
+ * Json replacer that replaces bigints with raw json number literals, encoding the entire number.
18
+ * @param _key The key at which the value lives
19
+ * @param value The value to encode
20
+ * @returns Replaced value
21
+ */
22
+ export declare function bigintJsonNumberReplacer(_key: string, value: any): any;
23
+ /**
24
+ * Json reviver that when encountering a number will decide whether that number needs to be
25
+ * represented as a bigint in order to be lossless. Uses normal numbers whenever possible or required.
26
+ * @param _key The key at which the value lives
27
+ * @param value The value that was read
28
+ * @param data Additional data, source includes the raw json value.
29
+ * @returns The javascript value
30
+ */
31
+ export declare function bigintJsonNumberReviver(_key: string, value: any, data?: {
32
+ source?: string;
33
+ }): any;
34
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Json replacer that writes bigints as a json string of the form `"$$type:bigint;$$value:91"`.
3
+ * Intended to be used with `bigintJsonLosslessReviver`
4
+ * @param _key The key at which the value lives
5
+ * @param value The value to encode
6
+ * @returns Replaced value
7
+ */
8
+ export function bigintJsonLosslessReplacer(_key, value) {
9
+ return typeof value === 'bigint'
10
+ ? `$$type:bigint;$$value:${value}`
11
+ : value;
12
+ }
13
+ /**
14
+ * Json reviver that revives bigints encoded by `bigintJsonLosslessReplacer`
15
+ * @param _key
16
+ * @param value
17
+ * @returns
18
+ */
19
+ export function bigintJsonLosslessReviver(_key, value) {
20
+ return typeof value === 'string' && value.startsWith('$$type:bigint;$$value:')
21
+ ? BigInt(value.substring(22))
22
+ : value;
23
+ }
24
+ /**
25
+ * Json replacer that replaces bigints with raw json number literals, encoding the entire number.
26
+ * @param _key The key at which the value lives
27
+ * @param value The value to encode
28
+ * @returns Replaced value
29
+ */
30
+ export function bigintJsonNumberReplacer(_key, value) {
31
+ return typeof value === 'bigint'
32
+ ? JSON.rawJSON(value.toString())
33
+ : value;
34
+ }
35
+ /**
36
+ * Json reviver that when encountering a number will decide whether that number needs to be
37
+ * represented as a bigint in order to be lossless. Uses normal numbers whenever possible or required.
38
+ * @param _key The key at which the value lives
39
+ * @param value The value that was read
40
+ * @param data Additional data, source includes the raw json value.
41
+ * @returns The javascript value
42
+ */
43
+ export function bigintJsonNumberReviver(_key, value, data) {
44
+ return typeof value === 'number'
45
+ && data?.source !== undefined
46
+ && !data.source.includes('.')
47
+ && !data.source.includes('e')
48
+ && !data.source.includes('E')
49
+ && BigInt(value).toString() !== data.source
50
+ ? BigInt(data.source)
51
+ : value;
52
+ }
53
+ //# sourceMappingURL=json.js.map
@@ -141,4 +141,34 @@ export declare function normalizeUri(uri: string): string;
141
141
  * ```
142
142
  */
143
143
  export type InheritReadonly<TARGET extends AstNode, INPUT extends DeepReadonly<AstNode> | undefined> = INPUT & (INPUT extends ReadWrite<AstNode> ? TARGET : DeepReadonly<TARGET>);
144
+ /**
145
+ * Checks if the numeric value of a number or bigint is the same. Undefined is **not** the same as
146
+ * 0 for this function.
147
+ * @param a The first number to compare
148
+ * @param b The second number to compare
149
+ * @returns True if the numeric falue is equal, false otherwise.
150
+ */
151
+ export declare function numericEquals(a: bigint | number | undefined, b: bigint | number | undefined): boolean;
152
+ /**
153
+ * Tries to convert a numeric type to number if that is possible without precision loss.
154
+ * Undefined stays untouched.
155
+ * @param n The numeric value
156
+ * @returns The numeric value converted to a number if there was no precision loss, the given value
157
+ * otherwise
158
+ */
159
+ export declare function tryConvertToNumberWithoutPrecisionLoss<T extends (number | bigint | undefined)>(n: T): number | T;
160
+ /**
161
+ * Compares two numeric types and finds the smallest
162
+ * @param a The first value
163
+ * @param b The second value
164
+ * @returns The smaller value of `a` and `b`
165
+ */
166
+ export declare function min<T extends (number | bigint)>(a: T, b: T): T;
167
+ /**
168
+ * Compares two numeric types and finds the biggest
169
+ * @param a The first value
170
+ * @param b The second value
171
+ * @returns The bigger value of `a` and `b`
172
+ */
173
+ export declare function max<T extends (number | bigint)>(a: T, b: T): T;
144
174
  //# sourceMappingURL=util.d.ts.map
@@ -267,4 +267,48 @@ export function normalizeUri(uri) {
267
267
  obj.pathname = normalizeUriPathname(obj.pathname);
268
268
  return obj.toString();
269
269
  }
270
+ /**
271
+ * Checks if the numeric value of a number or bigint is the same. Undefined is **not** the same as
272
+ * 0 for this function.
273
+ * @param a The first number to compare
274
+ * @param b The second number to compare
275
+ * @returns True if the numeric falue is equal, false otherwise.
276
+ */
277
+ export function numericEquals(a, b) {
278
+ return tryConvertToNumberWithoutPrecisionLoss(a) === tryConvertToNumberWithoutPrecisionLoss(b);
279
+ }
280
+ /**
281
+ * Tries to convert a numeric type to number if that is possible without precision loss.
282
+ * Undefined stays untouched.
283
+ * @param n The numeric value
284
+ * @returns The numeric value converted to a number if there was no precision loss, the given value
285
+ * otherwise
286
+ */
287
+ export function tryConvertToNumberWithoutPrecisionLoss(n) {
288
+ if (typeof n === 'bigint') {
289
+ const num = Number(n);
290
+ if (BigInt(num) === n) {
291
+ return num;
292
+ }
293
+ }
294
+ return n;
295
+ }
296
+ /**
297
+ * Compares two numeric types and finds the smallest
298
+ * @param a The first value
299
+ * @param b The second value
300
+ * @returns The smaller value of `a` and `b`
301
+ */
302
+ export function min(a, b) {
303
+ return a < b ? a : b;
304
+ }
305
+ /**
306
+ * Compares two numeric types and finds the biggest
307
+ * @param a The first value
308
+ * @param b The second value
309
+ * @returns The bigger value of `a` and `b`
310
+ */
311
+ export function max(a, b) {
312
+ return a > b ? a : b;
313
+ }
270
314
  //# sourceMappingURL=util.js.map
@@ -6,11 +6,11 @@ import type { Parser, Result, Returnable } from './Parser.js';
6
6
  export declare function string(options: StringOptions): InfallibleParser<StringNode>;
7
7
  export declare function parseStringValue<T extends Returnable>(parser: Parser<T>, value: string, map: IndexMap, ctx: ParserContext): Result<T>;
8
8
  export declare const BrigadierUnquotableCharacters: readonly ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "_", ".", "+", "-"];
9
- export declare const BrigadierUnquotableCharacterSet: Set<"0" | "k" | "v" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "." | "i" | "p" | "-" | "+" | "e" | "a" | "b" | "c" | "d" | "f" | "g" | "h" | "j" | "l" | "m" | "n" | "o" | "q" | "r" | "s" | "t" | "u" | "w" | "x" | "y" | "z" | "_" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z">;
9
+ export declare const BrigadierUnquotableCharacterSet: Set<"0" | "k" | "v" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "." | "e" | "E" | "i" | "p" | "-" | "+" | "a" | "b" | "c" | "d" | "f" | "g" | "h" | "j" | "l" | "m" | "n" | "o" | "q" | "r" | "s" | "t" | "u" | "w" | "x" | "y" | "z" | "_" | "A" | "B" | "C" | "D" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z">;
10
10
  export declare const BrigadierUnquotablePattern: RegExp;
11
11
  export declare const BrigadierUnquotableOption: {
12
12
  allowEmpty: boolean;
13
- allowList: Set<"0" | "k" | "v" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "." | "i" | "p" | "-" | "+" | "e" | "a" | "b" | "c" | "d" | "f" | "g" | "h" | "j" | "l" | "m" | "n" | "o" | "q" | "r" | "s" | "t" | "u" | "w" | "x" | "y" | "z" | "_" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z">;
13
+ allowList: Set<"0" | "k" | "v" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "." | "e" | "E" | "i" | "p" | "-" | "+" | "a" | "b" | "c" | "d" | "f" | "g" | "h" | "j" | "l" | "m" | "n" | "o" | "q" | "r" | "s" | "t" | "u" | "w" | "x" | "y" | "z" | "_" | "A" | "B" | "C" | "D" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z">;
14
14
  };
15
15
  export declare const BrigadierStringOptions: StringOptions;
16
16
  export declare const brigadierString: InfallibleParser<StringNode>;
@@ -7,7 +7,7 @@ import type { Project } from './Project.js';
7
7
  * The format version of the cache. Should be increased when any changes that
8
8
  * could invalidate the cache are introduced to the Spyglass codebase.
9
9
  */
10
- export declare const LatestCacheVersion = 6;
10
+ export declare const LatestCacheVersion = 7;
11
11
  /**
12
12
  * Checksums of cached files or roots.
13
13
  */
@@ -1,4 +1,4 @@
1
- import { Uri } from '../common/index.js';
1
+ import { bigintJsonLosslessReplacer, bigintJsonLosslessReviver, Uri } from '../common/index.js';
2
2
  import { SymbolTable } from '../symbol/index.js';
3
3
  import { ArchiveUriSupporter } from './FileService.js';
4
4
  import { fileUtil } from './fileUtil.js';
@@ -6,7 +6,7 @@ import { fileUtil } from './fileUtil.js';
6
6
  * The format version of the cache. Should be increased when any changes that
7
7
  * could invalidate the cache are introduced to the Spyglass codebase.
8
8
  */
9
- export const LatestCacheVersion = 6;
9
+ export const LatestCacheVersion = 7;
10
10
  var Checksums;
11
11
  (function (Checksums) {
12
12
  function create() {
@@ -87,7 +87,7 @@ export class CacheService {
87
87
  try {
88
88
  filePath = await this.getCacheFileUri();
89
89
  this.project.logger.info(`[CacheService#load] symbolCachePath = ${filePath}`);
90
- const cache = (await fileUtil.readGzippedJson(this.project.externals, filePath));
90
+ const cache = (await fileUtil.readGzippedJson(this.project.externals, filePath, bigintJsonLosslessReviver));
91
91
  __profiler.task('Read File');
92
92
  if (cache.version === LatestCacheVersion) {
93
93
  this.checksums = cache.checksums;
@@ -186,7 +186,7 @@ export class CacheService {
186
186
  errors: this.errors,
187
187
  };
188
188
  __profiler.task('Unlink Symbols');
189
- await fileUtil.writeGzippedJson(this.project.externals, filePath, cache);
189
+ await fileUtil.writeGzippedJson(this.project.externals, filePath, cache, bigintJsonLosslessReplacer);
190
190
  __profiler.task('Write File').finalize();
191
191
  return true;
192
192
  }
@@ -109,10 +109,10 @@ export declare namespace fileUtil {
109
109
  /**
110
110
  * @throws
111
111
  */
112
- function readGzippedJson(externals: Externals, path: FsLocation): Promise<unknown>;
112
+ function readGzippedJson(externals: Externals, path: FsLocation, reviver?: (this: any, key: string, value: any) => any): Promise<unknown>;
113
113
  /**
114
114
  * @throws
115
115
  */
116
- function writeGzippedJson(externals: Externals, path: FsLocation, data: any): Promise<void>;
116
+ function writeGzippedJson(externals: Externals, path: FsLocation, data: any, replacer?: (this: any, key: string, value: any) => any): Promise<void>;
117
117
  }
118
118
  //# sourceMappingURL=fileUtil.d.ts.map
@@ -1,4 +1,4 @@
1
- import { bufferToString, Uri } from '../common/index.js';
1
+ import { bigintJsonNumberReplacer, bigintJsonNumberReviver, bufferToString, Uri, } from '../common/index.js';
2
2
  export var fileUtil;
3
3
  (function (fileUtil) {
4
4
  /**
@@ -228,7 +228,7 @@ export var fileUtil;
228
228
  * @throws
229
229
  */
230
230
  async function readJson(externals, path) {
231
- return JSON.parse(bufferToString(await readFile(externals, path)));
231
+ return JSON.parse(bufferToString(await readFile(externals, path)), bigintJsonNumberReviver);
232
232
  }
233
233
  fileUtil.readJson = readJson;
234
234
  /* istanbul ignore next */
@@ -238,7 +238,7 @@ export var fileUtil;
238
238
  * @see {@link writeFile}
239
239
  */
240
240
  async function writeJson(externals, path, data) {
241
- return writeFile(externals, path, JSON.stringify(data));
241
+ return writeFile(externals, path, JSON.stringify(data, bigintJsonNumberReplacer));
242
242
  }
243
243
  fileUtil.writeJson = writeJson;
244
244
  /**
@@ -261,15 +261,15 @@ export var fileUtil;
261
261
  /**
262
262
  * @throws
263
263
  */
264
- async function readGzippedJson(externals, path) {
265
- return JSON.parse(bufferToString(await readGzippedFile(externals, path)));
264
+ async function readGzippedJson(externals, path, reviver) {
265
+ return JSON.parse(bufferToString(await readGzippedFile(externals, path)), reviver ?? bigintJsonNumberReviver);
266
266
  }
267
267
  fileUtil.readGzippedJson = readGzippedJson;
268
268
  /**
269
269
  * @throws
270
270
  */
271
- async function writeGzippedJson(externals, path, data) {
272
- return writeGzippedFile(externals, path, JSON.stringify(data));
271
+ async function writeGzippedJson(externals, path, data, replacer) {
272
+ return writeGzippedFile(externals, path, JSON.stringify(data, replacer ?? bigintJsonNumberReplacer));
273
273
  }
274
274
  fileUtil.writeGzippedJson = writeGzippedJson;
275
275
  })(fileUtil || (fileUtil = {}));
@@ -1,5 +1,6 @@
1
1
  import rfdc from 'rfdc';
2
2
  import { isIterable } from '../common/index.js';
3
+ import { bigintJsonLosslessReplacer, bigintJsonLosslessReviver } from '../common/json.js';
3
4
  import { Location, PositionRange, Range } from '../source/index.js';
4
5
  // #region Mcdoc Categories
5
6
  export const McdocCategories = Object.freeze(['mcdoc', 'mcdoc/dispatcher']);
@@ -399,14 +400,14 @@ export var SymbolTable;
399
400
  * a symbol table through the {@link deserialize} method.
400
401
  */
401
402
  function serialize(table) {
402
- return JSON.stringify(unlink(table));
403
+ return JSON.stringify(unlink(table), bigintJsonLosslessReplacer);
403
404
  }
404
405
  SymbolTable.serialize = serialize;
405
406
  /**
406
407
  * @returns The symbol table represented by the string returned by the {@link serialize} method.
407
408
  */
408
409
  function deserialize(json) {
409
- return link(JSON.parse(json));
410
+ return link(JSON.parse(json, bigintJsonLosslessReviver));
410
411
  }
411
412
  SymbolTable.deserialize = deserialize;
412
413
  })(SymbolTable || (SymbolTable = {}));
@@ -1,5 +1,5 @@
1
1
  import { TextDocument } from 'vscode-languageserver-textdocument';
2
- import type { DeepReadonly, ExternalEventEmitter, Externals } from '../common/index.js';
2
+ import { type DeepReadonly, type ExternalEventEmitter, type Externals } from '../common/index.js';
3
3
  import type { AstNode } from '../node/index.js';
4
4
  import type { RangeLike } from '../source/index.js';
5
5
  import type { AllCategory, Symbol, SymbolLocationBuiltInContributor, SymbolLocationMetadata, SymbolMap, SymbolMetadata, SymbolTable, SymbolUsageType } from './Symbol.js';
@@ -5,6 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { TextDocument } from 'vscode-languageserver-textdocument';
8
+ import { bigintJsonNumberReplacer, } from '../common/index.js';
8
9
  import { Range } from '../source/index.js';
9
10
  import { SymbolLocation, SymbolPath, SymbolUsageTypes } from './Symbol.js';
10
11
  export class SymbolUtil {
@@ -831,7 +832,7 @@ export var SymbolFormatter;
831
832
  + ` {${symbol.category}${symbol.subcategory ? ` (${symbol.subcategory})` : ''}}`
832
833
  + ` [${stringifyVisibility(symbol.visibility, symbol.visibilityRestriction)}]`);
833
834
  if (symbol.data) {
834
- ans.push(`${IndentChar}data: ${JSON.stringify(symbol.data)}`);
835
+ ans.push(`${IndentChar}data: ${JSON.stringify(symbol.data, bigintJsonNumberReplacer)}`);
835
836
  }
836
837
  if (symbol.desc) {
837
838
  ans.push(`${IndentChar}description: ${symbol.desc}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spyglassmc/core",
3
- "version": "0.4.45",
3
+ "version": "0.4.46",
4
4
  "type": "module",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "rfdc": "^1.3.0",
24
24
  "vscode-languageserver-textdocument": "^1.0.4",
25
25
  "whatwg-url": "^14.0.0",
26
- "@spyglassmc/locales": "0.3.23"
26
+ "@spyglassmc/locales": "0.3.24"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/decompress": "^4.2.3",