@swf2es/player-hosts 0.1.3 → 0.1.5

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 (45) hide show
  1. package/dist/thread/format/bitmap.js +13 -14
  2. package/dist/thread/format/index.js +1 -1
  3. package/dist/thread/format/swf.js +11 -1
  4. package/dist/thread/player/avm1/globals/BitmapData.js +2 -1
  5. package/dist/thread/player/avm1/keyboard.js +13 -0
  6. package/dist/thread/player/avm1/loads.js +3 -0
  7. package/dist/thread/player/bitmap/composite.js +767 -0
  8. package/dist/thread/player/bitmap/draw.js +3 -3
  9. package/dist/thread/player/bitmap/filters.js +32 -32
  10. package/dist/thread/player/bitmap/ops.js +2 -766
  11. package/dist/thread/player/bitmap/pixel-bender.js +4 -1
  12. package/dist/thread/player/display/displayobject.js +1 -1
  13. package/dist/thread/player/display/instantiate.js +28 -29
  14. package/dist/thread/player/input/keyboard.js +20 -1
  15. package/dist/thread/player/input/text-input.js +99 -0
  16. package/dist/thread/player/media/audio.js +11 -0
  17. package/dist/thread/player/media/sounds.js +20 -0
  18. package/dist/thread/player/player.js +3 -1
  19. package/dist/thread/player/playerglobal/flash/desktop/NativeApplication.js +1 -1
  20. package/dist/thread/player/playerglobal/flash/display/BitmapData.js +3 -2
  21. package/dist/thread/player/playerglobal/flash/display/SimpleButton.js +12 -11
  22. package/dist/thread/player/playerglobal/flash/display/Stage.js +2 -8
  23. package/dist/thread/player/playerglobal/flash/display/shaders.js +1 -1
  24. package/dist/thread/player/playerglobal/flash/filesystem/paths.js +1 -1
  25. package/dist/thread/player/playerglobal/flash/filesystem/writes.js +1 -1
  26. package/dist/thread/player/playerglobal/flash/globalization/locale.js +1 -1
  27. package/dist/thread/player/playerglobal/flash/media/Sound.js +3 -0
  28. package/dist/thread/player/scripting/events.js +2 -2
  29. package/dist/thread/player/scripting/loads.js +4 -1
  30. package/dist/thread/player/scripting/symbols.js +24 -30
  31. package/dist/thread/player/scripting.js +1 -6
  32. package/dist/thread/runtime/avm1/errors.js +1 -1
  33. package/dist/thread/runtime/avm1/numbers.js +7 -8
  34. package/dist/thread/runtime/avm2/amf.js +2 -1
  35. package/dist/thread/runtime/avm2/names.js +0 -4
  36. package/dist/thread/runtime/avm2/natives/bytearray.js +6 -166
  37. package/dist/thread/runtime/avm2/natives/regexp.js +68 -64
  38. package/dist/thread/runtime/avm2/natives/shell-workers.js +1 -1
  39. package/dist/thread/runtime/avm2/natives/shell.js +2 -1
  40. package/dist/thread/runtime/avm2/natives/xml/parser.js +2 -2
  41. package/dist/thread/runtime/avm2/numbers.js +1 -1
  42. package/dist/thread/runtime/avm2/runtime.js +10 -8
  43. package/dist/thread/runtime/avm2/traits.js +1 -1
  44. package/dist/thread/runtime/avm2/utf8.js +167 -0
  45. package/package.json +2 -2
@@ -2,13 +2,14 @@
2
2
  // DataInput/DataOutput implement them. The buffer keeps avmplus' capacity:
3
3
  // it grows as avmplus' Grower grows it, zeroing what a reallocation adds,
4
4
  // so bytes a shorter length left behind come back when the length grows
5
- // within the capacity, as they do in avmplus. UTF-8 is avmplus' own: an
6
- // invalid byte reads as the character of its value.
5
+ // within the capacity, as they do in avmplus. UTF-8 is avmplus' own
6
+ // (utf8.ts).
7
7
  //
8
- // Translated from avmplus' core/ByteArrayGlue.cpp, core/DataIO.cpp and
9
- // core/UnicodeUtils.cpp, this file is subject to the Mozilla Public
10
- // License, v. 2.0: http://mozilla.org/MPL/2.0/.
8
+ // Translated from avmplus' core/ByteArrayGlue.cpp and core/DataIO.cpp,
9
+ // this file is subject to the Mozilla Public License, v. 2.0:
10
+ // http://mozilla.org/MPL/2.0/.
11
11
  import { CompressedDataError, CompressedDataTooLargeError, deflateCompress, LZMA_HEADER, lzmaByteArrayCompress, lzmaByteArrayUncompress, zlibCompress, zlibUncompress, } from "../../../format/index.js";
12
+ import { fromCodes, fromUtf8, utf8 } from "../utf8.js";
12
13
  import { registerNativeClass } from "./define.js";
13
14
  const kGrowthIncr = 4096;
14
15
  const kHugeGrowthThreshold = 24 * 1024 * 1024;
@@ -527,167 +528,6 @@ export function sharedByteArray(rt, memory) {
527
528
  export function knownSharedByteArray(rt, id) {
528
529
  return sharedObjectsOf(rt).get(id)?.deref();
529
530
  }
530
- /** The host's UTF-8 encoder, which writes a lone surrogate as U+FFFD, as utf8() does. */
531
- const encoder = new TextEncoder();
532
- /**
533
- * Below this length, a string encodes faster here than through
534
- * TextEncoder, whose call costs more than the loop saves (about 90
535
- * characters in V8).
536
- */
537
- const ENCODER_LENGTH = 96;
538
- /**
539
- * As UnicodeUtils::Utf16ToUtf8: a surrogate pair as four bytes, a lone
540
- * surrogate as U+FFFD. avmshell's writeUTFBytes loses characters around a
541
- * lone one instead; this keeps them, and the UTF-8 valid.
542
- */
543
- export function utf8(s) {
544
- if (s.length >= ENCODER_LENGTH) {
545
- return encoder.encode(s);
546
- }
547
- // ASCII, byte for byte.
548
- let ascii = true;
549
- for (let i = 0; i < s.length && ascii; i++) {
550
- ascii = s.charCodeAt(i) < 0x80;
551
- }
552
- if (ascii) {
553
- const out = new Uint8Array(s.length);
554
- for (let i = 0; i < s.length; i++) {
555
- out[i] = s.charCodeAt(i);
556
- }
557
- return out;
558
- }
559
- const out = new Uint8Array(s.length * 3);
560
- let n = 0;
561
- for (let i = 0; i < s.length; i++) {
562
- let ch = s.charCodeAt(i);
563
- if (ch < 0x80) {
564
- out[n++] = ch;
565
- continue;
566
- }
567
- if (ch < 0x800) {
568
- out[n++] = 0xc0 | ((ch >> 6) & 0x1f);
569
- out[n++] = 0x80 | (ch & 0x3f);
570
- continue;
571
- }
572
- if (ch >= 0xd800 && ch <= 0xdbff) {
573
- const ch2 = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;
574
- if (ch2 >= 0xdc00 && ch2 <= 0xdfff) {
575
- i++;
576
- const ucs4 = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
577
- out[n++] = 0xf0 | ((ucs4 >> 18) & 0x07);
578
- out[n++] = 0x80 | ((ucs4 >> 12) & 0x3f);
579
- out[n++] = 0x80 | ((ucs4 >> 6) & 0x3f);
580
- out[n++] = 0x80 | (ucs4 & 0x3f);
581
- continue;
582
- }
583
- ch = 0xfffd;
584
- }
585
- else if (ch >= 0xdc00 && ch <= 0xdfff) {
586
- ch = 0xfffd;
587
- }
588
- out[n++] = 0xe0 | ((ch >> 12) & 0x0f);
589
- out[n++] = 0x80 | ((ch >> 6) & 0x3f);
590
- out[n++] = 0x80 | (ch & 0x3f);
591
- }
592
- return out.subarray(0, n);
593
- }
594
- /**
595
- * As UnicodeUtils::Utf8ToUtf16, not strict: a byte that does not start a
596
- * valid sequence is the character of its value, and a four-byte sequence
597
- * may start with 0xF8 to 0xFF, as Flash Player 9 and 10 read them.
598
- */
599
- /** The length from which fromUtf8 first looks for ASCII. */
600
- const ASCII_LENGTH = 16;
601
- export function fromUtf8(bytes) {
602
- const n = bytes.length;
603
- // ASCII, as most text is: its bytes are its characters. Below
604
- // ASCII_LENGTH bytes, a character at a time, until one is not.
605
- if (n < ASCII_LENGTH) {
606
- let s = "";
607
- let k = 0;
608
- for (; k < n && bytes[k] < 0x80; k++) {
609
- s += String.fromCharCode(bytes[k]);
610
- }
611
- if (k === n) {
612
- return s;
613
- }
614
- }
615
- else {
616
- let ascii = 0;
617
- while (ascii < n && bytes[ascii] < 0x80) {
618
- ascii++;
619
- }
620
- if (ascii === n) {
621
- let s = "";
622
- for (let k = 0; k < n; k += 8192) {
623
- s += String.fromCharCode.apply(null, bytes.subarray(k, k + 8192));
624
- }
625
- return s;
626
- }
627
- }
628
- const out = [];
629
- let i = 0;
630
- while (i < n) {
631
- const c = bytes[i];
632
- const left = n - i;
633
- switch (c >> 4) {
634
- case 12:
635
- case 13: {
636
- if (left >= 2 && (bytes[i + 1] & 0xc0) === 0x80) {
637
- const ch = ((c << 6) & 0x7c0) | (bytes[i + 1] & 0x3f);
638
- if (ch >= 0x80) {
639
- out.push(ch);
640
- i += 2;
641
- continue;
642
- }
643
- }
644
- break;
645
- }
646
- case 14: {
647
- if (left >= 3 && (bytes[i + 1] & 0xc0) === 0x80 && (bytes[i + 2] & 0xc0) === 0x80) {
648
- const ch = ((c << 12) & 0xf000) | ((bytes[i + 1] << 6) & 0xfc0) | (bytes[i + 2] & 0x3f);
649
- if (ch >= 0x800) {
650
- out.push(ch);
651
- i += 3;
652
- continue;
653
- }
654
- }
655
- break;
656
- }
657
- case 15: {
658
- if (left >= 4 &&
659
- (bytes[i + 1] & 0xc0) === 0x80 &&
660
- (bytes[i + 2] & 0xc0) === 0x80 &&
661
- (bytes[i + 3] & 0xc0) === 0x80) {
662
- const ch = ((c << 18) & 0x1c0000) |
663
- ((bytes[i + 1] << 12) & 0x3f000) |
664
- ((bytes[i + 2] << 6) & 0xfc0) |
665
- (bytes[i + 3] & 0x3f);
666
- if (ch >= 0x10000) {
667
- out.push((((ch - 0x10000) >> 10) & 0x3ff) + 0xd800, ((ch - 0x10000) & 0x3ff) + 0xdc00);
668
- i += 4;
669
- continue;
670
- }
671
- }
672
- break;
673
- }
674
- default:
675
- break;
676
- }
677
- // Not a sequence: the byte itself.
678
- out.push(c);
679
- i++;
680
- }
681
- return fromCodes(out);
682
- }
683
- /** A string of UTF-16 code units, in chunks, as String.fromCharCode takes only so many arguments. */
684
- function fromCodes(units) {
685
- let s = "";
686
- for (let k = 0; k < units.length; k += 8192) {
687
- s += String.fromCharCode(...units.slice(k, k + 8192));
688
- }
689
- return s;
690
- }
691
531
  /** The bytes up to the first NUL, as avmplus reads a C string. */
692
532
  function toNul(bytes) {
693
533
  const nul = bytes.indexOf(0);
@@ -170,25 +170,25 @@ function variableLookbehind(source) {
170
170
  /** The length of the item at i, which it steps past. */
171
171
  const item = () => {
172
172
  const c = source[i++];
173
- if (c === "(") {
174
- return group();
175
- }
176
- if (c === "^" || c === "$") {
177
- return 0;
178
- }
179
- if (c === "[") {
180
- if (source[i] === "^") {
181
- i++;
182
- }
183
- // A ] first is a literal.
184
- if (source[i] === "]") {
173
+ switch (c) {
174
+ case "(":
175
+ return group();
176
+ case "^":
177
+ case "$":
178
+ return 0;
179
+ case "[":
180
+ if (source[i] === "^") {
181
+ i++;
182
+ }
183
+ // A ] first is a literal.
184
+ if (source[i] === "]") {
185
+ i++;
186
+ }
187
+ while (i < source.length && source[i] !== "]") {
188
+ i += source[i] === "\\" ? 2 : 1;
189
+ }
185
190
  i++;
186
- }
187
- while (i < source.length && source[i] !== "]") {
188
- i += source[i] === "\\" ? 2 : 1;
189
- }
190
- i++;
191
- return 1;
191
+ return 1;
192
192
  }
193
193
  if (c !== "\\") {
194
194
  // A character beyond the BMP is one in PCRE's UTF-8 too.
@@ -265,57 +265,61 @@ function nestedTooDeep(source) {
265
265
  for (let i = 0; i < source.length; i++) {
266
266
  const c = source[i];
267
267
  let item = 2;
268
- if (c === "(") {
269
- const capture = source[i + 1] !== "?" || source.startsWith("(?P<", i);
270
- outer.push(held);
271
- held += previous + (capture ? 5 : 3);
272
- previous = 0;
273
- if (held > WORKSPACE) {
274
- return true;
275
- }
276
- // Past the group's kind: ?: ?= ?! ?<= ?<! ?P<name> or flags.
277
- if (source[i + 1] === "?") {
278
- const end = source.slice(i + 2).search(/[:=!>)]/);
279
- i = end < 0 ? source.length : i + 2 + end;
268
+ switch (c) {
269
+ case "(": {
270
+ const capture = source[i + 1] !== "?" || source.startsWith("(?P<", i);
271
+ outer.push(held);
272
+ held += previous + (capture ? 5 : 3);
273
+ previous = 0;
274
+ if (held > WORKSPACE) {
275
+ return true;
276
+ }
277
+ // Past the group's kind: ?: ?= ?! ?<= ?<! ?P<name> or flags.
278
+ if (source[i + 1] === "?") {
279
+ const end = source.slice(i + 2).search(/[:=!>)]/);
280
+ i = end < 0 ? source.length : i + 2 + end;
281
+ }
282
+ continue;
280
283
  }
281
- continue;
282
- }
283
- if (c === ")") {
284
- held = outer.pop() ?? held;
285
- // The group is the next one's previous item, but what it holds is gone.
286
- previous = 0;
287
- continue;
288
- }
289
- if (c === "|") {
290
- previous = 0;
291
- continue;
292
- }
293
- if (c === "\\") {
294
- i++;
295
- }
296
- else if (c === "[") {
297
- // A class is its opcode and a 32-byte bitmap.
298
- item = 33;
299
- i++;
300
- if (source[i] === "^") {
284
+ case ")":
285
+ held = outer.pop() ?? held;
286
+ // The group is the next one's previous item, but what it holds is gone.
287
+ previous = 0;
288
+ continue;
289
+ case "|":
290
+ previous = 0;
291
+ continue;
292
+ case "\\":
301
293
  i++;
302
- }
303
- // A ] first is a literal.
304
- if (source[i] === "]") {
294
+ break;
295
+ case "[":
296
+ // A class is its opcode and a 32-byte bitmap.
297
+ item = 33;
305
298
  i++;
306
- }
307
- while (i < source.length && source[i] !== "]") {
308
- if (source[i] === "\\") {
299
+ if (source[i] === "^") {
309
300
  i++;
310
301
  }
311
- i++;
312
- }
313
- }
314
- else if (c === "." || c === "^" || c === "$") {
315
- item = 1;
316
- }
317
- else if ("*+?{".includes(c)) {
318
- continue;
302
+ // A ] first is a literal.
303
+ if (source[i] === "]") {
304
+ i++;
305
+ }
306
+ while (i < source.length && source[i] !== "]") {
307
+ if (source[i] === "\\") {
308
+ i++;
309
+ }
310
+ i++;
311
+ }
312
+ break;
313
+ case ".":
314
+ case "^":
315
+ case "$":
316
+ item = 1;
317
+ break;
318
+ case "*":
319
+ case "+":
320
+ case "?":
321
+ case "{":
322
+ continue;
319
323
  }
320
324
  previous = item;
321
325
  if (held + previous > WORKSPACE) {
@@ -8,7 +8,7 @@
8
8
  // The host starts the threads (RuntimeOptions.workers); each runs a
9
9
  // runtime made with its worker's ShellWorkerInit, which the runtime finds
10
10
  // here by its id.
11
- import { fromUtf8, utf8 } from "./bytearray.js";
11
+ import { fromUtf8, utf8 } from "../utf8.js";
12
12
  import { Sync } from "./sync.js";
13
13
  /** avmplus' Isolate::State. */
14
14
  export const NEW = 1;
@@ -3,7 +3,8 @@
3
3
  // the host starts (RuntimeOptions.workers; shell-workers.ts).
4
4
  import { Reader, Writer } from "../amf.js";
5
5
  import { setStaticVar } from "../traits.js";
6
- import { byteArrayCapacity, bytesOf, fromUtf8, GLOBAL_MEMORY_MIN_SIZE, knownSharedByteArray, setDomainMemory, sharedByteArray, utf8, } from "./bytearray.js";
6
+ import { fromUtf8, utf8 } from "../utf8.js";
7
+ import { byteArrayCapacity, bytesOf, GLOBAL_MEMORY_MIN_SIZE, knownSharedByteArray, setDomainMemory, sharedByteArray, } from "./bytearray.js";
7
8
  import { syncObject, syncOf, syncRef } from "./concurrent.js";
8
9
  import { elements, registerNativeClass } from "./define.js";
9
10
  import { CANSTART, entryKey, FAILED, ITEM_AMF, ITEM_BYTES, ITEM_NUMBER, ITEM_SHARED, ITEM_SYNC, NEW, newWorkersMemory, RUNNING, STATE_NAMES, sleep, Workers, WorkerTerminated, } from "./shell-workers.js";
@@ -11,8 +11,8 @@ export const TAG_TEXT = 3;
11
11
  export const TAG_CDATA = 4;
12
12
  export const TAG_PROCESSING_INSTRUCTION = 7;
13
13
  export const TAG_COMMENT = 8;
14
- export const TAG_DOCTYPE = 10;
15
- export const TAG_XML_DECLARATION = 13;
14
+ const TAG_DOCTYPE = 10;
15
+ const TAG_XML_DECLARATION = 13;
16
16
  // What getNext gives, as XMLParser's status codes: a tag, the end, or the
17
17
  // error E4X throws for each (see PARSE_ERRORS in values.ts).
18
18
  export const OK = 0;
@@ -7,7 +7,7 @@
7
7
  //
8
8
  // Translated from avmplus' core/MathUtils.cpp and core/d2a.cpp, this file is
9
9
  // subject to the Mozilla Public License, v. 2.0: http://mozilla.org/MPL/2.0/.
10
- export const DTOSTR_NORMAL = 0;
10
+ const DTOSTR_NORMAL = 0;
11
11
  export const DTOSTR_FIXED = 1;
12
12
  export const DTOSTR_PRECISION = 2;
13
13
  export const DTOSTR_EXPONENTIAL = 3;
@@ -574,14 +574,16 @@ export class Runtime {
574
574
  if (!traits) {
575
575
  traits = this.builtinClass(name).$it;
576
576
  this.builtinTraitsByName.set(name, traits);
577
- if (name === "String") {
578
- this.stringTraits = traits;
579
- }
580
- else if (name === "Number") {
581
- this.numberTraits = traits;
582
- }
583
- else if (name === "Boolean") {
584
- this.booleanTraits = traits;
577
+ switch (name) {
578
+ case "String":
579
+ this.stringTraits = traits;
580
+ break;
581
+ case "Number":
582
+ this.numberTraits = traits;
583
+ break;
584
+ case "Boolean":
585
+ this.booleanTraits = traits;
586
+ break;
585
587
  }
586
588
  }
587
589
  return traits;
@@ -473,7 +473,7 @@ const HOME_SLACK = 16;
473
473
  * array through an accessor on the prototype (spilledSlot), so that what
474
474
  * looks slots up by name finds them as any other.
475
475
  */
476
- export const SPILL_SLOTS = 900;
476
+ const SPILL_SLOTS = 900;
477
477
  /** Slot `slot`'s accessor in `home`, a prototype of its objects: the object's `$S` at its place. */
478
478
  function spilledSlot(home, slot) {
479
479
  const at = slot - SPILL_SLOTS;
@@ -0,0 +1,167 @@
1
+ // UTF-8 as avmplus reads and writes it: an invalid byte reads as the
2
+ // character of its value, a lone surrogate writes as U+FFFD. ByteArray,
3
+ // AMF and the shell's natives share it.
4
+ //
5
+ // Translated from avmplus' core/UnicodeUtils.cpp, this file is subject to
6
+ // the Mozilla Public License, v. 2.0: http://mozilla.org/MPL/2.0/.
7
+ /** The host's UTF-8 encoder, which writes a lone surrogate as U+FFFD, as utf8() does. */
8
+ const encoder = new TextEncoder();
9
+ /**
10
+ * Below this length, a string encodes faster here than through
11
+ * TextEncoder, whose call costs more than the loop saves (about 90
12
+ * characters in V8).
13
+ */
14
+ const ENCODER_LENGTH = 96;
15
+ /**
16
+ * As UnicodeUtils::Utf16ToUtf8: a surrogate pair as four bytes, a lone
17
+ * surrogate as U+FFFD. avmshell's writeUTFBytes loses characters around a
18
+ * lone one instead; this keeps them, and the UTF-8 valid.
19
+ */
20
+ export function utf8(s) {
21
+ if (s.length >= ENCODER_LENGTH) {
22
+ return encoder.encode(s);
23
+ }
24
+ // ASCII, byte for byte.
25
+ let ascii = true;
26
+ for (let i = 0; i < s.length && ascii; i++) {
27
+ ascii = s.charCodeAt(i) < 0x80;
28
+ }
29
+ if (ascii) {
30
+ const out = new Uint8Array(s.length);
31
+ for (let i = 0; i < s.length; i++) {
32
+ out[i] = s.charCodeAt(i);
33
+ }
34
+ return out;
35
+ }
36
+ const out = new Uint8Array(s.length * 3);
37
+ let n = 0;
38
+ for (let i = 0; i < s.length; i++) {
39
+ let ch = s.charCodeAt(i);
40
+ if (ch < 0x80) {
41
+ out[n++] = ch;
42
+ continue;
43
+ }
44
+ if (ch < 0x800) {
45
+ out[n++] = 0xc0 | ((ch >> 6) & 0x1f);
46
+ out[n++] = 0x80 | (ch & 0x3f);
47
+ continue;
48
+ }
49
+ if (ch >= 0xd800 && ch <= 0xdbff) {
50
+ const ch2 = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;
51
+ if (ch2 >= 0xdc00 && ch2 <= 0xdfff) {
52
+ i++;
53
+ const ucs4 = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
54
+ out[n++] = 0xf0 | ((ucs4 >> 18) & 0x07);
55
+ out[n++] = 0x80 | ((ucs4 >> 12) & 0x3f);
56
+ out[n++] = 0x80 | ((ucs4 >> 6) & 0x3f);
57
+ out[n++] = 0x80 | (ucs4 & 0x3f);
58
+ continue;
59
+ }
60
+ ch = 0xfffd;
61
+ }
62
+ else if (ch >= 0xdc00 && ch <= 0xdfff) {
63
+ ch = 0xfffd;
64
+ }
65
+ out[n++] = 0xe0 | ((ch >> 12) & 0x0f);
66
+ out[n++] = 0x80 | ((ch >> 6) & 0x3f);
67
+ out[n++] = 0x80 | (ch & 0x3f);
68
+ }
69
+ return out.subarray(0, n);
70
+ }
71
+ /**
72
+ * As UnicodeUtils::Utf8ToUtf16, not strict: a byte that does not start a
73
+ * valid sequence is the character of its value, and a four-byte sequence
74
+ * may start with 0xF8 to 0xFF, as Flash Player 9 and 10 read them.
75
+ */
76
+ /** The length from which fromUtf8 first looks for ASCII. */
77
+ const ASCII_LENGTH = 16;
78
+ export function fromUtf8(bytes) {
79
+ const n = bytes.length;
80
+ // ASCII, as most text is: its bytes are its characters. Below
81
+ // ASCII_LENGTH bytes, a character at a time, until one is not.
82
+ if (n < ASCII_LENGTH) {
83
+ let s = "";
84
+ let k = 0;
85
+ for (; k < n && bytes[k] < 0x80; k++) {
86
+ s += String.fromCharCode(bytes[k]);
87
+ }
88
+ if (k === n) {
89
+ return s;
90
+ }
91
+ }
92
+ else {
93
+ let ascii = 0;
94
+ while (ascii < n && bytes[ascii] < 0x80) {
95
+ ascii++;
96
+ }
97
+ if (ascii === n) {
98
+ let s = "";
99
+ for (let k = 0; k < n; k += 8192) {
100
+ s += String.fromCharCode.apply(null, bytes.subarray(k, k + 8192));
101
+ }
102
+ return s;
103
+ }
104
+ }
105
+ const out = [];
106
+ let i = 0;
107
+ while (i < n) {
108
+ const c = bytes[i];
109
+ const left = n - i;
110
+ switch (c >> 4) {
111
+ case 12:
112
+ case 13: {
113
+ if (left >= 2 && (bytes[i + 1] & 0xc0) === 0x80) {
114
+ const ch = ((c << 6) & 0x7c0) | (bytes[i + 1] & 0x3f);
115
+ if (ch >= 0x80) {
116
+ out.push(ch);
117
+ i += 2;
118
+ continue;
119
+ }
120
+ }
121
+ break;
122
+ }
123
+ case 14: {
124
+ if (left >= 3 && (bytes[i + 1] & 0xc0) === 0x80 && (bytes[i + 2] & 0xc0) === 0x80) {
125
+ const ch = ((c << 12) & 0xf000) | ((bytes[i + 1] << 6) & 0xfc0) | (bytes[i + 2] & 0x3f);
126
+ if (ch >= 0x800) {
127
+ out.push(ch);
128
+ i += 3;
129
+ continue;
130
+ }
131
+ }
132
+ break;
133
+ }
134
+ case 15: {
135
+ if (left >= 4 &&
136
+ (bytes[i + 1] & 0xc0) === 0x80 &&
137
+ (bytes[i + 2] & 0xc0) === 0x80 &&
138
+ (bytes[i + 3] & 0xc0) === 0x80) {
139
+ const ch = ((c << 18) & 0x1c0000) |
140
+ ((bytes[i + 1] << 12) & 0x3f000) |
141
+ ((bytes[i + 2] << 6) & 0xfc0) |
142
+ (bytes[i + 3] & 0x3f);
143
+ if (ch >= 0x10000) {
144
+ out.push((((ch - 0x10000) >> 10) & 0x3ff) + 0xd800, ((ch - 0x10000) & 0x3ff) + 0xdc00);
145
+ i += 4;
146
+ continue;
147
+ }
148
+ }
149
+ break;
150
+ }
151
+ default:
152
+ break;
153
+ }
154
+ // Not a sequence: the byte itself.
155
+ out.push(c);
156
+ i++;
157
+ }
158
+ return fromCodes(out);
159
+ }
160
+ /** A string of UTF-16 code units, in chunks, as String.fromCharCode takes only so many arguments. */
161
+ export function fromCodes(units) {
162
+ let s = "";
163
+ for (let k = 0; k < units.length; k += 8192) {
164
+ s += String.fromCharCode(...units.slice(k, k + 8192));
165
+ }
166
+ return s;
167
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swf2es/player-hosts",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Optional Node and WebSocket transports, worker threads, an IndexedDB module cache and precompiled modules for the swf2es player",
5
5
  "keywords": [
6
6
  "swf",
@@ -60,6 +60,6 @@
60
60
  "LICENSE.third-party"
61
61
  ],
62
62
  "dependencies": {
63
- "@swf2es/player": "0.1.3"
63
+ "@swf2es/player": "0.1.5"
64
64
  }
65
65
  }