Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVM2 interpreter #404

Merged
merged 189 commits into from
Jul 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
189 commits
Select commit Hold shift + click to select a range
a852a69
Add an extremely trivial implementation for the AVM2 interpreter state.
kmeisthax Feb 4, 2020
b7f257e
Add a path to get from the movie clip to the Avm2.
kmeisthax Feb 4, 2020
e80c887
Add a very basic object model to the AVM2 interpreter.
kmeisthax Feb 5, 2020
7f60fab
Add the bare minimum necessary to get opcodes out of an ABC and into …
kmeisthax Feb 6, 2020
5600ac4
Always execute any AVM2 code that may have been queued as a result of…
kmeisthax Feb 6, 2020
4d000e1
Implement `pushxyz` opcodes for all value types that we currently sup…
kmeisthax Feb 7, 2020
d1aeae8
Add support for local registers in the interpreter.
kmeisthax Feb 7, 2020
115f039
Add `call` method to the object trait. Only functions are callable in…
kmeisthax Feb 8, 2020
52ac7a6
Implement call/return for bare functions
kmeisthax Feb 8, 2020
43f1080
Implement namespaces as a value type
kmeisthax Feb 8, 2020
6bd94d6
`from_abc_namespace` should accept a namespace index and retrieve it …
kmeisthax Feb 8, 2020
c65d93d
Implement multinames, sans runtime namespace support.
kmeisthax Feb 8, 2020
6d8dc6e
Pull ABC constant pool methods out of Avm2 and into Value.
kmeisthax Feb 9, 2020
2f3a3af
Add exact type assertion methods for strings and namespace values.
kmeisthax Feb 9, 2020
1a6acb9
Implement late binding and runtime qualifications for names.
kmeisthax Feb 9, 2020
3b476cb
Implement `pushnamespace` since that's a value type now
kmeisthax Feb 10, 2020
376d1a8
Add scope support
kmeisthax Feb 10, 2020
0ff1ba7
Multiname resolution is another object method.
kmeisthax Feb 11, 2020
12223d5
Add support methods in `Scope` to support opcodes that traverse the s…
kmeisthax Feb 11, 2020
3c8035f
clippy pls
kmeisthax Feb 11, 2020
60c16b0
Implement `findproperty`, `findpropstrict`, and `getlex`; which are n…
kmeisthax Feb 11, 2020
5e6fc79
Implement `getproperty`, `setproperty`
kmeisthax Feb 11, 2020
78a1c9a
Implement `pushscope`, `popscope`, and `pushwith`.
kmeisthax Feb 11, 2020
d56db06
Implement `resolve_multiname`, sort of.
kmeisthax Feb 11, 2020
e5142e8
Replace `get_property` and `set_property` with slightly-less-stub impls.
kmeisthax Feb 12, 2020
984e701
Swap out `has_property`'s stub impl.
kmeisthax Feb 12, 2020
7d75255
Add global scope which is automatically included on all new activations.
kmeisthax Feb 12, 2020
b12c6e0
Implement closure scope stacks.
kmeisthax Feb 12, 2020
cf490be
Unstub `proto`.
kmeisthax Feb 13, 2020
eb0c9dc
Allow constructing a function around a particular class definition.
kmeisthax Feb 14, 2020
12e9fbb
Impl virtual property slots
kmeisthax Feb 15, 2020
502936f
Implement non-slot trait properties (Method, Getter, and Setter)
kmeisthax Feb 18, 2020
560900e
ABC files are always pre-loaded.
kmeisthax Feb 18, 2020
35c36a8
Always execute the last script when loading an ABC file
kmeisthax Feb 18, 2020
1945f36
When running the initial script, also install it's traits onto the gl…
kmeisthax Feb 19, 2020
88957b2
Add stub builtins for Object and Function. These are more-or-less ide…
kmeisthax Feb 19, 2020
1ab4091
Implement slots and related opcodes.
kmeisthax Feb 19, 2020
ecfd5ab
Impl `construct` and `constructprop`.
kmeisthax Feb 19, 2020
04879fc
Implement class traits.
kmeisthax Feb 20, 2020
bc0bdf8
The public namespace appears to just be an unnamed package namespace,…
kmeisthax Feb 20, 2020
cfe0e33
Fix invalid script index when loading an ABC file.
kmeisthax Feb 20, 2020
e191651
Add debug for trait installs
kmeisthax Feb 20, 2020
3622941
Implement constant pool default values (index 0).
kmeisthax Feb 21, 2020
ebcfee4
Add specific error messages for unresolvable super classes
kmeisthax Feb 21, 2020
d42b16f
Add stub impl of `flash.display.MovieClip`.
kmeisthax Feb 21, 2020
200c10b
Classes can fit in slots, so let's stick them in there.
kmeisthax Feb 21, 2020
af70024
Implement slot traits.
kmeisthax Feb 21, 2020
412c3d8
Implement `Function` traits.
kmeisthax Feb 21, 2020
fd275bd
Implement constant slots and traits.
kmeisthax Feb 21, 2020
8b56973
Remove scope methods that aren't necessary.
kmeisthax Feb 21, 2020
d19d9ef
Clean up unused variables
kmeisthax Feb 21, 2020
cbce866
Implement `deleteproperty`.
kmeisthax Feb 21, 2020
279d90e
Remove `define_value` from AVM2 objects.
kmeisthax Feb 21, 2020
5f98a19
Remove dead code in Activation
kmeisthax Feb 22, 2020
4ab9a46
Impl `getscopeobject`
kmeisthax Feb 22, 2020
b2f5307
Add `flash.display.Sprite` because Flash Builder tests demand it.
kmeisthax Feb 22, 2020
5b00c1f
Ensure that `this` is properly populated into local registers.
kmeisthax Feb 22, 2020
9e120c2
Propagate arguments into local registers when calling AVM functions.
kmeisthax Feb 22, 2020
5c0e095
`getlex` does not support runtime multinames according to spec.
kmeisthax Feb 22, 2020
5042fc1
Debug all multiname resolutions
kmeisthax Feb 22, 2020
0ff1c04
Impl `initproperty`
kmeisthax Feb 22, 2020
1fe73b3
Impl `dup`
kmeisthax Feb 22, 2020
074ba94
Impl `newfunction` and `newclass`.
kmeisthax Feb 22, 2020
1d1bad1
Impl `getglobalscope`
kmeisthax Feb 22, 2020
7201f6c
Impl `debug`, `debugfile` and `debugline`.
kmeisthax Feb 22, 2020
843de29
Impl `newobject`
kmeisthax Feb 22, 2020
38b1524
Fix the error messages for `findpropstrict` and `getlex` to be more i…
kmeisthax Feb 23, 2020
f6e2ca1
Clean up the current set of builtins to accurately reflect the namesp…
kmeisthax Feb 23, 2020
a557867
Add the entire class hierarchy of `MovieClip` and `Sprite`.
kmeisthax Feb 23, 2020
7792fd5
Impl `trace`, which is a free function rather than an opcode this time.
kmeisthax Feb 23, 2020
bf45f7f
Fix crash when reading or writing a property that redirects to a slot.
kmeisthax Feb 23, 2020
dd6b0a8
Remove unused reference to slot property fields
kmeisthax Feb 23, 2020
a7ff2de
Don't spam the test log with `Resolving Multiname` messages for each …
kmeisthax Feb 23, 2020
68cf9e8
Upon encountering an `Err`, dispose of the current AVM2 stack.
kmeisthax Feb 23, 2020
a0ab978
Impl `callmethod`, `callproperty`, `callproplex`, `callpropvoid`, and…
kmeisthax Feb 24, 2020
7d57620
Impl `coerce_a`.
kmeisthax Feb 24, 2020
a2dfffc
Add our first AVM2 regression test: hello world!
kmeisthax Feb 24, 2020
38868fb
Args are pushed onto the stack in normal order, so we need to pop the…
kmeisthax Feb 24, 2020
bedf5cb
Add a basic test for function calls.
kmeisthax Feb 24, 2020
9431e02
The class function should use the *instance* initializer as it's call…
kmeisthax Feb 24, 2020
0fc9b9a
`construct` and `constructprop` should take their args in reverse-ord…
kmeisthax Feb 24, 2020
a77f676
`construct` and `constructprop` should push the object that was just …
kmeisthax Feb 24, 2020
f3dee5c
Add (currently failing) test for constructors.
kmeisthax Feb 24, 2020
1b67bb9
Impl `callsuper`, `callsupervoid`, and `constructsuper`.
kmeisthax Feb 25, 2020
73966f1
Make sure that we actually call the super constructor, not our own co…
kmeisthax Feb 26, 2020
687a82f
Constructors should also inherit closure scope.
kmeisthax Feb 26, 2020
fa4369d
Execute static class initializers.
kmeisthax Feb 26, 2020
1c3b9c5
Implement prototype awareness for `get_property`, `has_property`, and…
kmeisthax Feb 26, 2020
ab5a95c
Add a test for various types of class methods.
kmeisthax Feb 26, 2020
43da7ac
`resolve_multiname` should actually return it's prototype's return va…
kmeisthax Feb 27, 2020
e8fbac6
Refactor the base_proto system to more accurately record what prototy…
kmeisthax Feb 28, 2020
785832b
Add `as3_inheritance` test, which is primarily designed to test metho…
kmeisthax Feb 28, 2020
665d7a4
Implement `getsuper` and `setsuper`.
kmeisthax Feb 28, 2020
b8106d2
Ensure virtual setters are run when defined on a prototype.
kmeisthax Feb 29, 2020
54b792e
Ensure that called setters are properly resolved so that errors in se…
kmeisthax Feb 29, 2020
c5e3af2
When resolving `get_property`, skip over virtual properties that do n…
kmeisthax Feb 29, 2020
5abc78d
Add test of AVM2 virtual properties.
kmeisthax Feb 29, 2020
6cc3f7e
Add a test for stored properties as well.
kmeisthax Feb 29, 2020
6774465
Pass the ABC name and lazy init flag to the AVM2.
kmeisthax Mar 1, 2020
f10920a
Implement `Object.prototype.hasOwnProperty` and resolution of `Namesp…
kmeisthax Mar 1, 2020
3530175
`ScriptObject` now holds a reference to a class and allows retrieving…
kmeisthax Mar 2, 2020
2f95a7a
Completely overhaul the way traits are defined on objects.
kmeisthax Mar 4, 2020
f042e45
Add a test for interactions between prototype and class-trait propert…
kmeisthax Mar 4, 2020
915b2da
Allow binding a reciever to a function, and make all method traits bi…
kmeisthax Mar 4, 2020
ddc9aa4
Add a test for ES4 method binding of `this`.
kmeisthax Mar 4, 2020
b33c246
Implement `is_property_overwritable`.
kmeisthax Mar 4, 2020
9c5ea1d
Implement `jump`, `iftrue`, `iffalse`, `ifstricteq`, and `ifstrictne`.
kmeisthax Mar 4, 2020
7253c09
Add tests for control flow instructions that use booleans or strict e…
kmeisthax Mar 4, 2020
a44e700
Sign extend negative `s24` values correctly.
kmeisthax Mar 6, 2020
da6a7c0
Implement `kill`, at least a little.
kmeisthax Mar 6, 2020
67b7fbb
Implement `label`, which is a no-op designed specifically to silence …
kmeisthax Mar 6, 2020
9496fbd
Remove `DontEnum`, `is_enumerable` and attribute mutation. They won't…
kmeisthax Mar 6, 2020
1cc8954
Impl `pop`, which is the opposite of `dup`; and also the opposite of …
kmeisthax Mar 6, 2020
73189b6
Properly unwind errors thrown from the AVM2 reader.
kmeisthax Mar 6, 2020
c014b40
Implement `hasnext`, `hasnext2`, `nextname`, `nextvalue`, and the und…
kmeisthax Mar 6, 2020
d29f3dc
Add `as3_object_enumeration` and `as3_class_enumeration` tests.
kmeisthax Mar 6, 2020
0e89cb2
Impl `Object.isPrototypeOf` w/ test
kmeisthax Mar 6, 2020
00186f7
Free functions always have a `prototype`, this is a holdover from ES3.
kmeisthax Mar 6, 2020
c6265bb
Allow tracing booleans.
kmeisthax Mar 6, 2020
8677804
Actually enable the `isPrototypeOf` test.
kmeisthax Mar 6, 2020
6e2508a
Fix `any` name resolution, at least enough for the `has_own_property`…
kmeisthax Mar 7, 2020
42cb8f5
Add a test for `has_own_property` in various class instance scenarios.
kmeisthax Mar 7, 2020
307a95e
`callproperty` and `callpropvoid` should *never* get callables from `…
kmeisthax Mar 7, 2020
a0ca589
Prevent instance traits from being accessible directly from prototypes.
kmeisthax Mar 7, 2020
2afbcf4
Impl `propertyIsEnumerable`
kmeisthax Mar 8, 2020
dc0cb00
Add a test for `propertyIsEnumerable`.
kmeisthax Mar 8, 2020
f13e2ea
Implement `setPropertyIsEnumerable`
kmeisthax Mar 8, 2020
ba2c1f5
Add test for `setPropertyIsEnumerable`
kmeisthax Mar 8, 2020
f493cf9
Make `toString` and `valueOf` methods of `TObject`, called `to_string…
kmeisthax Mar 9, 2020
37cdcb3
Add tests for `toString` on objects, functions, and classes.
kmeisthax Mar 9, 2020
8b36751
Several built-in functions are not `public`, but instead live in the …
kmeisthax Mar 9, 2020
4b66af8
ES4 classes, while superficially similar to functions, are not functi…
kmeisthax Mar 9, 2020
16774aa
Add a test for legacy / ES3 inheritance.
kmeisthax Mar 9, 2020
3558c3a
Add test of `Function.prototype.call`
kmeisthax Mar 9, 2020
cf6714d
Implement and test `toLocaleString`.
kmeisthax Mar 9, 2020
3b52dfe
Since we have an `es3_inheritance` test now, rename the existing inhe…
kmeisthax Mar 9, 2020
b4d907b
Implement `strictequals`.
kmeisthax Mar 9, 2020
03a240e
Add tests for `valueOf`.
kmeisthax Mar 9, 2020
ecfd16c
Add global constants `undefined`, `null`, and `NaN`.
kmeisthax Mar 9, 2020
34b3bba
*Correctly* implement `ifstricteq` and `ifstrictne`.
kmeisthax Mar 9, 2020
34ab8c8
`NaN` is not special-cased in AS3.
kmeisthax Mar 9, 2020
6117288
Add tests for `ifstricteq`, `ifstrictne`, and `strictequals`.
kmeisthax Mar 9, 2020
fe283e6
Silence this warning about occupied slots being an unused variant.
kmeisthax Mar 9, 2020
3362ec0
chore: Clippy conformance
kmeisthax Apr 21, 2020
4cd3045
Excise `ReturnValue<'gc>` from all `TObject` methods.
kmeisthax Jun 23, 2020
15a62d3
Add an internal representation of `Trait`, separate from `swf::avm2::…
kmeisthax Jun 30, 2020
70e9030
Decouple the entire trait machinery from ABC-provided traits.
kmeisthax Jul 1, 2020
b4f944b
Wrap ABC loading inside of a `TranslationUnit`.
kmeisthax Jul 2, 2020
f549d01
Fix compilation bugs involved with automatic script initializer execu…
kmeisthax Jul 2, 2020
60f3ae3
Remove `Avm2ScriptEntry`. It is now obsolete and unused.
kmeisthax Jul 2, 2020
4467bc3
Make `TranslationUnit` a GC-mandatory type (only referred to by `GcCe…
kmeisthax Jul 2, 2020
eaebd3c
Make `Avm2MethodEntry` hold it's `TranslationUnit` rather than an `Ab…
kmeisthax Jul 2, 2020
232c29d
Fix remaining problems with method loading using `callstatic`
kmeisthax Jul 2, 2020
7684736
`table_class` should resolve `Class`es straight from the current tran…
kmeisthax Jul 2, 2020
0d2235d
Resolve all remaining compilation issues with this refactor.
kmeisthax Jul 2, 2020
041cb0b
Resolve multiname constant zero as an error rather than a panic.
kmeisthax Jul 3, 2020
12fc13d
Clippy compliance for the last batch of commits.
kmeisthax Jul 3, 2020
b6e0551
Remove `Avm2ClassEntry`. It is no longer used.
kmeisthax Jul 3, 2020
098b034
Refactor method-related structs into a separate method module.
kmeisthax Jul 3, 2020
5b5bf07
Remove `Avm2Function` as it is no longer used.
kmeisthax Jul 3, 2020
97e0056
Invert the role of `Avm2` and it's `Activation`, similar to what was …
kmeisthax Jul 4, 2020
090fe56
Wrap `BytecodeMethod` (and the bytecode half of `Executable`) in a `Gc`.
kmeisthax Jul 4, 2020
5d89d4e
Allow methods to not hold a body.
kmeisthax Jul 8, 2020
8f2d331
Allow the construction of classes with no base class.
kmeisthax Jul 8, 2020
563a515
Add a test for loading interfaces into the AVM2.
kmeisthax Jul 8, 2020
cce68db
Add trait methods for getting and setting the interfaces list.
kmeisthax Jul 8, 2020
3fae8b3
Read the interface list when instantiating classes, resolve them, and…
kmeisthax Jul 8, 2020
a0cb052
Add `is_instance_of` trait method to `TObject`
kmeisthax Jul 9, 2020
c917b3d
Implement `istype`, `istypelate`, and `instanceof`.
kmeisthax Jul 9, 2020
39a4566
Instances should be listed as their prototypes (empty as they are)
kmeisthax Jul 9, 2020
64e5b46
Add tests for `instanceof` and `is` operators.
kmeisthax Jul 9, 2020
f0c633f
Allow borrowing string values from an ABC file instead of cloning eve…
kmeisthax Jul 10, 2020
ae26615
`coerce_string` may return a static string, which we shouldn't clone.
kmeisthax Jul 11, 2020
a406bda
Don't attempt to log debugging information if we're not in a debug bu…
kmeisthax Jul 11, 2020
508fcd6
`pool_string` should return a `Ref<str>` just like `value::abc_string`.
kmeisthax Jul 11, 2020
2021cec
Impl `Copy`, `Eq`, `PartialOrd`, `Ord`, and `Hash` for `AvmString`.
kmeisthax Jul 14, 2020
61a3ff8
Replace `String` or `&str` references with `AvmString` everywhere in …
kmeisthax Jul 14, 2020
e1b9b82
Remove `abc_string` and replace it with `abc_string_copy`. All code t…
kmeisthax Jul 14, 2020
70e9e7e
Add support for cached/interned pool strings in the `TranslationUnit`.
kmeisthax Jul 14, 2020
f4c5075
Run all string constant retrieval through the `TranslationUnit`, prev…
kmeisthax Jul 15, 2020
e354c53
Remove any remaining uses of `abc_ref`.
kmeisthax Jul 15, 2020
ccacc54
Remove dead code on all now-in-use structs and methods.
kmeisthax Jul 18, 2020
37b6b89
Add a stub AVM2 string representation to allow for both VMs' strings …
kmeisthax Jul 18, 2020
dc962f2
Add AVM2 equivalent of `PropertyMap` for further expansion.
kmeisthax Jul 18, 2020
c415190
Zero-index multinames should generate a validation error in `QName::f…
kmeisthax Jul 18, 2020
262bb14
Rename `a2me` to `entry` (or `method` in one case where it lets me si…
kmeisthax Jul 18, 2020
575a9b0
Use FnvHashMap for the translation unit pools.
kmeisthax Jul 18, 2020
44b924d
`Script` should not hold write locks when probing it's internal caches.
kmeisthax Jul 18, 2020
7adabc8
Use `unwrap_or_default`
kmeisthax Jul 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions core/src/avm1/string.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use gc_arena::{Collect, Gc, MutationContext};
use std::cmp::{Eq, Ord, Ordering, PartialOrd};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Deref;

#[derive(Debug, Clone, Collect)]
#[derive(Debug, Clone, Copy, Collect)]
#[collect(no_drop)]
enum Source<'gc> {
Owned(Gc<'gc, String>),
Static(&'static str),
}

#[derive(Debug, Clone, Collect)]
#[derive(Debug, Clone, Copy, Collect)]
#[collect(no_drop)]
pub struct AvmString<'gc> {
source: Source<'gc>,
Expand Down Expand Up @@ -78,6 +80,29 @@ impl<'gc> PartialEq<AvmString<'gc>> for AvmString<'gc> {
}
}

impl<'gc> Eq for AvmString<'gc> {}

impl<'gc> PartialOrd<AvmString<'gc>> for AvmString<'gc> {
fn partial_cmp(&self, other: &AvmString<'gc>) -> Option<Ordering> {
self.as_ref().partial_cmp(other.as_ref())
}
}

impl<'gc> Ord for AvmString<'gc> {
fn cmp(&self, other: &AvmString<'gc>) -> Ordering {
self.as_ref().cmp(other.as_ref())
}
}

impl<'gc> Hash for AvmString<'gc> {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.as_ref().hash(state)
}
}

kmeisthax marked this conversation as resolved.
Show resolved Hide resolved
macro_rules! impl_eq {
($lhs:ty, $rhs: ty) => {
#[allow(unused_lifetimes)]
Expand Down
164 changes: 164 additions & 0 deletions core/src/avm2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
//! ActionScript Virtual Machine 2 (AS3) support

use crate::avm2::activation::Activation;
use crate::avm2::globals::SystemPrototypes;
use crate::avm2::object::{Object, TObject};
use crate::avm2::scope::Scope;
use crate::avm2::script::Script;
use crate::avm2::script::TranslationUnit;
use crate::avm2::value::Value;
use crate::context::UpdateContext;
use crate::tag_utils::SwfSlice;
use gc_arena::{Collect, GcCell, MutationContext};
use std::rc::Rc;
use swf::avm2::read::Reader;

#[macro_export]
macro_rules! avm_debug {
($($arg:tt)*) => (
#[cfg(feature = "avm_debug")]
log::debug!($($arg)*)
)
}

mod activation;
mod class;
mod function;
mod globals;
mod method;
mod names;
mod object;
mod property;
mod property_map;
mod return_value;
mod scope;
mod script;
mod script_object;
mod slot;
mod string;
mod r#trait;
mod value;

/// Boxed error alias.
///
/// As AVM2 is a far stricter VM than AVM1, this may eventually be replaced
/// with a proper Avm2Error enum.
type Error = Box<dyn std::error::Error>;

/// The state of an AVM2 interpreter.
#[derive(Collect)]
#[collect(no_drop)]
pub struct Avm2<'gc> {
/// Values currently present on the operand stack.
stack: Vec<Value<'gc>>,

/// Global scope object.
globals: Object<'gc>,

/// System prototypes.
system_prototypes: SystemPrototypes<'gc>,
}

impl<'gc> Avm2<'gc> {
/// Construct a new AVM interpreter.
pub fn new(mc: MutationContext<'gc, '_>) -> Self {
let (globals, system_prototypes) = globals::construct_global_scope(mc);

Self {
stack: Vec::new(),
globals,
system_prototypes,
}
}

/// Return the current set of system prototypes.
pub fn prototypes(&self) -> &SystemPrototypes<'gc> {
&self.system_prototypes
}

/// Run a script's initializer method.
pub fn run_script_initializer(
&mut self,
script: GcCell<'gc, Script<'gc>>,
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<(), Error> {
let mut init_activation = Activation::from_script(self, context, script, self.globals)?;

init_activation.run_stack_frame_for_script(context, script)
}

/// Load an ABC file embedded in a `SwfSlice`.
///
/// The `SwfSlice` must resolve to the contents of an ABC file.
pub fn load_abc(
&mut self,
abc: SwfSlice,
_abc_name: &str,
_lazy_init: bool,
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<(), Error> {
let mut read = Reader::new(abc.as_ref());

let abc_file = Rc::new(read.read()?);
let tunit = TranslationUnit::from_abc(abc_file.clone(), context.gc_context);

for i in (0..abc_file.scripts.len()).rev() {
let script = tunit.load_script(i as u32, context.gc_context)?;
let mut globals = self.globals();
let scope = Scope::push_scope(None, globals, context.gc_context);
let mut null_activation = Activation::from_nothing(self, context);

// TODO: Lazyinit means we shouldn't do this until traits are
// actually mentioned...
for trait_entry in script.read().traits()?.iter() {
globals.install_foreign_trait(
&mut null_activation,
context,
trait_entry.clone(),
Some(scope),
globals,
)?;
}

drop(null_activation);

self.run_script_initializer(script, context)?;
}

Ok(())
}

pub fn globals(&self) -> Object<'gc> {
self.globals
}

/// Push a value onto the operand stack.
fn push(&mut self, value: impl Into<Value<'gc>>) {
let value = value.into();
avm_debug!("Stack push {}: {:?}", self.stack.len(), value);
self.stack.push(value);
}

/// Retrieve the top-most value on the operand stack.
#[allow(clippy::let_and_return)]
fn pop(&mut self) -> Value<'gc> {
let value = self.stack.pop().unwrap_or_else(|| {
log::warn!("Avm1::pop: Stack underflow");
Value::Undefined
});

avm_debug!("Stack pop {}: {:?}", self.stack.len(), value);

value
}

fn pop_args(&mut self, arg_count: u32) -> Vec<Value<'gc>> {
let mut args = Vec::with_capacity(arg_count as usize);
args.resize(arg_count as usize, Value::Undefined);
for arg in args.iter_mut().rev() {
*arg = self.pop();
}

args
}
}
Loading