Skip to content

Commit

Permalink
avm2: Implement SharedObject.size
Browse files Browse the repository at this point in the history
  • Loading branch information
n0samu authored and Dinnerbone committed Jul 16, 2023
1 parent fea0df1 commit de9ea95
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 17 deletions.
5 changes: 2 additions & 3 deletions core/src/avm2/globals/flash/net/SharedObject.as
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package flash.net

native public static function getLocal(name:String, localPath:String = null, secure:Boolean = false): SharedObject;

native public function get size() : uint;

native public function flush(minDiskSpace:int = 0) : String;
native public function close() : void;
native public function clear() : void;
Expand All @@ -29,9 +31,6 @@ package flash.net

// note: this is supposed to be a read-only property
public var data: Object;

// note: this is supposed to be a read-only property
public var size: uint;

ruffle var _ruffleName: String;
}
Expand Down
63 changes: 51 additions & 12 deletions core/src/avm2/globals/flash/net/shared_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,23 @@ use crate::string::AvmString;
use flash_lso::types::{AMFVersion, Lso};
use std::borrow::Cow;

fn new_lso<'gc>(
activation: &mut Activation<'_, 'gc>,
name: &str,
data: Object<'gc>,
) -> Result<Lso, Error<'gc>> {
let mut elements = Vec::new();
crate::avm2::amf::recursive_serialize(activation, data, &mut elements, AMFVersion::AMF3)?;
Ok(Lso::new(
elements,
name.split('/')
.last()
.map(|e| e.to_string())
.unwrap_or_else(|| "<unknown>".to_string()),
AMFVersion::AMF3,
))
}

pub fn get_local<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
Expand Down Expand Up @@ -193,20 +210,42 @@ pub fn flush<'gc>(
.coerce_to_string(activation)?;
let name = name.to_utf8_lossy();

let mut elements = Vec::new();
crate::avm2::amf::recursive_serialize(activation, data, &mut elements, AMFVersion::AMF3)?;
let mut lso = Lso::new(
elements,
name.split('/')
.last()
.map(|e| e.to_string())
.unwrap_or_else(|| "<unknown>".to_string()),
AMFVersion::AMF3,
);
let mut lso = new_lso(activation, &name, data)?;
// Flash does not write empty LSOs to disk
if lso.body.is_empty() {
Ok(true.into())
} else {
let bytes = flash_lso::write::write_to_bytes(&mut lso).unwrap_or_default();
Ok(activation.context.storage.put(&name, &bytes).into())
}
}

pub fn get_size<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let data = this
.get_public_property("data", activation)?
.coerce_to_object(activation)?;

let bytes = flash_lso::write::write_to_bytes(&mut lso).unwrap_or_default();
let ruffle_name = Multiname::new(
Namespace::package("__ruffle__", &mut activation.borrow_gc()),
"_ruffleName",
);
let name = this
.get_property(&ruffle_name, activation)?
.coerce_to_string(activation)?;
let name = name.to_utf8_lossy();

Ok(activation.context.storage.put(&name, &bytes).into())
let mut lso = new_lso(activation, &name, data)?;
// Flash returns 0 for empty LSOs, but the actual number of bytes (including the header) otherwise
if lso.body.is_empty() {
Ok(0.into())
} else {
let bytes = flash_lso::write::write_to_bytes(&mut lso).unwrap_or_default();
Ok(bytes.len().into())
}
}

pub fn close<'gc>(
Expand Down
11 changes: 9 additions & 2 deletions tests/tests/swfs/avm2/shared_object/Test.as
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

if(obj.data.props === undefined) {
trace("No data found. Initializing...");
trace("sizes: obj = " + obj.size + ", otherObj = " + otherObj.size);

storeData(obj.data)
storeData(otherObj.data)
Expand All @@ -74,8 +75,10 @@
trace("otherObj.data.props:")
dump(otherObj.data.props);

trace("sizes: obj = " + obj.size + ", otherObj = " + otherObj.size);
obj.flush();
otherObj.flush();
trace("sizes: obj = " + obj.size + ", otherObj = " + otherObj.size);
} else {
trace("obj.data.hidden: " + obj.data.hidden);
trace("otherObj.data.hidden: " + otherObj.data.hidden);
Expand All @@ -87,6 +90,9 @@
trace()
trace("otherObj dump:")
dump(otherObj.data.props)

trace();
trace("sizes: obj = " + obj.size + ", otherObj = " + otherObj.size);

// Test SharedObject.clear()
trace();
Expand All @@ -98,6 +104,9 @@
trace();
trace("obj dump:");
dump(obj.data);

trace();
trace("sizes: obj = " + obj.size + ", otherObj = " + otherObj.size);

trace();
trace("obj dump again:");
Expand Down Expand Up @@ -132,5 +141,3 @@ function dump(obj:Object) {

}
}

test.main();
3 changes: 3 additions & 0 deletions tests/tests/swfs/avm2/shared_object/output1.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
typeof obj =object
typeof otherObj =object
No data found. Initializing...
sizes: obj = 0, otherObj = 0
otherObj.data.props:
0 = true type boolean
1 = hello type string
Expand All @@ -13,3 +14,5 @@ otherObj.data.props:
8 = type object
val.aPropertyThatIsNotANumber: strange property
9 = (UTC) Sun Jan 25 20:31:23 1970 UTC
sizes: obj = 299, otherObj = 330
sizes: obj = 299, otherObj = 330
4 changes: 4 additions & 0 deletions tests/tests/swfs/avm2/shared_object/output2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ otherObj dump:
val.aPropertyThatIsNotANumber: strange property
9 = (UTC) Sun Jan 25 20:31:23 1970 UTC

sizes: obj = 299, otherObj = 330

obj.clear()
obj == previousData: false

obj dump:

sizes: obj = 0, otherObj = 330

obj dump again:
Binary file modified tests/tests/swfs/avm2/shared_object/test.swf
Binary file not shown.

0 comments on commit de9ea95

Please sign in to comment.