Skip to content

avm2: Fix Vector.<Boolean> default value in non-script-init contexts#23527

Open
chabeck1 wants to merge 1 commit intoruffle-rs:masterfrom
chabeck1:fix-vector-bool-default
Open

avm2: Fix Vector.<Boolean> default value in non-script-init contexts#23527
chabeck1 wants to merge 1 commit intoruffle-rs:masterfrom
chabeck1:fix-vector-bool-default

Conversation

@chabeck1
Copy link
Copy Markdown

Summary

Fixes #23317.

In Flash Player on SWF version >= 14, new Vector.<Boolean>(n, true) fills the new slots with false when called from inside a class method or constructor, but with null when called from a script initializer. Ruffle was returning null in both cases. This PR makes the non-script-init case match Flash on SWF >= 14 while leaving SWF <= 13 and the script-init case unchanged.

Approach

VectorStorage::default() for Boolean now delegates to a bool_default() helper in core/src/avm2/vector.rs that walks the AVM2 call stack from the top, finds the first bytecode method, and checks whether it is the instance initializer of a script's global class (Class::is_script_traits()). If so, the default is Value::Null (preserving the existing vector_holes behavior). Otherwise it is Value::Bool(false) for SWF >= 14 and Value::Null below.

To enable the call-stack walk inside VectorStorage, VectorStorage::new now takes &mut Activation; the change is threaded through every call site (amf.rs, object/vector_object.rs, globals/vector.rs, two globals/flash/* files). A small iter_top_down() helper was added to CallStack.

Acknowledgement of maintainer feedback

@Lord-McSweeney and @kjarosh noted on the issue that the Flash behavior here is a JIT specialization artifact, not a Vector semantic rule, and that any fix without a JIT would likely cost Vector construction performance. I understand this PR takes the "encode the JIT behavior as a runtime check" approach, which the issue thread explicitly cautioned against. I'm opening it anyway so the approach is on the record and reviewable; I fully understand if the preferred resolution is to close without merging. If there are changes that would make a variant of this acceptable (e.g. restricting the call-stack walk to SWF >= 14 paths only, or gating behind a config flag), I'm happy to iterate.

Tests

  • tests/tests/swfs/avm2/vector_boolean_default_constructor/ -- SWF v14, the bug case. Expected output null then false captured from Adobe debug Flash Player.
  • tests/tests/swfs/avm2/vector_boolean_default_constructor_v13/ -- SWF v13 sanity check, expected output null then null. Pins the pre-existing behavior below the version threshold.
  • Full regression suite: 4016 passed; 0 failed. Pre-existing vector_holes test continues to pass.

Out of scope

The Haxe-generated static-method case from the issue (where Flash returns false regardless of SWF version) is not handled here; the discriminator appears to be Haxe's bytecode pattern rather than the Vector default rule, which is a separate investigation. Noted in the issue thread.

Makes VectorStorage::default() for Boolean walk the AVM2 call stack to
distinguish script-init callers (return null) from other callers (return
false on SWF >= 14, null below). Matches Flash Player behavior for the
non-script-init case while preserving the existing vector_holes semantics.

Adds two regression tests covering SWF versions 14 and 13. Ground truth
captured from Adobe's debug Flash Player.

Fixes ruffle-rs#23317.
@kjarosh kjarosh requested a review from Lord-McSweeney April 24, 2026 15:48
@kjarosh kjarosh added A-avm2 Area: AVM2 (ActionScript 3) T-fix Type: Bug fix (in something that's supposed to work already) labels Apr 24, 2026
Copy link
Copy Markdown
Collaborator

@Lord-McSweeney Lord-McSweeney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix is incorrect. The Vector is not filled as false or null depending on whether the activation is in interpreter mode or not; rather, the value is read as false or null depending on whether the activation is in interpreter mode or not. A boolean Vector is always filled with null when initialized.

@Lord-McSweeney
Copy link
Copy Markdown
Collaborator

Was an LLM used to write any of this code?

@chabeck1
Copy link
Copy Markdown
Author

Yes, mostly LLM-generated. Sorry for not flagging it upfront. Your review also makes clear I was on the wrong code path (fill vs read). Close or iterate, whichever you prefer.

@Lord-McSweeney Lord-McSweeney added the llm The PR contains mostly LLM-generated code label Apr 24, 2026
@Lord-McSweeney
Copy link
Copy Markdown
Collaborator

You can close this PR if you'd like, but if you want to implement the correct fix it's fine to do so on this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-avm2 Area: AVM2 (ActionScript 3) llm The PR contains mostly LLM-generated code T-fix Type: Bug fix (in something that's supposed to work already)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect default values for Vector.<Boolean> in some contexts

3 participants