Commit Graph

107 Commits

Author SHA1 Message Date
David Wendt 3d8bf90794 core: Also allow converting `TextFormat` back into an AVM2 object. 2021-03-19 12:39:57 -07:00
EmperorBale b68eeeae26
avm2: Implement ByteArray 2021-03-05 15:01:02 -08:00
paq d866f73c5e avm2: Implement RegExp 2021-03-03 03:37:34 -08:00
David Wendt 999100a332 avm2: Only track broadcast lists for events that are actually broadcasts. 2021-03-03 03:08:01 -08:00
David Wendt 540a68fb68 avm2: Grant each event it's own, separate broadcast list. 2021-03-03 03:08:01 -08:00
David Wendt d1ffa3254b Store a list of every constructed event dispatcher so we can broadcast events on them. 2021-03-03 03:08:01 -08:00
David Wendt 63af38be9a avm2: Add convenience method for natively-dispatched events. 2021-03-03 03:08:01 -08:00
David Wendt 58f4470dc5 avm2: Add `Event` class, object type, and native representation 2020-12-14 16:46:33 -08:00
David Wendt d27360b282 avm2: Enable lazy initialization for ABCs that request it. 2020-10-17 03:32:09 -07:00
David Wendt 0d1676afda avm2: Create a separate domain for each loaded movie and pull symbols out of each. 2020-10-17 03:32:09 -07:00
David Wendt f2caf60d3e avm2: Scripts should run in a child of the global domain. 2020-10-17 03:32:09 -07:00
David Wendt 6a736b0d2b avm2: Wrap all player globals in a separate appdomain and script.
This entirely abolishes the "global scope object" in AVM2. I even had to redefine several global object functions to work with the bottom of the scope stack, which seems to be where ASC likes to stick the script scope.
2020-10-17 03:32:09 -07:00
David Wendt add7c4d43d avm2: Collect all script definition names and associated scripts into a `Domain`. 2020-10-17 03:32:09 -07:00
David Wendt 02e05e3d7f Add separate scope object for each script. 2020-10-17 03:32:09 -07:00
David Wendt 542147d657 avm2: Run all AVM2 frame scripts on the action queue.
This is the same way that AVM1 actions run and it appears that frame scripts work exactly the same way. It fixes all outstanding bugs with movie clip navigation in AVM2 and allows me to remove a lot of weird workarounds I was writing for the old, incorrect behavior.

I'm also removing the "last run script frame" rule as `run_frame_internal` already had rules to prevent stopped clips from rerunning actions.
2020-10-06 06:03:22 -07:00
David Wendt a70e1be466 Add code to instantiate AVM2 movie clips correctly.
This also includes several bits to build an effective VM barrier.
2020-10-06 06:03:22 -07:00
David Wendt 3128bbcda6 core: Implement `SymbolClass` tag. 2020-10-06 06:03:22 -07:00
David Wendt f85319aa4c core: Allow `DisplayObject` to hold AVM2 objects.
This requires the use of an intermediary enum called `AvmObject` which can hold either object representation. Currently, it's mostly just being unwrapped as AVM1 objects, which we will need to fix.
2020-10-06 06:03:22 -07:00
David Wendt 88fc9b1538 avm2: Implement base types for array-shaped objects. 2020-09-15 02:20:11 -07:00
David Wendt 4c824fcefe Rename `trait.rs` to `traits.rs` to avoid the use of reserved keyword syntax. 2020-08-14 21:20:41 -04:00
David Wendt 11ddccfa6a Remove the two-step initialization process and construct an ES4 class for `Object`, `Function`, and `Class`.
This has some particularly annoying consequences for initialization order: notably, we can't actually create any ES4 classes using the standard machinery until after the three objects I just mentioned get created. Ergo, we have to create them through lower-level means, handing prototypes around, and then initialize AVM2's system prototypes list for it.

When we start adding more system prototypes, we'll also have to fill the extras with blank objects and then slot them in as we create them.
2020-08-11 00:02:12 -04:00
David Wendt a8e267ed16 Allow system prototypes to be initialized after the fact. 2020-08-10 23:35:37 -04:00
David Wendt 3585cf983b Convert our stub implementations of all non-ECMA classes into `Class`es.
This was surprisingly tricky - due to the need to look up superclasses, class trait instantiation requires an active `Activation` and `UpdateContext`. We can't get those during VM instance creation, since the player needs the VM first before it can give it a context to work with. Ergo, we have to tear the global scope initialization in two. At the first possible moment, the player calls a new `load_player_globals` method that initializes all class traits in global scope.
2020-08-10 23:16:07 -04:00
David Wendt 566b262d60 Move all our custom object implementations into a separate module, and use a macro to implement them. 2020-08-10 16:38:04 -07:00
David Wendt d14fa845c2 Remove `Value::Namespace`.
Namespaces as values adds a bunch of extra special cases to the coercion and equality rules that don't really belong there. Namespace itself just returns it's URI as a string, so we can just make `NamespaceObject` do that and then treat it the same way we treat boxed primitives.
2020-08-10 16:38:04 -07:00
David Wendt e6aac48ae2 Add `NamespaceObject` to hold `Namespace`s.
The reason for this will become very apparent, very shortly.
2020-08-10 16:38:04 -07:00
David Wendt cb0f1e9099 Add a new object variant for boxed primitives. 2020-08-10 16:38:04 -07:00
David Wendt 8ebf5405e2 Move AVM2 into the UpdateContext. 2020-08-01 15:49:29 -04:00
Nathan Adams 7f7281493f core: Allow toggling avm_debug output on and off with ctrl+alt+d, defaults to off 2020-07-23 19:14:32 -07:00
David Wendt dc962f2abd Add AVM2 equivalent of `PropertyMap` for further expansion. 2020-07-18 16:41:35 -04:00
David Wendt 37b6b89d26 Add a stub AVM2 string representation to allow for both VMs' strings to diverge. 2020-07-18 16:20:58 -04:00
David Wendt 97e005622b Invert the role of `Avm2` and it's `Activation`, similar to what was done with `Avm1` and it's `Activation`.
This also results in a far reduced role for `ReturnValue`, since I also took the liberty of removing most of it's use. Furthermore, I also made it apply equally to native and AVM2 code, which ensures all native implementations of methods don't double-borrow.

In AVM1, `ReturnValue` was actually removed entirely, because it's not needed. I attempted to do the same, but the fact that we're currently embedding `ScriptObjectData` in native objects means that we need it for virtual properties. Otherwise, virtual property implementations will see locked objects, which is bad.
2020-07-13 17:45:06 -04:00
David Wendt 098b034de0 Refactor method-related structs into a separate method module.
This also renames `NativeFunction` and `Avm2MethodEntry` to `NativeMethod` and `BytecodeMethod`, respectively.
2020-07-13 17:45:05 -04:00
David Wendt 0d2235d2e0 Resolve all remaining compilation issues with this refactor. 2020-07-13 17:45:04 -04:00
David Wendt 7684736bf7 `table_class` should resolve `Class`es straight from the current translation unit. 2020-07-13 17:45:04 -04:00
David Wendt 232c29dc5e Fix remaining problems with method loading using `callstatic` 2020-07-13 17:45:03 -04:00
David Wendt eaebd3c63c Make `Avm2MethodEntry` hold it's `TranslationUnit` rather than an `AbcFile`. 2020-07-13 17:45:03 -04:00
David Wendt 4467bc3193 Make `TranslationUnit` a GC-mandatory type (only referred to by `GcCell`). 2020-07-13 17:45:03 -04:00
David Wendt f549d0146e Fix compilation bugs involved with automatic script initializer execution. 2020-07-13 17:45:02 -04:00
David Wendt b4f944b37b Wrap ABC loading inside of a `TranslationUnit`. 2020-07-13 17:45:01 -04:00
David Wendt 15a62d31cb Add an internal representation of `Trait`, separate from `swf::avm2::types::Trait`, which is specific to the ABC file format.
The intention is to completely replace all usage of `Avm2XYZEntry` with `Class`, `Trait`, and `Method`. This will allow runtime-provided global class traits to coexist with those provided by user code.
2020-07-13 17:45:01 -04:00
David Wendt 4cd30455de Excise `ReturnValue<'gc>` from all `TObject` methods.
Inspired by Dinnerbone's PR doing the exact same thing to AVM1.

On AVM2 we have a bit of a subtle issue: the base implementation of `set_property_local` and `init_property_local` *must* return `ReturnValue`s to avoid double-borrows. Each implementation of `TObject` must resolve them before returning.
2020-07-13 17:45:00 -04:00
David Wendt 34b3bbae63 *Correctly* implement `ifstricteq` and `ifstrictne`.
The previous implementation suffered from copypasta and was attempting to assert that both of it's values were `bool`.
2020-07-13 17:44:59 -04:00
David Wendt b4d907bf2e Implement `strictequals`. 2020-07-13 17:44:58 -04:00
David Wendt 307a95e5c4 `callproperty` and `callpropvoid` should *never* get callables from `base_proto`. 2020-07-13 17:44:35 -04:00
David Wendt 00186f7602 Free functions always have a `prototype`, this is a holdover from ES3. 2020-07-13 17:44:33 -04:00
David Wendt c014b40109 Implement `hasnext`, `hasnext2`, `nextname`, `nextvalue`, and the underlying enumeration machinery that powers it.
I have... significant reservations with the way object enumeration happens in AVM2. For comparison, AVM1 enumeration works like this: You enumerate the entire object at once, producing a list of property names, which are then pushed onto the stack after a sentinel value. This is a properly abstract way to handle property enumeration.

In AVM2, they completely replaced this with index-based enumeration. What this means is that you hand the object an index and it gives you back a name or value. There's also an instruction that will give you the next index in the object.

The only advantage I can think of is that it results in less stack manipulation if you want to bail out of iteration early. You just jump out of your loop and kill the registers you don't care about. The disadvantage is that it locks the object representation down pretty hard. They also screwed up the definition of `hasnext`, and thus the VM is stuck enumerating properties from 1. This is because `hasnext` and `hasnext2` increment the index value before checking the object. Code generated by Animate 2020 (which I suspect to be the final version of that software that generates AVM2 code) initializes the index at hero, and then does `hasnext2`, hence we have to start from one.

I actually cheated a little and added a separate `Vec` for storing enumerant names. I strongly suspect that Adobe's implementation has objects be inherently slot-oriented, and named properties are just hashmap lookups to slots. This would allow enumerating the slots to get names out of the object.
2020-07-13 17:44:32 -04:00
David Wendt 73189b6449 Properly unwind errors thrown from the AVM2 reader. 2020-07-13 17:44:32 -04:00
David Wendt 1cc8954747 Impl `pop`, which is the opposite of `dup`; and also the opposite of all the `push` instructions.
Confusingly, this one isn't documented in the AVM2 spec at all, but it's method of operation is fairly obvious.
2020-07-13 17:44:31 -04:00
David Wendt 67b7fbb593 Implement `label`, which is a no-op designed specifically to silence verifier errors about unreachable code. 2020-07-13 17:44:31 -04:00