Skip to content

Commit 8886bbb

Browse files
committed
avm1: Store AvmStrings in FileReference
This avoids extra `RefCell`s and back-and-forth conversions to `String`.
1 parent 1b8418b commit 8886bbb

File tree

1 file changed

+48
-70
lines changed

1 file changed

+48
-70
lines changed

core/src/avm1/globals/file_reference.rs

+48-70
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use crate::backend::ui::{FileDialogResult, FileFilter};
1111
use crate::string::{AvmString, StringContext};
1212
use gc_arena::barrier::unlock;
1313
use gc_arena::lock::Lock;
14-
use gc_arena::{Collect, Gc, Mutation};
14+
use gc_arena::{Collect, Gc};
15+
use ruffle_macros::istr;
1516
use url::Url;
1617

1718
// There are two undocumented functions in FileReference: convertToPPT and deleteConvertedPPT.
@@ -30,58 +31,59 @@ impl<'gc> FileReferenceObject<'gc> {
3031
pub fn init_from_dialog_result(
3132
self,
3233
activation: &mut Activation<'_, 'gc>,
33-
dialog_result: &dyn FileDialogResult,
34+
result: &dyn FileDialogResult,
3435
) {
36+
let mc = activation.gc();
37+
let write = Gc::write(mc, self.0);
38+
3539
self.0.is_initialised.set(true);
3640

3741
let date_proto = activation.context.avm1.prototypes().date_constructor;
38-
if let Some(creation_time) = dialog_result.creation_time() {
42+
if let Some(creation_time) = result.creation_time() {
3943
if let Ok(Value::Object(obj)) = date_proto.construct(
4044
activation,
4145
&[(creation_time.timestamp_millis() as f64).into()],
4246
) {
43-
self.set_creation_date(activation.gc(), Some(obj));
47+
unlock!(write, FileReferenceData, creation_date).set(Some(obj));
4448
}
4549
}
4650

47-
if let Some(modification_time) = dialog_result.modification_time() {
51+
if let Some(modification_time) = result.modification_time() {
4852
if let Ok(Value::Object(obj)) = date_proto.construct(
4953
activation,
5054
&[(modification_time.timestamp_millis() as f64).into()],
5155
) {
52-
self.set_modification_date(activation.gc(), Some(obj));
56+
unlock!(write, FileReferenceData, modification_date).set(Some(obj));
5357
}
5458
}
5559

56-
self.0.file_type.replace(dialog_result.file_type());
57-
self.0.name.replace(dialog_result.file_name());
58-
self.0.size.replace(dialog_result.size());
59-
self.0.creator.replace(dialog_result.creator());
60-
self.0.data.replace(dialog_result.contents().to_vec());
61-
}
60+
let file_type = result.file_type().map(|s| AvmString::new_utf8(mc, s));
61+
unlock!(write, FileReferenceData, file_type).set(file_type);
6262

63-
fn set_creation_date(self, gc: &'gc Mutation<'gc>, creation_date: Option<Object<'gc>>) {
64-
unlock!(Gc::write(gc, self.0), FileReferenceData, creation_date).set(creation_date);
65-
}
63+
let file_name = result.file_name().map(|s| AvmString::new_utf8(mc, s));
64+
unlock!(write, FileReferenceData, name).set(file_name);
65+
66+
let creator = result.creator().map(|s| AvmString::new_utf8(mc, s));
67+
unlock!(write, FileReferenceData, creator).set(creator);
6668

67-
fn set_modification_date(self, gc: &'gc Mutation<'gc>, modification_date: Option<Object<'gc>>) {
68-
unlock!(Gc::write(gc, self.0), FileReferenceData, modification_date).set(modification_date);
69+
self.0.size.replace(result.size());
70+
self.0.data.replace(result.contents().to_vec());
6971
}
7072
}
7173

72-
#[derive(Default, Clone, Collect)]
74+
#[derive(Clone, Default, Collect)]
7375
#[collect(no_drop)]
7476
pub struct FileReferenceData<'gc> {
7577
/// Has this object been initialised from a dialog
7678
is_initialised: Cell<bool>,
7779

7880
creation_date: Lock<Option<Object<'gc>>>,
79-
creator: RefCell<Option<String>>,
81+
creator: Lock<Option<AvmString<'gc>>>,
8082
modification_date: Lock<Option<Object<'gc>>>,
81-
name: RefCell<Option<String>>,
82-
post_data: RefCell<String>,
83+
name: Lock<Option<AvmString<'gc>>>,
84+
post_data: Lock<Option<AvmString<'gc>>>,
8385
size: Cell<Option<u64>>,
84-
file_type: RefCell<Option<String>>,
86+
file_type: Lock<Option<AvmString<'gc>>>,
8587

8688
/// The contents of the referenced file
8789
/// We track this here so that it can be referenced in FileReference.upload
@@ -110,30 +112,21 @@ pub fn creation_date<'gc>(
110112
_args: &[Value<'gc>],
111113
) -> Result<Value<'gc>, Error<'gc>> {
112114
if let NativeObject::FileReference(file_ref) = this.native() {
113-
return Ok(file_ref
114-
.0
115-
.creation_date
116-
.get()
117-
.map_or(Value::Undefined, |x| x.into()));
115+
let creation_date = file_ref.0.creation_date.get();
116+
return Ok(creation_date.map_or(Value::Undefined, Into::into));
118117
}
119118

120119
Ok(Value::Undefined)
121120
}
122121

123122
pub fn creator<'gc>(
124-
activation: &mut Activation<'_, 'gc>,
123+
_activation: &mut Activation<'_, 'gc>,
125124
this: Object<'gc>,
126125
_args: &[Value<'gc>],
127126
) -> Result<Value<'gc>, Error<'gc>> {
128127
if let NativeObject::FileReference(file_ref) = this.native() {
129-
return Ok(file_ref
130-
.0
131-
.creator
132-
.borrow()
133-
.as_ref()
134-
.map_or(Value::Undefined, |x| {
135-
AvmString::new_utf8(activation.gc(), x).into()
136-
}));
128+
let creator = file_ref.0.creator.get();
129+
return Ok(creator.map_or(Value::Undefined, Into::into));
137130
}
138131

139132
Ok(Value::Undefined)
@@ -145,30 +138,20 @@ pub fn modification_date<'gc>(
145138
_args: &[Value<'gc>],
146139
) -> Result<Value<'gc>, Error<'gc>> {
147140
if let NativeObject::FileReference(file_ref) = this.native() {
148-
return Ok(file_ref
149-
.0
150-
.modification_date
151-
.get()
152-
.map_or(Value::Undefined, |x| x.into()));
141+
let modification_date = file_ref.0.modification_date.get();
142+
return Ok(modification_date.map_or(Value::Undefined, Into::into));
153143
}
154144

155145
Ok(Value::Undefined)
156146
}
157147

158148
pub fn name<'gc>(
159-
activation: &mut Activation<'_, 'gc>,
149+
_activation: &mut Activation<'_, 'gc>,
160150
this: Object<'gc>,
161151
_args: &[Value<'gc>],
162152
) -> Result<Value<'gc>, Error<'gc>> {
163153
if let NativeObject::FileReference(file_ref) = this.native() {
164-
return Ok(file_ref
165-
.0
166-
.name
167-
.borrow()
168-
.as_ref()
169-
.map_or(Value::Undefined, |x| {
170-
AvmString::new_utf8(activation.gc(), x).into()
171-
}));
154+
return Ok(file_ref.0.name.get().map_or(Value::Undefined, Into::into));
172155
}
173156

174157
Ok(Value::Undefined)
@@ -180,9 +163,8 @@ pub fn post_data<'gc>(
180163
_args: &[Value<'gc>],
181164
) -> Result<Value<'gc>, Error<'gc>> {
182165
if let NativeObject::FileReference(file_ref) = this.native() {
183-
return Ok(
184-
AvmString::new_utf8(activation.gc(), file_ref.0.post_data.borrow().clone()).into(),
185-
);
166+
let post_data = file_ref.0.post_data.get();
167+
return Ok(post_data.unwrap_or_else(|| istr!("")).into());
186168
}
187169

188170
Ok(Value::Undefined)
@@ -199,7 +181,8 @@ pub fn set_post_data<'gc>(
199181
.coerce_to_string(activation)?;
200182

201183
if let NativeObject::FileReference(file_ref) = this.native() {
202-
file_ref.0.post_data.replace(post_data.to_string());
184+
let write = Gc::write(activation.gc(), file_ref.0);
185+
unlock!(write, FileReferenceData, post_data).set(Some(post_data));
203186
}
204187

205188
Ok(Value::Undefined)
@@ -211,26 +194,21 @@ pub fn size<'gc>(
211194
_args: &[Value<'gc>],
212195
) -> Result<Value<'gc>, Error<'gc>> {
213196
if let NativeObject::FileReference(file_ref) = this.native() {
214-
return Ok(file_ref.0.size.get().map_or(Value::Undefined, |x| x.into()));
197+
let size = file_ref.0.size.get();
198+
return Ok(size.map_or(Value::Undefined, Into::into));
215199
}
216200

217201
Ok(Value::Undefined)
218202
}
219203

220204
pub fn file_type<'gc>(
221-
activation: &mut Activation<'_, 'gc>,
205+
_activation: &mut Activation<'_, 'gc>,
222206
this: Object<'gc>,
223207
_args: &[Value<'gc>],
224208
) -> Result<Value<'gc>, Error<'gc>> {
225209
if let NativeObject::FileReference(file_ref) = this.native() {
226-
return Ok(file_ref
227-
.0
228-
.file_type
229-
.borrow()
230-
.as_ref()
231-
.map_or(Value::Undefined, |x| {
232-
AvmString::new_utf8(activation.gc(), x).into()
233-
}));
210+
let file_type = file_ref.0.file_type.get();
211+
return Ok(file_type.map_or(Value::Undefined, Into::into));
234212
}
235213

236214
Ok(Value::Undefined)
@@ -401,17 +379,17 @@ pub fn upload<'gc>(
401379
_ => return Ok(false.into()),
402380
}
403381

382+
let file_name = match file_reference.0.name.get() {
383+
Some(name) => name.to_string(),
384+
None => "file".to_string(),
385+
};
386+
404387
let process = activation.context.load_manager.upload_file(
405388
activation.context.player.clone(),
406389
this,
407390
url_string,
408391
file_reference.0.data.borrow().clone(),
409-
file_reference
410-
.0
411-
.name
412-
.borrow()
413-
.clone()
414-
.unwrap_or_else(|| "file".to_string()),
392+
file_name,
415393
);
416394

417395
activation.context.navigator.spawn_future(process);

0 commit comments

Comments
 (0)