avm2: Switch ByteArray to AS

avm2: Fix ByteArray

avm2: Implement ByteArray.defaultObjectEncoding

avm2: Rename ByteArray allocator
This commit is contained in:
EmperorBale 2022-09-15 23:48:40 -07:00 committed by EmperorBale
parent f101160abc
commit e1eaa9770a
10 changed files with 87 additions and 113 deletions

View File

@ -458,14 +458,6 @@ pub fn load_player_globals<'gc>(
);
// package `flash.utils`
avm2_system_class!(
bytearray,
activation,
flash::utils::bytearray::create_class(mc),
script
);
domain.init_default_domain_memory(activation)?;
class(
activation,
@ -722,8 +714,11 @@ fn load_playerglobal<'gc>(
("flash.geom", "Rectangle", rectangle),
("flash.geom", "Transform", transform),
("flash.geom", "ColorTransform", colortransform),
("flash.utils", "ByteArray", bytearray),
]
);
// Domain memory must be initialized after playerglobals is loaded because it relies on ByteArray.
domain.init_default_domain_memory(activation)?;
Ok(())
}

View File

@ -8,7 +8,7 @@ use crate::string::WString;
use instant::Instant;
use std::fmt::Write;
pub mod bytearray;
pub mod byte_array;
pub mod dictionary;
pub mod proxy;
pub mod timer;

View File

@ -1,5 +1,72 @@
// This is a stub - the actual class is defined in `bytearray.rs`
package flash.utils {
[Ruffle(InstanceAllocator)]
public class ByteArray {
private static var _defaultObjectEncoding:uint = 3;
public static function get defaultObjectEncoding():uint {
return _defaultObjectEncoding;
}
public static function set defaultObjectEncoding(encoding:uint):void {
_defaultObjectEncoding = encoding;
}
public native function get bytesAvailable():uint;
public native function get endian():String;
public native function set endian(value:String):void;
public native function get length():uint;
public native function set length(value:uint):void;
public native function get objectEncoding():uint;
public native function set objectEncoding(value:uint):void;
public native function get position():uint;
public native function set position(value:uint):void;
public function ByteArray() {
this.init();
this.objectEncoding = _defaultObjectEncoding;
}
private native function init():void;
public native function clear():void;
public native function compress(algorithm:String):void;
public native function deflate():void;
public native function inflate():void;
public native function uncompress(algorithm:String):void;
public native function toString():String;
public function toJSON(k:String):String {
return "ByteArray"
}
public native function readBoolean():Boolean;
public native function readByte():int;
public native function readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void;
public native function readDouble():Number;
public native function readFloat():Number;
public native function readInt():int;
public native function readMultiByte(length:uint, charSet:String):String;
public native function readObject():*;
public native function readShort():int;
public native function readUnsignedByte():uint;
public native function readUnsignedInt():uint;
public native function readUnsignedShort():uint;
public native function readUTF():String;
public native function readUTFBytes(length:uint):String;
public native function writeBoolean(value:Boolean):void;
public native function writeByte(value:int):void;
public native function writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void;
public native function writeDouble(value:Number):void;
public native function writeFloat(value:Number):void;
public native function writeInt(value:int):void;
public native function writeMultiByte(value:String, charSet:String):void;
public native function writeShort(value:int):void;
public native function writeUnsignedInt(value:uint):void;
public native function writeUTF(value:String):void;
public native function writeUTFBytes(value:String):void;
}
}

View File

@ -1,23 +1,18 @@
use crate::avm2::activation::Activation;
use crate::avm2::bytearray::{CompressionAlgorithm, Endian, ObjectEncoding};
use crate::avm2::class::{Class, ClassAttributes};
use crate::avm2::method::{Method, NativeMethodImpl};
use crate::avm2::object::{bytearray_allocator, Object, TObject};
pub use crate::avm2::object::byte_array_allocator;
use crate::avm2::object::{Object, TObject};
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::avm2::Multiname;
use crate::avm2::Namespace;
use crate::avm2::QName;
use crate::character::Character;
use crate::string::AvmString;
use encoding_rs::Encoding;
use encoding_rs::UTF_8;
use flash_lso::amf0::read::AMF0Decoder;
use flash_lso::amf3::read::AMF3Decoder;
use gc_arena::{GcCell, MutationContext};
/// Implements `flash.utils.ByteArray`'s instance constructor.
pub fn instance_init<'gc>(
pub fn init<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
@ -50,15 +45,6 @@ pub fn instance_init<'gc>(
Ok(Value::Undefined)
}
/// Implements `flash.utils.ByteArray`'s class constructor.
pub fn class_init<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
_this: Option<Object<'gc>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
Ok(Value::Undefined)
}
/// Writes a single byte to the bytearray
pub fn write_byte<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
@ -251,7 +237,7 @@ pub fn clear<'gc>(
Ok(Value::Undefined)
}
pub fn position<'gc>(
pub fn get_position<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
@ -283,7 +269,7 @@ pub fn set_position<'gc>(
Ok(Value::Undefined)
}
pub fn bytes_available<'gc>(
pub fn get_bytes_available<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
@ -297,7 +283,7 @@ pub fn bytes_available<'gc>(
Ok(Value::Undefined)
}
pub fn length<'gc>(
pub fn get_length<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
@ -329,7 +315,7 @@ pub fn set_length<'gc>(
Ok(Value::Undefined)
}
pub fn endian<'gc>(
pub fn get_endian<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
@ -623,7 +609,7 @@ pub fn write_short<'gc>(
Ok(Value::Undefined)
}
pub fn write_multibyte<'gc>(
pub fn write_multi_byte<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
args: &[Value<'gc>],
@ -649,7 +635,7 @@ pub fn write_multibyte<'gc>(
Ok(Value::Undefined)
}
pub fn read_multibyte<'gc>(
pub fn read_multi_byte<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
args: &[Value<'gc>],
@ -804,7 +790,7 @@ pub fn read_object<'gc>(
Ok(Value::Undefined)
}
pub fn object_encoding<'gc>(
pub fn get_object_encoding<'gc>(
_activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
@ -839,77 +825,3 @@ pub fn set_object_encoding<'gc>(
Ok(Value::Undefined)
}
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
let class = Class::new(
QName::new(Namespace::package("flash.utils"), "ByteArray"),
Some(Multiname::public("Object")),
Method::from_builtin(instance_init, "<ByteArray instance initializer>", mc),
Method::from_builtin(class_init, "<ByteArray class initializer>", mc),
mc,
);
let mut write = class.write(mc);
write.set_attributes(ClassAttributes::SEALED);
write.set_instance_allocator(bytearray_allocator);
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
("writeByte", write_byte),
("writeBytes", write_bytes),
("readBytes", read_bytes),
("toString", to_string),
("readShort", read_short),
("writeShort", write_short),
("readUnsignedShort", read_unsigned_short),
("readDouble", read_double),
("writeDouble", write_double),
("readFloat", read_float),
("writeFloat", write_float),
("readInt", read_int),
("writeInt", write_int),
("readUnsignedInt", read_unsigned_int),
("writeUnsignedInt", write_unsigned_int),
("readBoolean", read_boolean),
("writeBoolean", write_boolean),
("readByte", read_byte),
("readUnsignedByte", read_unsigned_byte),
("writeUTF", write_utf),
("readUTF", read_utf),
("clear", clear),
("compress", compress),
("uncompress", uncompress),
("inflate", inflate),
("deflate", deflate),
("writeMultiByte", write_multibyte),
("readMultiByte", read_multibyte),
("writeUTFBytes", write_utf_bytes),
("readUTFBytes", read_utf_bytes),
("readObject", read_object),
];
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
const PUBLIC_INSTANCE_PROPERTIES: &[(
&str,
Option<NativeMethodImpl>,
Option<NativeMethodImpl>,
)] = &[
("bytesAvailable", Some(bytes_available), None),
("length", Some(length), Some(set_length)),
("position", Some(position), Some(set_position)),
("endian", Some(endian), Some(set_endian)),
(
"objectEncoding",
Some(object_encoding),
Some(set_object_encoding),
),
];
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
// TODO: This property should have a setter
const CONSTANTS: &[(&str, u32)] = &[("defaultObjectEncoding", 3)];
write.define_public_constant_uint_class_traits(CONSTANTS);
class
}

View File

@ -6,6 +6,7 @@ include "Math.as"
include "flash/accessibility/AccessibilityProperties.as"
include "flash/crypto.as"
include "flash/utils/ByteArray.as"
include "flash/desktop/ClipboardFormats.as"
include "flash/desktop/ClipboardTransferMode.as"
include "flash/display/ActionScriptVersion.as"

View File

@ -16,7 +16,6 @@ include "flash/display/DisplayObjectContainer.as"
include "flash/display/LoaderInfo.as"
include "flash/events/EventDispatcher.as"
include "flash/system/ApplicationDomain.as"
include "flash/utils/ByteArray.as"
include "flash/utils/Dictionary.as"
include "Function.as"
include "Number.as"

View File

@ -54,7 +54,7 @@ mod xml_object;
pub use crate::avm2::object::array_object::{array_allocator, ArrayObject};
pub use crate::avm2::object::bitmapdata_object::{bitmapdata_allocator, BitmapDataObject};
pub use crate::avm2::object::bytearray_object::{bytearray_allocator, ByteArrayObject};
pub use crate::avm2::object::bytearray_object::{byte_array_allocator, ByteArrayObject};
pub use crate::avm2::object::class_object::ClassObject;
pub use crate::avm2::object::date_object::{date_allocator, DateObject};
pub use crate::avm2::object::dictionary_object::{dictionary_allocator, DictionaryObject};

View File

@ -9,7 +9,7 @@ use gc_arena::{Collect, GcCell, MutationContext};
use std::cell::{Ref, RefMut};
/// A class instance allocator that allocates ByteArray objects.
pub fn bytearray_allocator<'gc>(
pub fn byte_array_allocator<'gc>(
class: ClassObject<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Object<'gc>, Error<'gc>> {

View File

@ -24,7 +24,6 @@
public function testToObject(arr)
{
var ba = new ByteArray();
ba.objectEncoding = "AMF0";
for (var i = 0; i < arr.length; i++)
{
ba.writeByte(arr[i]);
@ -34,6 +33,7 @@
}
public function Test()
{
ByteArray.defaultObjectEncoding = 0;
for (var i = 0; i < TESTS.length; i++)
{
var obj = testToObject(TESTS[i]);