@mirascript/mirascript 0.1.87 → 0.1.88

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 (47) hide show
  1. package/dist/{chunk-LSPCAN32.js → chunk-HHKY7Y7L.js} +125 -756
  2. package/dist/chunk-HHKY7Y7L.js.map +6 -0
  3. package/dist/{chunk-A425FGG3.js → chunk-Y7S6AHE7.js} +689 -32
  4. package/dist/chunk-Y7S6AHE7.js.map +6 -0
  5. package/dist/compiler/{emit → bytecode}/consts.d.ts +0 -2
  6. package/dist/compiler/bytecode/consts.d.ts.map +1 -0
  7. package/dist/compiler/bytecode/index.d.ts +28 -0
  8. package/dist/compiler/bytecode/index.d.ts.map +1 -0
  9. package/dist/compiler/emit/index.d.ts +2 -13
  10. package/dist/compiler/emit/index.d.ts.map +1 -1
  11. package/dist/compiler/emit/utils.d.ts +6 -0
  12. package/dist/compiler/emit/utils.d.ts.map +1 -0
  13. package/dist/compiler/generate-bytecode.d.ts +1 -1
  14. package/dist/compiler/generate-bytecode.d.ts.map +1 -1
  15. package/dist/compiler/index.d.ts +1 -1
  16. package/dist/compiler/index.d.ts.map +1 -1
  17. package/dist/compiler/options.d.ts +5 -0
  18. package/dist/compiler/options.d.ts.map +1 -0
  19. package/dist/compiler/verbose.d.ts +11 -0
  20. package/dist/compiler/verbose.d.ts.map +1 -0
  21. package/dist/compiler/worker.d.ts +1 -1
  22. package/dist/compiler/worker.js +3 -3
  23. package/dist/compiler/worker.js.map +1 -1
  24. package/dist/index.js +17 -51
  25. package/dist/index.js.map +2 -2
  26. package/dist/subtle.d.ts +3 -1
  27. package/dist/subtle.d.ts.map +1 -1
  28. package/dist/subtle.js +18 -14
  29. package/dist/subtle.js.map +1 -1
  30. package/dist/vm/lib/index.d.ts +9 -1
  31. package/dist/vm/lib/index.d.ts.map +1 -1
  32. package/package.json +3 -3
  33. package/src/compiler/{emit → bytecode}/consts.ts +0 -16
  34. package/src/compiler/bytecode/index.ts +58 -0
  35. package/src/compiler/emit/index.ts +19 -72
  36. package/src/compiler/emit/sourcemap.ts +1 -1
  37. package/src/compiler/emit/utils.ts +28 -0
  38. package/src/compiler/generate-bytecode.ts +3 -3
  39. package/src/compiler/index.ts +9 -29
  40. package/src/compiler/options.ts +16 -0
  41. package/src/compiler/verbose.ts +32 -0
  42. package/src/compiler/worker.ts +2 -2
  43. package/src/subtle.ts +3 -1
  44. package/src/vm/lib/index.ts +10 -1
  45. package/dist/chunk-A425FGG3.js.map +0 -6
  46. package/dist/chunk-LSPCAN32.js.map +0 -6
  47. package/dist/compiler/emit/consts.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"subtle.d.ts","sourceRoot":"","sources":["../src/subtle.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,UAAU,MAAM,0BAA0B,CAAC;AACvD,OAAO,EACH,OAAO,IAAI,mBAAmB,EAC9B,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,KAAK,gBAAgB,GACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAChH,OAAO,EAAE,KAAK,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"subtle.d.ts","sourceRoot":"","sources":["../src/subtle.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,UAAU,MAAM,0BAA0B,CAAC;AACvD,OAAO,EACH,OAAO,IAAI,mBAAmB,EAC9B,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,KAAK,gBAAgB,GACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAChH,OAAO,EAAE,KAAK,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/subtle.js CHANGED
@@ -1,32 +1,34 @@
1
1
  import {
2
2
  DefaultVmContext,
3
+ compileVerbose,
4
+ constants_exports,
5
+ convert_exports,
3
6
  createScript,
7
+ display,
4
8
  emitScript,
5
9
  lib,
6
10
  operations_exports,
11
+ serialize,
12
+ serializeArray,
13
+ serializeBoolean,
14
+ serializeNil,
15
+ serializeNumber,
16
+ serializeRecord,
17
+ serializeRecordKey,
18
+ serializeString,
7
19
  wrapScript
8
- } from "./chunk-A425FGG3.js";
20
+ } from "./chunk-Y7S6AHE7.js";
9
21
  import {
22
+ BytecodeReader,
10
23
  DiagnosticCode,
11
- constants_exports,
12
- convert_exports,
13
- display,
14
24
  formatDiagnosticMessage,
15
25
  formatDiagnostics,
16
26
  generateBytecode,
17
27
  generateBytecodeSync,
18
28
  getDiagnosticMessage,
19
29
  getDiagnosticSeverity,
20
- parseDiagnostics,
21
- serialize,
22
- serializeArray,
23
- serializeBoolean,
24
- serializeNil,
25
- serializeNumber,
26
- serializeRecord,
27
- serializeRecordKey,
28
- serializeString
29
- } from "./chunk-LSPCAN32.js";
30
+ parseDiagnostics
31
+ } from "./chunk-HHKY7Y7L.js";
30
32
 
31
33
  // src/subtle.ts
32
34
  import { OpCode, isKeyword } from "@mirascript/constants";
@@ -92,10 +94,12 @@ function analyzeGlobalReferences(expression, mode) {
92
94
  return accessChains;
93
95
  }
94
96
  export {
97
+ BytecodeReader,
95
98
  DefaultVmContext,
96
99
  DiagnosticCode,
97
100
  OpCode,
98
101
  analyzeGlobalReferences,
102
+ compileVerbose,
99
103
  constants_exports as constants,
100
104
  convert_exports as convert,
101
105
  createScript,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/subtle.ts", "../src/helpers/analyze.ts"],
4
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,QAAQ,iBAAiB;;;ACFlC,SAAS,sBAAsB;AAQ/B,IAAM,YAAY;AAClB,IAAM,YAAY,IAAI;AAAA,EAClB,OAAO,QAAQ,eAAe,MAAM,OAAO,UAAU,MAAM,UAAU,eAAe,MAAM;AAAA,EAC1F;AACJ;AACA,IAAM,kBAAkB;AAExB,IAAM,EAAE,SAAS,IAAI;AAId,SAAS,wBAAwB,YAAoB,MAA0C;AAClG,MAAI,WAAW,KAAK,MAAM,IAAI;AAC1B,WAAO,CAAC;AAAA,EACZ;AACA,QAAM,CAAC,MAAM,WAAW,IAAI,qBAAqB,YAAY;AAAA,IACzD,YAAY,QAAQ;AAAA,IACpB,8BAA8B;AAAA;AAAA,IAE9B,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,sBAAsB;AAAA,IACtB,QAAQ;AAAA,EACZ,CAAC;AACD,MAAI,QAAQ,QAAQ,YAAY,WAAW,GAAG;AAC1C,WAAO,CAAC;AAAA,EACZ;AACA,QAAM,oBAAoB,iBAAiB,YAAY,WAAW;AAClE,QAAM,UAAU,kBAAkB,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,eAAe,cAAc;AAC7F,MAAI,QAAQ,WAAW,GAAG;AACtB,WAAO,CAAC;AAAA,EACZ;AACA,QAAM,QAAQ,WAAW,MAAM,OAAO;AACtC,QAAM,SAAS,oBAAI,IAAY;AAC/B,aAAW,UAAU,SAAS;AAE1B,UAAM,OAAO,MAAM,OAAO,MAAM,kBAAkB,CAAC;AACnD,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,SAAS,gBAAiB;AACnC,UAAM,SAAS,KAAK,MAAM,OAAO,MAAM,cAAc,CAAC;AACtD,UAAM,QAAQ,UAAU,KAAK,MAAM;AACnC,QAAI,SAAS,KAAM;AACnB,UAAM,aAAa,MAAM,CAAC;AAC1B,QAAI,YAAY,WAAW,OAAO,MAAM,YAAY,OAAO,MAAM,YAAa;AAC9E,UAAM,WAAW,MAAM,CAAC,EAAE,MAAM,SAAS,EAAE,KAAK,GAAG;AACnD,WAAO,IAAI,QAAQ;AAAA,EACvB;AACA,QAAM,eAAuC,CAAC;AAC9C,aAAW,YAAY,QAAQ;AAC3B,UAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS;AAC5C,UAAI,MAAM,KAAK,IAAI,GAAG;AAElB,eAAO,SAAS,MAAM,EAAE;AAAA,MAC5B;AACA,aAAO;AAAA,IACX,CAAC;AACD,iBAAa,KAAK,KAAwC;AAAA,EAC9D;AACA,SAAO;AACX;",
4
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,QAAQ,iBAAiB;;;ACFlC,SAAS,sBAAsB;AAQ/B,IAAM,YAAY;AAClB,IAAM,YAAY,IAAI;AAAA,EAClB,OAAO,QAAQ,eAAe,MAAM,OAAO,UAAU,MAAM,UAAU,eAAe,MAAM;AAAA,EAC1F;AACJ;AACA,IAAM,kBAAkB;AAExB,IAAM,EAAE,SAAS,IAAI;AAId,SAAS,wBAAwB,YAAoB,MAA0C;AAClG,MAAI,WAAW,KAAK,MAAM,IAAI;AAC1B,WAAO,CAAC;AAAA,EACZ;AACA,QAAM,CAAC,MAAM,WAAW,IAAI,qBAAqB,YAAY;AAAA,IACzD,YAAY,QAAQ;AAAA,IACpB,8BAA8B;AAAA;AAAA,IAE9B,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,sBAAsB;AAAA,IACtB,QAAQ;AAAA,EACZ,CAAC;AACD,MAAI,QAAQ,QAAQ,YAAY,WAAW,GAAG;AAC1C,WAAO,CAAC;AAAA,EACZ;AACA,QAAM,oBAAoB,iBAAiB,YAAY,WAAW;AAClE,QAAM,UAAU,kBAAkB,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,eAAe,cAAc;AAC7F,MAAI,QAAQ,WAAW,GAAG;AACtB,WAAO,CAAC;AAAA,EACZ;AACA,QAAM,QAAQ,WAAW,MAAM,OAAO;AACtC,QAAM,SAAS,oBAAI,IAAY;AAC/B,aAAW,UAAU,SAAS;AAE1B,UAAM,OAAO,MAAM,OAAO,MAAM,kBAAkB,CAAC;AACnD,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,SAAS,gBAAiB;AACnC,UAAM,SAAS,KAAK,MAAM,OAAO,MAAM,cAAc,CAAC;AACtD,UAAM,QAAQ,UAAU,KAAK,MAAM;AACnC,QAAI,SAAS,KAAM;AACnB,UAAM,aAAa,MAAM,CAAC;AAC1B,QAAI,YAAY,WAAW,OAAO,MAAM,YAAY,OAAO,MAAM,YAAa;AAC9E,UAAM,WAAW,MAAM,CAAC,EAAE,MAAM,SAAS,EAAE,KAAK,GAAG;AACnD,WAAO,IAAI,QAAQ;AAAA,EACvB;AACA,QAAM,eAAuC,CAAC;AAC9C,aAAW,YAAY,QAAQ;AAC3B,UAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS;AAC5C,UAAI,MAAM,KAAK,IAAI,GAAG;AAElB,eAAO,SAAS,MAAM,EAAE;AAAA,MAC5B;AACA,aAAO;AAAA,IACX,CAAC;AACD,iBAAa,KAAK,KAAwC;AAAA,EAC9D;AACA,SAAO;AACX;",
5
5
  "names": []
6
6
  }
@@ -1,4 +1,12 @@
1
1
  import * as global from './global/index.js';
2
2
  import * as mods from './mod/index.js';
3
- export declare const lib: Readonly<typeof global & typeof mods>;
3
+ /** 标准库 */
4
+ type LibData = typeof global & typeof mods;
5
+ /** 标准库 */
6
+ export type Lib = {
7
+ readonly [key in keyof LibData]: LibData[key];
8
+ };
9
+ /** 标准库 */
10
+ export declare const lib: Lib;
11
+ export type { VmLibOption } from './helpers.js';
4
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/vm/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAkBvC,eAAO,MAAM,GAAG,EAAE,QAAQ,CAAC,OAAO,MAAM,GAAG,OAAO,IAAI,CAA4D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/vm/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAkBvC,UAAU;AACV,KAAK,OAAO,GAAG,OAAO,MAAM,GAAG,OAAO,IAAI,CAAC;AAC3C,UAAU;AACV,MAAM,MAAM,GAAG,GAAG;IACd,QAAQ,EAAE,GAAG,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC;CAChD,CAAC;AAEF,UAAU;AACV,eAAO,MAAM,GAAG,EAAE,GAA8D,CAAC;AACjF,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirascript/mirascript",
3
- "version": "0.1.87",
3
+ "version": "0.1.88",
4
4
  "author": "CloudPSS",
5
5
  "license": "MIT",
6
6
  "description": "An expression based scripting language.",
@@ -42,8 +42,8 @@
42
42
  "@cloudpss/worker": "^0.1.11",
43
43
  "source-map-js": "^1.2.1",
44
44
  "supports-color": "^11.0.0",
45
- "@mirascript/bindings": "~0.1.87",
46
- "@mirascript/constants": "~0.1.87"
45
+ "@mirascript/constants": "~0.1.88",
46
+ "@mirascript/bindings": "~0.1.88"
47
47
  },
48
48
  "devDependencies": {
49
49
  "ava": "^8.0.1",
@@ -1,21 +1,5 @@
1
1
  /* eslint-disable no-useless-assignment */
2
2
  import type { VmPrimitive } from '../../vm/index.js';
3
- const { stringify } = JSON;
4
- /** 将值转为 JS 字面量 */
5
- export function toJsLiteral(value: VmPrimitive | undefined): string {
6
- /* c8 ignore next 2 */
7
- if (value === null) return 'null';
8
- if (value === undefined) return 'undefined';
9
- if (typeof value == 'string') {
10
- return stringify(value);
11
- }
12
- // JSON 无法处理 NaN 等特殊数字
13
- if (value === 0) {
14
- if (1 / value === -Infinity) return '-0';
15
- return '0';
16
- }
17
- return String(value satisfies number | boolean);
18
- }
19
3
 
20
4
  const DECODER = new TextDecoder();
21
5
  const { fromCharCode } = String;
@@ -0,0 +1,58 @@
1
+ import type { OpCode } from '@mirascript/constants';
2
+ import type { VmPrimitive } from '../../vm/index.js';
3
+ import { readConsts } from './consts.js';
4
+
5
+ /** MiraScript 字节码读取器。 */
6
+ export class BytecodeReader {
7
+ constructor(readonly chunk: Uint8Array) {
8
+ const reader = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);
9
+ this.chunkSize = reader.getUint32(0, true);
10
+ this.codeSize = reader.getUint32(4, true);
11
+ this.constSize = reader.getUint32(8 + this.codeSize, true);
12
+ this.codeReader = new DataView(chunk.buffer, chunk.byteOffset + 8, this.codeSize);
13
+ this.constVals = readConsts(
14
+ new Uint8Array(chunk.buffer, chunk.byteOffset + 12 + this.codeSize, this.constSize),
15
+ );
16
+ }
17
+
18
+ readonly chunkSize: number;
19
+ readonly codeSize: number;
20
+ readonly constSize: number;
21
+ readonly constVals: VmPrimitive[];
22
+ protected readonly codeReader: DataView;
23
+ protected codeOffset = 0;
24
+
25
+ /** 是否仍有指令可读。 */
26
+ protected get hasCode(): boolean {
27
+ return this.codeOffset < this.codeSize;
28
+ }
29
+
30
+ /** 读取操作码。 */
31
+ protected readOpcode(): { opcode: OpCode; wide: boolean; offset: number } {
32
+ const offset = this.codeOffset;
33
+ const raw = this.codeReader.getUint8(this.codeOffset++);
34
+ return { opcode: raw & 0x7f, wide: raw >= 0x80, offset };
35
+ }
36
+
37
+ /** 读取操作码。 */
38
+ protected peekOpcode(): OpCode {
39
+ const raw = this.codeReader.getUint8(this.codeOffset);
40
+ return raw & 0x7f;
41
+ }
42
+
43
+ /** 读取无符号参数。 */
44
+ protected readParam(wide: boolean): number {
45
+ const value = wide
46
+ ? this.codeReader.getUint32(this.codeOffset, true)
47
+ : this.codeReader.getUint8(this.codeOffset);
48
+ this.codeOffset += wide ? 4 : 1;
49
+ return value;
50
+ }
51
+
52
+ /** 读取有符号索引。 */
53
+ protected readIndex(wide: boolean): number {
54
+ const value = wide ? this.codeReader.getInt32(this.codeOffset, true) : this.codeReader.getInt8(this.codeOffset);
55
+ this.codeOffset += wide ? 4 : 1;
56
+ return value;
57
+ }
58
+ }
@@ -1,11 +1,10 @@
1
1
  import { OpCode } from '@mirascript/constants';
2
- import { toString } from '../../helpers/convert/index.js';
3
- import type { VmPrimitive } from '../../vm/index.js';
4
2
  import type { ScriptInput, TranspileOptions } from '../types.js';
5
3
  import type { IRange } from '../diagnostic.js';
6
- import { readConsts, toJsLiteral } from './consts.js';
7
4
  import { createSourceMap } from './sourcemap.js';
8
5
  import { SCRIPT_PREFIX, SCRIPT_PREFIX_NO_GLOBAL, type ScriptPrefix } from './constants.js';
6
+ import { BytecodeReader } from '../bytecode/index.js';
7
+ import { createArray, toJsLiteral } from './utils.js';
9
8
 
10
9
  /** 生成代码 */
11
10
  export function emit(
@@ -20,39 +19,18 @@ export function emit(
20
19
  return code;
21
20
  }
22
21
 
23
- /** 创建数组 */
24
- function createArray<T>(length: number, fn: (index: number) => T): T[] {
25
- // micro bench shows that this is faster than Array.from
26
- const result: T[] = [];
27
- for (let i = 0; i < length; i++) {
28
- result.push(fn(i));
29
- }
30
- return result;
31
- }
32
-
33
22
  /** 代码生成 */
34
- export class Emitter {
23
+ export class Emitter extends BytecodeReader {
35
24
  constructor(
36
25
  readonly source: ScriptInput,
37
- readonly chunk: Uint8Array,
26
+ chunk: Uint8Array,
38
27
  readonly sourcemaps: readonly IRange[],
39
28
  readonly options: TranspileOptions,
40
29
  ) {
30
+ super(chunk);
41
31
  this.pretty = options.pretty ?? false;
42
-
43
- const reader = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);
44
- this.chunkSize = reader.getUint32(0, true);
45
- this.codeSize = reader.getUint32(4, true);
46
- this.constSize = reader.getUint32(8 + this.codeSize, true);
47
-
48
- this.codeReader = new DataView(chunk.buffer, chunk.byteOffset + 8, this.codeSize);
49
- this.constVals = readConsts(
50
- new Uint8Array(chunk.buffer, chunk.byteOffset + 12 + this.codeSize, this.constSize),
51
- );
52
32
  }
53
33
  readonly pretty: boolean;
54
- readonly chunkSize: number;
55
- readonly codeSize: number;
56
34
  /** 读取常量表 */
57
35
  private readConsts(): void {
58
36
  const { constVals, constLits } = this;
@@ -60,12 +38,7 @@ export class Emitter {
60
38
  constLits.push(toJsLiteral(constVals[i]));
61
39
  }
62
40
  }
63
- readonly constVals: VmPrimitive[];
64
41
  readonly constLits: string[] = [];
65
-
66
- readonly constSize: number;
67
- private readonly codeReader: DataView;
68
- private codeOffset = 0;
69
42
  private closureCounter = 0;
70
43
  private identCounter = 0;
71
44
  /** 记录函数声明所在位置 */
@@ -81,13 +54,7 @@ export class Emitter {
81
54
  private useGlobal = false;
82
55
  /** 读取全局变量 */
83
56
  private rg(constIdx: number): string {
84
- const constName = this.constVals[constIdx]!;
85
- let lit;
86
- if (typeof constName == 'string') {
87
- lit = this.constLits[constIdx]!;
88
- } else {
89
- lit = toJsLiteral(toString(constName, undefined));
90
- }
57
+ const lit = this.constLits[constIdx]!;
91
58
  this.useGlobal = true;
92
59
  return `global.get(${lit})`;
93
60
  }
@@ -105,27 +72,12 @@ export class Emitter {
105
72
  if (!i) return '_';
106
73
  return this.rv(i, level);
107
74
  }
108
- /** 读取 code param */
109
- private readParam(wide: boolean): number {
110
- const value = wide
111
- ? this.codeReader.getUint32(this.codeOffset, true)
112
- : this.codeReader.getUint8(this.codeOffset);
113
- this.codeOffset += wide ? 4 : 1;
114
- return value;
115
- }
116
- /** 读取 code param */
117
- private readIndex(wide: boolean): number {
118
- const value = wide ? this.codeReader.getInt32(this.codeOffset, true) : this.codeReader.getInt8(this.codeOffset);
119
- this.codeOffset += wide ? 4 : 1;
120
- return value;
121
- }
122
75
  /** 读取闭包 */
123
76
  private readClosure(): void {
124
77
  this.closureCounter++;
125
78
  this.identCounter++;
126
79
  while (this.codeOffset < this.codeSize) {
127
- const opcode_raw = this.codeReader.getUint8(this.codeOffset);
128
- const opcode = opcode_raw & 0x7f;
80
+ const opcode = this.peekOpcode();
129
81
  if (opcode !== OpCode.FuncEnd) {
130
82
  this.readCode();
131
83
  continue;
@@ -142,8 +94,7 @@ export class Emitter {
142
94
  /** 读取块结束 */
143
95
  private readBlockEnd(end: OpCode): void {
144
96
  while (this.codeOffset < this.codeSize) {
145
- const opcode_raw = this.codeReader.getUint8(this.codeOffset);
146
- const opcode = opcode_raw & 0x7f;
97
+ const opcode = this.peekOpcode();
147
98
  if (opcode !== end) {
148
99
  this.readCode();
149
100
  continue;
@@ -163,8 +114,7 @@ export class Emitter {
163
114
  private readIfElse(): void {
164
115
  this.identCounter++;
165
116
  while (this.codeOffset < this.codeSize) {
166
- const opcode_raw = this.codeReader.getUint8(this.codeOffset);
167
- const opcode = opcode_raw & 0x7f;
117
+ const opcode = this.peekOpcode();
168
118
  if (opcode === OpCode.IfEnd) {
169
119
  return this.readBlockEnd(OpCode.IfEnd);
170
120
  }
@@ -183,11 +133,10 @@ export class Emitter {
183
133
  private readModule(obj: number): void {
184
134
  this.identCounter++;
185
135
  while (this.codeOffset < this.codeSize) {
186
- const opcode_raw = this.codeReader.getUint8(this.codeOffset++);
187
- const opcode = opcode_raw & 0x7f;
188
- const wide = opcode_raw >= 0x80;
136
+ const { opcode, wide } = this.readOpcode();
189
137
  const read = () => this.readParam(wide);
190
138
  let code: string;
139
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
191
140
  switch (opcode) {
192
141
  case OpCode.Field: {
193
142
  const field = read();
@@ -222,11 +171,10 @@ export class Emitter {
222
171
  private readRecord(obj: number): void {
223
172
  this.identCounter++;
224
173
  while (this.codeOffset < this.codeSize) {
225
- const opcode_raw = this.codeReader.getUint8(this.codeOffset++);
226
- const opcode = opcode_raw & 0x7f;
227
- const wide = opcode_raw >= 0x80;
174
+ const { opcode, wide } = this.readOpcode();
228
175
  const read = () => this.readParam(wide);
229
176
  let code: string;
177
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
230
178
  switch (opcode) {
231
179
  case OpCode.FieldOpt:
232
180
  case OpCode.Field: {
@@ -289,11 +237,10 @@ export class Emitter {
289
237
  private readArray(arr: number): void {
290
238
  this.identCounter++;
291
239
  while (this.codeOffset < this.codeSize) {
292
- const opcode_raw = this.codeReader.getUint8(this.codeOffset++);
293
- const opcode = opcode_raw & 0x7f;
294
- const wide = opcode_raw >= 0x80;
240
+ const { opcode, wide } = this.readOpcode();
295
241
  const read = () => this.readParam(wide);
296
242
  let code: string;
243
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
297
244
  switch (opcode) {
298
245
  case OpCode.Item: {
299
246
  const value = read();
@@ -343,14 +290,13 @@ export class Emitter {
343
290
 
344
291
  /** 读取代码 */
345
292
  private readCode(): void {
346
- const opcode_raw = this.codeReader.getUint8(this.codeOffset++);
347
- const opcode = opcode_raw & 0x7f;
348
- const wide = opcode_raw >= 0x80;
293
+ const { opcode, wide } = this.readOpcode();
349
294
  const read = () => this.readParam(wide);
350
295
  const readIndex = () => this.readIndex(wide);
351
296
  const ident = this.ident();
352
297
  let code: string;
353
298
  let reg = 0;
299
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
354
300
  switch (opcode) {
355
301
  case OpCode.FuncVarg:
356
302
  case OpCode.Func: {
@@ -635,7 +581,7 @@ export class Emitter {
635
581
  }
636
582
  case OpCode.Module: {
637
583
  reg = read();
638
- const nameIdx = readIndex();
584
+ const nameIdx = read();
639
585
  const name = this.constLits[nameIdx];
640
586
  code = `${this.wv(reg)} = $Module(${name}, {`;
641
587
  break;
@@ -725,6 +671,7 @@ export class Emitter {
725
671
  }
726
672
  }
727
673
  this.codeLines.push(ident + code);
674
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
728
675
  switch (opcode) {
729
676
  case OpCode.FuncVarg:
730
677
  case OpCode.Func: {
@@ -2,7 +2,7 @@ import { SourceMapGenerator } from 'source-map-js';
2
2
  import type { IRange } from '../diagnostic.js';
3
3
  import type { ScriptInput, TranspileOptions } from '../types.js';
4
4
  import type { ScriptPrefix } from './constants.js';
5
- import { toJsLiteral } from './consts.js';
5
+ import { toJsLiteral } from './utils.js';
6
6
 
7
7
  const ORIGIN = `mira://MiraScript/`;
8
8
  const { SOURCE_URL, SOURCE_MAPPING_URL } = ((source, mapping, url) => {
@@ -0,0 +1,28 @@
1
+ import type { VmPrimitive } from '../../index.js';
2
+
3
+ const { stringify } = JSON;
4
+ /** 将值转为 JS 字面量 */
5
+ export function toJsLiteral(value: VmPrimitive | undefined): string {
6
+ /* c8 ignore next 2 */
7
+ if (value === null) return 'null';
8
+ if (value === undefined) return 'undefined';
9
+ if (typeof value == 'string') {
10
+ return stringify(value);
11
+ }
12
+ // JSON 无法处理 NaN 等特殊数字
13
+ if (value === 0) {
14
+ if (1 / value === -Infinity) return '-0';
15
+ return '0';
16
+ }
17
+ return String(value satisfies number | boolean);
18
+ }
19
+
20
+ /** 创建数组 */
21
+ export function createArray<T>(length: number, fn: (index: number) => T): T[] {
22
+ // micro bench shows that this is faster than Array.from
23
+ const result: T[] = [];
24
+ for (let i = 0; i < length; i++) {
25
+ result.push(fn(i));
26
+ }
27
+ return result;
28
+ }
@@ -2,7 +2,7 @@ import { getModule, loadModule } from '@mirascript/bindings';
2
2
  import type { CompileOptions, ScriptInput } from './types.js';
3
3
 
4
4
  /** MiraScript 字节码 */
5
- export type VmBytecodeResult = [code: Uint8Array | undefined, diagnostics: Uint32Array];
5
+ export type VmBytecodeResult = [code: Uint8Array<ArrayBuffer> | undefined, diagnostics: Uint32Array<ArrayBuffer>];
6
6
 
7
7
  /**
8
8
  * 生成 MiraScript 字节码
@@ -10,7 +10,7 @@ export type VmBytecodeResult = [code: Uint8Array | undefined, diagnostics: Uint3
10
10
  export function generateBytecodeSync(script: ScriptInput, options: CompileOptions): VmBytecodeResult {
11
11
  const module = getModule();
12
12
  const result = module.compileSync(script, options);
13
- return [result.chunk, result.diagnostics];
13
+ return [result.chunk as Uint8Array<ArrayBuffer> | undefined, result.diagnostics as Uint32Array<ArrayBuffer>];
14
14
  }
15
15
 
16
16
  /**
@@ -22,5 +22,5 @@ export async function generateBytecode(script: ScriptInput, options: CompileOpti
22
22
  }
23
23
  const module = await loadModule();
24
24
  const result = 'compile' in module ? await module.compile(script, options) : module.compileSync(script, options);
25
- return [result.chunk, result.diagnostics];
25
+ return [result.chunk as Uint8Array<ArrayBuffer> | undefined, result.diagnostics as Uint32Array<ArrayBuffer>];
26
26
  }
@@ -1,54 +1,34 @@
1
1
  import './load-module.js';
2
2
  import type { ScriptInput, TranspileOptions } from './types.js';
3
- import { createScript, type VmScript } from './create-script.js';
3
+ import type { VmScript } from './create-script.js';
4
4
  import { compileFast } from './compile-fast.js';
5
- import { generateBytecode, generateBytecodeSync } from './generate-bytecode.js';
6
- import { compileWorker } from './worker-manager.js';
5
+ import { generateBytecodeSync } from './generate-bytecode.js';
7
6
  import { emitScript, CompileError } from './emit-script.js';
7
+ import { normalizeTranspileOptions } from './options.js';
8
+ import { compileVerbose } from './verbose.js';
8
9
 
9
10
  export * from './types.js';
10
11
  export type { VmScript };
11
12
  export { CompileError };
12
13
 
13
- // 目前编译速度约 2000kB/s
14
- const WORKER_MIN_LEN = typeof Worker != 'function' ? Number.MAX_VALUE : 1024;
15
-
16
- /** 设置 options */
17
- function getOptions(options: TranspileOptions | undefined): TranspileOptions {
18
- options ??= {};
19
- if (options.sourceMap) {
20
- options.diagnostic_sourcemap = true;
21
- // https://tc39.es/ecma426/#sec-terms-and-definitions-colun
22
- options.diagnostic_position_encoding ??= 'Utf16';
23
- }
24
- options.input_mode ??= 'Script';
25
- return options;
26
- }
27
-
28
14
  /**
29
15
  * 生成 MiraScript 对应的 JavaScript 代码
30
16
  */
31
17
  export async function compile(this: void, source: ScriptInput, options?: TranspileOptions): Promise<VmScript> {
32
- options = getOptions(options);
33
18
  if (typeof source == 'string') {
19
+ options = normalizeTranspileOptions(options);
34
20
  const result = compileFast(source, options);
35
21
  if (result) return result;
36
22
  }
37
- if (source.length < WORKER_MIN_LEN) {
38
- const bc = await generateBytecode(source, options);
39
- return emitScript(source, bc, options);
40
- }
41
- const [target, diagnostics] = await compileWorker(source, options);
42
- if (target == null) {
43
- throw new CompileError(source, diagnostics, options.fileName);
44
- }
45
- return createScript(source, options.input_mode ?? 'Script', target);
23
+ const { script } = await compileVerbose(source, options);
24
+ return script;
46
25
  }
26
+
47
27
  /**
48
28
  * 生成 MiraScript 对应的 JavaScript 代码
49
29
  */
50
30
  export function compileSync(this: void, source: ScriptInput, options?: TranspileOptions): VmScript {
51
- options = getOptions(options);
31
+ options = normalizeTranspileOptions(options);
52
32
  if (typeof source == 'string') {
53
33
  const result = compileFast(source, options);
54
34
  if (result) return result;
@@ -0,0 +1,16 @@
1
+ import type { TranspileOptions } from './types.js';
2
+
3
+ // 目前编译速度约 2000kB/s
4
+ export const WORKER_MIN_LEN = typeof Worker != 'function' ? Number.MAX_VALUE : 1024;
5
+
6
+ /** 补全代码生成选项。 */
7
+ export function normalizeTranspileOptions(options: TranspileOptions | undefined): TranspileOptions {
8
+ options ??= {};
9
+ if (options.sourceMap) {
10
+ options.diagnostic_sourcemap = true;
11
+ // https://tc39.es/ecma426/#sec-terms-and-definitions-colun
12
+ options.diagnostic_position_encoding ??= 'Utf16';
13
+ }
14
+ options.input_mode ??= 'Script';
15
+ return options;
16
+ }
@@ -0,0 +1,32 @@
1
+ import type { ScriptInput, TranspileOptions } from './types.js';
2
+ import { createScript, type VmScript } from './create-script.js';
3
+ import { generateBytecode } from './generate-bytecode.js';
4
+ import { compileWorker } from './worker-manager.js';
5
+ import { emitScript, CompileError } from './emit-script.js';
6
+ import { normalizeTranspileOptions, WORKER_MIN_LEN } from './options.js';
7
+
8
+ /**
9
+ * 生成 MiraScript 对应的 JavaScript 代码
10
+ */
11
+ export async function compileVerbose(
12
+ this: void,
13
+ source: ScriptInput,
14
+ options?: TranspileOptions,
15
+ ): Promise<{ script: VmScript; bytecode: Uint8Array<ArrayBuffer>; diagnostics: Uint32Array<ArrayBuffer> }> {
16
+ options = normalizeTranspileOptions(options);
17
+ if (source.length < WORKER_MIN_LEN) {
18
+ const bc = await generateBytecode(source, options);
19
+ const script = emitScript(source, bc, options);
20
+ return {
21
+ script,
22
+ bytecode: bc[0]!, // Will throw if bytecode is undefined, but that should be handled by emitScript
23
+ diagnostics: bc[1],
24
+ };
25
+ }
26
+ const [bytecode, target, diagnostics] = await compileWorker(source, options);
27
+ if (target == null) {
28
+ throw new CompileError(source, diagnostics, options.fileName);
29
+ }
30
+ const script = createScript(source, options.input_mode ?? 'Script', target);
31
+ return { script, bytecode, diagnostics };
32
+ }
@@ -12,13 +12,13 @@ export default expose(async () => {
12
12
  async compile(script: ScriptInput, options: TranspileOptions) {
13
13
  const [bytecode, errors] = await generateBytecode(script, options);
14
14
  if (bytecode == null) {
15
- return WorkerResult([undefined, errors], [errors.buffer]);
15
+ return WorkerResult([undefined, undefined, errors], [errors.buffer]);
16
16
  }
17
17
  const sourcemaps = options.sourceMap
18
18
  ? parseDiagnostics(script, errors, (c) => c === DiagnosticCode.SourceMap).sourcemaps
19
19
  : [];
20
20
  const generatedCode = emit(script, bytecode, sourcemaps, options);
21
- return WorkerResult([generatedCode, errors], [errors.buffer]);
21
+ return WorkerResult([bytecode, generatedCode, errors], [bytecode.buffer, errors.buffer]);
22
22
  },
23
23
  };
24
24
  // 预热编译器
package/src/subtle.ts CHANGED
@@ -17,9 +17,11 @@ export {
17
17
  serializeRecord,
18
18
  type SerializeOptions,
19
19
  } from './helpers/serialize.js';
20
- export { lib } from './vm/lib/index.js';
20
+ export { lib, type Lib, type VmLibOption } from './vm/lib/index.js';
21
21
  export * from './compiler/diagnostic.js';
22
+ export { compileVerbose } from './compiler/verbose.js';
22
23
  export { emitScript } from './compiler/emit-script.js';
23
24
  export { createScript, wrapScript } from './compiler/create-script.js';
25
+ export { BytecodeReader } from './compiler/bytecode/index.js';
24
26
  export { generateBytecode, generateBytecodeSync, type VmBytecodeResult } from './compiler/generate-bytecode.js';
25
27
  export { type GlobalReferenceChain, analyzeGlobalReferences } from './helpers/analyze.js';
@@ -17,4 +17,13 @@ for (const [name, value] of entries(mods)) {
17
17
  VM_SHARED_CONTEXT_DESCRIPTIONS[name] = description;
18
18
  }
19
19
 
20
- export const lib: Readonly<typeof global & typeof mods> = Object.freeze(Object.assign(create(null), global, mods));
20
+ /** 标准库 */
21
+ type LibData = typeof global & typeof mods;
22
+ /** 标准库 */
23
+ export type Lib = {
24
+ readonly [key in keyof LibData]: LibData[key];
25
+ };
26
+
27
+ /** 标准库 */
28
+ export const lib: Lib = Object.freeze(Object.assign(create(null), global, mods));
29
+ export type { VmLibOption } from './helpers.js';