* core: add temporary, ruffle-internal copy of `gc-arena` crate
This will allow bumping the upstream `gc-arena` version while
reexporting our own version of the old `GcCell` API, so that
Ruffle's code can be gradually migrated.
Once the migration is done, this crate should be removed.
* core: bump `gc-arena` to kyren/gc-arena#56
Add back the removed `GcCell` to our internal facade crate
* core: bump `gc-arena` to current master
This bump renames `Gc::allocate` to `Gc::new`
* core: rename `GcCell::allocate` to `GcCell::new`, to match `Gc`
* core: bump gc-arena to (slighly after) v0.3.1
Add typedefs for old `*Context` names in the gc-arena facade crate
* core: replace uses of `CollectionContext<'_>` by `&Collection`
* core: Add `gc()` convenience method for `*Context` and `Activation` types
This allows shortening most instances of `[activation.]context.gc_context`
to `activation.gc()` or `context.gc()` (but not all instances, because of
borrowck) Note that this doesn't actually do these shortenings to avoid
major code churn.
I've moved our special entity handling logic into
a `custom_unescape` function. This lets us move off
of our fork of `quick-xml` back onto the crates.io release
In future versions of `gc-arena`, the `Debug` impl. of `Gc`
and `GcCell` will print the pointed-to value, which will cause
derived `Debug` impls. to enter an infinite recursion.
As such, this manually implements `Debug` on types wrapping a
`Gc/GcCell` to maintain the current behavior.
Use a bare `ScriptObject` instead. This matches Flash's behavior in
many aspects:
* Attribute values can now store arbitrary AVM1 values, rather than
just strings. These are coerced to string lazily on demand (e.g.
when coercing the whole XML node to a string).
* Attributes iteration order is the same as their definition order,
not sorted by their name.
Also fix some bugs in `XmlNode::lookup_namespace_uri` (renamed from
`lookup_uri_for_namespace`):
* Iterate attributes by their definition order, so the first matching
one is returned.
* The empty prefix matches every attribute that starts with "xmlns"
(with/without a colon).
And inline `XmlNode::lookup_namespace_for_uri` into `get_prefix_for_namespace`,
and fix some bugs in there as well:
* Iterate attributes by their definition order, so the first matching
one is returned.
* Match any attribute that start with "xmlns" (with/without a colon).
Unify the previous 3 creation methods to a single `XmlNode::new`.
This allows supporting arbitrary `nodeType` values passed to the
`XMLNode` constructor.
The difference between element nodes and text nodes is very minor.
So instead of representing them by two distinct enum members, make
`XmlNodeData` a single unified struct that can represent both. A new
`node_type` field is introduced, in order to still distinguish
between element and text nodes. Also, Ruffle made some incorrect
assumptions, which are now corrected, including:
* Nodes can have any arbitrary `u8` type. This is resolved by the
introduction of the `node_type` field which is a `u8`.
* Text nodes can have children. This is resolved by simply not checking
for text nodes in `append_child` etc.
Document roots (a.k.a. `XML` objects) are very similar to regular
element nodes (a.k.a. `XMLNode` objects). The primary difference is
that `XML` objects return `null` for their `nodeName`. But this can
be changed too; Setting `xml.nodeName = "someName"` will make `XML`
objects behave much like `XMLNode`. Moreover, many checks in Ruffle
that refuse to operate on document roots were wrong, and actually
these should be accepted as normal element nodes.
Besides the functional corrections, this also simplifies the code.
Instead of returning a `Result` which is anyway always handled with
a `log::warn!()`, simply `log::warn!()` in place of errors. This
removes the last 3 remaining `Error` enum members besides `InvalidXml`.
The 2 existing usages of `remove_node` always operated on a child and
its parent: One iterates over all of its children and removes each one,
and the other explicitly grabs the parent of a given node.
As a simplification, `remove_node` operates only on a child node,
without the need for the parent node in addition; it grabs the parent
from the child by itself. As such, it's non-failable.
Text nodes are guaranteed to not be parents, as `adopt_child`
refuses to adopt children into them. So instead of returning an
`Err(Error::TextNodeCantHaveChildren)` in case of a text node parent,
mark those code paths as `unreachable!()`. This makes `orphan_child`
non-failable.
Revert some of e50aea864b for an even
better approach - Remove `XmlNodeObject::empty_node` entirely by
making `XmlNodeObject::from_xml_node` a suitable alternative. That is,
being able to accept a custom `proto` like before.
Also, make it return an `XmlNodeObject` instead of an `Object`, and
add a few `.into()` where needed.
* Don't use `quick_xml::Writer` for formatting the XML, being much
more simple.
* Return `WString` instead of `String`, reducing `to_utf8_lossy()`
calls except when the string needs to be escaped (attribute values
and text contents).
As `XmlDocument` and `XmlObject` had 1-to-1 relation, and `XmlDocument`
is already tightly coupled with AVM1, there's no good reason for them
being separate objects.
This brings us one step closer towards an XML implementation hosted
completely in AVM1.
A future PR will merge `XmlNode` into `XmlNodeObject` in a similar
manner.
`XmlNode::is_as2_compatible` returns `false` for `XmlNodeData::DocType`
nodes, which means they are not included in string representations of
XML documents, and they cannot be traversed using the DOM methods.
So don't create those when parsing an XML from string, but still
store the `DOCTYPE` declaration string on the `XmlDocument`, which
is accissible through the `.docTypeDecl` property.
`XmlNode::is_as2_compatible` returns `false` for `XmlNodeData::Comment`
nodes, which means they are not included in string representations of
XML documents, and they cannot be traversed using the DOM methods.
So simply don't create those when parsing an XML from string.
Now that `replace_with_str` is defined in `XmlDocument`, there is
no need anymore for a separate function that handles nodes which have
document-wide implications.