In both `FrameLabel` and `Scene`, we define multiple
'public property / private slot' pairs.
The public property has a getter which delegates to the private
property. There is no setter for the property, ensuring that
the private slot can only be modified from within Ruffle itself.
This PR adds a macro `define_indirect_properties` to abstract over
this pattern. Currently, it only supports the read-only property
pattern - however, it could be extended in the future to generate
a setter that invokes a caller-provided callback function.
This needs to be a macro (rather than a method) so that we can
generate a function with the property name hard-coded into it.
Using a closure that references an upvar will not work, since
`Method::from_builtin` requires a function pointer.
This PR adds the following class stubs:
* 'flash.display.Loader'
* 'flash.net.URLRequest'
* 'flash.ui.Keyboard'
* 'flash.utils.Timer'
These are needed for 'This is the Only Level TOO' (though we'll need
actual implementations to get this game past the loading screen).
* avm2: Implement JSON.parse
* avm2: Add AvmSerializer for serializing AVM values to JSON
* avm2: Add support for replacer objects
* avm2: use *const ObjectPtr for object stack
* avm2: Add support for space parameter is JSON.stringify
* avm2: Refactor AvmSerializer design
* avm2: Restrict spaces to a maximum of 10
* avm2: Refactor map_value
* tests: Add JSON.parse test
* chore: Appease clippy
* avm2: Check if value is undefined before inserting
* tests: Add test for JSON.stringify
* tests: Improve JSON.stringify test
* chore: Replace map_or with explicit match statements
* chore: Use QName::dynamic_name
* avm2: Use Object<'gc> instead of ObjectPtr
* chore: Use explicit match in deserialize_value
* Rebase fixes
Co-authored-by: Adrian Wielgosik <adrian.wielgosik@gmail.com>
* avm2: Properly make all classes an instance of `Class`.
Also, does this technically mean that `Class` is a metaclass?
* avm2: Remove `Function::from_method_and_proto` as it will no longer be needed
* avm2: Ensure builtin classes are also instances of `Class`.
This requires tying a veritable gordian knot of classes; everything needs to be allocated up-front, linked together, and then properly initialized later on. This necessitated splitting the whole class construction process up into three steps:
1. Allocation via `from_class_partial`, which does everything that can be done without any other classes
2. Weaving via `link_prototype` and `link_type`, which links all of the allocated parts together correctly. This also includes initializing `SystemClasses` and `SystemPrototypes`.
3. Initialization via `into_finished_class`, which must be done *after* the weave has finished.
Once complete you have core classes that are all instances of `Class`, along with prototypes that have their usual legacy quirks.
Note that this does *not* make prototypes instances of their class. We do need to do that, but doing so breaks ES3 legacy support. This is because we currently only work with bound methods, but need to be able to call unbound methods in `callproperty`.
* tests: Add a test for all core classes' instance-of relationships