@swf2es/runtime 0.1.19 → 0.1.21

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 (64) hide show
  1. package/dist/avm2/amf.d.ts +1 -1
  2. package/dist/avm2/amf.d.ts.map +1 -1
  3. package/dist/avm2/amf.js +1 -1
  4. package/dist/avm2/amf.js.map +1 -1
  5. package/dist/avm2/enumeration.d.ts +1 -19
  6. package/dist/avm2/enumeration.d.ts.map +1 -1
  7. package/dist/avm2/enumeration.js +1 -51
  8. package/dist/avm2/enumeration.js.map +1 -1
  9. package/dist/avm2/errors.d.ts +2 -0
  10. package/dist/avm2/errors.d.ts.map +1 -1
  11. package/dist/avm2/errors.js +40 -2
  12. package/dist/avm2/errors.js.map +1 -1
  13. package/dist/avm2/index.d.ts +3 -1
  14. package/dist/avm2/index.d.ts.map +1 -1
  15. package/dist/avm2/index.js +3 -1
  16. package/dist/avm2/index.js.map +1 -1
  17. package/dist/avm2/natives/aliases.js +1 -1
  18. package/dist/avm2/natives/aliases.js.map +1 -1
  19. package/dist/avm2/natives/bytearray.d.ts +0 -154
  20. package/dist/avm2/natives/bytearray.d.ts.map +1 -1
  21. package/dist/avm2/natives/bytearray.js +1 -495
  22. package/dist/avm2/natives/bytearray.js.map +1 -1
  23. package/dist/avm2/natives/bytes.d.ts +141 -0
  24. package/dist/avm2/natives/bytes.d.ts.map +1 -0
  25. package/dist/avm2/natives/bytes.js +458 -0
  26. package/dist/avm2/natives/bytes.js.map +1 -0
  27. package/dist/avm2/natives/concurrent.js +1 -1
  28. package/dist/avm2/natives/concurrent.js.map +1 -1
  29. package/dist/avm2/natives/shared-bytes.d.ts +45 -0
  30. package/dist/avm2/natives/shared-bytes.d.ts.map +1 -0
  31. package/dist/avm2/natives/shared-bytes.js +52 -0
  32. package/dist/avm2/natives/shared-bytes.js.map +1 -0
  33. package/dist/avm2/natives/shell.d.ts.map +1 -1
  34. package/dist/avm2/natives/shell.js +3 -1
  35. package/dist/avm2/natives/shell.js.map +1 -1
  36. package/dist/avm2/options.d.ts +1 -1
  37. package/dist/avm2/options.d.ts.map +1 -1
  38. package/dist/avm2/runtime-xml.d.ts +11 -0
  39. package/dist/avm2/runtime-xml.d.ts.map +1 -0
  40. package/dist/avm2/runtime-xml.js +44 -0
  41. package/dist/avm2/runtime-xml.js.map +1 -0
  42. package/dist/avm2/runtime.d.ts +5 -13
  43. package/dist/avm2/runtime.d.ts.map +1 -1
  44. package/dist/avm2/runtime.js +17 -67
  45. package/dist/avm2/runtime.js.map +1 -1
  46. package/dist/avm2/sparse-indices.d.ts +34 -0
  47. package/dist/avm2/sparse-indices.d.ts.map +1 -0
  48. package/dist/avm2/sparse-indices.js +54 -0
  49. package/dist/avm2/sparse-indices.js.map +1 -0
  50. package/package.json +2 -2
  51. package/src/avm2/amf.ts +1 -1
  52. package/src/avm2/enumeration.ts +1 -76
  53. package/src/avm2/errors.ts +48 -3
  54. package/src/avm2/index.ts +9 -12
  55. package/src/avm2/natives/aliases.ts +1 -1
  56. package/src/avm2/natives/bytearray.ts +1 -604
  57. package/src/avm2/natives/bytes.ts +543 -0
  58. package/src/avm2/natives/concurrent.ts +1 -1
  59. package/src/avm2/natives/shared-bytes.ts +99 -0
  60. package/src/avm2/natives/shell.ts +3 -8
  61. package/src/avm2/options.ts +1 -1
  62. package/src/avm2/runtime-xml.ts +54 -0
  63. package/src/avm2/runtime.ts +31 -78
  64. package/src/avm2/sparse-indices.ts +80 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swf2es/runtime",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "AVM2 and AVM1 language runtime used by generated code",
5
5
  "keywords": [
6
6
  "actionscript",
@@ -41,6 +41,6 @@
41
41
  "LICENSE.third-party"
42
42
  ],
43
43
  "dependencies": {
44
- "@swf2es/format": "0.1.19"
44
+ "@swf2es/format": "0.1.21"
45
45
  }
46
46
  }
package/src/avm2/amf.ts CHANGED
@@ -15,7 +15,7 @@
15
15
  import type { AsObject, Value } from "./descriptors.js";
16
16
  import { FloatValue } from "./float.js";
17
17
  import { NS_PackageInternal, NS_Public, namespace, publicQname, qname } from "./names.js";
18
- import { type Bytes, bytesOf } from "./natives/bytearray.js";
18
+ import { type Bytes, bytesOf } from "./natives/bytes.js";
19
19
  import { xmlToXMLString } from "./natives/xml/strings.js";
20
20
  import type { Runtime } from "./runtime.js";
21
21
  import type { Traits } from "./traits.js";
@@ -9,6 +9,7 @@ import { DictionaryKeys } from "./dictionary-keys.js";
9
9
  import { type DynamicProperties, GONE, type Walk } from "./dynamic-properties.js";
10
10
  import { Namespace } from "./names.js";
11
11
  import { FloatVector } from "./natives/float-vector.js";
12
+ import { firstAtOrAfter, hashed, indicesOf, retake, type SparseIndices } from "./sparse-indices.js";
12
13
  import type { Traits } from "./traits.js";
13
14
 
14
15
  /**
@@ -22,25 +23,6 @@ export interface Enumeration {
22
23
  sparse?: SparseIndices;
23
24
  }
24
25
 
25
- /**
26
- * The indices of a sparse Array, in order, taken when a for-in first meets
27
- * a run of holes too long to step through, so that it crosses each gap by
28
- * them, and dropped when the for-in ends or another starts.
29
- */
30
- interface SparseIndices {
31
- indices: number[];
32
- /** The Array's length when they were last brought up to it. */
33
- length: number;
34
- /** Where in them the index last given is, and that index, so that the next step goes on from there. */
35
- at: number;
36
- given: number;
37
- /** How many were given since they were taken, and whether they were taken again since this for-in met them. */
38
- sinceTaken: number;
39
- retaken: boolean;
40
- /** Whether avmplus holds the Array's elements in its hashtable (see hashed). */
41
- hashed: boolean;
42
- }
43
-
44
26
  /**
45
27
  * How many Arrays keep sparse indices, across runtimes, so that a for-in
46
28
  * over a dense one, as nearly all are, never looks for them. One collected
@@ -559,63 +541,6 @@ function nextSparse(o: AsObject, a: Value[], sparse: SparseIndices, from: number
559
541
  return -1;
560
542
  }
561
543
 
562
- /** Take a sparse Array's indices again. */
563
- function retake(a: Value[], sparse: SparseIndices): void {
564
- sparse.indices = indicesOf(a, 0);
565
- sparse.length = a.length;
566
- sparse.at = -1;
567
- sparse.given = -1;
568
- sparse.sinceTaken = 0;
569
- // An Array in avmplus' hashtable never leaves it.
570
- sparse.hashed ||= hashed(sparse.indices);
571
- }
572
-
573
- /**
574
- * Whether avmplus holds an Array with these elements in its hashtable, as
575
- * it must when they span more than 32 slots and more than four times one
576
- * more than their count (ArrayObject's shouldBeSparse): its dense part
577
- * never holds so few over so many. Else avmplus may hold them dense,
578
- * walking them by index, as the for-in here does.
579
- */
580
- function hashed(indices: number[]): boolean {
581
- const n = indices.length;
582
- if (n === 0) {
583
- return false;
584
- }
585
-
586
- const span = indices[n - 1] - indices[0] + 1;
587
- return span > 32 && span > (n + 1) * 4;
588
- }
589
-
590
- /** An Array's indices from `from` on, in order, as Object.keys gives them, appended to `indices`. */
591
- function indicesOf(a: Value[], from: number, indices: number[] = []): number[] {
592
- const keys = Object.keys(a);
593
- for (let k = 0; k < keys.length; k++) {
594
- const i = Number(keys[k]);
595
- if (i >= from) {
596
- indices.push(i);
597
- }
598
- }
599
-
600
- return indices;
601
- }
602
-
603
- /** Where in `indices`, in order, the first at or after `from` is. */
604
- function firstAtOrAfter(indices: number[], from: number): number {
605
- let low = 0;
606
- let high = indices.length;
607
- while (low < high) {
608
- const mid = (low + high) >>> 1;
609
- if (indices[mid] < from) {
610
- low = mid + 1;
611
- } else {
612
- high = mid;
613
- }
614
- }
615
-
616
- return low;
617
- }
618
-
619
544
  /** Whether element `i` of `o`, the object nextIndex steps over, is there and not hidden. */
620
545
  function enumerable(o: AsObject, a: Value[], i: number): boolean {
621
546
  const hidden = hiddenOf(o);
@@ -1,10 +1,12 @@
1
1
  // What the runtime's errors say: their messages, the number alone or, in
2
2
  // debugger mode, its text, as avmplus words them; how a value is named in
3
- // one; and where an AS3 error was made, for a host to show.
3
+ // one; where an AS3 error was made, for a host to show; and what an AS3
4
+ // catch gets, Runtime.caught's.
4
5
 
5
- import type { Value } from "./descriptors.js";
6
+ import type { AsObject, Value } from "./descriptors.js";
7
+ import { isViewRangeError } from "./domain-memory.js";
6
8
  import { FloatValue } from "./float.js";
7
- import { Namespace } from "./names.js";
9
+ import { Namespace, NS_Public, namespace } from "./names.js";
8
10
  import { errorMessages } from "./player-messages.js";
9
11
  import type { Runtime } from "./runtime.js";
10
12
 
@@ -72,3 +74,46 @@ export function describe(rt: Runtime, v: Value): string {
72
74
  const colons = name.lastIndexOf("::");
73
75
  return `${colons < 0 ? name : name.slice(colons + 2)}@0`;
74
76
  }
77
+
78
+ /** An exception as AS3 catches it: a stack overflow is an AS3 Error; the runtime's own errors are not caught. */
79
+ export function caught(rt: Runtime, e: unknown): Value {
80
+ if (e instanceof RangeError && /call stack/.test(e.message)) {
81
+ return rt.error("Error", 1023);
82
+ }
83
+
84
+ // Domain memory's, in the handler's own method (see memoryError).
85
+ if (isViewRangeError(e)) {
86
+ return rt.error("RangeError", 1506);
87
+ }
88
+
89
+ if (e instanceof UnsupportedError) {
90
+ return unsupportedCaught(rt, e);
91
+ }
92
+
93
+ if (e instanceof Error && !(e instanceof AsError)) {
94
+ throw e;
95
+ }
96
+
97
+ return e;
98
+ }
99
+
100
+ /**
101
+ * What is not supported as the AS3 error a catch gets: an
102
+ * IllegalOperationError with its message, or an Error where the player's
103
+ * classes are not loaded; said once to the host, as the code may say nothing.
104
+ */
105
+ function unsupportedCaught(rt: Runtime, e: UnsupportedError): Value {
106
+ if (!rt.unsupportedTold.has(e.message)) {
107
+ rt.unsupportedTold.add(e.message);
108
+ rt.onUnsupported?.(e.message);
109
+ }
110
+
111
+ let cls: AsObject;
112
+ try {
113
+ cls = rt.resolve(rt.cls(namespace(NS_Public, "flash.errors"), "IllegalOperationError"));
114
+ } catch {
115
+ cls = rt.builtinClass("Error");
116
+ }
117
+
118
+ return rt.constructClass(cls, [e.message, 0]);
119
+ }
package/src/avm2/index.ts CHANGED
@@ -17,18 +17,8 @@ export { floatLibrary } from "./float-library.js";
17
17
  export type { ClassHook, NativesProvider } from "./hooks.js";
18
18
  export { messages } from "./messages.js";
19
19
  export { publicNs, qname } from "./names.js";
20
- export {
21
- Bytes,
22
- byteArrayHook,
23
- bytesOf,
24
- canShareMemory,
25
- GLOBAL_MEMORY_MIN_SIZE,
26
- notIsolated,
27
- type SharedBytesMemory,
28
- setDomainMemory,
29
- shareBytes,
30
- sharedByteArray,
31
- } from "./natives/bytearray.js";
20
+ export { byteArrayHook, setDomainMemory } from "./natives/bytearray.js";
21
+ export { Bytes, bytesOf, GLOBAL_MEMORY_MIN_SIZE } from "./natives/bytes.js";
32
22
  export {
33
23
  type SyncRef,
34
24
  syncError,
@@ -40,6 +30,13 @@ export type { Natives } from "./natives/define.js";
40
30
  export { type NativeClass, plain, registerNativeClass } from "./natives/define.js";
41
31
  // The builtins' natives and hooks, for a player that adds playerglobal's to them.
42
32
  export { builtinHooks, builtinNatives } from "./natives/index.js";
33
+ export {
34
+ canShareMemory,
35
+ notIsolated,
36
+ type SharedBytesMemory,
37
+ shareBytes,
38
+ sharedByteArray,
39
+ } from "./natives/shared-bytes.js";
43
40
  export {
44
41
  endShellWorker,
45
42
  shellWorkerTerminated,
@@ -1,7 +1,7 @@
1
1
  // Class aliases, and AMF through ByteArray's readObject and writeObject.
2
2
  import { readObject, writeObject } from "../amf.js";
3
3
  import type { AsObject, Value } from "../descriptors.js";
4
- import { bytesOf } from "./bytearray.js";
4
+ import { bytesOf } from "./bytes.js";
5
5
  import type { Natives } from "./define.js";
6
6
 
7
7
  export const aliasesNatives: Natives = {