@spyglassmc/core 0.4.45 → 0.4.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.
Files changed (36) hide show
  1. package/lib/common/Dev.d.ts +1 -1
  2. package/lib/common/Dev.js +3 -2
  3. package/lib/common/EventDispatcher.d.ts +6 -0
  4. package/lib/common/EventDispatcher.js +15 -0
  5. package/lib/common/ReadonlyProxy.js +2 -2
  6. package/lib/common/StateProxy.js +2 -2
  7. package/lib/common/externals/BrowserExternals.d.ts +1 -9
  8. package/lib/common/externals/BrowserExternals.js +0 -59
  9. package/lib/common/externals/NodeJsExternals.d.ts +0 -19
  10. package/lib/common/externals/NodeJsExternals.js +0 -20
  11. package/lib/common/externals/index.d.ts +0 -17
  12. package/lib/common/index.d.ts +2 -0
  13. package/lib/common/index.js +2 -0
  14. package/lib/common/json.d.ts +34 -0
  15. package/lib/common/json.js +53 -0
  16. package/lib/common/util.d.ts +44 -7
  17. package/lib/common/util.js +94 -18
  18. package/lib/node/StringNode.d.ts +1 -1
  19. package/lib/parser/string.d.ts +2 -2
  20. package/lib/processor/colorizer/Colorizer.d.ts +2 -2
  21. package/lib/service/CacheService.d.ts +1 -1
  22. package/lib/service/CacheService.js +7 -8
  23. package/lib/service/Config.d.ts +6 -10
  24. package/lib/service/Config.js +3 -15
  25. package/lib/service/FileService.js +5 -5
  26. package/lib/service/FileWatcher.d.ts +9 -12
  27. package/lib/service/Project.d.ts +14 -27
  28. package/lib/service/Project.js +6 -18
  29. package/lib/service/fetcher.js +1 -1
  30. package/lib/service/fileUtil.d.ts +2 -2
  31. package/lib/service/fileUtil.js +9 -9
  32. package/lib/symbol/Symbol.d.ts +6 -6
  33. package/lib/symbol/Symbol.js +3 -2
  34. package/lib/symbol/SymbolUtil.d.ts +9 -18
  35. package/lib/symbol/SymbolUtil.js +6 -19
  36. package/package.json +4 -5
@@ -1,7 +1,7 @@
1
1
  export declare namespace Dev {
2
2
  function assertDefined<T>(value: T): asserts value is Exclude<T, undefined>;
3
3
  function assertNever(value: never): never;
4
- function assertTrue(value: boolean, message: string): void;
4
+ function assertTrue(value: unknown, message: string): asserts value;
5
5
  /**
6
6
  * @returns An estimate of the memory taken by the given value, assuming objects are stored as array-like structures instead of dictionaries in the V8 engine.
7
7
  */
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
  }
@@ -0,0 +1,6 @@
1
+ export declare class EventDispatcher<TEvents extends Record<string, unknown>> {
2
+ #private;
3
+ emit<K extends keyof TEvents & string>(name: K, data: TEvents[K]): void;
4
+ on<K extends keyof TEvents & string>(name: K, listener: (data: TEvents[K]) => unknown, options?: AddEventListenerOptions): this;
5
+ }
6
+ //# sourceMappingURL=EventDispatcher.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { Dev } from './Dev.js';
2
+ export class EventDispatcher {
3
+ #target = new EventTarget();
4
+ emit(name, data) {
5
+ this.#target.dispatchEvent(new CustomEvent(name, { detail: data }));
6
+ }
7
+ on(name, listener, options) {
8
+ this.#target.addEventListener(name, (event) => {
9
+ Dev.assertTrue(event instanceof CustomEvent, 'event must be an instance of CustomEvent');
10
+ listener(event.detail);
11
+ }, options);
12
+ return this;
13
+ }
14
+ }
15
+ //# sourceMappingURL=EventDispatcher.js.map
@@ -1,4 +1,4 @@
1
- import { emplaceMap, isObject } from './util.js';
1
+ import { getOrInsertComputed, isObject } from './util.js';
2
2
  export var ReadonlyProxy;
3
3
  (function (ReadonlyProxy) {
4
4
  function create(obj) {
@@ -11,7 +11,7 @@ class ReadonlyProxyHandler {
11
11
  get(target, p, receiver) {
12
12
  const value = Reflect.get(target, p, receiver);
13
13
  if (p !== 'prototype' && isObject(value)) {
14
- return emplaceMap(this.map, p, { insert: () => ReadonlyProxy.create(value) });
14
+ return getOrInsertComputed(this.map, p, () => ReadonlyProxy.create(value));
15
15
  }
16
16
  return value;
17
17
  }
@@ -1,4 +1,4 @@
1
- import { emplaceMap, isObject } from '../common/index.js';
1
+ import { getOrInsertComputed, isObject } from '../common/index.js';
2
2
  import { Operations } from './Operations.js';
3
3
  const BranchOff = Symbol('StateBranchOff');
4
4
  const Is = Symbol('IsStateProxy');
@@ -63,7 +63,7 @@ class StateProxyHandler {
63
63
  }
64
64
  const value = Reflect.get(target, p, receiver);
65
65
  if (p !== 'prototype' && isObject(value)) {
66
- return emplaceMap(this.map, p, { insert: () => _createStateProxy(value, this.rootOps) });
66
+ return getOrInsertComputed(this.map, p, () => _createStateProxy(value, this.rootOps));
67
67
  }
68
68
  return value;
69
69
  }
@@ -1,11 +1,3 @@
1
- import type { ExternalEventEmitter, Externals } from './index.js';
2
- type Listener = (...args: unknown[]) => unknown;
3
- export declare class BrowserEventEmitter implements ExternalEventEmitter {
4
- #private;
5
- emit(eventName: string, ...args: unknown[]): boolean;
6
- on(eventName: string, listener: Listener): this;
7
- once(eventName: string, listener: Listener): this;
8
- }
1
+ import type { Externals } from './index.js';
9
2
  export declare const BrowserExternals: Externals;
10
- export {};
11
3
  //# sourceMappingURL=BrowserExternals.d.ts.map
@@ -1,40 +1,5 @@
1
1
  import { decode as arrayBufferFromBase64, encode as arrayBufferToBase64 } from 'base64-arraybuffer';
2
- import pako from 'pako';
3
2
  import { fileUtil } from '../../service/fileUtil.js';
4
- export class BrowserEventEmitter {
5
- #listeners = new Map();
6
- emit(eventName, ...args) {
7
- const listeners = this.#listeners.get(eventName);
8
- if (!listeners?.all?.size) {
9
- return false;
10
- }
11
- for (const listener of listeners.all) {
12
- listener(...args);
13
- if (listeners.once.has(listener)) {
14
- listeners.all.delete(listener);
15
- listeners.once.delete(listener);
16
- }
17
- }
18
- return false;
19
- }
20
- on(eventName, listener) {
21
- if (!this.#listeners.has(eventName)) {
22
- this.#listeners.set(eventName, { all: new Set(), once: new Set() });
23
- }
24
- const listeners = this.#listeners.get(eventName);
25
- listeners.all.add(listener);
26
- return this;
27
- }
28
- once(eventName, listener) {
29
- if (!this.#listeners.has(eventName)) {
30
- this.#listeners.set(eventName, { all: new Set(), once: new Set() });
31
- }
32
- const listeners = this.#listeners.get(eventName);
33
- listeners.all.add(listener);
34
- listeners.once.add(listener);
35
- return this;
36
- }
37
- }
38
3
  // TODO: Use Origin Private File System (OPFS) instead
39
4
  class BrowserFileSystem {
40
5
  static LocalStorageKey = 'spyglassmc-browser-fs';
@@ -113,21 +78,6 @@ export const BrowserExternals = {
113
78
  decompressBall(_buffer, _options) {
114
79
  throw new Error('decompressBall not supported on browser.');
115
80
  },
116
- async gunzip(buffer) {
117
- return pako.inflate(buffer);
118
- },
119
- async gzip(buffer) {
120
- return pako.gzip(buffer);
121
- },
122
- },
123
- crypto: {
124
- async getSha1(data) {
125
- if (typeof data === 'string') {
126
- data = new TextEncoder().encode(data);
127
- }
128
- const hash = await crypto.subtle.digest('SHA-1', data.buffer);
129
- return uint8ArrayToHex(new Uint8Array(hash));
130
- },
131
81
  },
132
82
  error: {
133
83
  createKind(kind, message) {
@@ -137,19 +87,10 @@ export const BrowserExternals = {
137
87
  return e instanceof Error && e.message.startsWith(kind);
138
88
  },
139
89
  },
140
- event: { EventEmitter: BrowserEventEmitter },
141
90
  fs: new BrowserFileSystem(),
142
91
  web: {
143
- fetch,
144
92
  getCache: () => window.caches.open('spyglassmc'),
145
93
  },
146
94
  };
147
- function uint8ArrayToHex(array) {
148
- let ans = '';
149
- for (const v of array) {
150
- ans += v.toString(16).padStart(2, '0');
151
- }
152
- return ans;
153
- }
154
95
  Object.freeze(BrowserExternals);
155
96
  //# sourceMappingURL=BrowserExternals.js.map
@@ -1,4 +1,3 @@
1
- import { EventEmitter } from 'node:events';
2
1
  import fs, { promises as fsp } from 'node:fs';
3
2
  import type { DecompressedFile, RootUriString } from '../../index.js';
4
3
  import type { FsLocation } from './index.js';
@@ -10,19 +9,11 @@ export declare function getNodeJsExternals({ cacheRoot, nodeFsp }?: {
10
9
  decompressBall(buffer: Uint8Array<ArrayBuffer>, options: {
11
10
  stripLevel?: number;
12
11
  } | undefined): Promise<DecompressedFile[]>;
13
- gunzip(buffer: Uint8Array<ArrayBuffer>): Promise<NonSharedBuffer>;
14
- gzip(buffer: Uint8Array<ArrayBuffer>): Promise<NonSharedBuffer>;
15
- };
16
- crypto: {
17
- getSha1(data: string | Uint8Array<ArrayBuffer>): Promise<string>;
18
12
  };
19
13
  error: {
20
14
  createKind(kind: import("./index.js").ExternalErrorKind, message: string): Error;
21
15
  isKind(e: unknown, kind: import("./index.js").ExternalErrorKind): boolean;
22
16
  };
23
- event: {
24
- EventEmitter: typeof EventEmitter;
25
- };
26
17
  fs: {
27
18
  chmod(location: FsLocation, mode: number): Promise<void>;
28
19
  mkdir(location: FsLocation, options: {
@@ -42,7 +33,6 @@ export declare function getNodeJsExternals({ cacheRoot, nodeFsp }?: {
42
33
  } | undefined): Promise<void>;
43
34
  };
44
35
  web: {
45
- fetch: typeof fetch;
46
36
  getCache: () => Promise<HttpCache>;
47
37
  };
48
38
  }>;
@@ -51,19 +41,11 @@ export declare const NodeJsExternals: Readonly<{
51
41
  decompressBall(buffer: Uint8Array<ArrayBuffer>, options: {
52
42
  stripLevel?: number;
53
43
  } | undefined): Promise<DecompressedFile[]>;
54
- gunzip(buffer: Uint8Array<ArrayBuffer>): Promise<NonSharedBuffer>;
55
- gzip(buffer: Uint8Array<ArrayBuffer>): Promise<NonSharedBuffer>;
56
- };
57
- crypto: {
58
- getSha1(data: string | Uint8Array<ArrayBuffer>): Promise<string>;
59
44
  };
60
45
  error: {
61
46
  createKind(kind: import("./index.js").ExternalErrorKind, message: string): Error;
62
47
  isKind(e: unknown, kind: import("./index.js").ExternalErrorKind): boolean;
63
48
  };
64
- event: {
65
- EventEmitter: typeof EventEmitter;
66
- };
67
49
  fs: {
68
50
  chmod(location: FsLocation, mode: number): Promise<void>;
69
51
  mkdir(location: FsLocation, options: {
@@ -83,7 +65,6 @@ export declare const NodeJsExternals: Readonly<{
83
65
  } | undefined): Promise<void>;
84
66
  };
85
67
  web: {
86
- fetch: typeof fetch;
87
68
  getCache: () => Promise<HttpCache>;
88
69
  };
89
70
  }>;
@@ -1,17 +1,12 @@
1
1
  import decompress from 'decompress';
2
2
  import { Buffer } from 'node:buffer';
3
3
  import cp from 'node:child_process';
4
- import crypto from 'node:crypto';
5
- import { EventEmitter } from 'node:events';
6
4
  import fs, { promises as fsp } from 'node:fs';
7
5
  import os from 'node:os';
8
6
  import process from 'node:process';
9
7
  import stream from 'node:stream';
10
8
  import url from 'node:url';
11
9
  import { promisify } from 'node:util';
12
- import zlib from 'node:zlib';
13
- const gunzip = promisify(zlib.gunzip);
14
- const gzip = promisify(zlib.gzip);
15
10
  export function getNodeJsExternals({ cacheRoot, nodeFsp = fsp } = {}) {
16
11
  return Object.freeze({
17
12
  archive: {
@@ -21,19 +16,6 @@ export function getNodeJsExternals({ cacheRoot, nodeFsp = fsp } = {}) {
21
16
  }
22
17
  return decompress(buffer, { strip: options?.stripLevel });
23
18
  },
24
- gunzip(buffer) {
25
- return gunzip(buffer);
26
- },
27
- gzip(buffer) {
28
- return gzip(buffer);
29
- },
30
- },
31
- crypto: {
32
- async getSha1(data) {
33
- const hash = crypto.createHash('sha1');
34
- hash.update(data);
35
- return hash.digest('hex');
36
- },
37
19
  },
38
20
  error: {
39
21
  createKind(kind, message) {
@@ -45,7 +27,6 @@ export function getNodeJsExternals({ cacheRoot, nodeFsp = fsp } = {}) {
45
27
  return e instanceof Error && e.code === kind;
46
28
  },
47
29
  },
48
- event: { EventEmitter },
49
30
  fs: {
50
31
  chmod(location, mode) {
51
32
  return nodeFsp.chmod(toFsPathLike(location), mode);
@@ -92,7 +73,6 @@ export function getNodeJsExternals({ cacheRoot, nodeFsp = fsp } = {}) {
92
73
  },
93
74
  },
94
75
  web: {
95
- fetch,
96
76
  getCache: async () => {
97
77
  return new HttpCache(cacheRoot);
98
78
  },
@@ -4,14 +4,6 @@ export interface Externals {
4
4
  decompressBall: (buffer: Uint8Array<ArrayBuffer>, options?: {
5
5
  stripLevel?: number;
6
6
  }) => Promise<DecompressedFile[]>;
7
- gzip: (buffer: Uint8Array<ArrayBuffer>) => Promise<Uint8Array<ArrayBuffer>>;
8
- gunzip: (buffer: Uint8Array<ArrayBuffer>) => Promise<Uint8Array<ArrayBuffer>>;
9
- };
10
- crypto: {
11
- /**
12
- * @returns SHA-1 digest of the given data in hexadecimal format.
13
- */
14
- getSha1: (data: string | Uint8Array<ArrayBuffer>) => Promise<string>;
15
7
  };
16
8
  error: {
17
9
  /**
@@ -23,12 +15,8 @@ export interface Externals {
23
15
  */
24
16
  isKind: (e: unknown, kind: ExternalErrorKind) => boolean;
25
17
  };
26
- event: {
27
- EventEmitter: new () => ExternalEventEmitter;
28
- };
29
18
  fs: ExternalFileSystem;
30
19
  web: {
31
- fetch: typeof fetch;
32
20
  getCache: () => Promise<Cache>;
33
21
  };
34
22
  }
@@ -40,11 +28,6 @@ export interface DecompressedFile {
40
28
  type: string;
41
29
  }
42
30
  export type ExternalErrorKind = 'EEXIST' | 'EISDIR' | 'ENOENT';
43
- export interface ExternalEventEmitter {
44
- emit(eventName: string, ...args: unknown[]): boolean;
45
- on(eventName: string, listener: (...args: unknown[]) => unknown): this;
46
- once(eventName: string, listener: (...args: unknown[]) => unknown): this;
47
- }
48
31
  export interface ExternalFileSystem {
49
32
  /**
50
33
  * @param mode File mode bit mask (e.g. `0o775`).
@@ -1,5 +1,7 @@
1
1
  export * from './Dev.js';
2
+ export * from './EventDispatcher.js';
2
3
  export * from './externals/index.js';
4
+ export * from './json.js';
3
5
  export * from './Logger.js';
4
6
  export * from './Operations.js';
5
7
  export * from './ReadonlyProxy.js';
@@ -1,5 +1,7 @@
1
1
  export * from './Dev.js';
2
+ export * from './EventDispatcher.js';
2
3
  export * from './externals/index.js';
4
+ export * from './json.js';
3
5
  export * from './Logger.js';
4
6
  export * from './Operations.js';
5
7
  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
@@ -1,7 +1,6 @@
1
1
  import externalBinarySearch from 'binary-search';
2
2
  import type { AstNode } from '../node/index.js';
3
3
  import type { ProcessorContext } from '../service/index.js';
4
- import type { Externals } from './externals/index.js';
5
4
  import type { DeepReadonly, ReadWrite } from './ReadonlyProxy.js';
6
5
  export declare const Uri: {
7
6
  new (url: string | URL, base?: string | URL): URL;
@@ -77,7 +76,7 @@ export declare namespace TypePredicates {
77
76
  function isString(value: unknown): value is string;
78
77
  }
79
78
  export declare function promisifyAsyncIterable<T, U>(iterable: AsyncIterable<T>, joiner: (chunks: T[]) => U): Promise<U>;
80
- export declare function parseGzippedJson(externals: Externals, buffer: Uint8Array<ArrayBuffer>): Promise<unknown>;
79
+ export declare function parseGzippedJson(bytes: Uint8Array<ArrayBuffer>): Promise<unknown>;
81
80
  /**
82
81
  * @returns Is Plain Old JavaScript Object (POJO).
83
82
  */
@@ -110,17 +109,25 @@ export declare namespace Lazy {
110
109
  export declare function getStates(category: 'block' | 'fluid', ids: readonly string[], ctx: ProcessorContext): Record<string, string[]>;
111
110
  export declare const binarySearch: typeof externalBinarySearch;
112
111
  export declare function isIterable(value: unknown): value is Iterable<unknown>;
113
- export declare function atArray<T>(array: readonly T[] | undefined, index: number): T | undefined;
114
- export declare function emplaceMap<K, V>(map: Map<K, V>, key: K, handler: {
115
- insert?: (key: K, map: Map<K, V>) => V;
116
- update?: (existing: V, key: K, map: Map<K, V>) => V;
117
- }): V;
112
+ export declare function getOrInsert<K, V>(map: Map<K, V>, key: K, defaultValue: V): V;
113
+ export declare function getOrInsertComputed<K, V>(map: Map<K, V>, key: K, callbackFunction: (key: K) => V): V;
114
+ /**
115
+ * TODO: replace with ESNext Uint8Array.prototype.toHex once it's widely supported
116
+ */
117
+ export declare function bytesToHex(bytes: Uint8Array): string;
118
118
  /**
119
119
  * @returns If `val` is an non-null object or a callable object (i.e. function).
120
120
  */
121
121
  export declare function isObject(val: unknown): val is object;
122
122
  export declare function normalizeUriPathname(pathname: string): string;
123
123
  export declare function normalizeUri(uri: string): string;
124
+ export declare function getSha1(data: string | Uint8Array<ArrayBuffer>): Promise<string>;
125
+ export declare function compressBytes(bytes: Uint8Array<ArrayBuffer>, algorithm: CompressionFormat): Promise<Uint8Array<ArrayBuffer>>;
126
+ export declare function compressStream(stream: ReadableStream<Uint8Array<ArrayBuffer>>, algorithm: CompressionFormat): ReadableStream<Uint8Array<ArrayBuffer>>;
127
+ export declare function decompressBytes(bytes: Uint8Array<ArrayBuffer>, algorithm: CompressionFormat): Promise<Uint8Array<ArrayBuffer>>;
128
+ export declare function decompressStream(stream: ReadableStream<Uint8Array<ArrayBuffer>>, algorithm: CompressionFormat): ReadableStream<Uint8Array<ArrayBuffer>>;
129
+ export declare function bytesToStream(bytes: Uint8Array<ArrayBuffer>): ReadableStream<Uint8Array<ArrayBuffer>>;
130
+ export declare function streamToBytes(stream: ReadableStream<Uint8Array<ArrayBuffer>>): Promise<Uint8Array<ArrayBuffer>>;
124
131
  /**
125
132
  * Return a read-write TARGET type if the INPUT type is read-write, and a
126
133
  * readonly TARGET type if the INPUT type is readonly, and `never` if the INPUT
@@ -141,4 +148,34 @@ export declare function normalizeUri(uri: string): string;
141
148
  * ```
142
149
  */
143
150
  export type InheritReadonly<TARGET extends AstNode, INPUT extends DeepReadonly<AstNode> | undefined> = INPUT & (INPUT extends ReadWrite<AstNode> ? TARGET : DeepReadonly<TARGET>);
151
+ /**
152
+ * Checks if the numeric value of a number or bigint is the same. Undefined is **not** the same as
153
+ * 0 for this function.
154
+ * @param a The first number to compare
155
+ * @param b The second number to compare
156
+ * @returns True if the numeric falue is equal, false otherwise.
157
+ */
158
+ export declare function numericEquals(a: bigint | number | undefined, b: bigint | number | undefined): boolean;
159
+ /**
160
+ * Tries to convert a numeric type to number if that is possible without precision loss.
161
+ * Undefined stays untouched.
162
+ * @param n The numeric value
163
+ * @returns The numeric value converted to a number if there was no precision loss, the given value
164
+ * otherwise
165
+ */
166
+ export declare function tryConvertToNumberWithoutPrecisionLoss<T extends (number | bigint | undefined)>(n: T): number | T;
167
+ /**
168
+ * Compares two numeric types and finds the smallest
169
+ * @param a The first value
170
+ * @param b The second value
171
+ * @returns The smaller value of `a` and `b`
172
+ */
173
+ export declare function min<T extends (number | bigint)>(a: T, b: T): T;
174
+ /**
175
+ * Compares two numeric types and finds the biggest
176
+ * @param a The first value
177
+ * @param b The second value
178
+ * @returns The bigger value of `a` and `b`
179
+ */
180
+ export declare function max<T extends (number | bigint)>(a: T, b: T): T;
144
181
  //# sourceMappingURL=util.d.ts.map
@@ -146,8 +146,8 @@ export function promisifyAsyncIterable(iterable, joiner) {
146
146
  return joiner(chunks);
147
147
  })();
148
148
  }
149
- export async function parseGzippedJson(externals, buffer) {
150
- return JSON.parse(bufferToString(await externals.archive.gunzip(buffer)));
149
+ export async function parseGzippedJson(bytes) {
150
+ return JSON.parse(bufferToString(await decompressBytes(bytes, 'gzip')));
151
151
  }
152
152
  /**
153
153
  * @returns Is Plain Old JavaScript Object (POJO).
@@ -218,26 +218,33 @@ export function isIterable(value) {
218
218
  return !!value[Symbol.iterator];
219
219
  }
220
220
  // #region ESNext functions polyfill
221
- export function atArray(array, index) {
222
- return index >= 0 ? array?.[index] : array?.[array.length + index];
221
+ export function getOrInsert(map, key, defaultValue) {
222
+ if (!map.has(key)) {
223
+ map.set(key, defaultValue);
224
+ }
225
+ return map.get(key);
223
226
  }
224
- export function emplaceMap(map, key, handler) {
225
- if (map.has(key)) {
226
- let value = map.get(key);
227
- if (handler.update) {
228
- value = handler.update(value, key, map);
229
- map.set(key, value);
230
- }
231
- return value;
227
+ export function getOrInsertComputed(map, key, callbackFunction) {
228
+ if (!map.has(key)) {
229
+ map.set(key, callbackFunction(key));
230
+ }
231
+ return map.get(key);
232
+ }
233
+ /**
234
+ * TODO: replace with ESNext Uint8Array.prototype.toHex once it's widely supported
235
+ */
236
+ export function bytesToHex(bytes) {
237
+ if ('Buffer' in globalThis && bytes instanceof Buffer) {
238
+ return bytes.toString('hex');
232
239
  }
233
- else if (handler.insert) {
234
- const value = handler.insert(key, map);
235
- map.set(key, value);
236
- return value;
240
+ else if ('toHex' in Uint8Array.prototype && typeof Uint8Array.prototype.toHex === 'function') {
241
+ return Uint8Array.prototype.toHex.call(bytes);
237
242
  }
238
- else {
239
- throw new Error(`No key ${key} in map and no insert handler provided`);
243
+ let ans = '';
244
+ for (const v of bytes) {
245
+ ans += v.toString(16).padStart(2, '0');
240
246
  }
247
+ return ans;
241
248
  }
242
249
  // #endregion
243
250
  /**
@@ -267,4 +274,73 @@ export function normalizeUri(uri) {
267
274
  obj.pathname = normalizeUriPathname(obj.pathname);
268
275
  return obj.toString();
269
276
  }
277
+ export async function getSha1(data) {
278
+ if (typeof data === 'string') {
279
+ data = new TextEncoder().encode(data);
280
+ }
281
+ const hash = await crypto.subtle.digest('SHA-1', data.buffer);
282
+ return bytesToHex(new Uint8Array(hash));
283
+ }
284
+ export function compressBytes(bytes, algorithm) {
285
+ return streamToBytes(compressStream(bytesToStream(bytes), algorithm));
286
+ }
287
+ export function compressStream(stream, algorithm) {
288
+ return stream.pipeThrough(new CompressionStream(algorithm));
289
+ }
290
+ export function decompressBytes(bytes, algorithm) {
291
+ return streamToBytes(decompressStream(bytesToStream(bytes), algorithm));
292
+ }
293
+ export function decompressStream(stream, algorithm) {
294
+ return stream.pipeThrough(new DecompressionStream(algorithm));
295
+ }
296
+ export function bytesToStream(bytes) {
297
+ return new Blob([bytes]).stream();
298
+ }
299
+ export function streamToBytes(stream) {
300
+ return new Response(stream).bytes();
301
+ }
302
+ /**
303
+ * Checks if the numeric value of a number or bigint is the same. Undefined is **not** the same as
304
+ * 0 for this function.
305
+ * @param a The first number to compare
306
+ * @param b The second number to compare
307
+ * @returns True if the numeric falue is equal, false otherwise.
308
+ */
309
+ export function numericEquals(a, b) {
310
+ return tryConvertToNumberWithoutPrecisionLoss(a) === tryConvertToNumberWithoutPrecisionLoss(b);
311
+ }
312
+ /**
313
+ * Tries to convert a numeric type to number if that is possible without precision loss.
314
+ * Undefined stays untouched.
315
+ * @param n The numeric value
316
+ * @returns The numeric value converted to a number if there was no precision loss, the given value
317
+ * otherwise
318
+ */
319
+ export function tryConvertToNumberWithoutPrecisionLoss(n) {
320
+ if (typeof n === 'bigint') {
321
+ const num = Number(n);
322
+ if (BigInt(num) === n) {
323
+ return num;
324
+ }
325
+ }
326
+ return n;
327
+ }
328
+ /**
329
+ * Compares two numeric types and finds the smallest
330
+ * @param a The first value
331
+ * @param b The second value
332
+ * @returns The smaller value of `a` and `b`
333
+ */
334
+ export function min(a, b) {
335
+ return a < b ? a : b;
336
+ }
337
+ /**
338
+ * Compares two numeric types and finds the biggest
339
+ * @param a The first value
340
+ * @param b The second value
341
+ * @returns The bigger value of `a` and `b`
342
+ */
343
+ export function max(a, b) {
344
+ return a > b ? a : b;
345
+ }
270
346
  //# sourceMappingURL=util.js.map
@@ -2,7 +2,7 @@ import type { Parser } from '../parser/index.js';
2
2
  import type { ColorTokenType } from '../processor/index.js';
3
3
  import type { IndexMap, RangeLike } from '../source/index.js';
4
4
  import type { AstNode } from './AstNode.js';
5
- export declare const EscapeChars: readonly ["\"", "'", "\\", "b", "f", "n", "r", "s", "t"];
5
+ export declare const EscapeChars: readonly ['"', "'", '\\', 'b', 'f', 'n', 'r', 's', 't'];
6
6
  export type EscapeChar = (typeof EscapeChars)[number];
7
7
  export declare namespace EscapeChar {
8
8
  function is(expected: EscapeChar[] | undefined, c: string): c is EscapeChar;