Commit Graph

1660 Commits

Author SHA1 Message Date
David Wendt e354c53075 Remove any remaining uses of `abc_ref`.
Holding a `Ref` on a garbage-collected object inherently extends any borrow locks on that object. Since ABC files are references already, taking a `Ref` to them only helps to skip the refcount update. This is less useful than expected: in most situations, using `abc_ref` causes double-borrow panics. The few methods that can use it are going to be fragile in the face of future refactors, so I'm nipping the problem in the bud now.
2020-07-14 20:14:23 -04:00
David Wendt f4c5075086 Run all string constant retrieval through the `TranslationUnit`, preventing us from making multiple copies of the same string.
For good measure, most of the other methods in `value` for retrieving pool primitives now also use `TranslationUnit` instead of `AbcFile`. This is the result of a handful of cascading changes throughout the project, and itself caused a few more.
2020-07-14 20:05:25 -04:00
David Wendt 70e9e7e9e9 Add support for cached/interned pool strings in the `TranslationUnit`. 2020-07-13 23:42:07 -04:00
David Wendt e1b9b823fc Remove `abc_string` and replace it with `abc_string_copy`. All code that pulls strings from the ABC file now uses `AvmString`s. 2020-07-13 23:41:46 -04:00
David Wendt 61a3ff8ae6 Replace `String` or `&str` references with `AvmString` everywhere in the AVM2 runtime. 2020-07-13 22:21:18 -04:00
David Wendt 2021cec9d3 Impl `Copy`, `Eq`, `PartialOrd`, `Ord`, and `Hash` for `AvmString`. 2020-07-13 22:09:34 -04:00
David Wendt 508fcd6e9e `pool_string` should return a `Ref<str>` just like `value::abc_string`. 2020-07-13 17:45:12 -04:00
David Wendt a406bdada2 Don't attempt to log debugging information if we're not in a debug build. 2020-07-13 17:45:12 -04:00
David Wendt ae26615bb4 `coerce_string` may return a static string, which we shouldn't clone. 2020-07-13 17:45:12 -04:00
David Wendt f0c633fe81 Allow borrowing string values from an ABC file instead of cloning everything. 2020-07-13 17:45:11 -04:00
David Wendt 64e5b46259 Add tests for `instanceof` and `is` operators. 2020-07-13 17:45:10 -04:00
David Wendt 39a4566f20 Instances should be listed as their prototypes (empty as they are) 2020-07-13 17:45:10 -04:00
David Wendt c917b3d411 Implement `istype`, `istypelate`, and `instanceof`. 2020-07-13 17:45:10 -04:00
David Wendt a0cb052795 Add `is_instance_of` trait method to `TObject` 2020-07-13 17:45:09 -04:00
David Wendt 3fae8b3832 Read the interface list when instantiating classes, resolve them, and stick them in the prototype for later use. 2020-07-13 17:45:09 -04:00
David Wendt cce68dbc21 Add trait methods for getting and setting the interfaces list. 2020-07-13 17:45:08 -04:00
David Wendt 563a515189 Add a test for loading interfaces into the AVM2.
This test will fail if the AVM2 implementation does not support bodyless methods or bare classes properly.
2020-07-13 17:45:07 -04:00
David Wendt 8f2d3315f3 Allow the construction of classes with no base class.
This is primarily used for interfaces, in case you can't guess by the previous commit.
2020-07-13 17:45:07 -04:00
David Wendt 5d89d4ed85 Allow methods to not hold a body.
Interface methods are specifically not allowed to be called: as a result, they don't get a method body. Existing code assumed a 1:1 relationship between methods and bodies, which causes spurious errors.
2020-07-13 17:45:07 -04:00
David Wendt 090fe56bd3 Wrap `BytecodeMethod` (and the bytecode half of `Executable`) in a `Gc`.
This is inspired by Dinnerbone's similar PR on the AVM1 side, where the Action half of that VM's `Executable` was reduced from 128 bytes to 16 by shoving it in a `Gc`. This won't be as dramatic but should still save some memory.

In fact, it should save a *lot* of memory in bytecode execution, where thanks to the previous commit's rebase, we now need to clone the current method once *for each instruction executed*. That is terrible, but should stop now.
2020-07-13 17:45:06 -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 5b5bf0719e Remove `Avm2Function` as it is no longer used. 2020-07-13 17:45:05 -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 b6e05519cd Remove `Avm2ClassEntry`. It is no longer used. 2020-07-13 17:45:05 -04:00
David Wendt 12fc13da7f Clippy compliance for the last batch of commits. 2020-07-13 17:45:05 -04:00
David Wendt 041cb0b5c3 Resolve multiname constant zero as an error rather than a panic.
While some code that references pool multinames has zero as a valid index, we cannot validate exactly what the zero index is for a given index. Hence, callers instantiating multinames must check for zero and substitute the correct zero-value interpretation for their given type. If zero is an invalid value, it should ideally throw a different error than what's provided here.
2020-07-13 17:45:04 -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 60f3ae3ba7 Remove `Avm2ScriptEntry`. It is now obsolete and unused. 2020-07-13 17:45:02 -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 70e9030072 Decouple the entire trait machinery from ABC-provided traits.
This commit breaks the build: we still need to tell `Avm2` how to turn ABC traits into our own internal `Trait<'gc>`, `Class<'gc>`, and `Method<'gc>` types. We also need something to track which traits have already been instantiated, because `callstatic` would otherwise reinstantiate the trait in a different scope. (In fact, I think it *does* do exactly that right now...)
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 3362ec09e8 chore: Clippy conformance 2020-07-13 17:45:00 -04:00
David Wendt fe283e6770 Silence this warning about occupied slots being an unused variant.
I don't know if I'm missing something, but I'm pretty sure this variant is reachable via `TObject::install_slot`.
2020-07-13 17:45:00 -04:00
David Wendt 6117288fe2 Add tests for `ifstricteq`, `ifstrictne`, and `strictequals`. 2020-07-13 17:44:59 -04:00
David Wendt 34ab8c8ce6 `NaN` is not special-cased in AS3. 2020-07-13 17:44:59 -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 ecfd16cec9 Add global constants `undefined`, `null`, and `NaN`. 2020-07-13 17:44:58 -04:00
David Wendt 03a240ebcd Add tests for `valueOf`. 2020-07-13 17:44:58 -04:00
David Wendt b4d907bf2e Implement `strictequals`. 2020-07-13 17:44:58 -04:00
David Wendt 3b52dfe2ba Since we have an `es3_inheritance` test now, rename the existing inheritance test to `es4_inheritance`. 2020-07-13 17:44:57 -04:00
David Wendt cf6714d33c Implement and test `toLocaleString`.
This function has vague documentation about enabling locale-specific formatting in subclasses. As far as I can tell, none of the objects I implemented so far do anything different than `toString`, so I just have it use the same `TObject` property I set up for `toString`.
2020-07-13 17:44:57 -04:00
David Wendt 3558c3afa0 Add test of `Function.prototype.call` 2020-07-13 17:44:56 -04:00
David Wendt 16774aa055 Add a test for legacy / ES3 inheritance.
This was originally something *way* more evil: mixed inheritance between ES3 and ES4 classes. It didn't pan out due to fundamental limitations of the two object models. How the hell did Brendan Eich/Adobe/TC-39 expect ES4 classes to be adopted in already-existing codebases?!
2020-07-13 17:44:56 -04:00
David Wendt 4b66af8dc3 ES4 classes, while superficially similar to functions, are not functions and should not inherit from the `Function` prototype.
We still reuse the `FunctionObject` machinery internally. If necessary, we may want to split this into a separate `ClassObject` if some internal `TObject` method needs replacing for classes.
2020-07-13 17:44:55 -04:00
David Wendt 8b36751fbb Several built-in functions are not `public`, but instead live in the `AS3` namespace. This moves those functions there.
In practice not many movies will care about this, because the `AS3` namespace is open by default. You could opt-out of that, and I suppose that was there for using existing ES3 code in AS3 projects. ES4 would have had a similar ES4 namespace, which "JavaScript 2.0" code would need to opt into. Of course, ES4/JS2 never happened, so we just have this weird historical quirk here.
2020-07-13 17:44:55 -04:00
David Wendt 37cdcb3bce Add tests for `toString` on objects, functions, and classes. 2020-07-13 17:44:54 -04:00
David Wendt f493cf954f Make `toString` and `valueOf` methods of `TObject`, called `to_string` and `value_of` respectively.
The reason for this is that, in AVM2, `toString` and `valueOf` are not defined on the classes or prototypes of `Function` or `Class`. Instead, they use the `Object.prototype` versions of those functions. Ergo, string and primitive coercion are inherent object methods (the ones that get `[[DoubleSquareBrackets]]` in the ECMA standards). In Ruffle, our equivalent to `[[DoubleSquareBrackets]]` methods are methods on the `TObject` trait, so we're adding them there.

This mechanism will make implementing boxed value types (ala AVM1's `BoxedObject`) easier, too.

We also add some reasonable defaults for `ScriptObject` and `FunctionObject` which will appear on objects, functions, and classes.
2020-07-13 17:44:53 -04:00
David Wendt ba2c1f5750 Add test for `setPropertyIsEnumerable` 2020-07-13 17:44:39 -04:00
David Wendt f13e2ea3c4 Implement `setPropertyIsEnumerable` 2020-07-13 17:44:37 -04:00
David Wendt dc0cb00a03 Add a test for `propertyIsEnumerable`. 2020-07-13 17:44:37 -04:00
David Wendt 2afbcf450a Impl `propertyIsEnumerable` 2020-07-13 17:44:36 -04:00
David Wendt a0ca5891e4 Prevent instance traits from being accessible directly from prototypes. 2020-07-13 17:44:36 -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 42cb8f57c8 Add a test for `has_own_property` in various class instance scenarios. 2020-07-13 17:44:35 -04:00
David Wendt 6e2508a79d Fix `any` name resolution, at least enough for the `has_own_property` test to work.
Private names now return `false`, and we run any names through trait lookups. This also means any namespace resolution can fail now, in case we need to throw a `VerifyError`.
2020-07-13 17:44:34 -04:00
David Wendt 8677804ea0 Actually enable the `isPrototypeOf` test. 2020-07-13 17:44:34 -04:00
David Wendt c6265bb50c Allow tracing booleans.
This requires implementing *some level* of coercions, even though this isn't the way to do it.
2020-07-13 17:44:34 -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 0e89cb2175 Impl `Object.isPrototypeOf` w/ test 2020-07-13 17:44:33 -04:00
David Wendt d29f3dc1d0 Add `as3_object_enumeration` and `as3_class_enumeration` tests.
The former tests iterating normal objects and the latter tests iterating objects with prototypes.
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 9496fbde0a Remove `DontEnum`, `is_enumerable` and attribute mutation. They won't be needed. 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
David Wendt da6a7c0723 Implement `kill`, at least a little.
I'm sure there's some other part of AVM2 that cares about killed registers, but I couldn't find it yet.
2020-07-13 17:44:30 -04:00
David Wendt 7253c091a2 Add tests for control flow instructions that use booleans or strict equality.
Other comparisons will have to wait until we have ECMA-compliant abstract comparison and coercion.
2020-07-13 17:44:30 -04:00
David Wendt 9c5ea1d30c Implement `jump`, `iftrue`, `iffalse`, `ifstricteq`, and `ifstrictne`. 2020-07-13 17:44:30 -04:00
David Wendt b33c246713 Implement `is_property_overwritable`. 2020-07-13 17:44:29 -04:00
David Wendt ddc9aa4cca Add a test for ES4 method binding of `this`. 2020-07-13 17:44:29 -04:00
David Wendt 915b2da42b Allow binding a reciever to a function, and make all method traits bind themselves to the object they were constructed on.
Our already odd `super` handling throws up another subtlety regarding bound recievers. Since we have to construct an instance of a parent class in order to get traits on it, we also have to make sure that we initialize traits with the correct reciever. I'll demonstrate here:

```let mut base = base_proto.construct(avm, context, &[])?;
let name = base.resolve_multiname(&multiname).unwrap();
let value = base.get_property(object, &name, avm, context)?.resolve(avm, context)?```

In this case, if `name` is the name of a method, getter, or setter trait, then `get_property` will instantiate that trait on `base` but bound to `reciever`. This is correct behavior for this case, but more generally, trait instantiation is permenant and therefore there's potential for confusing shenanigans if you `get_property` with the wrong reciever.

To be very clear, `reciever` should *always* be the same object that is getting `get_property` et. all called on it. In the event that you need to instantiate traits with a different `reciever`, you should construct a one-off object and retrieve prototypes from that.
2020-07-13 17:44:28 -04:00
David Wendt f042e453a3 Add a test for interactions between prototype and class-trait properties.
This is the test that broke the old object model's back, please see parent commit's description for more details.
2020-07-13 17:44:27 -04:00
David Wendt 2f95a7a81b Completely overhaul the way traits are defined on objects.
Previously, we were treating ES4 classes like syntactic sugar over a prototype chain (like ES6 classes); e.g. each declared trait was set in the given prototype and then property look-ups happened as normal.

This already caused problems with virtual properties, which could be partially-defined in subclasses and required careful checks to make sure we stopped checking the prototype chain on the *correct* half of the property.

However, this is a hint of a larger problem, which is that ES4 classes don't actually define anything on the prototype chain. Instead, the instance itself constructs class properties and methods on itself. This allows things like methods automatically binding `this`, which isn't included in this commit but will be implemented really soon.

The prototype chain still exists even on pure ES4 classes, due to the need for backwards compatibility with ES3 code. Object, for example, still defines it's methods as prototype methods and thus there needs to be a prototype chain to reach them. I actually could have gotten away with using the prototype chain if AS3 *hadn't* retained this "legacy" detail of ES3 allowing this class/prototype distinction to leak out into upcoming tests.

We still actually use the prototype chain for one other thing: trait resolution. When we look for a trait to install onto an object, we pull traits from the prototype chain using a special set of `TObject` methods. This happens in opposite order from normal prototype lookups so that subclassing and verification can proceed correctly.

`super` somehow became even harder to implement: we now actually construct the parent class so we can get traits from it, which is going to complicate method binding as mentioned above.
2020-07-13 17:44:27 -04:00
David Wendt 353017576a `ScriptObject` now holds a reference to a class and allows retrieving traits from it. 2020-07-13 17:44:27 -04:00
David Wendt f10920adc0 Implement `Object.prototype.hasOwnProperty` and resolution of `Namespace::Any`. 2020-07-13 17:44:26 -04:00
David Wendt 67744650f1 Pass the ABC name and lazy init flag to the AVM2. 2020-07-13 17:44:25 -04:00
David Wendt 6cc3f7ecc3 Add a test for stored properties as well.
This test passed with no errors.
2020-07-13 17:44:24 -04:00
David Wendt 5abc78d3bd Add test of AVM2 virtual properties.
This tests:

 * Getter invocation
 * Setter invocation
 * Properties with one or the other, but not both
 * Inheritance
 * Superproperty getters and setters
 * Getters with inherited setter
 * Setters with inherited getter
2020-07-13 17:44:24 -04:00
David Wendt c5e3af2053 When resolving `get_property`, skip over virtual properties that do not have a defined getter. 2020-07-13 17:44:23 -04:00
David Wendt 54b792ef3a Ensure that called setters are properly resolved so that errors in setters propagate up the Rust stack correctly.
The previous system for handling setters would execute the setter and then return a value to indicate whether or not the caller needed to resolve a stack frame. However, no caller of `Property.set` actually did this. Ergo, errors in setters and getters would not resolve up the stack at the correct time.

This problem also exists in AVM1 but is far less noticable as AVM1 only has two very uncommon runtime errors and very few movies use `throw`.
2020-07-13 17:44:23 -04:00
David Wendt b8106d24d2 Ensure virtual setters are run when defined on a prototype.
Normally, `set_property` only affects the object it was called on, which makes sense: otherwise, we couldn't override values that originate from a class prototype without accidentally monkey-patching the prototype. However, virtual setters only exist in prototypes and need to be accessible from child objects.

The solution to this is to have a specific method to check if a virtual setter exists. Virtual setters are then resolved through the prototype chain. If no virtual setter exists, then the reciever object is handed the value.

Note that we always use the `reciever` object rather than `self` so that `setsuper` can work correctly. In `setsuper`, we resolve the base class, and then set properties on it with the actual object in question as it's reciever. If a virtual setter is called, it will get the actual object it should be manipulating; and otherwise, prototypes will not be modified or consulted.
2020-07-13 17:44:22 -04:00
David Wendt 665d7a4342 Implement `getsuper` and `setsuper`.
This required the reintroduction of dedicated reciever parameters to `Object.get_property_local` and `Object.set_property`, which I had removed from the AVM1 code I copied it from. It turns out being able to change the reciever was actually necessary in order to make super set/get work.
2020-07-13 17:44:22 -04:00
David Wendt 785832b7f3 Add `as3_inheritance` test, which is primarily designed to test method calls, constructor execution, and usage of `super`. 2020-07-13 17:44:22 -04:00
David Wendt e8fbac6cf2 Refactor the base_proto system to more accurately record what prototype methods come from.
The previous system primarily relied on `Executable` to automatically start and continue a super chain. This works, but only for class hierarchies without *override gaps* - methods that override another method not defined by the direct superclass of the method. In that case, the override method would be called twice as the `base_class` was moved up one prototype at a time, which is wrong.

The new system relies on the call site to accurately report the prototype from which the current method was retrieved from. Super calls then start the resolution process *from the superclass of this prototype*, to ensure that the already-called method is skipped.

It should be noted that the proper `base_class` for things like `callmethod`, `callstatic`, `call`, `get`/`set` methods, and other call opcodes that don't use property look-up are best-effort guesses that may need to be amended later with better tests.

To facilitate `base_proto` resolution, a new `Object` method has been added. It's similar to `get_property`, but instead returns the closest prototype that can resolve the given `QName`, rather than the actual property's `ReturnValue`. Call operations use this to resolve the `base_proto`, and then resolve the method being called in `base_proto`. The existing `exec_super` method was removed and a `base_proto` method added to `exec` and `call`.
2020-07-13 17:44:21 -04:00
David Wendt 43da7ac952 `resolve_multiname` should actually return it's prototype's return value. 2020-07-13 17:44:20 -04:00
David Wendt ab5a95c05b Add a test for various types of class methods. 2020-07-13 17:44:19 -04:00
David Wendt 1c3b9c50fe Implement prototype awareness for `get_property`, `has_property`, and `resolve_multiname`.
Furthermore, implement `has_own_property`.
2020-07-13 17:44:19 -04:00
David Wendt fa4369da72 Execute static class initializers.
This also fixes the lack of function prototype on classes.
2020-07-13 17:44:18 -04:00
David Wendt 687a82f643 Constructors should also inherit closure scope. 2020-07-13 17:44:18 -04:00
David Wendt 73966f1b31 Make sure that we actually call the super constructor, not our own constructor. 2020-07-13 17:44:17 -04:00
David Wendt 1b67bb94c8 Impl `callsuper`, `callsupervoid`, and `constructsuper`.
This works primarily by retaining the current superclass prototype in the activation object and then using it to retrieve the super method.

For constructors, we implement the `constructor` property, which is probably not the correct way to do this.
2020-07-13 17:44:15 -04:00
David Wendt f3dee5c310 Add (currently failing) test for constructors. 2020-07-13 17:44:14 -04:00
David Wendt a77f676279 `construct` and `constructprop` should push the object that was just constructed. 2020-07-13 17:44:13 -04:00
David Wendt 0fc9b9a287 `construct` and `constructprop` should take their args in reverse-order like the call functions do. 2020-07-13 17:44:13 -04:00
David Wendt 9431e02802 The class function should use the *instance* initializer as it's callable, not the class initializer. 2020-07-13 17:44:13 -04:00
David Wendt bedf5cb459 Add a basic test for function calls. 2020-07-13 17:44:13 -04:00
David Wendt 38868fbdfe Args are pushed onto the stack in normal order, so we need to pop them off in reverse order. 2020-07-13 17:44:12 -04:00
David Wendt a2dfffc56e Add our first AVM2 regression test: hello world! 2020-07-13 17:44:09 -04:00
David Wendt 7d576203c9 Impl `coerce_a`.
This currently treats `coerce_a` as a no-op. Strictly speaking, this is for type verification purposes, but we currently don't type-verify ABC code. Ergo, this requires no VM support at this time.
2020-07-13 17:43:50 -04:00
David Wendt a0ab978bed Impl `callmethod`, `callproperty`, `callproplex`, `callpropvoid`, and `callstatic`.
Also, implement a method table that method traits can optionally add themselves to.

Also also, add the ability to invoke a method without a `this` object. This required a non-trivial refactoring of the activation machinery, and changes to the signature of `NativeFunction`, and all native AVM2 functions.
2020-07-13 17:43:49 -04:00
David Wendt 68cf9e8869 Upon encountering an `Err`, dispose of the current AVM2 stack.
In the future, the `unwrap_stack_frame` mechanism should be expanded upon to allow running exception handlers and recovering from a Rust error - but not today.
2020-07-13 17:43:49 -04:00
David Wendt a7ff2de476 Don't spam the test log with `Resolving Multiname` messages for each scope that gets checked 2020-07-13 17:43:48 -04:00
David Wendt dd6b0a8728 Remove unused reference to slot property fields 2020-07-13 17:43:48 -04:00
David Wendt bf45f7f161 Fix crash when reading or writing a property that redirects to a slot. 2020-07-13 17:43:48 -04:00
David Wendt 7792fd5581 Impl `trace`, which is a free function rather than an opcode this time. 2020-07-13 17:43:48 -04:00
David Wendt a557867c71 Add the entire class hierarchy of `MovieClip` and `Sprite`. 2020-07-13 17:43:47 -04:00
David Wendt f6e2ca1fe5 Clean up the current set of builtins to accurately reflect the namespace hierarchy. 2020-07-13 17:43:47 -04:00
David Wendt 38b1524a49 Fix the error messages for `findpropstrict` and `getlex` to be more informative. 2020-07-13 17:43:47 -04:00
David Wendt 843de29460 Impl `newobject` 2020-07-13 17:43:46 -04:00
David Wendt 7201f6c4fe Impl `debug`, `debugfile` and `debugline`. 2020-07-13 17:43:46 -04:00
David Wendt 1d1bad1ab4 Impl `getglobalscope` 2020-07-13 17:43:46 -04:00
David Wendt 074ba94c17 Impl `newfunction` and `newclass`.
Notably, this also removes `new_closure_scope` as it is not needed. AVM1 does not capture `with` scopes in closures, but AVM2 (as well as modern ECMAScript) does.
2020-07-13 17:43:46 -04:00
David Wendt 1fe73b3329 Impl `dup` 2020-07-13 17:43:45 -04:00
David Wendt 0ff1c04697 Impl `initproperty` 2020-07-13 17:43:45 -04:00
David Wendt 5042fc1bc7 Debug all multiname resolutions 2020-07-13 17:43:44 -04:00
David Wendt 5c0e095ab5 `getlex` does not support runtime multinames according to spec. 2020-07-13 17:43:44 -04:00
David Wendt 9e120c216b Propagate arguments into local registers when calling AVM functions. 2020-07-13 17:43:44 -04:00
David Wendt 5b00c1fd96 Ensure that `this` is properly populated into local registers. 2020-07-13 17:43:44 -04:00
David Wendt b2f5307213 Add `flash.display.Sprite` because Flash Builder tests demand it. 2020-07-13 17:43:42 -04:00
David Wendt 4ab9a46515 Impl `getscopeobject` 2020-07-13 17:43:41 -04:00
David Wendt 5f98a198cb Remove dead code in Activation 2020-07-13 17:43:41 -04:00
David Wendt 279d90ec22 Remove `define_value` from AVM2 objects.
We already have a menagerie of `install_*` functions for adding static properties to a an object; and we don't have to support any kind of asinine nonsense liks `ASSetPropFlags` here. Ergo, we don't need this.
2020-07-13 17:43:39 -04:00
David Wendt cbce8660bc Implement `deleteproperty`. 2020-07-13 17:43:37 -04:00
David Wendt d19d9ef90e Clean up unused variables 2020-07-13 17:43:35 -04:00
David Wendt 8b56973d29 Remove scope methods that aren't necessary.
In AVM1, these are necessary because `ActionGetVariable` et. all directly interface with the scope chain. In AVM2, you `findpropstrict` up the scope chain, which gives you a normal object that you can interact with as you like. Ergo, the scope chain doesn't need set/get property methods.
2020-07-13 17:43:34 -04:00
David Wendt fd275bdcf3 Implement constant slots and traits.
Class and Function traits now generate const slots, too.
2020-07-13 17:43:33 -04:00
David Wendt 412c3d8489 Implement `Function` traits. 2020-07-13 17:43:29 -04:00
David Wendt af70024f62 Implement slot traits. 2020-07-13 17:43:28 -04:00
David Wendt 200c10b4a2 Classes can fit in slots, so let's stick them in there. 2020-07-13 17:43:27 -04:00
David Wendt d42b16f021 Add stub impl of `flash.display.MovieClip`. 2020-07-13 17:43:27 -04:00
David Wendt ebcfee4676 Add specific error messages for unresolvable super classes 2020-07-13 17:43:27 -04:00
David Wendt 362294181f Implement constant pool default values (index 0).
All constant pools in an ABC file are actually numbered starting from one; there's an implicit 0 entry not stored in the file that the runtime is expected to retrieve when pulling constants from the pool.

The AVM2/ABC spec only mentions this in passing.
2020-07-13 17:43:27 -04:00
David Wendt e1916519dd Add debug for trait installs 2020-07-13 17:43:26 -04:00
David Wendt cfe0e333be Fix invalid script index when loading an ABC file. 2020-07-13 17:43:26 -04:00
David Wendt bc0bdf8496 The public namespace appears to just be an unnamed package namespace, not a regular namespace. 2020-07-13 17:43:25 -04:00
David Wendt 04879fc419 Implement class traits.
This allows the AVM to declare classes, which necessitated some refactoring to avoid double-borrows or having to do something "magic" that would dodge virtual properties.
2020-07-13 17:43:25 -04:00
David Wendt ecfd5abb41 Impl `construct` and `constructprop`. 2020-07-13 17:43:24 -04:00
David Wendt 1ab4091050 Implement slots and related opcodes. 2020-07-13 17:43:24 -04:00
David Wendt 88957b2b3d Add stub builtins for Object and Function. These are more-or-less identical to the way we did it in AVM1 (e.g. no fancy player globals file) 2020-07-13 17:43:24 -04:00
David Wendt 1945f36dc0 When running the initial script, also install it's traits onto the global scope. 2020-07-13 17:43:23 -04:00
David Wendt 35c36a807b Always execute the last script when loading an ABC file 2020-07-13 17:43:23 -04:00
David Wendt 560900e708 ABC files are always pre-loaded.
Frame actions are handled as syntactic sugar on top of a `MovieClip` subclass and event handlers. ABC scripts do not live on the normal timeline.
2020-07-13 17:43:23 -04:00
David Wendt 502936f0fe Implement non-slot trait properties (Method, Getter, and Setter) 2020-07-13 17:43:22 -04:00
David Wendt 12e9fbbffb Impl virtual property slots 2020-07-13 17:43:22 -04:00
David Wendt eb0c9dcaec Allow constructing a function around a particular class definition.
I'm writing all this code assuming that classes and traits are syntactic sugar around ES3-style prototype chains on function objects. Hence, `FunctionObject` is still our workhorse object type for implementing typing.
2020-07-13 17:43:21 -04:00
David Wendt cf490bedfb Unstub `proto`. 2020-07-13 17:43:20 -04:00
David Wendt b12c6e0ff1 Implement closure scope stacks. 2020-07-13 17:43:20 -04:00
David Wendt 7d75255a1a Add global scope which is automatically included on all new activations. 2020-07-13 17:43:20 -04:00
David Wendt 984e701142 Swap out `has_property`'s stub impl. 2020-07-13 17:43:19 -04:00
David Wendt e5142e85e9 Replace `get_property` and `set_property` with slightly-less-stub impls. 2020-07-13 17:43:17 -04:00
David Wendt d56db06447 Implement `resolve_multiname`, sort of. 2020-07-13 17:43:16 -04:00
David Wendt 78a1c9a7e3 Implement `pushscope`, `popscope`, and `pushwith`. 2020-07-13 17:43:16 -04:00
David Wendt 5e6fc79f42 Implement `getproperty`, `setproperty` 2020-07-13 17:43:15 -04:00
David Wendt 60c16b0a60 Implement `findproperty`, `findpropstrict`, and `getlex`; which are necessary for interacting with global scope. 2020-07-13 17:43:15 -04:00
David Wendt 3c8035f871 clippy pls 2020-07-13 17:43:14 -04:00
David Wendt 12223d524a Add support methods in `Scope` to support opcodes that traverse the scope chain. 2020-07-13 17:43:14 -04:00
David Wendt 0ff1ba7120 Multiname resolution is another object method. 2020-07-13 17:43:14 -04:00
David Wendt 376d1a8ca6 Add scope support 2020-07-13 17:43:13 -04:00
David Wendt 3b476cba9e Implement `pushnamespace` since that's a value type now 2020-07-13 17:43:13 -04:00
David Wendt 1a6acb9440 Implement late binding and runtime qualifications for names. 2020-07-13 17:43:12 -04:00
David Wendt 2f3a3aff6f Add exact type assertion methods for strings and namespace values. 2020-07-13 17:43:11 -04:00
David Wendt 6d8dc6e63d Pull ABC constant pool methods out of Avm2 and into Value.
The old methods still exist and do the same thing, but the Value methods
accept arbitrary AbcFile references.
2020-07-13 17:42:51 -04:00
David Wendt c65d93d063 Implement multinames, sans runtime namespace support. 2020-07-13 17:42:50 -04:00
David Wendt 6bd94d6bc9 `from_abc_namespace` should accept a namespace index and retrieve it from the file's constant pool itself. 2020-07-13 17:42:50 -04:00
David Wendt 43f1080fab Implement namespaces as a value type 2020-07-13 17:42:49 -04:00
David Wendt 52ac7a6583 Implement call/return for bare functions 2020-07-13 17:42:49 -04:00
David Wendt 115f0393aa Add `call` method to the object trait. Only functions are callable in AVM2, all others error out. 2020-07-13 17:42:48 -04:00
David Wendt d1aeae8e02 Add support for local registers in the interpreter. 2020-07-13 17:42:47 -04:00
David Wendt 4d000e1ce0 Implement `pushxyz` opcodes for all value types that we currently support. 2020-07-13 17:42:46 -04:00
David Wendt 5600ac477c Always execute any AVM2 code that may have been queued as a result of loading ABC files. 2020-07-13 17:42:45 -04:00
David Wendt 7f60fab1e5 Add the bare minimum necessary to get opcodes out of an ABC and into an interpreter loop.
Surprisingly enough, the "bare minimum" includes a stack, object model, and values already.
2020-07-13 17:42:45 -04:00
David Wendt e80c887261 Add a very basic object model to the AVM2 interpreter. 2020-07-13 17:42:44 -04:00
David Wendt b7f257e7c8 Add a path to get from the movie clip to the Avm2. 2020-07-13 17:42:43 -04:00
David Wendt a852a6939a Add an extremely trivial implementation for the AVM2 interpreter state. 2020-07-13 17:42:31 -04:00
Nathan Adams fba8ccda81 avm1: Rename Avm1String to AvmString 2020-07-13 10:12:54 -07:00
Nathan Adams d8f043fa1a avm1: Value::coerce_to_string returns an Avm1String, as it can avoid a clone-and-reallocate 2020-07-13 10:12:54 -07:00
Nathan Adams f0ef68cb16 avm1: Reenabled paused string-value tests during string refactor 2020-07-13 10:12:54 -07:00
Nathan Adams c60b2cf4fc avm1: Implement From<&'static str> for Value 2020-07-13 10:12:54 -07:00
Nathan Adams e03e3f6c4e avm1: Allow Avm1String to contain &'static str 2020-07-13 10:12:54 -07:00
Nathan Adams ad733f2f21 avm1: Add Avm1String which wraps Gc<String> 2020-07-13 10:12:54 -07:00
Nathan Adams 016b9db3c5 avm1: Change Value::String(String) to Value::String(Gc<String>) 2020-07-13 10:12:54 -07:00
CUB3D 0591c0fe4b core: Add functions to prototypes 2020-07-12 15:25:58 -07:00
CUB3D ab022b66e9 chore: Format and cleanup clippy lints 2020-07-12 15:25:58 -07:00
CUB3D 83cca044ad core: Add tests for ContextMenu and ContextMenuItem 2020-07-12 15:25:58 -07:00
CUB3D 46cd8eb507 core: Add ContextMenuItem 2020-07-12 15:25:58 -07:00
CUB3D 04ca652f98 core: ContextMenu fully implemented 2020-07-12 15:25:58 -07:00
CUB3D 73a98c7f78 core: Implement copy() for ContextMenu 2020-07-12 15:25:58 -07:00
CUB3D f3aa6f7f01 core: Add stub of ContextMenuItem 2020-07-12 15:25:58 -07:00
CUB3D c8fefc56b5 core: Add stubs for context menu 2020-07-12 15:25:58 -07:00
dependabot-preview[bot] aaf42d1948 build(deps): bump syn from 1.0.33 to 1.0.34
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.33 to 1.0.34.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.33...1.0.34)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-12 15:01:43 -07:00
Nathan Adams 180891c58e avm1: Add impl_custom_object!() macro to simplify custom object types 2020-07-10 16:48:05 -07:00
Nathan Adams eb94cc54b2 chore: Move avm1 objects to their own module, we have plenty of them now 2020-07-10 16:48:05 -07:00
Mike Welsh 3322c2d916 avm1: Implement updateAfterEvent 2020-07-10 14:38:48 -07:00
Mike Welsh 8715589f50 tests: Add setInterval test 2020-07-10 14:38:48 -07:00
Mike Welsh 98e7da7d93 avm1: Implement setInterval 2020-07-10 14:38:48 -07:00
Mike Welsh a1ff80bb18 avm1: Object.watch is case insensitive on SWFv6 2020-07-10 12:02:26 -07:00
Nathan Adams 8a0430d744 avm1: Implement Object.watch & Object.unwatch (#268) 2020-07-10 12:02:26 -07:00
Nathan Adams ecbab536b5 avm1: Respect ScriptLimits for recursion depth, and use that in infinite_recursion_function 2020-07-08 14:47:38 -07:00
Nathan Adams 2b30fd32b7 avm1: Activation depth can be up to u16. 2020-07-08 14:47:38 -07:00
Nathan Adams 51ec5739c6 avm1: Throw errors when functions (user-called, or special) go too deep 2020-07-08 14:47:38 -07:00
Nathan Adams aa98c2c24f avm1: Track the reason for executions, if it's a function call vs
something special, like a getter
2020-07-08 14:47:38 -07:00
Nathan Adams 65396ba87a avm1: All errors are ignored during getters or setters 2020-07-08 14:47:38 -07:00
Nathan Adams 3ee1902117 avm1: Don't log errors at every Activation, only at the "root" frames 2020-07-08 14:47:38 -07:00
Nathan Adams 8218e14824 avm1: Remove unused field is_executing from Activation 2020-07-08 14:47:38 -07:00
dependabot-preview[bot] a3bdb20cf1 build(deps): bump smallvec from 1.4.0 to 1.4.1
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.4.0...v1.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-06 20:30:41 -07:00
Mike Welsh 2cbbe32412 tests: Add test for GetVariable/SetVariable on _x, etc. 2020-07-05 15:15:31 -07:00
Mike Welsh 804385347f tests: Add test for virtual properties on prototype 2020-07-05 15:15:31 -07:00
Mike Welsh fec8cf5e52 tests: Add tests for with from issue #792 2020-07-05 15:15:31 -07:00
Mike Welsh bd7f986594 avm1: Allow overwriting _parent 2020-07-05 15:15:31 -07:00
Mike Welsh ad6e2ceed4 avm1: Remove TObject::is_property_overwritable
Local virtual properties take precedence over prototype/parent
scopes, even for read-only propreties.
2020-07-05 15:15:31 -07:00
Mike Welsh 1240c79f70 avm1: StageObject::has_property should return true for _x, etc. 2020-07-05 15:15:31 -07:00
Mike Welsh 6feb266576 avm1: with(undefined) or with(null) is ignored 2020-07-05 15:15:31 -07:00
CUB3D 00d55b05a0 chore: Fix formatting 2020-07-05 13:49:59 -07:00
CUB3D 64eed4def9 chore: Cleanup 2020-07-05 13:49:59 -07:00
CUB3D ab58cff8b3 core: Add tests for ColorTransform and cleanup code 2020-07-05 13:49:59 -07:00
CUB3D 0dcbd05f5d chore: Fix formatting 2020-07-05 13:49:59 -07:00
CUB3D 68eb6a6342 core: Fix ColorTransformObject virtual prototype setters 2020-07-05 13:49:59 -07:00
CUB3D 73e9dc1a82 core: Refactor ColorTransform 2020-07-05 13:49:59 -07:00
CUB3D 26ae182584 core: Update to reflect avm changes 2020-07-05 13:49:59 -07:00
CUB3D 431cc532be core: ColorTransform no longer passed through engine ColorTransform object 2020-07-05 13:49:59 -07:00
CUB3D a8b1be2afa core: Remove useless to_owned in color_transform 2020-07-05 13:49:59 -07:00
CUB3D c0315dce3f chore: Format 2020-07-05 13:49:59 -07:00
CUB3D a8f7638d99 core: Implement ColorTransform 2020-07-05 13:49:59 -07:00
dependabot-preview[bot] 328246dc10 build(deps): bump jpeg-decoder from 0.1.19 to 0.1.20
Bumps [jpeg-decoder](https://github.com/image-rs/jpeg-decoder) from 0.1.19 to 0.1.20.
- [Release notes](https://github.com/image-rs/jpeg-decoder/releases)
- [Changelog](https://github.com/image-rs/jpeg-decoder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/image-rs/jpeg-decoder/compare/v0.1.19...v0.1.20)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-04 15:29:45 -07:00
Mike Welsh 7b4045f32b core: Remove some unneccessary `take` calls in tag functions 2020-07-03 18:52:26 -07:00
Mike Welsh 08569ae979 core: Limit tag parsing to slice of tag data 2020-07-03 18:52:26 -07:00
Nathan Adams c50c835790 avm1: Made Executable::Action take in a Gc to Avm1Function, reducing the size of the struct significantly 2020-07-03 18:47:34 -07:00
Nathan Adams c4980d0bf5 core: Make XMLName::node_name return Cow<str>. It's not always owned, and we don't always need it to be. 2020-07-03 17:30:59 -07:00
Nathan Adams c036e2cf88 avm1: Made f64_to_string return Cow<str> instead of String, as we sometimes return static values 2020-07-03 17:30:59 -07:00
Nathan Adams 938d644d7d core: Made PropertyMap::insert take &str instead of String, as ownership isn't always needed 2020-07-03 17:30:59 -07:00
Nathan Adams fb84999778 core: Made VacantEntry store a &str instead of a String, avoiding allocation until insertation is requested 2020-07-03 17:30:59 -07:00
Nathan Adams f4921fad45 core: Made PropertyMap::entry take &str instead of String. We often don't need ownership here. 2020-07-03 17:30:59 -07:00
Nathan Adams b5c06be8a2 avm1: Anonymous function names for debugging when not in debug mode 2020-07-03 17:24:20 -07:00
Nathan Adams 51321713b5 avm1: Show stack frame with the avm_debug feature 2020-07-03 17:24:20 -07:00
Nathan Adams c976cf8efb avm1: Replace action.avm() with activation.avm to help with borrow checker in next commit 2020-07-03 17:24:20 -07:00
Mike Welsh 07814fdf53 tests: Add test for Error 2020-07-02 20:58:01 -07:00
Jon Pacheco 48c65f02a1 avm1: Implement Error object (see #251) 2020-07-02 20:58:01 -07:00
Adrian Wielgosik 301d696670 Add a fast path for ASCII case conversions 2020-07-02 12:48:50 -07:00
Mike Welsh 3a4d432645 tests: Edit textfield_variable test for #777 2020-07-02 01:29:41 -07:00
Mike Welsh dd32acd8fc avm1: Empty text field does not initialize variable binding
If a text field with a variable binding is placed on the stage,
usually the variable is initialized with the initial text. However,
if the text field is empty, the variable remains undefined.

Fixes #777.
2020-07-02 01:29:41 -07:00
Mike Welsh b05da5ef0f avm1: CastOp fails for primitive values 2020-07-01 17:30:56 -07:00
Nathan Adams d86761db5d avm1: Implement try {..} catch {..} finally {..} - #731 2020-07-01 17:30:56 -07:00
Nathan Adams 7c0b0a7a57 avm1: Fix instanceof checks with primitives 2020-07-01 16:36:54 -07:00
Nathan Adams d1732dd3d6 avm1: Returning from with{} should return from the parent activation 2020-07-01 16:21:43 -07:00