@mirascript/mirascript 0.1.0 → 0.1.2

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 (63) hide show
  1. package/dist/chunk-35JGBXRE.js +1 -0
  2. package/dist/{chunk-5FQWUJIY.js → chunk-3RUWGMBP.js} +20 -6
  3. package/dist/chunk-3RUWGMBP.js.map +6 -0
  4. package/dist/{chunk-DCXIWIW5.js → chunk-AOINGBRS.js} +306 -84
  5. package/dist/chunk-AOINGBRS.js.map +6 -0
  6. package/dist/cli/index.js +10 -10
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/compiler/diagnostic.d.ts +1 -1
  9. package/dist/compiler/diagnostic.d.ts.map +1 -1
  10. package/dist/compiler/generate-bytecode.d.ts +12 -0
  11. package/dist/compiler/generate-bytecode.d.ts.map +1 -0
  12. package/dist/compiler/index.d.ts +6 -0
  13. package/dist/compiler/index.d.ts.map +1 -1
  14. package/dist/compiler/worker.js +4 -5
  15. package/dist/compiler/worker.js.map +1 -1
  16. package/dist/helpers/utils.d.ts +1 -0
  17. package/dist/helpers/utils.d.ts.map +1 -1
  18. package/dist/index.js +18 -7
  19. package/dist/subtle.d.ts +1 -0
  20. package/dist/subtle.d.ts.map +1 -1
  21. package/dist/subtle.js +9 -2
  22. package/dist/vm/error.d.ts.map +1 -1
  23. package/dist/vm/lib/_helpers.d.ts.map +1 -1
  24. package/dist/vm/lib/global/sequence/find.d.ts.map +1 -1
  25. package/dist/vm/operations.d.ts.map +1 -1
  26. package/dist/vm/types/boundary.d.ts +12 -0
  27. package/dist/vm/types/boundary.d.ts.map +1 -0
  28. package/dist/vm/types/context.d.ts.map +1 -1
  29. package/dist/vm/types/extern.d.ts +5 -7
  30. package/dist/vm/types/extern.d.ts.map +1 -1
  31. package/dist/vm/types/function.d.ts +0 -4
  32. package/dist/vm/types/function.d.ts.map +1 -1
  33. package/dist/vm/types/index.d.ts +5 -2
  34. package/dist/vm/types/index.d.ts.map +1 -1
  35. package/package.json +7 -5
  36. package/src/compiler/diagnostic.ts +2 -1
  37. package/src/compiler/emit.ts +4 -0
  38. package/src/compiler/{compile-bytecode.ts → generate-bytecode.ts} +5 -2
  39. package/src/compiler/index.ts +7 -6
  40. package/src/compiler/worker.ts +2 -2
  41. package/src/helpers/utils.ts +1 -0
  42. package/src/subtle.ts +1 -0
  43. package/src/vm/error.ts +15 -3
  44. package/src/vm/lib/_helpers.ts +3 -3
  45. package/src/vm/lib/_loader.ts +4 -4
  46. package/src/vm/lib/global/math.ts +1 -1
  47. package/src/vm/lib/global/sequence/find.ts +13 -11
  48. package/src/vm/lib/global/sequence/map-filter.ts +2 -2
  49. package/src/vm/lib/global/time.ts +1 -1
  50. package/src/vm/operations.ts +21 -9
  51. package/src/vm/types/boundary.ts +95 -0
  52. package/src/vm/types/context.ts +4 -4
  53. package/src/vm/types/extern.ts +19 -55
  54. package/src/vm/types/function.ts +2 -37
  55. package/src/vm/types/index.ts +9 -2
  56. package/dist/chunk-5FQWUJIY.js.map +0 -6
  57. package/dist/chunk-BTDGMWFK.js +0 -202
  58. package/dist/chunk-BTDGMWFK.js.map +0 -6
  59. package/dist/chunk-DCXIWIW5.js.map +0 -6
  60. package/dist/chunk-RAPJ3XLV.js +0 -10
  61. package/dist/compiler/compile-bytecode.d.ts +0 -12
  62. package/dist/compiler/compile-bytecode.d.ts.map +0 -1
  63. /package/dist/{chunk-RAPJ3XLV.js.map → chunk-35JGBXRE.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"function.d.ts","sourceRoot":"","sources":["../../../src/vm/types/function.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGjD,QAAA,MAAM,WAAW,eAAuC,CAAC;AAGzD;;;;GAIG;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,EAAE,aAAa,CAAC,OAAO,GAAG,SAAS,CAAC,KAAK,KAAK,GAAG,IAAI,CAAC;AAE3F,oBAAoB;AACpB,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC;AAEnH,sBAAsB;AACtB,MAAM,WAAW,cAAc;IAC3B,WAAW;IACX,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,aAAa;IACb,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,YAAY;IACZ,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY;IACZ,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,YAAY;IACZ,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,YAAY;IACZ,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY;IACZ,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY;IACZ,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,oBAAoB;IACpB,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;CACtC;AAED,wBAAwB;AACxB,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAClC,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,GAAG;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC9B,CACJ,CAAC;AAEF,0BAA0B;AAC1B,wBAAgB,YAAY,CAAC,CAAC,SAAS,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAE7F;AAED,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAG5E;AAED,uBAAuB;AACvB,wBAAgB,UAAU,CAAC,CAAC,SAAS,cAAc,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,GAAE,gBAAqB,GAAG,UAAU,CAAC,CAAC,CAAC,CAwCxG;AAED,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,cAAc,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAqBhF;AAED,iCAAiC;AACjC,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,cAAc,EAAE,EAAE,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAO9F"}
1
+ {"version":3,"file":"function.d.ts","sourceRoot":"","sources":["../../../src/vm/types/function.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGjD,QAAA,MAAM,WAAW,eAAuC,CAAC;AAEzD;;;;GAIG;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,EAAE,aAAa,CAAC,OAAO,GAAG,SAAS,CAAC,KAAK,KAAK,GAAG,IAAI,CAAC;AAE3F,oBAAoB;AACpB,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC;AAEnH,sBAAsB;AACtB,MAAM,WAAW,cAAc;IAC3B,WAAW;IACX,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,aAAa;IACb,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,YAAY;IACZ,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY;IACZ,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,YAAY;IACZ,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,YAAY;IACZ,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY;IACZ,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY;IACZ,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,oBAAoB;IACpB,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;CACtC;AAED,wBAAwB;AACxB,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAClC,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,GAAG;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC9B,CACJ,CAAC;AAEF,0BAA0B;AAC1B,wBAAgB,YAAY,CAAC,CAAC,SAAS,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAE7F;AAED,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAG5E;AAED,uBAAuB;AACvB,wBAAgB,UAAU,CAAC,CAAC,SAAS,cAAc,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,GAAE,gBAAqB,GAAG,UAAU,CAAC,CAAC,CAAC,CAwCxG"}
@@ -1,5 +1,5 @@
1
1
  import { VmExtern } from './extern.js';
2
- import type { VmFunction } from './function.js';
2
+ import { type VmFunction } from './function.js';
3
3
  import { VmModule } from './module.js';
4
4
  /** Mirascript 原始值 */
5
5
  export type VmPrimitive = null | string | number | boolean;
@@ -61,9 +61,12 @@ export declare function isVmRecord(value: VmAny): value is VmRecord;
61
61
  * 检查值是否为 Mirascript 原始值
62
62
  */
63
63
  export declare function isVmPrimitive(value: unknown): value is VmPrimitive;
64
- export { VmExtern, wrapToVmValue, unwrapFromVmValue } from './extern.js';
64
+ export { VmExtern } from './extern.js';
65
+ export { wrapToVmValue, unwrapFromVmValue, toVmFunctionProxy, fromVmFunctionProxy } from './boundary.js';
65
66
  /** 检查值是否为 Mirascript 外部值 */
66
67
  export declare function isVmExtern(value: unknown): value is VmExtern;
68
+ /** 检查值是否为 Mirascript 可调用值 */
69
+ export declare function isVmCallable(value: unknown): value is VmFunction | VmExtern<Function>;
67
70
  export { VmFunction, isVmFunction, getVmFunctionInfo, type VmFunctionInfo, type VmFunctionLike, type VmFunctionOption, } from './function.js';
68
71
  export { VmModule } from './module.js';
69
72
  /** 检查值是否为 Mirascript 模块 */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/vm/types/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,qBAAqB;AACrB,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAC3D;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG;IACnB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CAC/C,CAAC;AACF;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;AAEzD,2BAA2B;AAC3B,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvD,2BAA2B;AAC3B,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE1D,0BAA0B;AAC1B,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE7C,6BAA6B;AAC7B,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC;AAExC,kCAAkC;AAClC,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,eAAe,CAAC;AAE9C,WAAW;AACX,MAAM,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC;AAExC,aAAa;AACb,MAAM,WAAW,UAAU;IACvB,SAAS;IACT,GAAG,EAAE,IAAI,CAAC;IACV,UAAU;IACV,MAAM,EAAE,MAAM,CAAC;IACf,SAAS;IACT,MAAM,EAAE,MAAM,CAAC;IACf,UAAU;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,MAAM,EAAE,QAAQ,CAAC;IACjB,oBAAoB;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,oBAAoB;IACpB,QAAQ,EAAE,UAAU,CAAC;IACrB,aAAa;IACb,MAAM,EAAE,QAAQ,CAAC;IACjB,oBAAoB;IACpB,MAAM,EAAE,QAAQ,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,OAAO,CAIxD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,QAAQ,CAM1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAOlE;AAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEzE,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,OAAO,EACH,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,2BAA2B;AAC3B,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,WAAW,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAExH,OAAO,EAAE,KAAK,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE5E,eAAO,MAAM,mBAAmB,QAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/vm/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirascript/mirascript",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "An expression based scripting language.",
6
6
  "main": "./dist/index.js",
@@ -33,16 +33,18 @@
33
33
  "dependencies": {
34
34
  "@commander-js/extra-typings": "^14.0.0",
35
35
  "ansi-styles": "^6.2.3",
36
- "commander": "^14.0.1",
36
+ "commander": "^14.0.2",
37
37
  "js-base64": "^3.7.8",
38
- "@mirascript/wasm": "~0.1.0",
39
- "@mirascript/napi": "~0.1.0"
38
+ "@mirascript/napi": "~0.1.2",
39
+ "@mirascript/wasm": "~0.1.2"
40
40
  },
41
41
  "devDependencies": {
42
+ "@types/node": "^24.9.2",
42
43
  "@types/sinon": "^17.0.4",
43
44
  "ava": "^6.4.1",
44
45
  "c8": "^10.1.3",
45
- "sinon": "^21.0.0"
46
+ "sinon": "^21.0.0",
47
+ "type-fest": "^5.1.0"
46
48
  },
47
49
  "scripts": {
48
50
  "watch": "pnpm build:ts --watch",
@@ -1,3 +1,4 @@
1
+ import type { Writable } from 'type-fest';
1
2
  import { DiagnosticCode, wasm } from '@mirascript/wasm';
2
3
  import type { ScriptInput } from './types.js';
3
4
  import { isSafeInteger } from '../helpers/utils.js';
@@ -59,7 +60,7 @@ export interface SourceReference<T extends DiagnosticCode = DiagnosticCode> exte
59
60
  readonly diagnostic: SourceDiagnostic<T>;
60
61
  }
61
62
 
62
- /** 分析诊断信息 */
63
+ /** 分析诊断信息,{@link diagnostic_position_encoding} 不能设为 `None` */
63
64
  export function parseDiagnostics(
64
65
  source: ScriptInput,
65
66
  diagnostics: Uint32Array,
@@ -50,6 +50,10 @@ function toJavascript(value: VmConst | undefined): string {
50
50
  return JSON.stringify(value);
51
51
  }
52
52
  // JSON 无法处理 NaN 等特殊数字
53
+ if (value === 0) {
54
+ if (1 / value === -Infinity) return '-0';
55
+ return '0';
56
+ }
53
57
  return String(value);
54
58
  }
55
59
 
@@ -43,7 +43,7 @@ function checkModule(): void {
43
43
  /**
44
44
  * 生成 MiraScript 字节码
45
45
  */
46
- export function compileBytecodeSync(
46
+ export function generateBytecodeSync(
47
47
  script: ScriptInput,
48
48
  options: CompileOptions,
49
49
  ): [Uint8Array | undefined, Uint32Array] {
@@ -55,10 +55,13 @@ export function compileBytecodeSync(
55
55
  /**
56
56
  * 生成 MiraScript 字节码
57
57
  */
58
- export async function compileBytecode(
58
+ export async function generateBytecode(
59
59
  script: ScriptInput,
60
60
  options: CompileOptions,
61
61
  ): Promise<[Uint8Array | undefined, Uint32Array]> {
62
+ if (options == null) {
63
+ throw new TypeError('options must be provided');
64
+ }
62
65
  await loadModule();
63
66
  const result = 'compile' in module ? await module.compile(script, options) : module.compileSync(script, options);
64
67
  return [result.chunk, result.diagnostics];
@@ -5,10 +5,11 @@ import { emit } from './emit.js';
5
5
  import { createScript } from './create-script.js';
6
6
  import { compileFast } from './compile-fast.js';
7
7
  import { formatDiagnostic, parseDiagnostics } from './diagnostic.js';
8
- import { compileBytecode, compileBytecodeSync, loadModule } from './compile-bytecode.js';
8
+ import { generateBytecode, generateBytecodeSync, loadModule } from './generate-bytecode.js';
9
9
  import { compileWorker } from './worker-manager.js';
10
10
  await loadModule();
11
11
 
12
+ export { generateBytecode, generateBytecodeSync };
12
13
  export type { TranspileOptions, ScriptInput, InputMode } from './types.js';
13
14
 
14
15
  // 目前编译速度约 2000kB/s
@@ -24,7 +25,7 @@ function reportDiagnostic(source: ScriptInput, diagnostics: Uint32Array): never
24
25
  /**
25
26
  * 生成 MiraScript 对应的 JavaScript 代码
26
27
  */
27
- function emitImpl(
28
+ export function emitScript(
28
29
  source: ScriptInput,
29
30
  [code, diagnostics]: [Uint8Array | undefined, Uint32Array],
30
31
  options: TranspileOptions,
@@ -45,8 +46,8 @@ export async function compile(this: void, source: ScriptInput, options: Transpil
45
46
  if (result) return result;
46
47
  }
47
48
  if (source.length < WORKER_MIN_LEN) {
48
- const bc = await compileBytecode(source, options);
49
- return emitImpl(source, bc, options);
49
+ const bc = await generateBytecode(source, options);
50
+ return emitScript(source, bc, options);
50
51
  }
51
52
  const [target, diagnostics] = await compileWorker(source, options);
52
53
  if (target == null) {
@@ -62,6 +63,6 @@ export function compileSync(this: void, source: ScriptInput, options: TranspileO
62
63
  const result = compileFast(source, options);
63
64
  if (result) return result;
64
65
  }
65
- const bc = compileBytecodeSync(source, options);
66
- return emitImpl(source, bc, options);
66
+ const bc = generateBytecodeSync(source, options);
67
+ return emitScript(source, bc, options);
67
68
  }
@@ -1,6 +1,6 @@
1
1
  import type { ScriptInput, TranspileOptions } from './types.js';
2
2
  import { emit } from './emit.js';
3
- import { compileBytecode } from './compile-bytecode.js';
3
+ import { generateBytecode } from './generate-bytecode.js';
4
4
 
5
5
  /**
6
6
  * 生成 MiraScript 对应的 JavaScript 代码
@@ -9,7 +9,7 @@ export async function compile(
9
9
  script: ScriptInput,
10
10
  options: TranspileOptions,
11
11
  ): Promise<[string | undefined, Uint32Array]> {
12
- const [bytecode, errors] = await compileBytecode(script, options);
12
+ const [bytecode, errors] = await generateBytecode(script, options);
13
13
  if (bytecode == null) {
14
14
  return [undefined, errors];
15
15
  }
@@ -1,6 +1,7 @@
1
1
  export const { isArray } = Array;
2
2
  export const { isFinite, isNaN, isInteger, isSafeInteger } = Number;
3
3
  export const { hasOwn, keys, values, entries, create, getPrototypeOf, fromEntries, defineProperty } = Object;
4
+ export const { apply } = Reflect;
4
5
 
5
6
  /**
6
7
  * Determines whether an object has an enumerable property with the specified name.
package/src/subtle.ts CHANGED
@@ -4,3 +4,4 @@ export * as operations from './vm/operations.js';
4
4
  export { serialize, serializeString, serializePropName, type SerializeOptions } from './helpers/serialize.js';
5
5
  export { lib } from './vm/lib/_loader.js';
6
6
  export * from './compiler/diagnostic.js';
7
+ export { generateBytecode, generateBytecodeSync, emitScript } from './compiler/index.js';
package/src/vm/error.ts CHANGED
@@ -14,9 +14,21 @@ export class VmError extends Error {
14
14
 
15
15
  /** 从其他错误构造 */
16
16
  static from(prefix: string, error: unknown, recovered: VmAny): VmError {
17
- if (prefix && !prefix.endsWith(': ')) prefix += ': ';
18
- const vmError = new VmError(`${prefix}${error instanceof Error ? error.message : String(error)}`, recovered);
19
- vmError.stack = error instanceof Error ? error.stack : undefined;
17
+ if (prefix) {
18
+ if (prefix.endsWith(':')) {
19
+ prefix += ' ';
20
+ } else if (!prefix.endsWith(': ')) {
21
+ prefix += ': ';
22
+ }
23
+ }
24
+ let vmError: VmError;
25
+ if (error instanceof Error) {
26
+ vmError = new VmError(`${prefix}${error.message}`, recovered);
27
+ vmError.stack = error.stack;
28
+ } else {
29
+ vmError = new VmError(`${prefix}${String(error)}`, recovered);
30
+ }
31
+ vmError.cause = error;
20
32
  return vmError;
21
33
  }
22
34
  }
@@ -1,8 +1,8 @@
1
+ import type { Writable } from 'type-fest';
1
2
  import { VmError } from '../error.js';
2
3
  import { $ToNumber, $Type } from '../operations.js';
3
4
  import {
4
5
  isVmArray,
5
- isVmExtern,
6
6
  isVmFunction,
7
7
  type VmExtern,
8
8
  type VmFunction,
@@ -16,6 +16,7 @@ import {
16
16
  type VmConst,
17
17
  isVmConst,
18
18
  VM_ARRAY_MAX_LENGTH,
19
+ isVmCallable,
19
20
  } from '../types/index.js';
20
21
  import type { VmFunctionLike, VmFunctionOption } from '../types/function.js';
21
22
  import { Cp } from '../helpers.js';
@@ -126,8 +127,7 @@ export function expectCallable(
126
127
  recovered: VmAny | (() => VmAny),
127
128
  ): asserts value is VmFunction | VmExtern {
128
129
  required(name, value, recovered);
129
- const callable = isVmFunction(value) || isVmExtern(value);
130
- if (!callable) {
130
+ if (!isVmCallable(value)) {
131
131
  throwUnexpectedTypeError(name, 'callable', value, recovered);
132
132
  }
133
133
  }
@@ -6,7 +6,7 @@ import type { VmLib, VmLibOption } from './_helpers.js';
6
6
  import * as global from './global/index.js';
7
7
 
8
8
  for (const [name, value] of entries(global)) {
9
- VmSharedContext[name] = wrapEntry(name, value as RawValue);
9
+ VmSharedContext[name] = wrapEntry(name, value as RawValue, 'global');
10
10
  }
11
11
 
12
12
  /** 原始值 */
@@ -14,7 +14,7 @@ type RawValue = VmLib | VmConst | VmModule;
14
14
  /** 包装值 */
15
15
  type ToWrappedValue<V extends RawValue> = V extends VmFunctionLike ? VmFunction<V> : V;
16
16
  /** 包装值 */
17
- function wrapEntry<const T extends RawValue>(name: string, value: T): ToWrappedValue<T> {
17
+ function wrapEntry<const T extends RawValue>(name: string, value: T, module: string): ToWrappedValue<T> {
18
18
  if (typeof value == 'function') {
19
19
  if (value.name !== name) {
20
20
  // 如果函数名和导出名不一致,则重命名
@@ -26,7 +26,7 @@ function wrapEntry<const T extends RawValue>(name: string, value: T): ToWrappedV
26
26
  return VmFunction(value, {
27
27
  isLib: true,
28
28
  injectCp: true,
29
- fullName: `global.${name}`,
29
+ fullName: `${module}.${name}`,
30
30
  ...(value as VmLibOption),
31
31
  }) as ToWrappedValue<T>;
32
32
  } else {
@@ -43,7 +43,7 @@ export type ToWrappedModule<T extends Record<string, RawValue>> = VmModule<{
43
43
  export function createModule<const T extends Record<string, RawValue>>(name: string, lib: T): ToWrappedModule<T> {
44
44
  const mod = create(null) as Record<string, VmImmutable>;
45
45
  for (const [key, value] of entries(lib)) {
46
- mod[key] = wrapEntry(key, value);
46
+ mod[key] = wrapEntry(key, value, name);
47
47
  }
48
48
  return new VmModule(name, mod) as ToWrappedModule<T>;
49
49
  }
@@ -15,7 +15,7 @@ export const pow = VmLib((x, y) => _pow($ToNumber(x), $ToNumber(y)), {
15
15
  returnsType: 'number',
16
16
  });
17
17
  export const random = VmLib(Math.random, {
18
- summary: '返回 0 1 之间的伪随机数',
18
+ summary: '返回 [0, 1) 之间的伪随机数',
19
19
  params: {},
20
20
  paramsType: {},
21
21
  returnsType: 'number',
@@ -1,17 +1,19 @@
1
1
  import { entries } from '../../../../helpers/utils.js';
2
2
  import { Cp } from '../../../helpers.js';
3
- import { $Call, $ToBoolean } from '../../../operations.js';
4
- import { type VmValue, isVmArray } from '../../../types/index.js';
5
- import { VmLib, expectArrayOrRecord, expectCallable } from '../../_helpers.js';
3
+ import { $Call, $Same, $ToBoolean } from '../../../operations.js';
4
+ import { type VmValue, isVmArray, isVmCallable } from '../../../types/index.js';
5
+ import { VmLib, expectArrayOrRecord, required } from '../../_helpers.js';
6
6
 
7
7
  export const find = VmLib(
8
8
  (data, predicate) => {
9
9
  expectArrayOrRecord('data', data, null);
10
- expectCallable('predicate', predicate, data);
11
- const p = (value: VmValue, key: string | number, data: VmValue) => {
12
- const ret = $Call(predicate, [value, key, data]);
13
- return $ToBoolean(ret);
14
- };
10
+ required('predicate', predicate, null);
11
+ const p = isVmCallable(predicate)
12
+ ? (value: VmValue, key: string | number, data: VmValue) => {
13
+ const ret = $Call(predicate, [value, key, data]);
14
+ return $ToBoolean(ret);
15
+ }
16
+ : (value: VmValue) => $Same(predicate, value);
15
17
  if (isVmArray(data)) {
16
18
  const { length } = data;
17
19
  for (let i = 0; i < length; i++) {
@@ -37,13 +39,13 @@ export const find = VmLib(
37
39
  summary: '查找数组或记录中的键值对,返回第一个满足条件的键值对',
38
40
  params: {
39
41
  data: '查的数组或记录',
40
- predicate: '用于测试每个键值对的函数,返回 true 或 false',
42
+ predicate: '用于测试每个键值对的函数,或要查找的值',
41
43
  },
42
44
  paramsType: {
43
45
  data: 'array | record',
44
- predicate: 'fn(value: any, key: number | string | nil, input: type(data)) -> boolean',
46
+ predicate: '(fn(value: any, key: number | string | nil, input: type(data)) -> boolean) | any',
45
47
  },
46
48
  returnsType: '(string | number, any) | nil',
47
- examples: ['find([3, 5, 8], fn (v) { v % 2 == 0 }) // (2, 8)'],
49
+ examples: ['find([3, 5, 8], fn (v) { v % 2 == 0 }) // (2, 8)', `find((x: 1, y: 2, z: 3), 2) // ('y', 2)`],
48
50
  },
49
51
  );
@@ -49,7 +49,7 @@ export const filter = VmLib(
49
49
  summary: '过滤数组或记录中的元素,返回满足条件的元素',
50
50
  params: {
51
51
  data: '要过滤的数组或记录',
52
- predicate: '用于测试每个元素的函数,返回 true 或 false',
52
+ predicate: '用于测试每个元素的函数',
53
53
  },
54
54
  paramsType: {
55
55
  data: 'array | record',
@@ -70,7 +70,7 @@ export const filter_map = VmLib(
70
70
  summary: '对数组或记录中的每个元素应用函数,并返回非 nil 的结果',
71
71
  params: {
72
72
  data: '要映射的数组或记录',
73
- f: '应用于每个元素的函数,返回 nil 或非 nil 的值',
73
+ f: '应用于每个元素的函数',
74
74
  },
75
75
  paramsType: {
76
76
  data: 'array | record',
@@ -44,7 +44,7 @@ export const to_datetime = VmLib(
44
44
  };
45
45
  },
46
46
  {
47
- summary: '将数据转换为 Date 对象',
47
+ summary: '将数据转换为 Date 记录',
48
48
  params: {
49
49
  datetime: '要转换的数据,默认为当前时间',
50
50
  offset: '时区偏移量(单位:小时),默认为 0',
@@ -37,11 +37,11 @@ const isSame = (a: VmValue, b: VmValue): boolean => {
37
37
  if (b instanceof VmWrapper) return b.same(a);
38
38
  // Handle array values
39
39
  if (isVmArray(a) && isVmArray(b)) {
40
- // Compare array items
41
- if (a.length !== b.length) {
40
+ const len = a.length;
41
+ if (len !== b.length) {
42
42
  return false;
43
43
  }
44
- const len = a.length;
44
+ // Compare array items
45
45
  for (let i = 0; i < len; i++) {
46
46
  if (!isSame(a[i] ?? null, b[i] ?? null)) {
47
47
  return false;
@@ -138,7 +138,9 @@ export const $Eq = (a: VmAny, b: VmAny): boolean => {
138
138
  if (typeof a == 'number' && typeof b == 'number') return a === b;
139
139
  return isSame(a, b);
140
140
  };
141
- export const $Neq = (a: VmAny, b: VmAny): boolean => !$Eq(a, b);
141
+ export const $Neq = (a: VmAny, b: VmAny): boolean => {
142
+ return !$Eq(a, b);
143
+ };
142
144
  const stringComparer = new Intl.Collator('en', {
143
145
  usage: 'sort',
144
146
  numeric: false,
@@ -164,13 +166,17 @@ export const $Aeq = (a: VmAny, b: VmAny): boolean => {
164
166
  return stringComparer.compare(as, bs) === 0;
165
167
  }
166
168
  };
167
- export const $Naeq = (a: VmAny, b: VmAny): boolean => !$Aeq(a, b);
169
+ export const $Naeq = (a: VmAny, b: VmAny): boolean => {
170
+ return !$Aeq(a, b);
171
+ };
168
172
  export const $Same = (a: VmAny, b: VmAny): boolean => {
169
173
  $AssertInit(a);
170
174
  $AssertInit(b);
171
175
  return isSame(a, b);
172
176
  };
173
- export const $Nsame = (a: VmAny, b: VmAny): boolean => !$Same(a, b);
177
+ export const $Nsame = (a: VmAny, b: VmAny): boolean => {
178
+ return !$Same(a, b);
179
+ };
174
180
  export const $In = (value: VmAny, iterable: VmAny): boolean => {
175
181
  $AssertInit(value);
176
182
  $AssertInit(iterable);
@@ -198,9 +204,15 @@ export const $In = (value: VmAny, iterable: VmAny): boolean => {
198
204
  export const $Concat = (...args: string[]): string => {
199
205
  return args.map($Format).join('');
200
206
  };
201
- export const $Pos = (a: VmAny): number => $ToNumber(a);
202
- export const $Neg = (a: VmAny): number => -$ToNumber(a);
203
- export const $Not = (a: VmAny): boolean => !$ToBoolean(a);
207
+ export const $Pos = (a: VmAny): number => {
208
+ return $ToNumber(a);
209
+ };
210
+ export const $Neg = (a: VmAny): number => {
211
+ return -$ToNumber(a);
212
+ };
213
+ export const $Not = (a: VmAny): boolean => {
214
+ return !$ToBoolean(a);
215
+ };
204
216
  export const $Length = (value: VmAny): number => {
205
217
  $AssertInit(value);
206
218
  if (isVmArray(value)) return value.length;
@@ -0,0 +1,95 @@
1
+ import { isVmFunction, type VmFunctionLike, type VmFunction } from './function.js';
2
+ import { VmExtern } from './extern.js';
3
+ import { VmWrapper } from './wrapper.js';
4
+ import type { VmAny, VmConst, VmModule, VmPrimitive, VmValue } from './index.js';
5
+ import { $Call } from '../operations.js';
6
+ import { defineProperty, apply } from '../../helpers/utils.js';
7
+
8
+ const kProxy = Symbol.for('mirascript.vm.function.proxy');
9
+
10
+ /** 创建 Mirascript 函数在宿主语言运行的代理 */
11
+ export function toVmFunctionProxy<T extends VmFunctionLike>(fn: VmFunction<T>): T {
12
+ if (!isVmFunction(fn)) return fn;
13
+
14
+ const cached = (fn as unknown as { [kProxy]?: T })[kProxy];
15
+ if (cached != null) return cached;
16
+
17
+ const proxy = (...args: unknown[]) => {
18
+ const ret = $Call(
19
+ fn,
20
+ // 作为函数参数传入的值一定丢失了它的 this
21
+ args.map((v) => wrapToVmValue(v, null)),
22
+ );
23
+ return unwrapFromVmValue(ret);
24
+ };
25
+ defineProperty(fn, kProxy, { value: proxy });
26
+ defineProperty(proxy, kProxy, { value: fn });
27
+ defineProperty(proxy, 'name', {
28
+ value: fn.name,
29
+ configurable: true,
30
+ });
31
+ return proxy as T;
32
+ }
33
+
34
+ /** 解开 Mirascript 函数在宿主语言运行的代理 */
35
+ export function fromVmFunctionProxy<T extends VmFunctionLike>(fn: T): VmFunction<T> | undefined {
36
+ if (isVmFunction(fn)) return fn;
37
+
38
+ const original = (fn as unknown as { [kProxy]?: VmFunction<T> })[kProxy];
39
+ if (original && isVmFunction(original)) return original;
40
+
41
+ return undefined;
42
+ }
43
+
44
+ /** 将宿主语言的值包装为 Mirascript 类型 */
45
+ export function wrapToVmValue(
46
+ value: unknown,
47
+ thisArg: VmExtern | null = null,
48
+ assumeVmValue?: (obj: object) => obj is Exclude<VmConst, VmPrimitive>,
49
+ ): VmValue {
50
+ if (value == null) return null;
51
+ switch (typeof value) {
52
+ case 'function': {
53
+ const unwrapped = fromVmFunctionProxy(value as VmFunctionLike);
54
+ if (unwrapped) return unwrapped;
55
+ return new VmExtern(value as () => never, thisArg);
56
+ }
57
+ case 'object': {
58
+ if (value instanceof VmWrapper) return value as VmModule | VmExtern;
59
+ if (value instanceof Date) return value.valueOf();
60
+ if (assumeVmValue?.(value)) return value;
61
+ // Only functions preserve thisArg
62
+ return new VmExtern(value);
63
+ }
64
+ case 'string':
65
+ case 'number':
66
+ case 'boolean':
67
+ return value;
68
+ case 'bigint':
69
+ return Number(value);
70
+ case 'symbol':
71
+ case 'undefined':
72
+ default:
73
+ return null;
74
+ }
75
+ }
76
+
77
+ /** 取消宿主语言的值的 Mirascript 包装 */
78
+ export function unwrapFromVmValue(value: VmAny): unknown {
79
+ if (typeof value == 'function') {
80
+ return toVmFunctionProxy(value);
81
+ }
82
+ if (value == null || typeof value != 'object') return value;
83
+ if (!(value instanceof VmExtern)) return value;
84
+
85
+ if (value.thisArg == null || typeof value.value != 'function') {
86
+ return value.value;
87
+ }
88
+ const f = value as VmExtern<(...args: unknown[]) => unknown>;
89
+ const caller = f.thisArg!.value;
90
+ return new Proxy(f.value, {
91
+ apply(target, thisArg, args): unknown {
92
+ return apply(target, caller, args);
93
+ },
94
+ });
95
+ }
@@ -7,7 +7,7 @@ import {
7
7
  isVmAny,
8
8
  type VmFunctionLike,
9
9
  } from './index.js';
10
- import { entries, keys } from '../../helpers/utils.js';
10
+ import { create, entries, keys } from '../../helpers/utils.js';
11
11
  import type * as global from '../lib/global/index.js';
12
12
 
13
13
  /** 全局导入的标准库 */
@@ -36,7 +36,7 @@ export interface VmContext {
36
36
  }
37
37
  /** MiraScript 执行上下文 */
38
38
  export type VmContextRecord = Record<string, VmValue | undefined>;
39
- export const VmSharedContext = { __proto__: null } as object as VmSharedContext;
39
+ export const VmSharedContext = create(null) as VmSharedContext;
40
40
 
41
41
  /** 定义在所有 MiraScript 执行上下文中共享的全局变量 */
42
42
  export function defineVmContextValue(
@@ -91,7 +91,7 @@ class ValueVmContext implements VmContext {
91
91
  has(key: string): boolean {
92
92
  return key in this.env;
93
93
  }
94
- constructor(private readonly env: VmContextRecord & { __proto__: VmSharedContext }) {}
94
+ constructor(private readonly env: VmContextRecord) {}
95
95
  }
96
96
 
97
97
  /** 以工厂函数为后备的实现 */
@@ -139,7 +139,7 @@ export function createVmContext(
139
139
  }
140
140
 
141
141
  const [vmValues, externValues] = args;
142
- const env = { __proto__: VmSharedContext } as { __proto__: VmSharedContext } & VmContextRecord;
142
+ const env = create(VmSharedContext) as VmContextRecord;
143
143
  if (vmValues) {
144
144
  for (const [key, value] of entries(vmValues)) {
145
145
  if (!isVmAny(value, false)) continue;