avm2: The stage's loader info object allows access to `url`, `bytes`, and `parameters`.
This commit is contained in:
parent
b181debff6
commit
f041cced72
|
@ -8,7 +8,7 @@ use crate::avm2::names::{Namespace, QName};
|
||||||
use crate::avm2::object::{loaderinfo_allocator, DomainObject, LoaderStream, Object, TObject};
|
use crate::avm2::object::{loaderinfo_allocator, DomainObject, LoaderStream, Object, TObject};
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::{AvmString, Error};
|
use crate::avm2::{AvmString, Error};
|
||||||
use crate::display_object::TDisplayObject;
|
use crate::display_object::{TDisplayObject, TDisplayObjectContainer};
|
||||||
use gc_arena::{GcCell, MutationContext};
|
use gc_arena::{GcCell, MutationContext};
|
||||||
use swf::{write_swf, Compression};
|
use swf::{write_swf, Compression};
|
||||||
|
|
||||||
|
@ -242,14 +242,18 @@ pub fn url<'gc>(
|
||||||
) -> Result<Value<'gc>, Error> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
if let Some(this) = this {
|
if let Some(this) = this {
|
||||||
if let Some(loader_stream) = this.as_loader_stream() {
|
if let Some(loader_stream) = this.as_loader_stream() {
|
||||||
match &*loader_stream {
|
let root = match &*loader_stream {
|
||||||
LoaderStream::Stage => {
|
LoaderStream::Stage => activation
|
||||||
return Err("Error: The stage's loader info does not have a URL".into())
|
.context
|
||||||
}
|
.stage
|
||||||
LoaderStream::Swf(root, _) => {
|
.child_by_index(0)
|
||||||
let url = root.url().unwrap_or("");
|
.and_then(|c| c.movie()),
|
||||||
return Ok(AvmString::new_utf8(activation.context.gc_context, url).into());
|
LoaderStream::Swf(root, _) => Some(root.clone()),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
if let Some(root) = root {
|
||||||
|
let url = root.url().unwrap_or("");
|
||||||
|
return Ok(AvmString::new_utf8(activation.context.gc_context, url).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,44 +291,47 @@ pub fn bytes<'gc>(
|
||||||
) -> Result<Value<'gc>, Error> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
if let Some(this) = this {
|
if let Some(this) = this {
|
||||||
if let Some(loader_stream) = this.as_loader_stream() {
|
if let Some(loader_stream) = this.as_loader_stream() {
|
||||||
match &*loader_stream {
|
let root = match &*loader_stream {
|
||||||
LoaderStream::Stage => {
|
LoaderStream::Stage => activation
|
||||||
return Err("Error: The stage's loader info does not have a bytestream".into())
|
.context
|
||||||
}
|
.stage
|
||||||
LoaderStream::Swf(root, _) => {
|
.child_by_index(0)
|
||||||
let ba_class = activation.context.avm2.classes().bytearray;
|
.and_then(|c| c.movie()),
|
||||||
|
LoaderStream::Swf(root, _) => Some(root.clone()),
|
||||||
|
};
|
||||||
|
|
||||||
let ba = ba_class.construct(activation, &[])?;
|
if let Some(root) = root {
|
||||||
let mut ba_write = ba.as_bytearray_mut(activation.context.gc_context).unwrap();
|
let ba_class = activation.context.avm2.classes().bytearray;
|
||||||
|
|
||||||
// First, write a fake header corresponding to an
|
let ba = ba_class.construct(activation, &[])?;
|
||||||
// uncompressed SWF
|
let mut ba_write = ba.as_bytearray_mut(activation.context.gc_context).unwrap();
|
||||||
let mut header = root.header().swf_header().clone();
|
|
||||||
header.compression = Compression::None;
|
|
||||||
|
|
||||||
write_swf(&header, &[], &mut *ba_write).unwrap();
|
// First, write a fake header corresponding to an
|
||||||
|
// uncompressed SWF
|
||||||
|
let mut header = root.header().swf_header().clone();
|
||||||
|
header.compression = Compression::None;
|
||||||
|
|
||||||
// `swf` always writes an implicit end tag, let's cut that
|
write_swf(&header, &[], &mut *ba_write).unwrap();
|
||||||
// off. We scroll back 2 bytes before writing the actual
|
|
||||||
// datastream as it is guaranteed to at least be as long as
|
|
||||||
// the implicit end tag we want to get rid of.
|
|
||||||
let correct_header_length = ba_write.len() - 2;
|
|
||||||
ba_write.set_position(correct_header_length);
|
|
||||||
ba_write.write_bytes(root.data())?;
|
|
||||||
|
|
||||||
// `swf` wrote the wrong length (since we wrote the data
|
// `swf` always writes an implicit end tag, let's cut that
|
||||||
// ourselves), so we need to overwrite it ourselves.
|
// off. We scroll back 2 bytes before writing the actual
|
||||||
ba_write.set_position(4);
|
// datastream as it is guaranteed to at least be as long as
|
||||||
ba_write.set_endian(Endian::Little);
|
// the implicit end tag we want to get rid of.
|
||||||
ba_write
|
let correct_header_length = ba_write.len() - 2;
|
||||||
.write_unsigned_int((root.data().len() + correct_header_length) as u32)?;
|
ba_write.set_position(correct_header_length);
|
||||||
|
ba_write.write_bytes(root.data())?;
|
||||||
|
|
||||||
// Finally, reset the array to the correct state.
|
// `swf` wrote the wrong length (since we wrote the data
|
||||||
ba_write.set_position(0);
|
// ourselves), so we need to overwrite it ourselves.
|
||||||
ba_write.set_endian(Endian::Big);
|
ba_write.set_position(4);
|
||||||
|
ba_write.set_endian(Endian::Little);
|
||||||
|
ba_write.write_unsigned_int((root.data().len() + correct_header_length) as u32)?;
|
||||||
|
|
||||||
return Ok(ba.into());
|
// Finally, reset the array to the correct state.
|
||||||
}
|
ba_write.set_position(0);
|
||||||
|
ba_write.set_endian(Endian::Big);
|
||||||
|
|
||||||
|
return Ok(ba.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,30 +372,34 @@ pub fn parameters<'gc>(
|
||||||
) -> Result<Value<'gc>, Error> {
|
) -> Result<Value<'gc>, Error> {
|
||||||
if let Some(this) = this {
|
if let Some(this) = this {
|
||||||
if let Some(loader_stream) = this.as_loader_stream() {
|
if let Some(loader_stream) = this.as_loader_stream() {
|
||||||
match &*loader_stream {
|
let root = match &*loader_stream {
|
||||||
LoaderStream::Stage => {
|
LoaderStream::Stage => activation
|
||||||
return Err("Error: The stage's loader info does not have parameters".into())
|
.context
|
||||||
}
|
.stage
|
||||||
LoaderStream::Swf(root, _) => {
|
.child_by_index(0)
|
||||||
let mut params_obj = activation
|
.and_then(|c| c.movie()),
|
||||||
.avm2()
|
LoaderStream::Swf(root, _) => Some(root.clone()),
|
||||||
.classes()
|
};
|
||||||
.object
|
|
||||||
.construct(activation, &[])?;
|
|
||||||
let parameters = root.parameters();
|
|
||||||
|
|
||||||
for (k, v) in parameters.iter() {
|
if let Some(root) = root {
|
||||||
let avm_k = AvmString::new_utf8(activation.context.gc_context, k);
|
let mut params_obj = activation
|
||||||
let avm_v = AvmString::new_utf8(activation.context.gc_context, v);
|
.avm2()
|
||||||
params_obj.set_property(
|
.classes()
|
||||||
&QName::new(Namespace::public(), avm_k).into(),
|
.object
|
||||||
avm_v.into(),
|
.construct(activation, &[])?;
|
||||||
activation,
|
let parameters = root.parameters();
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(params_obj.into());
|
for (k, v) in parameters.iter() {
|
||||||
|
let avm_k = AvmString::new_utf8(activation.context.gc_context, k);
|
||||||
|
let avm_v = AvmString::new_utf8(activation.context.gc_context, v);
|
||||||
|
params_obj.set_property(
|
||||||
|
&QName::new(Namespace::public(), avm_k).into(),
|
||||||
|
avm_v.into(),
|
||||||
|
activation,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Ok(params_obj.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue