@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
@@ -3,164 +3,10 @@ import type { IndexHook } from "../hooks.js";
3
3
  import type { Runtime } from "../runtime.js";
4
4
  import type { Traits } from "../traits.js";
5
5
  import { type Natives } from "./define.js";
6
- /** DomainEnv::GLOBAL_MEMORY_MIN_SIZE: domain memory's least length. */
7
- export declare const GLOBAL_MEMORY_MIN_SIZE = 1024;
8
- /**
9
- * A shareable ByteArray's memory once it has crossed to another worker,
10
- * which every worker's ByteArray for it uses, as avmplus' ByteArrays share
11
- * one Buffer: its bytes grow in place, and its length is one for all.
12
- * Plain data, which a structured clone carries to another thread.
13
- */
14
- export interface SharedBytesMemory {
15
- /** The same in every worker, by which each VM keeps one ByteArray for it, as avmplus interns it. */
16
- id: number;
17
- /** Its words: the length, as a uint32. */
18
- meta: SharedArrayBuffer;
19
- /** Its bytes, as long as its capacity: growable, up to the most a ByteArray holds where it can. */
20
- data: SharedArrayBuffer;
21
- }
22
- /**
23
- * Whether this thread can share memory with others: SharedArrayBuffer is
24
- * there, as node always has it, and a browser only for a page that is
25
- * cross-origin isolated.
26
- */
27
- export declare function canShareMemory(): boolean;
28
- /** What a page that is not cross-origin isolated gets for sharing `what` with another worker. */
29
- export declare function notIsolated(what: string): Error;
30
- /** The capacity of `rt`'s ByteArrays, which avmshell's System counts in its memory. */
31
- export declare function byteArrayCapacity(rt: Runtime): number;
32
- /**
33
- * A ByteArray's state: its buffer, as long as its capacity, and its length
34
- * and position. A read or write takes its offset first: growing replaces
35
- * the buffer and its view.
36
- *
37
- * A length or position is stored through `>>> 0`, as a uint32: an int32
38
- * while below 2^31, and a double only from there.
39
- * JavaScriptCore keeps a number its JIT once made a double a double, and
40
- * an addition that has seen one makes doubles from then on: a double
41
- * offset fails the int32 check of a DataView or typed array access, and
42
- * after enough failures JavaScriptCore calls DataView's methods instead
43
- * of inlining them, a quarter slower on every read and write. V8 makes
44
- * small integers of them itself.
45
- */
46
- export declare class Bytes {
47
- readonly rt: Runtime;
48
- readonly owner: AsObject;
49
- buffer: Uint8Array;
50
- view: DataView<ArrayBufferLike>;
51
- length: number;
52
- position: number;
53
- littleEndian: boolean;
54
- /** As ByteArray's constructor: ByteArray.defaultObjectEncoding when it is made. */
55
- objectEncoding: number;
56
- /** Whether it is the domain memory, which it then tells when its buffer or length changes. */
57
- subscribed: boolean;
58
- /**
59
- * Whether `shareable` was set true, which cannot be undone: the
60
- * ByteArray then crosses to another worker as its memory, not a copy.
61
- */
62
- shareable: boolean;
63
- /**
64
- * Its memory once it has crossed to another worker (share), which its
65
- * buffer and view are then over, tracking its length as it grows; null
66
- * until then, when it is a ByteArray like any other.
67
- */
68
- shared: SharedBytesMemory | null;
69
- /** The shared memory's words, the length first, and its bytes as words for the atomics. */
70
- private sharedWords;
71
- private sharedInts;
72
- /** Its runtime's capacity count, and its own part of it. */
73
- private readonly capacity;
74
- constructor(rt: Runtime, owner: AsObject);
75
- /** Its buffer replaced by `next`, its runtime's capacity count with it. */
76
- setBuffer(next: Uint8Array<ArrayBuffer>): void;
77
- get available(): number;
78
- /** As Grower::ReallocBackingStore: a new buffer, the old length's bytes copied and the rest zero. */
79
- private realloc;
80
- /** As Grower::EnsureWritableCapacity: double, at least `minimum`, and 4096 unless the setter sizes an empty one. */
81
- private ensure;
82
- /** As ByteArray::SetLengthCommon. */
83
- setLength(length: number, fromSetter?: boolean): void;
84
- /**
85
- * The length made at least `length`, as a write past the end makes it:
86
- * shared, by a compare and swap that only ever raises it, so that
87
- * workers appending at once never lower what another made it.
88
- */
89
- extend(length: number): void;
90
- /** A shared length raised to `length` unless another worker made it as long. */
91
- private raise;
92
- /** As Grower::SetLengthCommon, before the length is set: the capacity for `length`. */
93
- private reserve;
94
- /** Tell the domain memory, if this is it, where the bytes are now: a new view only if they moved or their length changed. */
95
- notify(): void;
96
- /** As ByteArray::Clear: no buffer at all; shared, every worker's ByteArray for it empty. */
97
- clear(): void;
98
- /**
99
- * Its memory, shared from now on: a growable SharedArrayBuffer its bytes
100
- * move to once, and that this ByteArray, and every worker's ByteArray for
101
- * it, uses from then on. Where memory cannot be shared, the error that
102
- * names cross-origin isolation.
103
- */
104
- share(): SharedBytesMemory;
105
- /**
106
- * Use `memory`, shared, as its bytes and length from now on. Its length
107
- * becomes an accessor of the memory's word on this object alone, so that
108
- * every read sees another worker's change and every write is seen, and
109
- * a ByteArray that shares nothing reads a plain field as before.
110
- */
111
- adopt(memory: SharedBytesMemory): void;
112
- /**
113
- * A shared memory's capacity made at least `capacity`: it grows in place,
114
- * which every worker sees, and never shrinks, as another worker may have
115
- * grown it past what this one asks for since. Nor is what a smaller
116
- * buffer would drop zeroed: without avmplus' safepoint, another worker
117
- * may have grown the length again and written there meanwhile, so bytes
118
- * past a lowered length may come back when it grows again.
119
- */
120
- private reshare;
121
- /** As ByteArray::CAS, once the index is checked: atomic where the memory is shared. */
122
- compareAndSwapInt(at: number, expected: number, next: number): number;
123
- /**
124
- * As UnprotectedAtomicCompareAndSwapLength: the length set to `next`, as
125
- * its setter sets it, if it is `expected`; the length before. Shared,
126
- * the capacity is made first and the length swapped atomically, so that
127
- * of workers growing it at once one wins.
128
- */
129
- compareAndSwapLength(expected: number, next: number): number;
130
- /** As requestBytesForShortRead: the offset of `n` bytes to read, or EOFError. */
131
- shortRead(n: number): number;
132
- /** As requestBytesForShortWrite: the offset of `n` bytes to write, the length grown to hold them. */
133
- shortWrite(n: number): number;
134
- /** As DataInput::CheckEOF. */
135
- checkEOF(count: number): void;
136
- /** As ByteArray::Read: `count` bytes from the position. */
137
- read(count: number): Uint8Array;
138
- /** As read, but the bytes themselves, not a copy: for a caller that only reads them, at once. */
139
- readView(count: number): Uint8Array;
140
- /**
141
- * As ByteArray::Write: `count` bytes of `source` from `offset`, all of
142
- * it by default, at the position; the length grows to the position after.
143
- */
144
- write(source: Uint8Array, offset?: number, count?: number): void;
145
- /** As ByteArray's operator[] for a write: the length grows to hold `index`. */
146
- setByte(index: number, value: number): void;
147
- }
148
6
  /** How a ByteArray's elements are indexed: its bytes; past its length undefined, and a write grows it. */
149
7
  export declare const byteArrayHook: IndexHook & {
150
8
  create: (traits: Traits, rt: Runtime) => AsObject;
151
9
  };
152
- /** A ByteArray's state, made the first time a native needs it. */
153
- export declare function bytesOf(rt: Runtime, o: AsObject): Bytes;
154
- /**
155
- * A shareable ByteArray's memory, shared from now on, as it crosses to
156
- * another worker; where memory cannot be shared, the error that names
157
- * cross-origin isolation.
158
- */
159
- export declare function shareBytes(rt: Runtime, o: AsObject): SharedBytesMemory;
160
- /** This VM's one ByteArray for a shared memory, as avmplus interns one for its Buffer: shareable, at position 0. */
161
- export declare function sharedByteArray(rt: Runtime, memory: SharedBytesMemory): AsObject;
162
- /** This VM's ByteArray for the shared memory `id`, if it has one. */
163
- export declare function knownSharedByteArray(rt: Runtime, id: number): AsObject | undefined;
164
10
  /** ByteArray's natives, by the names the compiler gives them. */
165
11
  /** ByteArray's natives, for `rt`: written as a class, each running with the ByteArray object as `this`. */
166
12
  export declare function byteArrayNatives(rt: Runtime): Natives;
@@ -1 +1 @@
1
- {"version":3,"file":"bytearray.d.ts","sourceRoot":"","sources":["../../../src/avm2/natives/bytearray.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bytearray.d.ts","sourceRoot":"","sources":["../../../src/avm2/natives/bytearray.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,QAAQ,EAAU,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAE,KAAK,OAAO,EAAuB,MAAM,aAAa,CAAC;AAKhE,0GAA0G;AAC1G,eAAO,MAAM,aAAa,EAAE,SAAS,GAAG;IAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,KAAK,QAAQ,CAAA;CAkB1F,CAAC;AAkDF,iEAAiE;AACjE,2GAA2G;AAC3G,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAojBrD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,GAAG,IAAI,CA2B3D"}
@@ -10,473 +10,10 @@
10
10
  // http://mozilla.org/MPL/2.0/.
11
11
  import { CompressedDataError, CompressedDataTooLargeError, deflateCompress, LZMA_HEADER, lzmaByteArrayCompress, lzmaByteArrayUncompress, zlibCompress, zlibUncompress, } from "@swf2es/format";
12
12
  import { fromCodes, fromUtf8, utf8 } from "../utf8.js";
13
+ import { Bytes, bytesOf, copyBytes, GLOBAL_MEMORY_MIN_SIZE } from "./bytes.js";
13
14
  import { registerNativeClass } from "./define.js";
14
- const kGrowthIncr = 4096;
15
- const kHugeGrowthThreshold = 24 * 1024 * 1024;
16
- const kHugeGrowthIncr = 24 * 1024 * 1024;
17
- /**
18
- * The most a ByteArray holds: what a 32-bit avmshell, as the oracle's, can
19
- * allocate, beyond which it fails with MemoryError 1000, and less than a
20
- * browser's ArrayBuffer may be refused at.
21
- */
22
- const kMaxCapacity = 0x80000000;
23
- /** DomainEnv::GLOBAL_MEMORY_MIN_SIZE: domain memory's least length. */
24
- export const GLOBAL_MEMORY_MIN_SIZE = 1024;
25
15
  const kAMF0 = 0;
26
16
  const kAMF3 = 3;
27
- /** The ways a browser serves a page cross-origin isolated, for the error a page that is not gets. */
28
- const ISOLATION = "a cross-origin isolated page (served with Cross-Origin-Opener-Policy: same-origin and " +
29
- "Cross-Origin-Embedder-Policy: credentialless or require-corp)";
30
- /**
31
- * Whether this thread can share memory with others: SharedArrayBuffer is
32
- * there, as node always has it, and a browser only for a page that is
33
- * cross-origin isolated.
34
- */
35
- export function canShareMemory() {
36
- const g = globalThis;
37
- return typeof SharedArrayBuffer === "function" && g.crossOriginIsolated !== false;
38
- }
39
- /** What a page that is not cross-origin isolated gets for sharing `what` with another worker. */
40
- export function notIsolated(what) {
41
- return new Error(`swf2es: sharing ${what} with another worker needs shared memory, which a browser gives only ${ISOLATION}`);
42
- }
43
- /** Each runtime's ByteArray for each shared memory, by its id. */
44
- const sharedObjects = new WeakMap();
45
- function sharedObjectsOf(rt) {
46
- let objects = sharedObjects.get(rt);
47
- if (!objects) {
48
- objects = new Map();
49
- sharedObjects.set(rt, objects);
50
- }
51
- return objects;
52
- }
53
- /** The capacity of each runtime's ByteArrays, live or not yet collected. */
54
- const runtimeCapacity = new WeakMap();
55
- /** A ByteArray collected: its capacity no longer counted, by its runtime's count and its own. */
56
- const collected = new FinalizationRegistry(({ runtime, own }) => {
57
- runtime.bytes -= own.bytes;
58
- });
59
- /** The capacity of `rt`'s ByteArrays, which avmshell's System counts in its memory. */
60
- export function byteArrayCapacity(rt) {
61
- return runtimeCapacity.get(rt)?.bytes ?? 0;
62
- }
63
- /**
64
- * A ByteArray's state: its buffer, as long as its capacity, and its length
65
- * and position. A read or write takes its offset first: growing replaces
66
- * the buffer and its view.
67
- *
68
- * A length or position is stored through `>>> 0`, as a uint32: an int32
69
- * while below 2^31, and a double only from there.
70
- * JavaScriptCore keeps a number its JIT once made a double a double, and
71
- * an addition that has seen one makes doubles from then on: a double
72
- * offset fails the int32 check of a DataView or typed array access, and
73
- * after enough failures JavaScriptCore calls DataView's methods instead
74
- * of inlining them, a quarter slower on every read and write. V8 makes
75
- * small integers of them itself.
76
- */
77
- export class Bytes {
78
- rt;
79
- owner;
80
- buffer = new Uint8Array(0);
81
- view = new DataView(this.buffer.buffer);
82
- length = 0;
83
- position = 0;
84
- littleEndian = false;
85
- /** As ByteArray's constructor: ByteArray.defaultObjectEncoding when it is made. */
86
- objectEncoding;
87
- /** Whether it is the domain memory, which it then tells when its buffer or length changes. */
88
- subscribed = false;
89
- /**
90
- * Whether `shareable` was set true, which cannot be undone: the
91
- * ByteArray then crosses to another worker as its memory, not a copy.
92
- */
93
- shareable = false;
94
- /**
95
- * Its memory once it has crossed to another worker (share), which its
96
- * buffer and view are then over, tracking its length as it grows; null
97
- * until then, when it is a ByteArray like any other.
98
- */
99
- shared = null;
100
- /** The shared memory's words, the length first, and its bytes as words for the atomics. */
101
- sharedWords = null;
102
- sharedInts = null;
103
- /** Its runtime's capacity count, and its own part of it. */
104
- capacity;
105
- constructor(rt, owner) {
106
- this.rt = rt;
107
- this.owner = owner;
108
- this.objectEncoding = rt.defaultObjectEncoding;
109
- let runtime = runtimeCapacity.get(rt);
110
- if (!runtime) {
111
- runtime = { bytes: 0 };
112
- runtimeCapacity.set(rt, runtime);
113
- }
114
- this.capacity = { runtime, own: { bytes: 0 } };
115
- collected.register(this, this.capacity);
116
- }
117
- /** Its buffer replaced by `next`, its runtime's capacity count with it. */
118
- setBuffer(next) {
119
- const { runtime, own } = this.capacity;
120
- runtime.bytes += next.length - own.bytes;
121
- own.bytes = next.length;
122
- this.buffer = next;
123
- this.view = new DataView(next.buffer);
124
- }
125
- get available() {
126
- return this.length > this.position ? this.length - this.position : 0;
127
- }
128
- /** As Grower::ReallocBackingStore: a new buffer, the old length's bytes copied and the rest zero. */
129
- realloc(capacityIn, minimum, fromSetter) {
130
- let capacity = capacityIn;
131
- if (capacity < minimum) {
132
- capacity = minimum;
133
- }
134
- if (!(this.buffer.length === 0 && fromSetter) && capacity < kGrowthIncr) {
135
- capacity = kGrowthIncr;
136
- }
137
- if (minimum > kMaxCapacity) {
138
- throw this.rt.error("flash.errors::MemoryError", 1000);
139
- }
140
- capacity = Math.min(capacity, kMaxCapacity);
141
- if (capacity === this.buffer.length) {
142
- return;
143
- }
144
- if (this.shared !== null) {
145
- this.reshare(capacity);
146
- return;
147
- }
148
- let next;
149
- try {
150
- next = new Uint8Array(capacity);
151
- }
152
- catch {
153
- // The host would not give it the memory, as the system would not give avmplus.
154
- throw this.rt.error("flash.errors::MemoryError", 1000);
155
- }
156
- next.set(this.buffer.subarray(0, Math.min(capacity, this.length)));
157
- this.setBuffer(next);
158
- }
159
- /** As Grower::EnsureWritableCapacity: double, at least `minimum`, and 4096 unless the setter sizes an empty one. */
160
- ensure(minimum, fromSetter) {
161
- if (minimum > 0xffffffff - 2 * 4096) {
162
- throw this.rt.error("flash.errors::MemoryError", 1000);
163
- }
164
- if (minimum > this.buffer.length) {
165
- this.realloc(this.buffer.length * 2, minimum, fromSetter);
166
- }
167
- }
168
- /** As ByteArray::SetLengthCommon. */
169
- setLength(length, fromSetter = false) {
170
- if (this.subscribed && length < GLOBAL_MEMORY_MIN_SIZE) {
171
- throw this.rt.error("RangeError", 1506);
172
- }
173
- this.reserve(length, fromSetter);
174
- this.length = length >>> 0;
175
- if (this.position > length) {
176
- this.position = length >>> 0;
177
- }
178
- this.notify();
179
- }
180
- /**
181
- * The length made at least `length`, as a write past the end makes it:
182
- * shared, by a compare and swap that only ever raises it, so that
183
- * workers appending at once never lower what another made it.
184
- */
185
- extend(length) {
186
- if (this.shared === null) {
187
- this.setLength(length);
188
- return;
189
- }
190
- this.reserve(length, false);
191
- this.raise(length);
192
- this.notify();
193
- }
194
- /** A shared length raised to `length` unless another worker made it as long. */
195
- raise(length) {
196
- const words = this.sharedWords;
197
- for (;;) {
198
- const now = Atomics.load(words, 0) >>> 0;
199
- if (now >= length || Atomics.compareExchange(words, 0, now | 0, length | 0) >>> 0 === now) {
200
- return;
201
- }
202
- }
203
- }
204
- /** As Grower::SetLengthCommon, before the length is set: the capacity for `length`. */
205
- reserve(length, fromSetter) {
206
- if (!fromSetter || (length < kHugeGrowthThreshold && this.length < kHugeGrowthThreshold)) {
207
- if (length > this.buffer.length) {
208
- this.ensure(length, fromSetter);
209
- }
210
- }
211
- else {
212
- const rounded = Math.ceil(length / kHugeGrowthIncr) * kHugeGrowthIncr;
213
- const capacity = rounded <= 0xffffffff - 2 * 4096 ? rounded : length;
214
- if (capacity !== this.buffer.length) {
215
- this.realloc(capacity, length, true);
216
- }
217
- }
218
- }
219
- /** Tell the domain memory, if this is it, where the bytes are now: a new view only if they moved or their length changed. */
220
- notify() {
221
- const rt = this.rt;
222
- if (this.subscribed &&
223
- (rt.memory.buffer !== this.buffer.buffer || rt.memoryLength !== this.length)) {
224
- rt.memory = new DataView(this.buffer.buffer, 0, this.length);
225
- }
226
- }
227
- /** As ByteArray::Clear: no buffer at all; shared, every worker's ByteArray for it empty. */
228
- clear() {
229
- if (this.subscribed) {
230
- throw this.rt.error("RangeError", 1506);
231
- }
232
- this.position = 0;
233
- if (this.shared !== null) {
234
- // The memory cannot shrink: what it held is zeroed, as a new buffer
235
- // would be once it grows again, before the length is told, so that a
236
- // worker that grows it once it is empty writes into zeroes already.
237
- this.buffer.fill(0);
238
- this.length = 0;
239
- return;
240
- }
241
- this.setBuffer(new Uint8Array(0));
242
- this.length = 0;
243
- }
244
- /**
245
- * Its memory, shared from now on: a growable SharedArrayBuffer its bytes
246
- * move to once, and that this ByteArray, and every worker's ByteArray for
247
- * it, uses from then on. Where memory cannot be shared, the error that
248
- * names cross-origin isolation.
249
- */
250
- share() {
251
- if (this.shared !== null) {
252
- return this.shared;
253
- }
254
- if (!canShareMemory()) {
255
- throw notIsolated("a shareable ByteArray");
256
- }
257
- const capacity = Math.max(this.buffer.length, this.length);
258
- const Shared = SharedArrayBuffer;
259
- let data = null;
260
- // As much room to grow as a ByteArray has, or as much as the host reserves.
261
- for (let max = kMaxCapacity; data === null; max /= 2) {
262
- try {
263
- data = new Shared(capacity, { maxByteLength: Math.max(max, capacity) });
264
- }
265
- catch {
266
- if (max <= capacity) {
267
- throw this.rt.error("flash.errors::MemoryError", 1000);
268
- }
269
- }
270
- }
271
- new Uint8Array(data).set(this.buffer);
272
- const memory = {
273
- id: Math.floor(Math.random() * 2 ** 52),
274
- meta: new SharedArrayBuffer(8),
275
- data,
276
- };
277
- new Int32Array(memory.meta)[0] = this.length | 0;
278
- this.adopt(memory);
279
- sharedObjectsOf(this.rt).set(memory.id, new WeakRef(this.owner));
280
- return memory;
281
- }
282
- /**
283
- * Use `memory`, shared, as its bytes and length from now on. Its length
284
- * becomes an accessor of the memory's word on this object alone, so that
285
- * every read sees another worker's change and every write is seen, and
286
- * a ByteArray that shares nothing reads a plain field as before.
287
- */
288
- adopt(memory) {
289
- this.shared = memory;
290
- this.shareable = true;
291
- const words = new Int32Array(memory.meta);
292
- this.sharedWords = words;
293
- Object.defineProperty(this, "length", {
294
- get: () => Atomics.load(words, 0) >>> 0,
295
- set: (length) => Atomics.store(words, 0, length | 0),
296
- configurable: true,
297
- });
298
- // Views that track the memory's length as any worker grows it.
299
- this.buffer = new Uint8Array(memory.data);
300
- this.view = new DataView(memory.data);
301
- this.sharedInts = new Int32Array(memory.data);
302
- const { runtime, own } = this.capacity;
303
- runtime.bytes += memory.data.byteLength - own.bytes;
304
- own.bytes = memory.data.byteLength;
305
- if (this.subscribed) {
306
- this.rt.refreshMemory = () => this.notify();
307
- }
308
- this.notify();
309
- }
310
- /**
311
- * A shared memory's capacity made at least `capacity`: it grows in place,
312
- * which every worker sees, and never shrinks, as another worker may have
313
- * grown it past what this one asks for since. Nor is what a smaller
314
- * buffer would drop zeroed: without avmplus' safepoint, another worker
315
- * may have grown the length again and written there meanwhile, so bytes
316
- * past a lowered length may come back when it grows again.
317
- */
318
- reshare(capacity) {
319
- const data = this.shared.data;
320
- if (capacity <= data.byteLength) {
321
- return;
322
- }
323
- if (capacity > data.maxByteLength) {
324
- throw this.rt.error("flash.errors::MemoryError", 1000);
325
- }
326
- try {
327
- data.grow(capacity);
328
- }
329
- catch {
330
- // Another worker grew it meanwhile, to as much or more, or the host refused.
331
- if (data.byteLength < capacity) {
332
- throw this.rt.error("flash.errors::MemoryError", 1000);
333
- }
334
- }
335
- const { runtime, own } = this.capacity;
336
- runtime.bytes += data.byteLength - own.bytes;
337
- own.bytes = data.byteLength;
338
- }
339
- /** As ByteArray::CAS, once the index is checked: atomic where the memory is shared. */
340
- compareAndSwapInt(at, expected, next) {
341
- if (this.sharedInts !== null) {
342
- return Atomics.compareExchange(this.sharedInts, at >> 2, expected, next);
343
- }
344
- const previous = this.view.getInt32(at, true);
345
- if (previous === expected) {
346
- this.view.setInt32(at, next, true);
347
- }
348
- return previous;
349
- }
350
- /**
351
- * As UnprotectedAtomicCompareAndSwapLength: the length set to `next`, as
352
- * its setter sets it, if it is `expected`; the length before. Shared,
353
- * the capacity is made first and the length swapped atomically, so that
354
- * of workers growing it at once one wins.
355
- */
356
- compareAndSwapLength(expected, next) {
357
- if (this.shared === null) {
358
- const previous = this.length;
359
- if (previous === expected) {
360
- this.setLength(next, true);
361
- }
362
- return previous;
363
- }
364
- // Read once: another worker may change it between two reads.
365
- const now = this.length;
366
- if (now !== expected) {
367
- return now;
368
- }
369
- // Only grows the memory, so it does nothing another worker would undo if the swap fails.
370
- this.reserve(next, true);
371
- const previous = Atomics.compareExchange(this.sharedWords, 0, expected | 0, next | 0) >>> 0;
372
- if (previous === expected && this.position > next) {
373
- this.position = next;
374
- }
375
- this.notify();
376
- return previous;
377
- }
378
- /** As requestBytesForShortRead: the offset of `n` bytes to read, or EOFError. */
379
- shortRead(n) {
380
- const at = this.position;
381
- if (at >= this.length || at + n > this.length) {
382
- throw this.rt.error("flash.errors::EOFError", 2030);
383
- }
384
- this.position = (at + n) >>> 0;
385
- return at;
386
- }
387
- /** As requestBytesForShortWrite: the offset of `n` bytes to write, the length grown to hold them. */
388
- shortWrite(n) {
389
- const at = this.position;
390
- if (at >= this.length || at + n > this.length) {
391
- if (at + n > 0xffffffff) {
392
- throw this.rt.error("flash.errors::MemoryError", 1000);
393
- }
394
- this.extend(at + n);
395
- }
396
- this.position = (at + n) >>> 0;
397
- return at;
398
- }
399
- /** As DataInput::CheckEOF. */
400
- checkEOF(count) {
401
- if (this.available < count) {
402
- throw this.rt.error("flash.errors::EOFError", 2030);
403
- }
404
- }
405
- /** As ByteArray::Read: `count` bytes from the position. */
406
- read(count) {
407
- this.checkEOF(count);
408
- const bytes = this.buffer.slice(this.position, this.position + count);
409
- this.position = (this.position + count) >>> 0;
410
- return bytes;
411
- }
412
- /** As read, but the bytes themselves, not a copy: for a caller that only reads them, at once. */
413
- readView(count) {
414
- this.checkEOF(count);
415
- const bytes = this.buffer.subarray(this.position, this.position + count);
416
- this.position = (this.position + count) >>> 0;
417
- return bytes;
418
- }
419
- /**
420
- * As ByteArray::Write: `count` bytes of `source` from `offset`, all of
421
- * it by default, at the position; the length grows to the position after.
422
- */
423
- write(source, offset = 0, count = source.length) {
424
- if (count > 0xffffffff - this.position) {
425
- throw this.rt.error("flash.errors::MemoryError", 1000);
426
- }
427
- const end = (this.position + count) >>> 0;
428
- if (end > this.buffer.length) {
429
- this.ensure(end, false);
430
- }
431
- copyBytes(this.buffer, this.position, source, offset, count);
432
- this.position = end;
433
- if (this.length < end) {
434
- if (this.shared === null) {
435
- this.length = end;
436
- }
437
- else {
438
- this.raise(end);
439
- }
440
- }
441
- this.notify();
442
- }
443
- /** As ByteArray's operator[] for a write: the length grows to hold `index`. */
444
- setByte(index, value) {
445
- if (index >= this.length) {
446
- if (index === 0xffffffff) {
447
- throw this.rt.error("flash.errors::MemoryError", 1000);
448
- }
449
- this.extend(index + 1);
450
- }
451
- this.buffer[index] = value;
452
- }
453
- }
454
- /** Below this many bytes, copyBytes copies one at a time. */
455
- const COPY_LOOP_LENGTH = 32;
456
- /**
457
- * `count` bytes of `source` from `offset` copied into `target` at `at`,
458
- * as memmove copies them where the two are one array. Part of `source`,
459
- * fewer than COPY_LOOP_LENGTH bytes, is copied one at a time: the
460
- * subarray set() would take costs more than they do, in JavaScriptCore up
461
- * to about 64 bytes and in V8 up to about 32. All of it set() copies
462
- * faster than a loop in V8, and as fast in JavaScriptCore.
463
- */
464
- function copyBytes(target, at, source, offset, count) {
465
- if (source === target) {
466
- target.copyWithin(at, offset, offset + count);
467
- }
468
- else if (offset === 0 && count === source.length) {
469
- target.set(source, at);
470
- }
471
- else if (count < COPY_LOOP_LENGTH) {
472
- for (let i = 0; i < count; i++) {
473
- target[at + i] = source[offset + i];
474
- }
475
- }
476
- else {
477
- target.set(source.subarray(offset, offset + count), at);
478
- }
479
- }
480
17
  /** How a ByteArray's elements are indexed: its bytes; past its length undefined, and a write grows it. */
481
18
  export const byteArrayHook = {
482
19
  // Its state from the start: it takes defaultObjectEncoding as it is then.
@@ -497,37 +34,6 @@ export const byteArrayHook = {
497
34
  return b !== undefined && i < b.length;
498
35
  },
499
36
  };
500
- /** A ByteArray's state, made the first time a native needs it. */
501
- export function bytesOf(rt, o) {
502
- if (!o.$bytes) {
503
- o.$bytes = new Bytes(rt, o);
504
- }
505
- return o.$bytes;
506
- }
507
- /**
508
- * A shareable ByteArray's memory, shared from now on, as it crosses to
509
- * another worker; where memory cannot be shared, the error that names
510
- * cross-origin isolation.
511
- */
512
- export function shareBytes(rt, o) {
513
- return bytesOf(rt, o).share();
514
- }
515
- /** This VM's one ByteArray for a shared memory, as avmplus interns one for its Buffer: shareable, at position 0. */
516
- export function sharedByteArray(rt, memory) {
517
- const objects = sharedObjectsOf(rt);
518
- const known = objects.get(memory.id)?.deref();
519
- if (known) {
520
- return known;
521
- }
522
- const o = rt.construct(rt.classNamed("flash.utils::ByteArray"));
523
- bytesOf(rt, o).adopt(memory);
524
- objects.set(memory.id, new WeakRef(o));
525
- return o;
526
- }
527
- /** This VM's ByteArray for the shared memory `id`, if it has one. */
528
- export function knownSharedByteArray(rt, id) {
529
- return sharedObjectsOf(rt).get(id)?.deref();
530
- }
531
37
  /** The longest string readUTFBytes reads a character at a time. */
532
38
  const SHORT_STRING = 24;
533
39
  /** The bytes up to the first NUL, as avmplus reads a C string. */