@swf2es/player-hosts 0.1.2 → 0.1.3

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.
@@ -855,6 +855,10 @@ export class Avm1 {
855
855
  registeredName(constr) {
856
856
  return this.classes.registeredName(constr);
857
857
  }
858
+ /** SharedObject writes what its scripts changed, as Flash did as a SWF closed: the page may be going. */
859
+ saveSharedObjects() {
860
+ this.sharedObjects?.flush(this.swfVersion);
861
+ }
858
862
  /** The player gone: SharedObject writes what its scripts changed, as Flash did as a SWF closed. */
859
863
  destroy(closeAudio = true) {
860
864
  for (const bytes of this.codeLive) {
@@ -240,6 +240,16 @@ export class Player {
240
240
  * for the player, its renderer, its input bindings and its loop, is the
241
241
  * host's to let go.
242
242
  */
243
+ /**
244
+ * Write what scripts changed in their SharedObjects, as Flash did as a
245
+ * SWF closed, without stopping anything: a host calls it as its page goes
246
+ * away, where destroy() may never run.
247
+ */
248
+ saveSharedObjects() {
249
+ this.scripting?.flushSharedObjects?.();
250
+ this.scripting?.loads.saveAvm1SharedObjects();
251
+ this.avm1?.saveSharedObjects();
252
+ }
243
253
  destroy() {
244
254
  if (!this.stopped) {
245
255
  drawKernelLetGo();
@@ -247,8 +247,8 @@ export function sharedObjectNatives(s) {
247
247
  }
248
248
  }
249
249
  }
250
- // Flash wrote each open object as its SWF went: a destroyed player
251
- // writes those a script changed since they were read or written. Never
250
+ // Flash wrote each open object as its SWF went: a player hidden or
251
+ // destroyed writes those a script changed since they were read or written. Never
252
252
  // a removal: an object whose stored file it could not read starts empty,
253
253
  // and an unchanged one would take the file away.
254
254
  s.flushSharedObjects = () => {
@@ -257,6 +257,7 @@ export function sharedObjectNatives(s) {
257
257
  const file = serialize(o);
258
258
  if (file.length && !sameBytes(file, o.$saved)) {
259
259
  s.storage.set(o.$key, file);
260
+ o.$saved = file;
260
261
  }
261
262
  }
262
263
  catch {
@@ -65,6 +65,12 @@ export class Loads {
65
65
  }
66
66
  return frames;
67
67
  }
68
+ /** The AVM1 movies' SharedObjects written, as the page may be going. */
69
+ saveAvm1SharedObjects() {
70
+ for (const movie of this.avm1Movies.values()) {
71
+ movie.vm.saveSharedObjects();
72
+ }
73
+ }
68
74
  destroyAvm1() {
69
75
  for (const movie of this.avm1Movies.values()) {
70
76
  movie.vm.destroy(false);
@@ -73,6 +73,10 @@ export class ScriptFunction extends Avm1Function {
73
73
  this.clip = clip;
74
74
  this.definer = definer;
75
75
  }
76
+ /** The realm's count of removals as it last asked whether `target` was removed, -1 before. */
77
+ looked = -1;
78
+ /** Whether `target` was removed as it last asked. */
79
+ gone = false;
76
80
  /**
77
81
  * Run its body with `self` as `this`, `depth` how far up `this`'s
78
82
  * prototypes it was found (which `super` starts from), in an activation
@@ -98,7 +102,23 @@ export class ScriptFunction extends Avm1Function {
98
102
  let scope = this.scope;
99
103
  let target = this.target;
100
104
  let clip = this.clip;
101
- if (this.version < 6) {
105
+ if (this.version >= 6 && caller.host.removed !== undefined) {
106
+ // A clip whose code defined it may since be gone, a loaded SWF's
107
+ // classes after it was unloaded among them: it runs on `this` where
108
+ // that is a clip, else on the caller's target, rather than returning
109
+ // at its first call, as code returns whose clip a call removes
110
+ // (Ruffle's resolve_reference of its base clip, then this_do).
111
+ if (this.looked !== realm.removals) {
112
+ this.looked = realm.removals;
113
+ this.gone = caller.host.removed(target);
114
+ }
115
+ if (this.gone) {
116
+ const own = self instanceof Avm1Object ? caller.host.clipOf?.(self) : undefined;
117
+ target = own ?? targetOrRoot(caller);
118
+ clip = own !== undefined ? self : caller.clip;
119
+ }
120
+ }
121
+ else if (this.version < 6) {
102
122
  const own = self instanceof Avm1Object ? caller.host.clipOf?.(self) : undefined;
103
123
  if (own !== undefined) {
104
124
  target = own;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swf2es/player-hosts",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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.2"
63
+ "@swf2es/player": "0.1.3"
64
64
  }
65
65
  }