Commit Graph

497 Commits

Author SHA1 Message Date
David Wendt abc1d00276 Fix incorrect preload of `_root` in `DefineFunction2` function calls.
This is caused by the fact that `avm.root_object` references the *current* stack frame, not the one we are about to introduce. Ergo, we need to pull the base clip of the *new* stack frame and find it's root.

This particular behavior only crops up in situations where there can be multiple root objects, at least until we implement `_lockroot`.
2020-02-22 00:02:51 -05:00
David Wendt e0b4a0f193 Top-level layers are referenced via their path (`_leveln`) rather than name - in fact, their name is always the empty string. 2020-02-22 00:02:51 -05:00
David Wendt 00f88f9e87 Use the depth to indicate which layer a particular root clip is, and then use that to calculate it's `_leveln` path. 2020-02-22 00:02:50 -05:00
David Wendt 9adf0f43d7 Allow levels to be read as scope variables, and add a test for this. 2020-02-22 00:02:50 -05:00
David Wendt aa6aba13dd Abolish `context.root` completely.
`_root` is calculated dynamically based on the clip the currently executing function was called in.

Other things that used `context.root` have been changed to either update all layers or just update layer 0, which is the former `context.root`.
2020-02-22 00:02:46 -05:00
David Wendt aab339880d Implement `XML.load()`, with tests.
Interestingly enough, very little actually has to be done inside the async process for XML. The async process basically just fetches data and fires an event handler when it's done. Everything else is handled via a system builtin, `XML.onData`.
2020-02-22 00:02:45 -05:00
David Wendt c00ecccd1f Basic, stub implementation of `MovieClipLoader.getProgress`, plus test.
This implementation just returns the size of the current loaded movie. The test is also deliberately written to be loose on timings so that it likely won't see a partially loaded movie. (I don't want it to be a test of load events, so I just wait a few frames, rather than the correct way of waiting for `onLoadComplete`.)

Until we support streaming file loads, we can't faithfully support these properties. Still, it's better to have them, just in case.
2020-02-22 00:02:42 -05:00
David Wendt 3f7e3a9ed8 Implement `MovieClipLoader.unloadClip`, with tests. 2020-02-22 00:02:41 -05:00
David Wendt 89e5dd97f3 Implement `MovieClipLoader.loadClip` 2020-02-22 00:01:19 -05:00
David Wendt 162b6b70f8 Allow unloading a movie by sending `None` to `replace_with_movie`.
This also adjusts `MovieClip.unloadMovie` to do just that, instead of removing the clip from the display list. We also have to unload clips when loading new movies into them, since `unloadMovie` desugars to loading `""` as the URL.
2020-02-22 00:01:19 -05:00
David Wendt 7ff885a0de Implement `MovieClipLoader` event broadcasts for `onLoadStart`, `onLoadProgress`, `onLoadComplete`, and `onLoadError`.
Note that we do not implement `onLoadInit` yet - this requires some ability to trigger an event when another movie clip loads.
2020-02-22 00:01:14 -05:00
David Wendt db41bec91e Implement `MovieClipLoader`'s `addListener`, `removeListener`, and `broadcastMessage` methods.
Interestingly, this constitutes an implementation of `AsBroadcaster`. It appears Macromedia decided to implement event handling on `MovieClipLoader` in a very similar fashion to `AsBroadcaster`, down to invoking `broadcastMessage` and searching a `_listeners` property for listeners.
2020-02-22 00:01:12 -05:00
David Wendt b7d318a897 Implement `MovieClip.loadMovie`, `MovieClip.loadVariables`, and `MovieClip.unloadMovie`.
*De*implement the free function versions of the above, as well as their `Num` variants, since they don't actually exist as callables. Instead, the ActionScript compiler treats them as preprocessor functions that represent various forms of `ActionGetURL`/`ActionGetURL2`.
2020-02-21 23:59:13 -05:00
David Wendt 31b1364b82 Implement `unloadMovie` / `unloadMovieNum` 2020-02-21 23:58:00 -05:00
David Wendt b2b2a165fc Implement `loadVariables` and `loadVariablesNum`. 2020-02-21 23:58:00 -05:00
David Wendt c7539872f7 Add the ability to POST data from `fetch`, and allow methods that read AVM locals into form data to `GET` or `POST` them. 2020-02-21 23:58:00 -05:00
David Wendt 3fe6884c90 Refactor layer resolution into a separate function.
This function is part of `Avm1`, rather than a hypothetical `LayerManager`, because we're going to need to eventually construct layers differently for AVM2.
2020-02-21 23:57:59 -05:00
David Wendt ea28c2c4a2 Impl `loadMovie` / `loadMovieNum` (sans local variable support) 2020-02-21 23:57:59 -05:00
David Wendt d84e11ed40 Introduce a new top-level object, `LoadManager`, which is responsible for all asynchronous behavior in the program. Migrate the existing async impls to it. 2020-02-21 23:57:58 -05:00
David Wendt 2d7a4fef28 `Sound` methods that reference sounds by library export name should default to `_layer0`'s library if the `Sound` was created without a movie clip target. 2020-02-21 23:57:57 -05:00
David Wendt 2a82d21966 Change the layer list from a static array to a `BTreeMap`.
Flash allows creating layers at any 31-bit height without issue, so this should support similar limitations.
2020-02-21 23:57:57 -05:00
David Wendt 5ce499d11e Add separate libraries for each loaded movie. 2020-02-21 23:57:56 -05:00
David Wendt ed799fd2b9 Split the player up into nine layers, each of which is a separate root movie clip. 2020-02-21 23:57:55 -05:00
David Wendt 5ed5876e9a Merge SWF data and version into a single structure. Refactor everything that interacts with it to use `SwfSlice`s. 2020-02-21 23:57:53 -05:00
David Wendt 55149b7b7e Reference count the Player and provide a weak reference in UpdateContext.
This allows the formation of `'static` futures that can still interact with a player. Async code will need to upgrade the weak reference in order to be able to interact with the player.
2020-02-21 23:44:06 -05:00
Mike Welsh 6b503ac053 avm1: Fix DefineFunction2 preload order when _parent is undefined
The order is misdocumented in SWF19 (and also miscompiled assuming
this incorrect order by the Flash IDE!).

`_global` gets preloaded before `_parent`.
2020-02-20 12:58:26 -08:00
Mike Welsh 19d0bf64a9 avm1: Preload _parent directly from base clip
When `_parent` is preloaded  in a `DefineFunction2` action,
we previously resolve it on the scope chain. This could cause
double borrow panics as the parent object could already be
borrowed, and also this matches the behavior of the official Flash
player.

Addresses #398.
2020-02-19 23:22:33 -08:00
Mike Welsh 8d7e58011e avm1: undefined coerces to "" in SWFv6 and below
Except in the AVM1 trace op, which will print out "undefined".
2020-02-19 10:47:43 -08:00
Mike Welsh c073afb077 avm1: Use proper value for Number.MIN_VALUE
This is the smallest positive number, not the most negative value.
This is actually the smallest positive subnormal f64, which Rust
does not provide a constant for. This is ~5e-324.
2020-02-18 10:17:55 -08:00
Mike Welsh 6bbe1dbab8 avm1: Match Flash when converting exotic numbers to string (fix #361)
Match Flash's more closely when converting number to string:
 * NAN -> NaN
 * inf -> Infinity
 * -inf -> -Infinity
 * Use exponential notation for very large/very small

This is a little bit of a cheat by using Rust's number-to-string
formatting for exponentials, and shoving a sign in front of the
exponent.
2020-02-18 10:17:55 -08:00
Mike Welsh 2af21d87e0 avm1: Implement MovieClip.localToGlobal/globalToLocal 2020-02-17 15:42:29 -08:00
Mike Welsh 9ad069e11a avm1: Improve display object property setters for weird values
Setting a property such as _x to undefined or null should have no
effect. This was working for v7+ SWFs because it would coerce to
NaN and we toss out NaNs. But on v6 and below, these coerce to 0
and would end up setting the property to 0.

Explicitly check for undefined/null and bail out. Fixes #380.

Also adjust the _visible setter, since this actually coerces to a
number (because of its legacy from SWFv4). For example,
_visible = "" should have no effect.
2020-02-14 15:34:14 -08:00
Mike Welsh 7d14b98f3b avm1: Ignore undefined values in Color.setTransform
If a property is not set on the object passed to Color.setTransform,
then that channel is left unmodified. This fixes invisible objects
in some games (fixes #369, addresses #380).

Also improve handling of wrapping/invalid values to better match the
behavior in the Flash Player (some work pending on #193).
2020-02-13 18:06:27 -08:00
Mike Welsh 21f117e7bc avm1: Add Value::coerce_to_i16 2020-02-13 18:06:27 -08:00
David Wendt f95ec777de Also impl storage of the `wordWrap` flag 2020-02-03 14:46:34 -05:00
David Wendt 75022f36d2 Pull `TextFormat` into the `font` module.
Also, since there's a separate function for attaching virtual properties to an AVM1 `TextField` object, let's use that!
2020-02-03 14:46:33 -05:00
David Wendt 4b3660bf2c Impl get/set for `is_multiline`. 2020-02-03 14:46:32 -05:00
David Wendt 81b7958090 Impl `textWidth` / `textHeight`, although it currently only works well for single-line scenarios. 2020-02-03 14:46:32 -05:00
David Wendt 2181f0d0d0 Impl `getNewTextFormat`/`setNewTextFormat`.
These don't actually do anything yet, because we don't track text spans, nor do we actually use those text spans to alter rendering or text layout.
2020-02-03 14:46:30 -05:00
David Wendt db56217f20 `TextFormat` does *not* coerce `undefined` or `null`; instead those both become `null`. 2020-02-03 14:46:30 -05:00
David Wendt 8449d964ef Implement `TextFormat` as a property bag. 2020-02-03 14:46:29 -05:00
David Wendt 2b0600ab1a Impl `createTextField`. 2020-02-03 14:46:29 -05:00
Mike Welsh a55a378a73 avm1: Improve comments in MovieClip depth methods 2020-01-31 19:44:42 -08:00
Mike Welsh a4e175a790 avm1: Implement MovieClip.getNextHighestDepth 2020-01-31 19:44:42 -08:00
Mike Welsh 4d12cd1566 avm1: Implement MovieClip.getDepth 2020-01-31 19:44:42 -08:00
Mike Welsh 9e337ede34 avm1: Implement MovieClip.swapDepths 2020-01-31 19:44:42 -08:00
dependabot-preview[bot] 2f98fd1a0e build(deps-dev): bump webpack-dev-server in /web/selfhosted
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 3.10.1 to 3.10.2.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v3.10.1...v3.10.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-31 19:44:42 -08:00
Mike Welsh 0d91fb423e core: Goto only runs if frame is an integer 2020-01-30 15:17:01 -08:00
Mike Welsh c079cb3bca core: Don't run frame actions when seeking past end of timeline
If you goto past the final loaded frame of a timeline, for example,
with gotoAndStop(9999), this seeks to the final frame on the
timeline, but it doesn't run the actions on this frame.

MovieClip::goto_frame now will not run the final frame actions if
the target frame was not reached.
2020-01-30 15:17:01 -08:00
Mike Welsh 8aae07bbf3 core: Frame labels are case insensitive 2020-01-30 15:17:01 -08:00
Mike Welsh 62467bb880 avm1: Handle invalid parameters in GotoFrame2
Use the same code path for the global GotoFrame2 action and
MovieClip.gotoAndX, which properly handles out-of-range and invalid
values like NaN.

Fixes Disorderly hanging on game start
(https://www.newgrounds.com/portal/view/121896)
2020-01-30 15:17:01 -08:00
Mike Welsh 7532e89aff avm1: Use `resolve_target_display_object` in `Color`
Fixes the boss damage blinking in Alien Hominid. Target was a path
string.
2020-01-27 23:35:41 -08:00
David Wendt db51ec9e3c Implement a separate `Object` impl for functions that holds an `Executable`. 2020-01-27 21:57:32 -05:00
David Wendt d217f51c6c Don't crash if `Function.prototype.call` is called without arguments. 2020-01-27 21:50:10 -05:00
David Wendt 2c0d892154 Implement Function.call/apply 2020-01-27 21:50:09 -05:00
Mike Welsh 70bec9437f tests: Boolean() returns undefined 2020-01-21 18:24:49 -08:00
Mike Welsh d9e7a6a960 avm1: Implement Boolean class 2020-01-21 18:24:49 -08:00
Mike Welsh e71099edd5 tests: Add primitive_type_globals test 2020-01-21 18:24:49 -08:00
Mike Welsh 8263d13fd0 avm1: Implement Number class 2020-01-21 18:24:49 -08:00
Mike Welsh b49357e46f avm1: Boxing a value calls the object constructor 2020-01-21 18:24:49 -08:00
Mike Welsh ccf62979a1 avm1: Implement String methods 2020-01-21 18:24:49 -08:00
David Wendt 2f9d50cdb8 Very rudimentary/basic/not-good implementation of `String`, plus auto-boxing for primitive strings getting their methods taken. 2020-01-21 18:24:49 -08:00
David Wendt 4d1e49882b Add another object class for boxed primitive values, because the language demands it. 2020-01-21 18:24:49 -08:00
Mike Welsh 13b4cd4c1b avm1: Add Value::coerce_to_i32/u32/u16 methods
Add these methods that will explicilty coerce a value to an int,
following the wrapping behavior in the ECMAScript specs (ToInt32,
ToUInt32, ToUInt16).

This also fixed an off-by-one error for negative numbers in the
previous implementation.

These will call `valueOf` if necessary. AVM code that requires an
integer will probably use one of these (`coerce_to_i32` usually).
2020-01-20 13:28:27 -08:00
Nathan Adams 4ad6ef8b83 core: Implemented Key.getCode() 2020-01-17 15:11:38 -08:00
Nathan Adams adceceed5d avm1: Removed redundant double registration of Key 2020-01-17 15:11:38 -08:00
Nathan Adams cef7d3eba2 avm1: Implement Key constants 2020-01-17 15:11:38 -08:00
Nathan Adams fdf1d38d21 avm1: Implement remainder of Math 2020-01-13 15:57:56 -08:00
Mike Welsh 001a931afe avm1: Avm1::pop should always succeed
Don't return a Result from `pop`. Instead, emit a warning and
return Undefined if there is an underflow.
2020-01-07 15:59:14 -08:00
Mike Welsh a28e97d8c3 avm1: Don't push returns from non-function stack frames 2020-01-06 20:49:05 -08:00
Mike Welsh 7e05da6147 avm1: Fix issues with traversing the scope chain in SetVariable
When setting a variable in a function-local scope, if that variable
has not been defined in the function scope, it should be defined in
the executing movieclip's scope. Previously it would get defined
in the function's scope. Changed Scope::overwrite to Scope::set,
and modified the behavior to stop traversing and define the value
when it hits a movie clip Target scope.

Also, modified With scopes to properly add onto the end of the scope
chain.
2020-01-06 20:49:05 -08:00
David Wendt f8b5b8a032 Use `unwrap_or_default` where available 2020-01-05 00:22:36 -05:00
David Wendt ef7c5d7eb9 Move XML properties to separate functions rather than closures 2020-01-05 00:17:57 -05:00
David Wendt 14dba0d100 Log errors encountered when removing the children of a node we plan to parse XML into.
Also, remove a handful of unnecessary `#[allow(unused_must_use)]` instances.
2020-01-05 00:04:45 -05:00
David Wendt 750e6e4370 Replace bare number constants for XML errors with symbolic `const` values 2020-01-04 23:56:10 -05:00
David Wendt fd541fabea Implement `status`.
I'm not entirely sure how to test this one - the list of errors that Flash kicks out for XML and the list of errors that `quick_xml` kicks out don't line up at all; so I just ensured that any error is a negative number (currently the one for OOM errors) and stuck whatever errors *did* match up together.

Consequently I don't know entirely *how* to write tests for this.
2020-01-04 19:00:49 -05:00
David Wendt f3226537bf Implement `idMap`.
`idMap` is a strange property; it's only populated with nodes which had a given `id` *at the time of parsing*, and said nodes continue to be referenced even if the node is removed from the document. I have yet to find a way by which nodes can be deleted from `idMap`.

It also takes expandos, so this has to be a new retained object on the XML document. I originally considered not creating *another* `Object` impl and populating a regular `ScriptObject` with nodes, but that meant we couldn't lazy-instantiate their AVM1 side counterparts. Boo. :/
2020-01-04 19:00:48 -05:00
David Wendt 823e8602ff Impl `XML.parseXML` 2020-01-04 19:00:46 -05:00
David Wendt d00ef01965 Add a convenience method: `XMLNode.into_string` 2020-01-04 19:00:46 -05:00
David Wendt 2c790f1d41 Filter non-AS2 compatible nodes from toString output, and add non-SWF tests for XML filtering. 2020-01-04 19:00:45 -05:00
David Wendt e2fa685d41 Fix tagname parsing.
There is a bug in `quick_xml` - or at least, I *think* it's a bug - where the `unescaped` method of `BytesStart` yields a bunch of attributes if you have slightly invalid crap in your tag like `xmlns:`. To work around it, I turned off unescaping; we're instead using `name` and ignoring unescaping. This will probably fail somewhere.
2020-01-04 19:00:44 -05:00
David Wendt e1034fce31 clippy compliance 2020-01-04 19:00:44 -05:00
David Wendt 7ac3204759 format prev commit 2020-01-04 19:00:43 -05:00
David Wendt 91155d6870 Text nodes have empty arrays for `childNodes` rather than being `undefined`. 2020-01-04 19:00:42 -05:00
David Wendt d28094a019 Implement `createElement` and `createTextNode`. 2020-01-04 19:00:42 -05:00
David Wendt c02da74afa Expose the `<?xml ?>` declaration to ActionScript.
I can't write proper tests for this because our underlying XML parsing technology doesn't let us do what AS2 XML does: just copy the first xml tag out of the document and into a string. No, seriously, anything at the start of the parsed XML that starts with `<?xml` and ends with `?>` gets copied into Flash's moral equivalent of `xml::Document` as a string. We parse the whole thing, which is wrong, so we'll need to additionally retain the original xmldecl string in order to pass the test I wrote for this.
2020-01-04 19:00:41 -05:00
David Wendt a7a349b02b Expose `docTypeDecl` to ActionScript.
This also involves storing the `DocType` node on the document object and retrieving it later.
2020-01-04 19:00:40 -05:00
David Wendt 6a472d32bb Filter incompatible nodes from the sibling and child lists. 2020-01-04 19:00:39 -05:00
David Wendt fd14d0c9df Doctype nodes should be represented as text nodes to ActionScript (if they somehow grab hold of them) 2020-01-04 19:00:38 -05:00
David Wendt aa749dc1b0 Store the XML document version, encoding, and standalone flags. 2020-01-04 19:00:38 -05:00
David Wendt a869107480 The `DocumentRoot` node type should have it's own node type ID, and AS2 XML should filter it out. This also filters out comment nodes as text, which isn't technically wrong but we should do better 2020-01-04 19:00:37 -05:00
David Wendt 673f85f067 XMLNode type 1 is an element, not a text node. 2020-01-04 19:00:36 -05:00
David Wendt c76e5ce447 appendChild also refuses to orphan nodes already part of another XML tree. 2020-01-04 19:00:35 -05:00
David Wendt 34cbe2e04b insertNode rejects child nodes that already have a parent 2020-01-04 19:00:34 -05:00
David Wendt 8c5dcfe662 Swap in newly constructed nodes *before* filling them with content.
Fixes a bug where new XML("<node />").childNode[0].parentNode did NOT refer to the overall document object, but to a phantom text node.

This is because the swap operation used to construct an XMLObject's node in-place was happening AFTER parsing, which means that referents already existed to the temporary XMLNode created by XMLObject::new. swap is not to be called after tree structure has been created; it does not update referents to the swapped nodes.

In the future I should examine the implications of explicitly reconstructing already existing nodes, e.g. through XML.apply(some_xml). Right now, the existing node will be swapped with a new one, and two nodes will exist pointing to the same script object, which is a huge problem with our overall design. We should, at the very least, disassociate swapped nodes from their script object, just in case they still have referents.

Ideally, we wouldn't have to swap nodes, but to avoid a swap, I'd have to instead have a second layer of indirection just to hold a rewritable pointer that every XMLObject points to. This isn't really worth it unless I HAVE to do it, so I'm not going to do it.
2020-01-04 19:00:32 -05:00
David Wendt 568d90f4dc Warn if XML.removeNode fails for whatever reason 2020-01-04 19:00:32 -05:00
David Wendt 19ca11b08c Impl `toString` 2020-01-04 19:00:31 -05:00
David Wendt 513460e4e0 Implement `insertBefore` 2020-01-04 19:00:31 -05:00
David Wendt b0dce445b0 Impl `removeNode` 2020-01-04 19:00:29 -05:00
David Wendt 00319f14a8 Implement `namespaceURI` 2020-01-04 19:00:29 -05:00
David Wendt abb2690367 When constructing new XML nodes or documents, always ensure that the new node we swap in is properly linked to the same script object so that we don't accidentally recreate them. 2020-01-04 19:00:28 -05:00
David Wendt 8939dae90c Implement `XMLNode.attributes` w/ read tests 2020-01-04 19:00:27 -05:00
David Wendt 6f48f3436f Expose `previousSibling` and `nextSibling` to ActionScript.
This commit also fixes a bug caused by excessive use of copypaste, which was detected by the included test.
2020-01-04 19:00:25 -05:00
David Wendt 223320c98c Expose `parentNode` to ActionScript 2020-01-04 19:00:24 -05:00
David Wendt 807725d7aa Expose `firstChild` and `lastChild` to ActionScript w/ tests 2020-01-04 19:00:24 -05:00
David Wendt 48d68bebc4 Implement `hasChildNodes()` and add test 2020-01-04 19:00:23 -05:00
David Wendt 881dcb76ab `cloneNode` without arguments is morally equivalent to `false` 2020-01-04 19:00:21 -05:00
David Wendt 69a1ab1649 Expose namespace prefix and URI lookups to ActionScript.
Also, fix the previous commit's half-assed impl.
2020-01-04 19:00:20 -05:00
David Wendt 55fa6ef09b Add node cloning support 2020-01-04 19:00:19 -05:00
David Wendt 37f6efb753 Expose `appendChild` to ActionScript 2020-01-04 19:00:19 -05:00
David Wendt 7e45dee8cf Clippy said so. 2020-01-04 19:00:18 -05:00
David Wendt cfacd397cf Most XML properties return `null`, not `undefined`.
Furthermore, `prefix` does not distinguish between `<test>` and `<:test>` - they both have a `prefix` of `""`.
2020-01-04 19:00:17 -05:00
David Wendt e47a1d1e38 Fix newly constructed XML trees not actually containing the XML they just parsed. 2020-01-04 19:00:16 -05:00
David Wendt bec60acc1e `XML.prototype` should be an `XMLObject` so that instances of `XML` can hold a node 2020-01-04 19:00:15 -05:00
David Wendt 571c4bbd52 Cargo fmt compliance 2020-01-04 19:00:15 -05:00
David Wendt 0af248d81f Expose `childNodes` to ActionScript 2020-01-04 19:00:14 -05:00
David Wendt e7768d0802 Add methods to allow storing XML objects on the accompanying tree nodes, so that expando properties on child nodes will work. 2020-01-04 19:00:13 -05:00
David Wendt b06dd5d15e Add a special node to represent the document root in the node tree, and get rid of the explicit document reference type in `XMLObject`. 2020-01-04 19:00:12 -05:00
David Wendt bd1ea56cc3 Implement `XMLNode` properties that don't require child or attribute iteration. 2020-01-04 19:00:10 -05:00
David Wendt 4f5ac09b73 Expose XML document constructor, including text parsing ability 2020-01-04 19:00:09 -05:00
David Wendt 554f0dc1e5 Add XMLNode class and constructor impl 2020-01-04 19:00:07 -05:00
David Wendt 6a65e984ae Add a new `XMLObject` variant to the AVM1 object ecosystem.
This particular variant is actually a two-in-one deal: `XMLObject`s may either refer to a document or a node.
2020-01-04 18:58:42 -05:00
Mike Welsh 36b3e5b34f avm1: Implement Color class 2020-01-03 20:31:32 -08:00
Mike Welsh 4bf29f677f avm1: Implement Sound.duration
Add AudioBackend::get_sound_duration.
2020-01-03 17:11:00 -08:00
Mike Welsh b9d24d9a49 avm1: First pass at implementing Sound.stop 2020-01-03 17:11:00 -08:00
Mike Welsh 63dd92259b avm1: First pass of Sound object 2020-01-03 17:11:00 -08:00
Nathan Adams 9000451d58 core: Implemented Mouse.show() & Mouse.hide() 2019-12-22 14:33:46 -08:00
Mike Welsh a4a307cf9a avm1: Use proper bool conversions for logical ops
ActionAnd, ActionOr, and ActionNot were incorrectly comparing
to 0. This only works for SWF<4. Now they all go through the
Value::as_bool method to handle version specific behavior.

Value::from_bool_v1 was also renamed to Value::from_bool.
2019-12-21 23:01:10 -08:00
Nathan Adams eedc4bbe24 core: Added Input backend, currently unimplemented, for polling user input 2019-12-21 19:08:06 -08:00
Mike Welsh 531e4d640d avm1: Implement StartDrag/EndDrag 2019-12-21 16:28:41 -08:00
Mike Welsh d459bbe010 avm1: Functions store their base clip
Functions now store their base clip (the code that contains the
executing bytecode). This is because `GotoFrame` and other actions
will execute on the clip the bytecode exists on, not on `this`.

(Note that `this.gotoAndStop` uses `GetMember` actions, which
worked correctly).

`Activation` now stores `target_clip`, and `Avm1::target_clip` and
`target_clip_or_root` grab this from the current stack frame.

Renamed `start_clip` to `base_clip` to match Flash conventions.
Removed `active_clip` as this was superfluous. Now you can use
`Avm1::target_clip_or_root`.

`UpdateContext` no longer contains `target_clip` etc.
2019-12-19 17:30:50 -08:00
Mike Welsh 540b03090a avm1: hitTest point is actually in root coordinates (fix #185) 2019-12-19 12:35:56 -08:00
Nathan Adams f6f358b4de avm1: Expose TextFields and allow setting their .text 2019-12-19 10:19:43 -08:00
Mike Welsh c9a5d2dbb3 chore: Fix clippy lints in 1.40 2019-12-19 09:10:41 -08:00
Nathan Adams d3848f97ea avm1: Implemented MovieClip.hittest, without shape flag 2019-12-18 15:21:14 -08:00
Nathan Adams 5f6eea6f25 chore: Refactor system listeners into a reusable system 2019-12-18 15:15:56 -08:00
Mike Welsh 3a8256a993 avm1: Allow setting _name 2019-12-18 14:07:32 -08:00
Mike Welsh 3e003ed9dd avm1: Add missing stage.rs 2019-12-17 22:36:53 -08:00
Mike Welsh 3ebc1ed928 avm1: Stub out Stage properties
This is a very rough stub out of Stage.width and height to get
basic V-cams to start functioning.

TODO: Implement the different stage scaling modes. We will probably
want to add a "Stage" display object to handle this.
2019-12-17 22:28:44 -08:00
Mike Welsh 74aa127b74 avm1: Fix double borrow in Executable::exec 2019-12-17 21:35:22 -08:00
Mike Welsh dae3e27fb3 avm1: Rename Library::instantiate_by_id 2019-12-17 03:27:05 -08:00
Mike Welsh 1476930e0c avm1: Implement MovieClip.removeMovieClip 2019-12-17 03:20:01 -08:00
Mike Welsh 1668e823e6 avm1: Implement MovieClip.createEmptyMovieClip 2019-12-17 03:02:07 -08:00
Mike Welsh d33a8278d7 avm1: Implement MovieClip.duplicateMovieClip 2019-12-17 03:00:56 -08:00
Mike Welsh 009da39f12 avm1: Implement MovieClip.attachMovie 2019-12-17 03:00:56 -08:00
Nathan Adams 45e497826b avm1: Implement `Mouse` listeners & events (excluding scroll) 2019-12-16 19:22:10 -08:00
Mike Welsh c2f4633cdb avm1: Trace constant_pool in Collect for Activation 2019-12-16 16:14:49 -08:00
Mike Welsh f4f755e958 avm1: Remove warnings on _currentframe/_totalframe 2019-12-16 10:21:37 -08:00
Nathan Adams c8e42123cf avm1: Implemented `_xmouse` and `_ymouse` 2019-12-16 10:11:23 -08:00
Nathan Adams 783037e8cc chore: Removed array debug code that snuck in. Oops! 2019-12-16 09:56:46 -08:00
Mike Welsh bf0b777246 avm1: Use ECMA-262 ToInt32 modulo behavior
Everything is a double in ES land, so when converting a number to
int, the double is modulo'd to allow for wrapping 32-bit int
semantics.

See ToInt32 and ToUInt32 in the specs:
https://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%202nd%20edition,%20August%201998.pdf
2019-12-16 00:52:27 -08:00
Mike Welsh 39f54b4a16 avm1: Add gotoAndPlay and gotoAndStop MovieClip methods 2019-12-16 00:52:27 -08:00
Mike Welsh fa5a168fad avm1: Clean up MovieClip prototype 2019-12-16 00:52:27 -08:00
Mike Welsh 46365c5702 avm1: Implement clip event method callbacks 2019-12-15 20:01:50 -08:00
Mike Welsh 174426856f avm1: Use `EnumSet::from_bits` in `object::as_set_prop_func` 2019-12-15 14:26:43 -08:00
David Wendt d9aac0f2cf Adjust `SuperObject` based on actual Flash behavior. 2019-12-15 13:32:04 -08:00
David Wendt edf7a19eb7 Implement `Function.prototype.toString`. 2019-12-15 13:32:04 -08:00
David Wendt 33c66571f5 Allow `is_instance_of` to inspect the prototype chains of implemented interfaces.
This makes the `extends_chain` test pass.
2019-12-15 13:32:04 -08:00
David Wendt 854526923e Calls to `super` inherently bind to itself.
This requires some subclassing nonsense to be able to smuggle a self-reference into `SuperObject`s. When successfully smuggled, all calls to `call` will be invoked with the `super` object as `this`. This allows constructor chaining to work.

Note that not all `Object` trait methods are implemented on `SuperObject`, so things like `delete this.x` in super constructors will randomly fail. This should be fixed.
2019-12-15 13:32:04 -08:00
David Wendt eb06501492 Since `get_local` doesn't scale the prototype chain anymore, we don't need to change the prototype chain traversal anymore. 2019-12-15 13:32:04 -08:00
David Wendt 5c1ac19c1b Implement `super`, mostly.
We implement `super` by way of a new `Object` impl which wraps arbitrary objects with a modified prototype chain. Specifically, the lowest layer of the prototype chain is omitted. This new `SuperObject` script is composable: a chain of two `SuperObject`s will go two levels of inheritance upwards while still maintaining non-prototype property access.
2019-12-15 13:32:04 -08:00
David Wendt 681b4adfa4 Functions close over the constant pool they were defined with. 2019-12-15 13:17:41 -08:00
David Wendt 71d9655f6d Implement `ASSetPropFlags` 2019-12-15 13:17:41 -08:00
David Wendt 213b3cfca1 Store implemented interfaces on the prototype, not the constructor, so that InstanceOf can get at them. 2019-12-15 13:17:41 -08:00
David Wendt fcb37bd273 Implement `ActionCastOp`. 2019-12-15 13:17:41 -08:00
David Wendt ee4b47d062 Add interface support, and add interface checking to `ActionInstanceOf`. 2019-12-15 13:17:41 -08:00
Mike Welsh 81e5c7ba1d core: Rename get_length etc. -> length 2019-12-15 12:33:24 -08:00
Mike Welsh bc42004db5 core: Implement From for Object variants to Value/ReturnValue 2019-12-15 12:33:24 -08:00
Nathan Adams aca746eee7 core: Implemented Array.splice with tests 2019-12-15 12:33:24 -08:00
Nathan Adams 31b84c5f19 core: Made arrays a storage property of objects, not a unique object type. Added more corner case tests. 2019-12-15 12:33:24 -08:00
Nathan Adams 32a1eda080 core: Implement Arrays & array prototype 2019-12-15 12:33:24 -08:00
Mike Welsh 8c27097240 core: Implement _target property
Add DisplayObject::slash_path to get the Flash 4-style slash path
to the clip. This fixes the tellTarget regression test and removes
the superfluous `target_path` from `UpdateContext`.
2019-12-15 10:17:33 -08:00
Mike Welsh d5f7521061 core: Ignore NaN in StageObject setters 2019-12-15 10:17:33 -08:00
Mike Welsh c9864eb557 core: Add StageObject properties 2019-12-15 10:17:33 -08:00
Mike Welsh f2422a2c9f avm1: Add attributes for _global/_root/_parent 2019-12-15 08:54:26 -08:00
Mike Welsh c29b042f5e avm1: Get child clip instances in StageObject
Add the logic to get children display objects as properties in
`StageObject`.
2019-12-15 08:54:26 -08:00
Mike Welsh 783ede6f79 core: Add DisplayObject::path 2019-12-15 08:54:26 -08:00
David Wendt 724f845037 Remove the `DisplayNode` slot from `ScriptObject`, since all display node objects should be `StageObject`s now. 2019-12-15 08:54:26 -08:00
David Wendt fa9329df68 Instantiate all MovieClips as StageObjects. 2019-12-15 08:54:26 -08:00
David Wendt 3df6c7eeef Always post-instantiate display objects when running tests. 2019-12-15 08:54:26 -08:00
David Wendt 73655c0c88 Add a separate native object type for objects tied to the stage. 2019-12-15 08:54:26 -08:00
Mike Welsh f0c6b2d8d8 core: Remove this from Object::get/set 2019-12-15 08:54:26 -08:00
Mike Welsh b59bf40c78 core: Remove this from Object::get/set 2019-12-10 01:36:02 -08:00
Mike Welsh f7822141b7 core: Rename display_node methods to display_object 2019-12-10 01:36:02 -08:00
Mike Welsh 71e4eb87d7 core: Remove as_*_mut methods on DisplayObject/Object 2019-12-10 01:36:02 -08:00
Mike Welsh 12c1bf7cf1 core: Clean up UpdateContext creation
Added Player::mutate_with_update_context, which takes a closure
and passes it an UpdateContext.
2019-12-10 01:36:01 -08:00
Mike Welsh 30ecbd0ecc core: Use enum_trait_object for DisplayObject 2019-12-10 01:36:01 -08:00
Mike Welsh 23ca66a7e3 avm1: Use enum_trait_object for avm1::Object 2019-12-10 01:36:01 -08:00
Mike Welsh 90b6858bb2 avm1: Fix return value of `Object.addProperty` 2019-12-03 14:59:37 -08:00
Nathan Adams eb185982cd Add more Number(x) tests, and corrected primitive_as_number to match 2019-11-29 16:07:35 -08:00
Nathan Adams 85b9ffe102 core: Merge both test macros into a generic test_method 2019-11-29 13:12:00 -08:00
Nathan Adams 1f4405189a core: Make math test_std also take in versions 2019-11-29 13:12:00 -08:00
Nathan Adams 999bb128de core: Allow global test_std to test multiple swf versions 2019-11-29 13:12:00 -08:00
David Wendt 9ec85c3892 Add tests for SWF6 numerical coercions. 2019-11-28 21:32:10 -05:00
David Wendt f856243247 Primitive coercions should not yield an object just because valueOf is undefined. 2019-11-28 20:53:32 -05:00
David Wendt ec3ac4e5d6 `undefined` coerces to `0.0` on SWF6 2019-11-28 20:53:32 -05:00
David Wendt 16259ad74a Calling uncallable values does not actually cause a runtime error in Flash; it just returns null.
This was discovered almost by accident: @Dinnerbone noticed that `_global == null`, and surmised that `valueOf` was the culprit. However, this doesn't really make sense: `_global` is a bare object, so it shouldn't have a `valueOf` (and in practice, it doesn't).

The ultimate cause of such an odd comparison is as such:

1. Flash coerces the `_global` object to a numerical primitive by calling `valueOf`.
2. `_global.valueOf` is undefined. Flash handles calls to any uncallable value by literally just having it return `undefined`. In other words, all values are implicitly callable as empty functions.
3. `undefined` is then compared to `null`. These two values *are* equal under abstract equality (`==`). Hence, `_global == null`.

For comparison, modern ECMAScript engines throw errors on calls to uncallable values; and won't attempt to use an invalid `valueOf` to coerce objects. So none of this applies to, say, standard JavaScript in your browser.
2019-11-28 20:53:31 -05:00
Nathan Adams 638231e7fb swf4 doesn't have NaN or Infinity 2019-11-28 20:53:20 -05:00
Nathan Adams 581d0940b2 NaN == NaN without coercion 2019-11-28 20:43:59 -05:00
Nathan Adams f33229a2a1 `_global` == null && `_global` == undefined 2019-11-28 20:43:58 -05:00