1
1
//! XML class
2
2
3
+ use std:: cell:: Cell ;
4
+
3
5
use crate :: avm1:: function:: { Executable , ExecutionReason , FunctionObject } ;
4
6
use crate :: avm1:: property_decl:: { define_properties_on, Declaration } ;
5
7
use crate :: avm1:: {
@@ -9,7 +11,9 @@ use crate::avm_warn;
9
11
use crate :: backend:: navigator:: Request ;
10
12
use crate :: string:: { AvmString , StringContext , WStr , WString } ;
11
13
use crate :: xml:: { custom_unescape, XmlNode , ELEMENT_NODE , TEXT_NODE } ;
12
- use gc_arena:: { Collect , GcCell } ;
14
+ use gc_arena:: barrier:: unlock;
15
+ use gc_arena:: lock:: Lock ;
16
+ use gc_arena:: { Collect , Gc } ;
13
17
use quick_xml:: errors:: IllFormedError ;
14
18
use quick_xml:: events:: attributes:: AttrError ;
15
19
use quick_xml:: { events:: Event , Reader } ;
@@ -55,7 +59,7 @@ pub enum XmlStatus {
55
59
56
60
#[ derive( Copy , Clone , Collect ) ]
57
61
#[ collect( no_drop) ]
58
- pub struct Xml < ' gc > ( GcCell < ' gc , XmlData < ' gc > > ) ;
62
+ pub struct Xml < ' gc > ( Gc < ' gc , XmlData < ' gc > > ) ;
59
63
60
64
#[ derive( Clone , Collect ) ]
61
65
#[ collect( no_drop) ]
@@ -64,10 +68,10 @@ pub struct XmlData<'gc> {
64
68
root : XmlNode < ' gc > ,
65
69
66
70
/// The XML declaration, if set.
67
- xml_decl : Option < AvmString < ' gc > > ,
71
+ xml_decl : Lock < Option < AvmString < ' gc > > > ,
68
72
69
73
/// The XML doctype, if set.
70
- doctype : Option < AvmString < ' gc > > ,
74
+ doctype : Lock < Option < AvmString < ' gc > > > ,
71
75
72
76
/// The document's ID map.
73
77
///
@@ -77,7 +81,7 @@ pub struct XmlData<'gc> {
77
81
id_map : ScriptObject < ' gc > ,
78
82
79
83
/// The last parse error encountered, if any.
80
- status : XmlStatus ,
84
+ status : Cell < XmlStatus > ,
81
85
}
82
86
83
87
impl < ' gc > Xml < ' gc > {
@@ -88,14 +92,14 @@ impl<'gc> Xml<'gc> {
88
92
let mut root = XmlNode :: new ( gc_context, ELEMENT_NODE , None ) ;
89
93
root. introduce_script_object ( gc_context, object) ;
90
94
91
- let xml = Self ( GcCell :: new (
95
+ let xml = Self ( Gc :: new (
92
96
gc_context,
93
97
XmlData {
94
98
root,
95
- xml_decl : None ,
96
- doctype : None ,
99
+ xml_decl : Lock :: new ( None ) ,
100
+ doctype : Lock :: new ( None ) ,
97
101
id_map : ScriptObject :: new ( context, None ) ,
98
- status : XmlStatus :: NoError ,
102
+ status : Cell :: new ( XmlStatus :: NoError ) ,
99
103
} ,
100
104
) ) ;
101
105
object. set_native ( gc_context, NativeObject :: Xml ( xml) ) ;
@@ -104,33 +108,33 @@ impl<'gc> Xml<'gc> {
104
108
105
109
/// Yield the document in node form.
106
110
pub fn root ( self ) -> XmlNode < ' gc > {
107
- self . 0 . read ( ) . root
111
+ self . 0 . root
108
112
}
109
113
110
114
/// Retrieve the XML declaration of this document.
111
115
fn xml_decl ( self ) -> Option < AvmString < ' gc > > {
112
- self . 0 . read ( ) . xml_decl
116
+ self . 0 . xml_decl . get ( )
113
117
}
114
118
115
119
/// Retrieve the first DocType node in the document.
116
120
fn doctype ( self ) -> Option < AvmString < ' gc > > {
117
- self . 0 . read ( ) . doctype
121
+ self . 0 . doctype . get ( )
118
122
}
119
123
120
124
/// Obtain the script object for the document's `idMap` property.
121
125
fn id_map ( self ) -> ScriptObject < ' gc > {
122
- self . 0 . read ( ) . id_map
126
+ self . 0 . id_map
123
127
}
124
128
125
129
fn status ( self ) -> XmlStatus {
126
- self . 0 . read ( ) . status
130
+ self . 0 . status . get ( )
127
131
}
128
132
129
133
/// Replace the contents of this document with the result of parsing a string.
130
134
///
131
135
/// This method does not yet actually remove existing node contents.
132
136
fn parse (
133
- & self ,
137
+ self ,
134
138
activation : & mut Activation < ' _ , ' gc > ,
135
139
data : & WStr ,
136
140
ignore_white : bool ,
@@ -139,11 +143,11 @@ impl<'gc> Xml<'gc> {
139
143
let mut parser = Reader :: from_str ( & data_utf8) ;
140
144
let mut open_tags = vec ! [ self . root( ) ] ;
141
145
142
- self . 0 . write ( activation . gc ( ) ) . status = XmlStatus :: NoError ;
146
+ self . 0 . status . set ( XmlStatus :: NoError ) ;
143
147
144
148
loop {
145
149
let event = parser. read_event ( ) . map_err ( |error| {
146
- self . 0 . write ( activation . gc ( ) ) . status = match error {
150
+ self . 0 . status . set ( match error {
147
151
quick_xml:: Error :: Syntax ( _)
148
152
| quick_xml:: Error :: InvalidAttr ( AttrError :: ExpectedEq ( _) )
149
153
| quick_xml:: Error :: InvalidAttr ( AttrError :: Duplicated ( _, _) ) => {
@@ -165,7 +169,7 @@ impl<'gc> Xml<'gc> {
165
169
// quick_xml::Error::UnexpectedBang
166
170
// quick_xml::Error::TextNotFound
167
171
// quick_xml::Error::EscapeError(_)
168
- } ;
172
+ } ) ;
169
173
error
170
174
} ) ?;
171
175
@@ -211,8 +215,8 @@ impl<'gc> Xml<'gc> {
211
215
let mut xml_decl = WString :: from_buf ( b"<?" . to_vec ( ) ) ;
212
216
xml_decl. push_str ( WStr :: from_units ( & * bd) ) ;
213
217
xml_decl. push_str ( WStr :: from_units ( b"?>" ) ) ;
214
- self . 0 . write ( activation. gc ( ) ) . xml_decl =
215
- Some ( AvmString :: new ( activation. gc ( ) , xml_decl) ) ;
218
+ let xml_decl = Some ( AvmString :: new ( activation. gc ( ) , xml_decl ) ) ;
219
+ unlock ! ( Gc :: write ( activation. gc( ) , self . 0 ) , XmlData , xml_decl) . set ( xml_decl ) ;
216
220
}
217
221
Event :: DocType ( bt) => {
218
222
// TODO: `quick-xml` is case-insensitive for DOCTYPE declarations,
@@ -222,8 +226,8 @@ impl<'gc> Xml<'gc> {
222
226
let mut doctype = WString :: from_buf ( b"<!DOCTYPE " . to_vec ( ) ) ;
223
227
doctype. push_str ( WStr :: from_units ( & * bt. escape_ascii ( ) . collect :: < Vec < _ > > ( ) ) ) ;
224
228
doctype. push_byte ( b'>' ) ;
225
- self . 0 . write ( activation. gc ( ) ) . doctype =
226
- Some ( AvmString :: new ( activation. gc ( ) , doctype) ) ;
229
+ let doctype = Some ( AvmString :: new ( activation. gc ( ) , doctype ) ) ;
230
+ unlock ! ( Gc :: write ( activation. gc( ) , self . 0 ) , XmlData , doctype) . set ( doctype ) ;
227
231
}
228
232
Event :: Eof => break ,
229
233
_ => { }
0 commit comments