avm2: Add IS_QNAME flag to Multiname, improve XML name matching
This commit is contained in:
parent
d7b3a500d7
commit
fd281cc715
|
@ -1055,14 +1055,18 @@ impl<'gc> E4XNode<'gc> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Multiname is not a QName, so an any name matches everything.
|
||||||
|
// See https://github.com/adobe/avmplus/blob/858d034a3bd3a54d9b70909386435cf4aec81d21/core/Multiname.cpp#L59
|
||||||
|
if name.is_any_name() && !name.is_qname() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if !name.is_any_name() && self.local_name() != name.local_name() {
|
if !name.is_any_name() && self.local_name() != name.local_name() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Multiname is not a QName, so an any name matches everything.
|
if self.local_name().is_none() {
|
||||||
// See https://github.com/adobe/avmplus/blob/858d034a3bd3a54d9b70909386435cf4aec81d21/core/Multiname.cpp#L59
|
return false;
|
||||||
if name.is_any_name() && name.namespace_set().len() > 1 {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if name.is_any_namespace() {
|
if name.is_any_namespace() {
|
||||||
|
|
|
@ -68,6 +68,12 @@ bitflags! {
|
||||||
const HAS_LAZY_NAME = 1 << 1;
|
const HAS_LAZY_NAME = 1 << 1;
|
||||||
/// Whether this was a 'MultinameA' - used for XML attribute lookups
|
/// Whether this was a 'MultinameA' - used for XML attribute lookups
|
||||||
const ATTRIBUTE = 1 << 2;
|
const ATTRIBUTE = 1 << 2;
|
||||||
|
|
||||||
|
/// Represents the XML concept of "qualified name".
|
||||||
|
/// This also distinguishes a QName(x, y) from Multiname(x, [y])
|
||||||
|
/// Basically, marks multinames that come from multinames of kind `(RT)QName(L)(A)`
|
||||||
|
/// (and dynamically-generated multinames that are supposed to be equivalent to one).
|
||||||
|
const IS_QNAME = 1 << 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +127,15 @@ impl<'gc> Multiname<'gc> {
|
||||||
self.flags.set(MultinameFlags::ATTRIBUTE, is_attribute);
|
self.flags.set(MultinameFlags::ATTRIBUTE, is_attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_qname(&self) -> bool {
|
||||||
|
self.flags.contains(MultinameFlags::IS_QNAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_is_qname(&mut self, is_qname: bool) {
|
||||||
|
self.flags.set(MultinameFlags::IS_QNAME, is_qname);
|
||||||
|
}
|
||||||
|
|
||||||
/// Read a namespace set from the ABC constant pool, and return a list of
|
/// Read a namespace set from the ABC constant pool, and return a list of
|
||||||
/// copied namespaces.
|
/// copied namespaces.
|
||||||
pub fn abc_namespace_set(
|
pub fn abc_namespace_set(
|
||||||
|
@ -175,7 +190,7 @@ impl<'gc> Multiname<'gc> {
|
||||||
.pool_string_option(name.0, &mut context.borrow_gc())?
|
.pool_string_option(name.0, &mut context.borrow_gc())?
|
||||||
.map(|v| v.into()),
|
.map(|v| v.into()),
|
||||||
param: None,
|
param: None,
|
||||||
flags: Default::default(),
|
flags: MultinameFlags::IS_QNAME,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AbcMultiname::RTQName { name } | AbcMultiname::RTQNameA { name } => Self {
|
AbcMultiname::RTQName { name } | AbcMultiname::RTQNameA { name } => Self {
|
||||||
|
@ -184,13 +199,15 @@ impl<'gc> Multiname<'gc> {
|
||||||
.pool_string_option(name.0, &mut context.borrow_gc())?
|
.pool_string_option(name.0, &mut context.borrow_gc())?
|
||||||
.map(|v| v.into()),
|
.map(|v| v.into()),
|
||||||
param: None,
|
param: None,
|
||||||
flags: MultinameFlags::HAS_LAZY_NS,
|
flags: MultinameFlags::HAS_LAZY_NS | MultinameFlags::IS_QNAME,
|
||||||
},
|
},
|
||||||
AbcMultiname::RTQNameL | AbcMultiname::RTQNameLA => Self {
|
AbcMultiname::RTQNameL | AbcMultiname::RTQNameLA => Self {
|
||||||
ns: NamespaceSet::multiple(vec![], mc),
|
ns: NamespaceSet::multiple(vec![], mc),
|
||||||
name: None,
|
name: None,
|
||||||
param: None,
|
param: None,
|
||||||
flags: MultinameFlags::HAS_LAZY_NS | MultinameFlags::HAS_LAZY_NAME,
|
flags: MultinameFlags::HAS_LAZY_NS
|
||||||
|
| MultinameFlags::HAS_LAZY_NAME
|
||||||
|
| MultinameFlags::IS_QNAME,
|
||||||
},
|
},
|
||||||
AbcMultiname::Multiname {
|
AbcMultiname::Multiname {
|
||||||
namespace_set,
|
namespace_set,
|
||||||
|
@ -287,7 +304,7 @@ impl<'gc> Multiname<'gc> {
|
||||||
ns,
|
ns,
|
||||||
name,
|
name,
|
||||||
param: self.param,
|
param: self.param,
|
||||||
flags: self.flags & MultinameFlags::ATTRIBUTE,
|
flags: self.flags & (MultinameFlags::ATTRIBUTE | MultinameFlags::IS_QNAME),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
getdescendants QName(null, null)
|
||||||
|
element
|
||||||
|
element
|
||||||
|
|
||||||
|
getdescendants Multiname(null, [Namespace("")])
|
||||||
|
text
|
||||||
|
element
|
||||||
|
text
|
||||||
|
element
|
||||||
|
text
|
||||||
|
text
|
||||||
|
text
|
||||||
|
|
||||||
|
getdescendants Multiname(null, [Namespace(""), Namespace("x")])
|
||||||
|
text
|
||||||
|
element
|
||||||
|
text
|
||||||
|
element
|
||||||
|
text
|
||||||
|
text
|
||||||
|
text
|
|
@ -0,0 +1,32 @@
|
||||||
|
// compiled with mxmlc, with bytecode modifications in FFDEC
|
||||||
|
|
||||||
|
import flash.utils.getQualifiedClassName;
|
||||||
|
import flash.utils.getTimer;
|
||||||
|
|
||||||
|
class C{
|
||||||
|
public function test(x){
|
||||||
|
trace('getdescendants QName(null, null)')
|
||||||
|
var a = x; // note: put `getdescendants QName(null, null)` here
|
||||||
|
for each(var i in a) { trace(i.nodeKind()); }
|
||||||
|
trace();
|
||||||
|
trace('getdescendants Multiname(null, [Namespace("")])')
|
||||||
|
var b = x; // note: put `getdescendants Multiname(null, [Namespace("")])` here
|
||||||
|
for each(var i in b) { trace(i.nodeKind()); }
|
||||||
|
trace();
|
||||||
|
trace('getdescendants Multiname(null, [Namespace(""), Namespace("x")])')
|
||||||
|
var c = x; // note: put `getdescendants Multiname(null, [Namespace(""), Namespace("x")])` here
|
||||||
|
for each(var i in c) { trace(i.nodeKind()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XML.ignoreWhitespace = false;
|
||||||
|
var s = "<a> <b> x <c> y </c> </b> </a>";
|
||||||
|
var x = new XML(s);
|
||||||
|
new C().test(x);
|
||||||
|
|
||||||
|
package {
|
||||||
|
import flash.display.MovieClip;
|
||||||
|
public class Test extends MovieClip {
|
||||||
|
public function Test(){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
num_frames = 1
|
Loading…
Reference in New Issue