Skip to content

avm1: Display objects are indirectly referenced by string path (fix #1513) #5492

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

Herschel
Copy link
Member

@Herschel Herschel commented Oct 17, 2021

Proof-of-concept of changing avm1::StageObject to reference its display object via string path instead of GcCell. This is the last big gotcha to tackle in AVM1, so making a rough draft to gain an understanding of the behavior. Let's hold off on merging this until after #5339.

Display objects in AVM1 should not actually hold pointers to their linked display object, but instead refer to it indirectly via absolute string path (for example, _level0.clip.foo). See https://moock.org/asdg/technotes/movieclipDatatype for more info.

This means:

  • Every property access on an AVM1 display object requires dereferencing the path to grab the actual display object.
  • If that display object is removed from the stage, the AVM1 object still exists, but the the path no longer resolves to a display object, so the reference is "dangling". Any operations on the AVM1 object are noops.
  • If a display object with the same path is later added to the stage, the AVM1 object will once again resolve, and all operations will work using the new display object.

Every movieclip property access clip.foo now requires a full resolve of the path, so this could significantly hurt performance -- measurement is needed.

TODO:

  • Properly handle unload events (avm1: Unload clip event handlers should cause clips to be destroyed later #1535).
    • Currently onUnload tests fail because the path no longer resolves.
    • Clips with unload handlers should switch to "off-screen" depths (<0), which allows them to continue to exist for an extra frame.
  • Remove base from StageObject and instead change the DisplayObject::object into a ScriptObject/PropertyMap?
    • We have to resolve the path to a display object for every operation, so it makes sense that doing so should grab the base ScriptObject from the display object itself.
    • Forward gets/sets/other methods to this ScriptObject after dereferencing the path.
    • Test how watches etc. work on movieclip objects after removing + replacing a clip with the same path.
    • Be careful that prototype, interfaces etc. work correctly.
  • Add tests
  • Investigate performance and potential optimizations.
    • Having benchmarks would be helpful.
    • Idea: StageObject::path could store the parsed path segments instead of full string. Something like { level: Depth, segments: SmallVec<AvmString> }.
    • The Big UTF16 String Rewrite #5339 will help a lot; eventually will let us cache string hashes, etc.

Fixes #993, #1017, #1029, #1114, #1140, #1415, #1513, #3839, #3916, #4404, #4793, #5275, others...

@Herschel Herschel marked this pull request as draft October 17, 2021 23:34
AVM1 display objects do not actually hold pointers to their display
object, but instead refer to them indirectly via string path (for
example, `_level0.clip.foo`).

This means:
 * Every property access on an AVM1 display object requires
   re-resolving the path to the actual object.
 * If that display object is removed from the stage, the AVM1 object
   still exists, but the the path no longer resolves to a display
   object, so the reference is "dangling". Any operations on the
   AVM1 object are noops.
 * If a display object with the same path is later added to the
   stage, the AVM1 object will once again resolve, and all
   operations will work using the new display object.

Fixes ruffle-rs#993, ruffle-rs#1415, ruffle-rs#1513, ...
@Herschel Herschel changed the title avm1: Display objects are indirectly referenced by string path avm1: Display objects are indirectly referenced by string path (fix #1513) Oct 17, 2021
Coercing a display object to string results in the display object's
path. `toString` is not used.

If the clip has been removed from the stage, the empty string is
returned.

Remove `avm1::display_object::to_string`. (`MovieClip.toString` is
actually Object's `toString` from the prototype chain.)
This should return "object" for non-movieclips, but default to
"movieclip" if the display object reference is dangling.
Non-movieclip display objects  are not accessible from the AVM in
version 5 and earlier SWFs. For example, attempts to resolve to a
button will instead resolve to the button's parent.

Addresses ruffle-rs#1029.
@Toad06
Copy link
Member

Toad06 commented Oct 18, 2021

Awesome! This also seems to fix #5277 and Hellbound (the character was "stuttering" in the air after losing a life).

But there's a regression in Steppenwolf 5-1. The game softlocks when you try to climb the rope. The following messages are logged in the console:

SetTarget failed: _parent not found
Target not found: Target="_parent" Base="_level0.Corde.instance1611"
NextFrame: Invalid target

Could this be related to #5502?

@ousia
Copy link
Contributor

ousia commented Feb 2, 2022

@Herschel, this PR will help to solve at least 22 issues.

I mention this, just in case it could be finished and merged.

@ousia
Copy link
Contributor

ousia commented Feb 2, 2022

Many thanks for your help and your excellent work.

@ousia
Copy link
Contributor

ousia commented Jun 7, 2022

@Herschel,

just some comments that might help to consider finishing this PR.

  1. By the end of Agust, three related issues would have been reported for two years.
  2. By the end of this year, other five related issues would be added to that list.
  3. Since opened eight months ago, this PR has been steadily mentioned in other issues every month.

Many thanks for your excellent work.

@Aaron1011
Copy link
Member

Once #7254 is merged, this should fix a bug in FancyPants2 where the player gets frozen in midair.

@ousia
Copy link
Contributor

ousia commented Dec 17, 2022

Excuse me for asking this obvious question, this is an important issue in AVM1.

Is there any ETA for the merge of this PR?

@CUB3D
Copy link
Contributor

CUB3D commented Dec 31, 2022

This branch doesn't build anymore due to a borrowing issue, so I rebased this up to ~Nov to be able to test with it, see https://github.com/CUB3D/ruffle/tree/avm1-mc-string-ref

This also seems to fix #2840

@ousia
Copy link
Contributor

ousia commented Jan 1, 2023

@Toad06, does the regression mentioned in #5492 (comment) happen after the merge of #5502?

I wonder whether this PR may be merged when it doesn’t break anything.

I know that this isn’t ideal, but it will help to fix particular issues after the merge.

Happy New Year to everyone!

@relrelb
Copy link
Contributor

relrelb commented Mar 1, 2023

Superseded by #9447.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Skeleton Park] Issue with a specific animation
6 participants