When we iterate over the orphan list to run frame lifecyle methods,
the orphan list may be modified (e.g. an event listener creates a new
orphan object). To ensure that we iterate over all of the orphans
originally present, this commit wraps the orphan list in an `Rc`
(just like we do for the render list). Modifications to the list use
`Rc::make_mut`, and iteration operates on a clone of the `Rc`.
QName can contain characters like '.' and '<' as part of the
package or class name (though this requires editing the SWF
or using a nonstandard compiler). This broke our attempt to parse
generic type paramters by looking for '.<'
Instead, our 'Vector' special casing now operates on the unparsed
'AVMString' name, instead of attempting to construct a 'QName'.
This means that we don't need to handle generic paramters at
all for obfuscated names (which will never start with '__AS3__'
or 'Vector.<')
This fixes a bug in Red Ball 4v3, which has an obfuscated class
'!D.<H'
If we have two PlaceObject tags in the same frame with the same depth,
only the first one actually places an object. The second one is ignored
(Flash Player logs a warning).
There are only a few places where we actually need to use the
`caller_domain`, so we don't actually need it available for most native
method calls. This means that `Activation::from_nothing` can be used
in the vast majority of cases without causing a panic later on.
We now parse PixelBender bytecode, and populate the parameters
from the bytecode on `ShaderData`. This is enough to progress
Steamlands, which needs to access dynamically set properties
on `ShaderData`
Bytecode execution is not implemented yet.
When we create a DisplayObject from ActionScript, we should always
run `construct_frame` on it, regardless of what frame phase we
are currently in.
This fixes a regression in Fancy Pants World 4 Part 1, where entering
the first door produced an error.
Flash Player performs `x + width` and `y + height` as floating
point operations before `round_to_even`. This affects the extent
covered by a `Rectangle` in various BitmapData methods, as the sum
of two values might be large enough to be rounded up to a larger
value (when rounding `x` and `width` individually would have
produced a smaller overall extent).
These are directly set on the underlying navigator's HTTP
request type, and get printed out in our test navigator backend.
No validation of the header names is performed - on web, this will be
enforced by the browser.
When we iterate over a render list (in order to call
`enter_frame`, `construct_frame, etc.) we need to be sure
that we iterate over all of the original `DisplayObjects`
in the list, even if the list is modified during iteration
(e.g. some ActionScript code calls `parent.addChildAt`).
Previously, `RenderIter` would repeatedly call `child_by_index`
on the original `DisplayObjectContainer`, up to the original
child count. If new DisplayObjects were inserted into the list
during iteration, we could miss some of the original DisplayObjects
in the list (as they are now at a greater position in the list).
To solve this, we now store the render list as an `Rc<Vec>`,
and use `Rc::make_mut` to modify it. See the comments
for more details.
With SWF version < 30, Context3D.configureBackBuffer throws
an error with a less informative message when the width/height
are out of range. Additionally, it seems to special case
the case width=0, height=0, antiAlias=0. enableDepthAndStencil=false,
and does *not* throw an error. This is relied on by Sniper Team.
The Flash Player 'Matrix3D.recompose' method throws exceptions under
certain circumstances with the "quaternion" orientation style.
I haven't yet figured this out yet, so I've marked that case as a stub.
All of the implementations are based on the OpenFL code, with some
tweaks to match Flash Player's behavior.
TextFields have a very unusual behavior - if they are selectable
and have `was_static`, they *block* the dispatch of mouse events when
they're targeted (not even the Stage will receive the event).
This only occurs when the TextField is actually targeted
(which requires mouseEnabled=true). With mouseEnabled=false,
the event will be dispatched with an ancestor as the target,
following the usual logic.
Also, TextFields now properly propagate mouse picks to
their parent if mouseEnabled=false. Previously, setting
mouseEnabled=false for a TextField made all mouse picks
cause a miss on it. This was the cause of the Turbo Kids
regression.
Fixes#10245
This can actually affect runtime behavior - if the return type is
declared as 'int', then an instance of a custom class will get
coerced to 0 when returned by the function.
'Plants vs Zombies Demo' relies on this - it has a function which
incorrectly returns an object instead of an array index, but the
value gets silently coerced to 0 under Flash Player.
This is based on URLLoader, and doesn't actualy 'stream' data -
it all becomes available once the request finishes. However, this
is good enough to get Sniper Team working.
We now run all of the completion logic (including adding
the new DisplayObject as a child) in `Loader::movie_loader_complete`.
Previously, some of this logic was run from `Loader::preload_tick`,
which meant that loaded images did not have the logic run.
Also, `BitmapData` and `Bitmap` instances (with corresponding AVM2
objects) are now properly constructed for loaded images.
In a previous PR, I introduced an optimization that used
`copy_texture_to_texture` to copy directly from a BitmapData GPU
texture to a Stage3D GPU texture.
Unfortunately, this optimization is incorrect. A BitmapData GPU
texture can be modified at any time by normal AVM2 code - in
particular, in might be modified before we submit the encoded
`copy_texture_to_texture` command. This shows up in Sniper Team,
which re-uses BitmapData objects for multiple distinct textures.
The previous 'optimization' resulted in the wrong BitmapData contents
getting uploaded to a texture (since it was changed before the copy
command was submitted).
This matches the Flash Player documentation. Since we were
manually traversing the displayobject hierarching when firing
the event, we ended up firing duplicate events to parents
because bubbling was enabled.