@awayfl/avm2
Version:
Virtual machine for executing AS3 code
1,341 lines (1,333 loc) • 148 kB
JavaScript
import { __extends } from "tslib";
import { assert } from '@awayjs/graphics';
import { release, notImplemented, defineNonEnumerableProperty, isIndex, isNullOrUndefined, isObject, } from '@awayfl/swf-loader';
import { Namespace } from '../abc/lazy/Namespace';
import { Multiname } from '../abc/lazy/Multiname';
import { internPrefixedNamespace } from '../abc/lazy/internPrefixedNamespace';
import { internNamespace } from '../abc/lazy/internNamespace';
import { ASObject } from '../nat/ASObject';
import { addPrototypeFunctionAlias } from '../nat/addPrototypeFunctionAlias';
import { Errors } from '../errors';
import { axCoerceString } from '../run/axCoerceString';
import { checkValue } from '../run/checkValue';
import { validateCall } from '../run/validateCall';
import { getCurrentScope } from '../run/getCurrentScope';
/* tslint:disable */
/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
NOTE ON E4X METHOD CALLS
E4X specifies some magic when making calls on XML and XMLList values. If a
callee is not found on an XMLList value and the list has only one XML
child, then the call is delegated to that XML child. If a callee is not
found on an XML value and that value has simple content, then the simple
content is converted to a string value and the call is made on that string
value.
Here are the relevant texts from the spec section 11.2.2.1:
"If no such property exists and base is an XMLList of size 1, CallMethod
delegates the method invocation to the single property it contains. This
treatment intentionally blurs the distinction between XML objects and XMLLists
of size 1."
"If no such property exists and base is an XML object containing no XML valued
children (i.e., an attribute, leaf node or element with simple content),
CallMethod attempts to delegate the method lookup to the string value
contained in the leaf node. This treatment allows users to perform operations
directly on the value of a leaf node without having to explicitly select it."
NOTE ON E4X ANY NAME AND NAMESPACE
E4X allows the names of the form x.*, x.ns::*, x.*::id and x.*::* and their
attribute name counterparts x.@*, x.@ns::*, etc. These forms result in
Multiname values with the name part equal to undefined in the case of an ANY
name, and the namespace set being empty in the case of an ANY namespace.
Note also,
x.*
is shorthand for
x.*::*
.
*/
export function isXMLType(val, sec) {
return typeof val === 'object' && val &&
(val.axClass === sec.AXXML || val.axClass === sec.AXXMLList ||
val.axClass === sec.AXQName || val.axClass === sec.AXNamespace);
}
export function isXMLCollection(sec, val) {
return typeof val === 'object' && val &&
(val.axClass === sec.AXXML || val.axClass === sec.AXXMLList);
}
// 10.1 ToString
function toString(node, sec) {
if (!node || node.axClass !== sec.AXXML) {
return axCoerceString(node);
}
switch (node._kind) {
case 3 /* ASXMLKind.Text */:
case 2 /* ASXMLKind.Attribute */:
return node._value;
default:
if (node.hasSimpleContent()) {
var s = '';
for (var i = 0; i < node._children.length; i++) {
var child = node._children[i];
if (child._kind === 4 /* ASXMLKind.Comment */ ||
child._kind === 5 /* ASXMLKind.ProcessingInstruction */) {
continue;
}
s += toString(child, sec);
}
return s;
}
return toXMLString(sec, node);
}
}
// 10.2.1.1 EscapeElementValue ( s )
export function escapeElementValue(sec, s) {
if (isXMLCollection(sec, s)) {
return s.toXMLString();
}
s = axCoerceString(s);
var i = 0, ch;
while (i < s.length && (ch = s[i]) !== '&' && ch !== '<' && ch !== '>') {
i++;
}
if (i >= s.length) {
return s;
}
var buf = s.substring(0, i);
while (i < s.length) {
ch = s[i++];
switch (ch) {
case '&':
buf += '&';
break;
case '<':
buf += '<';
break;
case '>':
buf += '>';
break;
default:
buf += ch;
break;
}
}
return buf;
}
// 10.2.1.2 EscapeAttributeValue ( s )
export function escapeAttributeValue(s) {
s = String(s);
var i = 0, ch;
while (i < s.length && (ch = s[i]) !== '&' && ch !== '<' &&
ch !== '"' && ch !== '\n' && ch !== '\r' && ch !== '\t') {
i++;
}
if (i >= s.length) {
return s;
}
var buf = s.substring(0, i);
while (i < s.length) {
ch = s[i++];
switch (ch) {
case '&':
buf += '&';
break;
case '<':
buf += '<';
break;
case '"':
buf += '"';
break;
case '\n':
buf += '
';
break;
case '\r':
buf += '
';
break;
case '\t':
buf += '	';
break;
default:
buf += ch;
break;
}
}
return buf;
}
function isWhitespace(s, index) {
var ch = s[index];
return ch === ' ' || ch === '\n' || ch === '\r' || ch === '\t';
}
function isWhitespaceString(s) {
release || assert(typeof s === 'string');
for (var i = 0; i < s.length; i++) {
var ch = s[i];
if (!(ch === ' ' || ch === '\n' || ch === '\r' || ch === '\t')) {
return false;
}
}
return true;
}
function trimWhitespaces(s) {
var i = 0;
while (i < s.length && isWhitespace(s, i)) {
i++;
}
if (i >= s.length) {
return '';
}
var j = s.length - 1;
while (isWhitespace(s, j)) {
j--;
}
return i === 0 && j === s.length - 1 ? s : s.substring(i, j + 1);
}
var indentStringCache = [];
function getIndentString(indent) {
if (indent > 0) {
if (indentStringCache[indent] !== undefined) {
return indentStringCache[indent];
}
var s = '';
for (var i = 0; i < indent; i++) {
s += ' ';
}
indentStringCache[indent] = s;
return s;
}
return '';
}
function generateUniquePrefix(namespaces) {
var i = 1, newPrefix;
// eslint-disable-next-line no-constant-condition
while (true) {
newPrefix = '_ns' + i;
if (!namespaces.some(function (ns) { return ns.prefix === newPrefix; })) {
return newPrefix;
}
i++;
}
}
// 10.2 ToXMLString
function toXMLString(sec, node) {
if (node === null || node === undefined) {
throw new TypeError();
}
return escapeElementValue(sec, node);
}
// 10.3 ToXML
function toXML(v, sec) {
if (v === null) {
sec.throwError('TypeError', Errors.ConvertNullToObjectError);
}
if (v === undefined) {
sec.throwError('TypeError', Errors.ConvertUndefinedToObjectError);
}
if (v.axClass === sec.AXXML) {
return v;
}
if (v.axClass === sec.AXXMLList) {
if (v._children.length !== 1) {
sec.throwError('TypeError', Errors.XMLMarkupMustBeWellFormed);
}
return v._children[0];
}
// The E4X spec says we must throw a TypeError for non-Boolean, Number, or String objects.
// Flash thinks otherwise.
var x = sec.xmlParser.parseFromString(axCoerceString(v));
var length = x._children.length;
if (length === 0) {
return createXML(sec, 3 /* ASXMLKind.Text */);
}
if (length === 1) {
x._children[0]._parent = null;
return x._children[0];
}
if (length === 2) {
x._children[1]._parent = null;
return x._children[1];
}
sec.throwError('TypeError', Errors.XMLMarkupMustBeWellFormed);
}
// 10.4 ToXMLList
function toXMLList(value, targetList) {
// toXMLList is supposed to just return value if it's an XMLList already. For optimization
// purposes, we handle that case at the callsites.
release || assert(typeof value !== 'object' || value && value.axClass !== targetList.axClass);
if (value === null) {
targetList.sec.throwError('TypeError', Errors.ConvertNullToObjectError);
}
if (value === undefined) {
targetList.sec.throwError('TypeError', Errors.ConvertUndefinedToObjectError);
}
if (value.axClass === targetList.sec.AXXML) {
targetList.append(value);
return;
}
// The E4X spec says we must throw a TypeError for non-Boolean, Number, or String objects.
// Flash thinks otherwise.
var defaultNamespace = getDefaultNamespace(targetList.sec);
var parentString = '<parent xmlns="' + escapeAttributeValue(defaultNamespace.uri) + '">' +
value + '</parent>';
var x = toXML(parentString, targetList.sec);
var children = x._children;
if (!children) {
return;
}
for (var i = 0; i < children.length; i++) {
var v = children[i];
v._parent = null;
targetList.append(v);
}
}
// 10.6 ToXMLName
function toXMLName(mn, sec) {
if (mn === undefined) {
return anyMultiname;
}
var name;
// convert argument to a value of type AttributeName or a QName object
// according to the following:
if (typeof mn === 'object' && mn !== null) {
if (mn instanceof Multiname) {
return mn;
}
if (mn.axClass === sec.AXQName) {
// Object - If the input argument is a QName object,
// return its Multiname.
return mn.name;
}
// Object - Otherwise, convert the input argument to a string using ToString.
name = String(mn);
}
else if (typeof mn === 'number') {
name = mn + '';
}
else if (typeof mn === 'string') {
// String - Create a QName object or AttributeName from the String
// as specified below in section 10.6.1. See below.
if (mn === '*') {
name = null;
}
else {
name = mn;
}
}
else {
sec.throwError('TypeError', Errors.XMLInvalidName, mn);
}
// ... then convert the result to a QName object or AttributeName
// as specified in section 10.6.1.
if (name && name[0] === '@') {
// If the first character of s is "@", ToXMLName creates an
// AttributeName using the ToAttributeName operator.
name = name.substr(1);
if (name === '*') {
name = null;
}
return new Multiname(null, 0, 13 /* CONSTANT.QNameA */, [Namespace.PUBLIC], name);
}
return new Multiname(null, 0, 7 /* CONSTANT.QName */, [Namespace.PUBLIC], name);
}
function coerceE4XMultiname(mn, sec) {
var out = tmpMultiname;
out.kind = mn.kind;
// Queries of the foo[new QName('bar')] sort create this situation.
if (mn.name && mn.name.axClass === sec.AXQName) {
mn = mn.name.name;
}
if (mn.isQName()) {
out.name = mn.name;
out.namespaces = mn.namespaces;
}
else {
if (mn.isAnyNamespace()) {
out.namespaces = mn.namespaces;
}
else {
var defaultNS = getDefaultNamespace(sec);
var namespaces = mn.namespaces;
var containsDefaultNS = false;
for (var i = 0; i < namespaces.length; i++) {
var ns = namespaces[i];
if (ns.uri === defaultNS.uri && ns.prefix === defaultNS.prefix &&
ns.type === defaultNS.type) {
containsDefaultNS = true;
break;
}
}
if (!containsDefaultNS) {
out.namespaces = mn.namespaces.concat(defaultNS);
}
else {
out.namespaces = mn.namespaces;
}
}
}
var name = mn.name;
if (mn.isAnyName() || name === '*' || name === null) {
out.name = null;
}
else if (name.length > 1 && name[0] === '@') {
if (!out.isAttribute()) {
if (name === '@*') {
out.name = null;
}
else {
out.name = name.substr(1);
}
out.kind = out.namespaces.length === 1 ? 13 /* CONSTANT.QNameA */ : 14 /* CONSTANT.MultinameA */;
}
else {
out.name = name;
}
}
else {
out.name = name;
}
return out;
}
// 12.1 GetDefaultNamespace
function getDefaultNamespace(sec) {
var scope = getCurrentScope();
while (scope) {
if (scope.defaultNamespace) {
return scope.defaultNamespace;
}
scope = scope.parent;
}
if (!sec.AXNamespace.defaultNamespace) {
sec.AXNamespace.defaultNamespace = new Namespace(0 /* NamespaceType.Public */, 'default', '');
}
// The outermost default xml namespace is stored in sec.AXNamespace.defaultNamespace.
return sec.AXNamespace.defaultNamespace;
}
/**
* 13.3.5.4 [[GetNamespace]] ( [ InScopeNamespaces ] )
*
* The [[GetNamespace]] method is an internal method that returns a Namespace object with a URI
* matching the URI of this QName. InScopeNamespaces is an optional parameter. If
* InScopeNamespaces is unspecified, it is set to the empty set. If one or more Namespaces
* exists in InScopeNamespaces with a URI matching the URI of this QName, one of the matching
* Namespaces will be returned. If no such namespace exists in InScopeNamespaces,
* [[GetNamespace]] creates and returns a new Namespace with a URI matching that of this QName.
* For implementations that preserve prefixes in QNames, [[GetNamespace]] may return a
* Namespace that also has a matching prefix. The input argument InScopeNamespaces is a set of
* Namespace objects.
*/
function GetNamespace(mn, inScopeNamespaces) {
release || assert(mn.isQName());
var uri = mn.uri;
for (var i = 0; inScopeNamespaces && i < inScopeNamespaces.length; i++) {
if (uri === inScopeNamespaces[i].uri) {
return inScopeNamespaces[i];
}
}
return mn.namespaces[0];
}
// 13.1.2.1 isXMLName ( value )
export function isXMLName(v, sec) {
try {
sec.AXQName.Create(v);
}
catch (e) {
return false;
}
// FIXME scan v to see if it is a valid lexeme and return false if not
return true;
}
var tmpMultiname = new Multiname(null, 0, 7 /* CONSTANT.QName */, [], null, null, true);
var anyMultiname = new Multiname(null, 0, 7 /* CONSTANT.QName */, [], null, null, true);
release || Object.seal(anyMultiname);
var XMLParserBase = /** @class */ (function () {
function XMLParserBase() {
}
XMLParserBase.prototype.resolveEntities = function (s) {
return s.replace(/&([^;]+);/g, function (all, entity) {
if (entity.substring(0, 2) === '#x') {
return String.fromCharCode(parseInt(entity.substring(2), 16));
}
else if (entity.substring(0, 1) === '#') {
return String.fromCharCode(parseInt(entity.substring(1), 10));
}
switch (entity) {
case 'lt':
return '<';
case 'gt':
return '>';
case 'amp':
return '&';
case 'quot':
return '"';
}
// throw "Unknown entity: " + entity;
return all;
});
};
XMLParserBase.prototype.parseContent = function (s, start) {
var pos = start;
var attributes = [];
function skipWs() {
while (pos < s.length && isWhitespace(s, pos)) {
++pos;
}
}
while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '>' && s[pos] !== '/') {
++pos;
}
var name = s.substring(start, pos);
skipWs();
while (pos < s.length &&
s[pos] !== '>' &&
s[pos] !== '/' &&
s[pos] !== '?') {
skipWs();
var attrName = '', attrValue = '';
while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '=') {
attrName += s[pos];
++pos;
}
skipWs();
if (s[pos] !== '=') {
return null;
}
++pos;
skipWs();
var attrEndChar = s[pos];
if (attrEndChar !== '"' && attrEndChar !== '\'') {
return null;
}
var attrEndIndex = s.indexOf(attrEndChar, ++pos);
if (attrEndIndex < 0) {
return null;
}
attrValue = s.substring(pos, attrEndIndex);
attributes.push({ name: attrName, value: this.resolveEntities(attrValue) });
pos = attrEndIndex + 1;
skipWs();
}
return { name: name, attributes: attributes, parsed: pos - start };
};
XMLParserBase.prototype.parseProcessingInstruction = function (s, start) {
var pos = start;
function skipWs() {
while (pos < s.length && isWhitespace(s, pos)) {
++pos;
}
}
while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '>' && s[pos] !== '/') {
++pos;
}
var name = s.substring(start, pos);
skipWs();
var attrStart = pos;
while (pos < s.length && (s[pos] !== '?' || s[pos + 1] != '>')) {
++pos;
}
var value = s.substring(attrStart, pos);
return { name: name, value: value, parsed: pos - start };
};
XMLParserBase.prototype.parseXml = function (s) {
var i = 0;
while (i < s.length) {
var ch = s[i];
var j = i;
if (ch === '<') {
++j;
var ch2 = s[j];
var q = void 0;
switch (ch2) {
case '/':
++j;
q = s.indexOf('>', j);
if (q < 0) {
this.onError(-9 /* XMLParserErrorCode.UnterminatedElement */);
return;
}
this.onEndElement(s.substring(j, q));
j = q + 1;
break;
case '?': {
++j;
var pi = this.parseProcessingInstruction(s, j);
if (s.substring(j + pi.parsed, j + pi.parsed + 2) != '?>') {
this.onError(-3 /* XMLParserErrorCode.UnterminatedXmlDeclaration */);
return;
}
this.onPi(pi.name, pi.value);
j += pi.parsed + 2;
break;
}
case '!':
if (s.substring(j + 1, j + 3) === '--') {
q = s.indexOf('-->', j + 3);
if (q < 0) {
this.onError(-5 /* XMLParserErrorCode.UnterminatedComment */);
return;
}
this.onComment(s.substring(j + 3, q));
j = q + 3;
}
else if (s.substring(j + 1, j + 8) === '[CDATA[') {
q = s.indexOf(']]>', j + 8);
if (q < 0) {
this.onError(-2 /* XMLParserErrorCode.UnterminatedCdat */);
return;
}
this.onCdata(s.substring(j + 8, q));
j = q + 3;
}
else if (s.substring(j + 1, j + 8) === 'DOCTYPE') {
var q2 = s.indexOf('[', j + 8);
var complexDoctype = false;
q = s.indexOf('>', j + 8);
if (q < 0) {
this.onError(-4 /* XMLParserErrorCode.UnterminatedDoctypeDeclaration */);
return;
}
if (q2 > 0 && q > q2) {
q = s.indexOf(']>', j + 8);
if (q < 0) {
this.onError(-4 /* XMLParserErrorCode.UnterminatedDoctypeDeclaration */);
return;
}
complexDoctype = true;
}
var doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0));
this.onDoctype(doctypeContent);
// XXX pull entities ?
j = q + (complexDoctype ? 2 : 1);
}
else {
this.onError(-6 /* XMLParserErrorCode.MalformedElement */);
return;
}
break;
default: {
var content = this.parseContent(s, j);
if (content === null) {
this.onError(-6 /* XMLParserErrorCode.MalformedElement */);
return;
}
var isClosed = false;
if (s.substring(j + content.parsed, j + content.parsed + 2) === '/>') {
isClosed = true;
}
else if (s.substring(j + content.parsed, j + content.parsed + 1) !== '>') {
this.onError(-9 /* XMLParserErrorCode.UnterminatedElement */);
return;
}
this.onBeginElement(content.name, content.attributes, isClosed);
j += content.parsed + (isClosed ? 2 : 1);
break;
}
}
}
else {
do {
//
} while (j++ < s.length && s[j] !== '<');
var text = s.substring(i, j);
this.onText(this.resolveEntities(text));
}
i = j;
}
};
XMLParserBase.prototype.onPi = function (_name, _value) {
};
XMLParserBase.prototype.onComment = function (_text) {
};
XMLParserBase.prototype.onCdata = function (_text) {
};
XMLParserBase.prototype.onDoctype = function (_doctypeContent) {
};
XMLParserBase.prototype.onText = function (_text) {
};
XMLParserBase.prototype.onBeginElement = function (_name, _attributes, _isEmpty) {
};
XMLParserBase.prototype.onEndElement = function (_name) {
};
XMLParserBase.prototype.onError = function (_code) {
};
return XMLParserBase;
}());
export { XMLParserBase };
var XMLParser = /** @class */ (function (_super) {
__extends(XMLParser, _super);
function XMLParser(sec) {
var _this = _super.call(this) || this;
_this.sec = sec;
_this.scopes = [];
return _this;
}
XMLParser.prototype.isWhitespacePreserved = function () {
var scopes = this.scopes;
for (var j = scopes.length - 1; j >= 0; --j) {
if (scopes[j].space === 'preserve') {
return true;
}
}
return false;
};
XMLParser.prototype.lookupDefaultNs = function () {
var scopes = this.scopes;
for (var j = scopes.length - 1; j >= 0; --j) {
if ('xmlns' in scopes[j]) {
return scopes[j].xmlns;
}
}
return '';
};
XMLParser.prototype.lookupNs = function (prefix) {
var scopes = this.scopes;
for (var j = scopes.length - 1; j >= 0; --j) {
if (prefix in scopes[j].lookup) {
return scopes[j].lookup[prefix];
}
}
return undefined;
};
XMLParser.prototype.getName = function (name, resolveDefaultNs) {
var j = name.indexOf(':');
if (j >= 0) {
var prefix = name.substring(0, j);
var localName = name.substring(j + 1);
var namespace = this.lookupNs(prefix);
if (namespace === undefined) {
this.sec.throwError('TypeError', Errors.XMLPrefixNotBound, prefix, localName);
}
return {
name: namespace + '::' + localName,
localName: localName,
prefix: prefix,
namespace: namespace,
};
}
else if (resolveDefaultNs) {
return {
name: name,
localName: name,
prefix: '',
namespace: this.lookupDefaultNs()
};
}
else {
return {
name: name,
localName: name,
prefix: '',
namespace: ''
};
}
};
XMLParser.prototype.onError = function (code) {
switch (code) {
case -6 /* XMLParserErrorCode.MalformedElement */:
this.sec.throwError('TypeError', Errors.XMLMalformedElement);
return;
case -9 /* XMLParserErrorCode.UnterminatedElement */:
this.sec.throwError('TypeError', Errors.XMLUnterminatedElement);
return;
case -4 /* XMLParserErrorCode.UnterminatedDoctypeDeclaration */:
this.sec.throwError('TypeError', Errors.XMLUnterminatedDocTypeDecl);
return;
case -2 /* XMLParserErrorCode.UnterminatedCdat */:
this.sec.throwError('TypeError', Errors.XMLUnterminatedCData);
return;
case -5 /* XMLParserErrorCode.UnterminatedComment */:
this.sec.throwError('TypeError', Errors.XMLUnterminatedComment);
return;
case -3 /* XMLParserErrorCode.UnterminatedXmlDeclaration */:
this.sec.throwError('TypeError', Errors.XMLUnterminatedXMLDecl);
return;
}
};
XMLParser.prototype.onPi = function (name, value) {
this.pi(name, value);
};
XMLParser.prototype.onComment = function (text) {
this.comment(text);
};
XMLParser.prototype.onCdata = function (text) {
this.cdata(text);
};
XMLParser.prototype.onDoctype = function (doctypeContent) {
this.doctype(doctypeContent);
};
XMLParser.prototype.onText = function (text) {
this.text(text, this.isWhitespacePreserved());
};
XMLParser.prototype.onBeginElement = function (name, contentAttributes, isEmpty) {
var scopes = this.scopes;
var scope = {
namespaces: [],
lookup: Object.create(null),
inScopes: null
};
for (var q = 0; q < contentAttributes.length; ++q) {
var attribute = contentAttributes[q];
var attributeName = attribute.name;
if (attributeName.substring(0, 6) === 'xmlns:') {
var prefix = attributeName.substring(6);
var uri = attribute.value;
if (this.lookupNs(prefix) !== uri) {
scope.lookup[prefix] = trimWhitespaces(uri);
var ns = internPrefixedNamespace(0 /* NamespaceType.Public */, uri, prefix);
scope.namespaces.push(ns);
}
contentAttributes[q] = null;
}
else if (attributeName === 'xmlns') {
var uri = attribute.value;
if (this.lookupDefaultNs() !== uri) {
scope['xmlns'] = trimWhitespaces(uri);
var ns = internNamespace(0 /* NamespaceType.Public */, uri);
scope.namespaces.push(ns);
}
contentAttributes[q] = null;
}
else if (attributeName.substring(0, 4) === 'xml:') {
var xmlAttrName = attributeName.substring(4);
scope[xmlAttrName] = trimWhitespaces(attribute.value);
}
else {
// skip ordinary attributes until all xmlns have been handled
}
}
// build list of all namespaces including ancestors'
var inScopeNamespaces = [];
scope.namespaces.forEach(function (ns) {
if (!ns.prefix || scope.lookup[ns.prefix] === ns.uri) {
inScopeNamespaces.push(ns);
}
});
scopes[scopes.length - 1].inScopes.forEach(function (ns) {
if ((ns.prefix && !(ns.prefix in scope.lookup)) ||
(!ns.prefix && !('xmlns' in scope))) {
inScopeNamespaces.push(ns);
}
});
scope.inScopes = inScopeNamespaces;
scopes.push(scope);
var attributes = [];
for (var q = 0; q < contentAttributes.length; ++q) {
var attribute = contentAttributes[q];
if (attribute) {
attributes.push({
name: this.getName(attribute.name, false),
value: attribute.value
});
}
}
this.beginElement(this.getName(name, true), attributes, inScopeNamespaces, isEmpty);
if (isEmpty) {
scopes.pop();
}
};
XMLParser.prototype.onEndElement = function (name) {
this.endElement(this.getName(name, true));
this.scopes.pop();
};
XMLParser.prototype.beginElement = function (name, attrs, namespaces, isEmpty) {
var parent = this.currentElement;
this.elementsStack.push(parent);
this.currentElement = createXML(this.sec, 1 /* ASXMLKind.Element */, name.namespace, name.localName, name.prefix);
for (var i = 0; i < attrs.length; ++i) {
var rawAttr = attrs[i];
var attr = createXML(this.sec, 2 /* ASXMLKind.Attribute */, rawAttr.name.namespace, rawAttr.name.localName, rawAttr.name.prefix);
attr._value = rawAttr.value;
attr._parent = this.currentElement;
this.currentElement._attributes.push(attr);
}
for (var i = 0; i < namespaces.length; ++i) {
this.currentElement._inScopeNamespaces.push(namespaces[i]);
}
parent.insert(parent._children.length, this.currentElement);
if (isEmpty) {
this.currentElement = this.elementsStack.pop();
}
};
XMLParser.prototype.endElement = function (_name) {
this.currentElement = this.elementsStack.pop();
};
XMLParser.prototype.text = function (text, isWhitespacePreserve) {
if (this.sec.AXXML.ignoreWhitespace) {
text = trimWhitespaces(text);
}
// TODO: do an in-depth analysis of what isWhitespacePreserve is about.
if (text.length === 0 || isWhitespacePreserve && this.sec.AXXML.ignoreWhitespace) {
return;
}
var node = createXML(this.sec);
node._value = text;
this.currentElement.insert(this.currentElement._children.length, node);
};
XMLParser.prototype.cdata = function (text) {
var node = createXML(this.sec);
node._value = text;
this.currentElement.insert(this.currentElement._children.length, node);
};
XMLParser.prototype.comment = function (text) {
if (this.sec.AXXML.ignoreComments) {
return;
}
var node = createXML(this.sec, 4 /* ASXMLKind.Comment */, '', '');
node._value = text;
this.currentElement.insert(this.currentElement._children.length, node);
};
XMLParser.prototype.pi = function (name, value) {
if (this.sec.AXXML.ignoreProcessingInstructions) {
return;
}
var node = createXML(this.sec, 5 /* ASXMLKind.ProcessingInstruction */, '', name);
node._value = value;
this.currentElement.insert(this.currentElement._children.length, node);
};
XMLParser.prototype.doctype = function (_text) { };
XMLParser.prototype.parseFromString = function (s, _mimeType) {
// placeholder
var currentElement = this.currentElement = createXML(this.sec, 1 /* ASXMLKind.Element */, '', '', '');
this.elementsStack = [];
var defaultNs = getDefaultNamespace(this.sec);
var scopes = [{
namespaces: [],
lookup: {
'xmlns': 'http://www.w3.org/2000/xmlns/',
'xml': 'http://www.w3.org/XML/1998/namespace'
},
inScopes: [defaultNs],
space: 'default',
xmlns: defaultNs.uri
}];
this.scopes = scopes;
this.parseXml(s);
this.currentElement = null;
if (this.elementsStack.length > 0) {
var nm = this.elementsStack.pop()._name.name;
this.sec.throwError('TypeError', Errors.XMLUnterminatedElementTag, nm, nm);
}
this.elementsStack = null;
return currentElement;
};
return XMLParser;
}(XMLParserBase));
export { XMLParser };
var ASNamespace = /** @class */ (function (_super) {
__extends(ASNamespace, _super);
/**
* 13.2.2 The Namespace Constructor
*
* Namespace ()
* Namespace (uriValue)
* Namespace (prefixValue, uriValue)
*/
function ASNamespace(uriOrPrefix_, uri_) {
var _this = _super.call(this) || this;
// 1. Create a new Namespace object n
var uri = '';
var prefix = '';
// 2. If prefixValue is not specified and uriValue is not specified
/*
if (arguments.length === 0) {
// a. Let n.prefix be the empty string
// b. Let n.uri be the empty string
}
// 3. Else if prefixValue is not specified
else
*/
if (arguments.length === 1) {
var uriValue = uriOrPrefix_;
if (uriValue instanceof Namespace) {
_this._ns = uriValue;
return _this;
}
release || checkValue(uriValue);
if (uriValue && typeof uriValue === 'object') {
// Non-spec'ed, but very useful:
// a. If Type(uriValue) is Object and uriValue.[[Class]] == "Namespace"
if (uriValue.axClass === _this.sec.AXNamespace) {
var uriValueAsNamespace = uriValue;
// i. Let n.prefix = uriValue.prefix
prefix = uriValueAsNamespace.prefix;
uri = uriValueAsNamespace.uri;
// b. Else if Type(uriValue) is Object and uriValue.[[Class]] == "QName" and uriValue.uri
// is not null
}
else if (uriValue.axClass === _this.sec.AXQName &&
uriValue.uri !== null) {
// i. Let n.uri = uriValue.uri
uri = uriValue.uri;
// NOTE implementations that preserve prefixes in qualified names may also set n.prefix
// = uriValue.[[Prefix]]
}
}
else { // c. Else
// i. Let n.uri = ToString(uriValue)
uri = toString(uriValue, _this.sec);
// ii. If (n.uri is the empty string), let n.prefix be the empty string
if (uri === '') {
prefix = '';
}
else { // iii. Else n.prefix = undefined
prefix = undefined;
}
}
}
else { // 4. Else
var prefixValue = uriOrPrefix_;
var uriValue = uri_;
// a. If Type(uriValue) is Object and uriValue.[[Class]] == "QName" and uriValue.uri is not
// null
if (isObject(uriValue) &&
uriValue.axClass === _this.sec.AXQName &&
uriValue.uri !== null) {
// i. Let n.uri = uriValue.uri
uri = uriValue.uri;
}
else { // b. Else
// i. Let n.uri = ToString(uriValue)
uri = toString(uriValue, _this.sec);
}
// c. If n.uri is the empty string
if (uri === '') {
// i. If prefixValue is undefined or ToString(prefixValue) is the empty string
if (prefixValue === undefined || toString(prefixValue, _this.sec) === '') {
// 1. Let n.prefix be the empty string
prefix = '';
}
else {
// ii. Else throw a TypeError exception
_this.sec.throwError('TypeError', Errors.XMLNamespaceWithPrefixAndNoURI, prefixValue);
}
// d. Else if prefixValue is undefined, let n.prefix = undefined
}
else if (prefixValue === undefined) {
prefix = undefined;
// e. Else if isXMLName(prefixValue) == false
}
else if (isXMLName(prefixValue, _this.sec) === false) {
// i. Let n.prefix = undefined
prefix = undefined;
// f. Else let n.prefix = ToString(prefixValue)
}
else {
prefix = toString(prefixValue, _this.sec);
}
}
// 5. Return n
_this._ns = internPrefixedNamespace(0 /* NamespaceType.Public */, uri, prefix);
return _this;
}
ASNamespace.classInitializer = function () {
defineNonEnumerableProperty(this, '$Bglength', 2);
var proto = this.dPrototype;
var asProto = ASNamespace.prototype;
defineNonEnumerableProperty(proto, '$BgtoString', asProto.toString);
};
/**
* 13.2.1 The Namespace Constructor Called as a Function
*
* Namespace ()
* Namespace (uriValue)
* Namespace (prefixValue, uriValue)
*/
ASNamespace.axApply = function (_self, args) {
var a = args[0];
var b = args[1];
// 1. If (prefixValue is not specified and Type(uriValue) is Object and
// uriValue.[[Class]] == "Namespace")
if (args.length === 1 && isObject(a) && a.axClass === this.sec.AXNamespace) {
// a. Return uriValue
return a;
}
// 2. Create and return a new Namespace object exactly as if the Namespace constructor had
// been called with the same arguments (section 13.2.2).
switch (args.length) {
case 0:
return this.sec.AXNamespace.Create();
case 1:
return this.sec.AXNamespace.Create(a);
default:
return this.sec.AXNamespace.Create(a, b);
}
};
ASNamespace.Create = function (_uriOrPrefix_, _uri_) {
var ns = Object.create(this.sec.AXNamespace.tPrototype);
// The initializer relies on arguments.length being correct.
// eslint-disable-next-line prefer-spread, prefer-rest-params
ns.axInitializer.apply(ns, arguments);
return ns;
};
ASNamespace.FromNamespace = function (ns) {
var result = Object.create(this.sec.AXNamespace.tPrototype);
result._ns = ns;
return result;
};
// E4X 11.5.1 The Abstract Equality Comparison Algorithm, step 3.c.
ASNamespace.prototype.equals = function (other) {
return other && other.axClass === this.axClass &&
other._ns.uri === this._ns.uri ||
typeof other === 'string' && this._ns.uri === other;
};
Object.defineProperty(ASNamespace.prototype, "prefix", {
get: function () {
return this._ns.prefix;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ASNamespace.prototype, "uri", {
get: function () {
return this._ns.uri;
},
enumerable: false,
configurable: true
});
ASNamespace.prototype.toString = function () {
if (this === this.axClass.dPrototype) {
return '';
}
return this._ns.uri;
};
ASNamespace.prototype.valueOf = function () {
if (this === this.axClass.dPrototype) {
return '';
}
return this._ns.uri;
};
ASNamespace.instanceConstructor = ASNamespace;
ASNamespace.defaultNamespace = Namespace.PUBLIC;
return ASNamespace;
}(ASObject));
export { ASNamespace };
var ASQName = /** @class */ (function (_super) {
__extends(ASQName, _super);
/**
* 13.3.2 The QName Constructor
*
* new QName ()
* new QName (Name)
* new QName (Namespace, Name)
*/
function ASQName(nameOrNS_, name_) {
var _this = _super.call(this) || this;
var name;
var namespace;
if (arguments.length === 0) {
name = '';
}
else if (arguments.length === 1) {
name = nameOrNS_;
}
else { // if (arguments.length === 2) {
namespace = nameOrNS_;
name = name_;
}
// 1. If (Type(Name) is Object and Name.[[Class]] == "QName")
if (name && name.axClass === _this.sec.AXQName) {
// a. If (Namespace is not specified), return a copy of Name
if (arguments.length < 2) {
release || assert(name !== tmpMultiname);
_this.name = name.name;
return _this;
// b. Else let Name = Name.localName
}
else {
name = name.localName;
}
}
// 2. If (Name is undefined or not specified)
if (name === undefined) {
// a. Let Name = ""
name = '';
// 3. Else let Name = ToString(Name)
}
else {
name = toString(name, _this.sec);
}
// 4. If (Namespace is undefined or not specified)
if (namespace === undefined) {
// a. If Name = "*"
if (name === '*') {
// i. Let Namespace = null
namespace = null;
}
else { // b. Else
// i. Let Namespace = GetDefaultNamespace()
namespace = getDefaultNamespace(_this.sec);
}
}
// 5. Let q be a new QName with q.localName = Name
var localName = name;
var ns = null;
// 6. If Namespace == null
if (namespace !== null) {
// a. Let Namespace be a new Namespace created as if by calling the constructor new
// Namespace(Namespace)
if (namespace.axClass !== _this.sec.AXNamespace) {
namespace = _this.sec.AXNamespace.Create(namespace);
}
ns = namespace._ns;
//// b. Let q.uri = Namespace.uri
//uri = namespace.uri;
// NOTE implementations that preserve prefixes in qualified names may also set
// q.[[Prefix]] to Namespace.prefix
//} else {
// a. Let q.uri = null
// NOTE implementations that preserve prefixes in qualified names may also set q.[[Prefix]]
// to undefined
//uri = null;
}
// 8. Return q
_this.name = new Multiname(null, 0, 7 /* CONSTANT.QName */, [ns], localName);
return _this;
}
ASQName.classInitializer = function () {
defineNonEnumerableProperty(this, '$Bglength', 2);
var proto = this.dPrototype;
var asProto = ASQName.prototype;
defineNonEnumerableProperty(proto, '$BgtoString', asProto.ecmaToString);
};
ASQName.Create = function (_nameOrNS_, _name_, _isAttribute) {
var name = Object.create(this.sec.AXQName.tPrototype);
// The initializer relies on arguments.length being correct.
// eslint-disable-next-line prefer-spread, prefer-rest-params
name.axInitializer.apply(name, arguments);
return name;
};
ASQName.FromMultiname = function (mn) {
var name = Object.create(this.sec.AXQName.tPrototype);
name.name = mn;
return name;
};
/**
* 13.3.1 The QName Constructor Called as a Function
*
* QName ( )
* QName ( Name )
* QName ( Namespace , Name )
*/
ASQName.axApply = function (_self, args) {
var nameOrNS_ = args[0];
var name_ = args[1];
// 1. If Namespace is not specified and Type(Name) is Object and Name.[[Class]] == “QName”
if (args.length === 1 && nameOrNS_ && nameOrNS_.axClass === this.sec.AXQName) {
// a. Return Name
return nameOrNS_;
}
// 2. Create and return a new QName object exactly as if the QName constructor had been
// called with the same arguments (section 13.3.2).
switch (args.length) {
case 0:
return this.sec.AXQName.Create();
case 1:
return this.sec.AXQName.Create(nameOrNS_);
default:
return this.sec.AXQName.Create(nameOrNS_, name_);
}
};
// E4X 11.5.1 The Abstract Equality Comparison Algorithm, step 3.b.
ASQName.prototype.equals = function (other) {
return other && other.axClass === this.sec.AXQName &&
other.uri === this.uri && other.name.name === this.name.name ||
typeof other === 'string' && this.toString() === other;
};
Object.defineProperty(ASQName.prototype, "localName", {
get: function () {
return this.name.name != '' ? this.name.name : null;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ASQName.prototype, "uri", {
get: function () {
var namespaces = this.name.namespaces;
return namespaces.length > 1 ? '' : namespaces[0] ? namespaces[0].uri : null;
},
enumerable: false,
configurable: true
});
ASQName.prototype.ecmaToString = function () {
if (this && this === this.sec.AXQName.dPrototype) {
return '';
}
if (!(this && this.axClass === this.sec.AXQName)) {
this.sec.throwError('TypeError', Errors.InvokeOnIncompatibleObjectError, 'QName.prototype.toString');
}
return this.toString();
};
ASQName.prototype.toString = function () {
var uri = this.uri;
if (uri === '') {
return this.name.name;
}
if (uri === null) {
return '*::' + this.name.name;
}
uri = uri + '';
var cc = uri.charCodeAt(uri.length - 1);
// strip the version mark, if there is one
var base_uri = uri;
if (cc >= 0xE000 && cc <= 0xF8FF) {
base_uri = uri.substr(0, uri.length - 1);
}
if (base_uri === '') {
return this.name.name;
}
// causes issues in nitrome-games:
// return base_uri + "::" + this.name.name;
return this.name.name;
};
ASQName.prototype.valueOf = function () {
return this;
};
Object.defineProperty(ASQName.prototype, "prefix", {
/**
* 13.3.5.3 [[Prefix]]
* The [[Prefix]] property is an optional internal property that is not directly visible to
* users. It may be used by implementations that preserve prefixes in qualified names. The
* value of the [[Prefix]] property is a value of type string or undefined. If the [[Prefix]]
* property is undefined, the prefix associated with this QName is unknown.
*/
get: function () {
return this.name.namespaces[0] ? this.name.namespaces[0].prefix : null;
},
enumerable: false,
configurable: true
});
return ASQName;
}(ASObject));
export { ASQName };
var ASXML_FLAGS;
(function (ASXML_FLAGS) {
ASXML_FLAGS[ASXML_FLAGS["FLAG_IGNORE_COMMENTS"] = 1] = "FLAG_IGNORE_COMMENTS";
ASXML_FLAGS[ASXML_FLAGS["FLAG_IGNORE_PROCESSING_INSTRUCTIONS"] = 2] = "FLAG_IGNORE_PROCESSING_INSTRUCTIONS";
ASXML_FLAGS[ASXML_FLAGS["FLAG_IGNORE_WHITESPACE"] = 4] = "FLAG_IGNORE_WHITESPACE";
ASXML_FLAGS[ASXML_FLAGS["FLAG_PRETTY_PRINTING"] = 8] = "FLAG_PRETTY_PRINTING";
ASXML_FLAGS[ASXML_FLAGS["ALL"] = 15] = "ALL";
})(ASXML_FLAGS || (ASXML_FLAGS = {}));
var ASXMLKindNames = [null, 'element', 'attribute', 'text', 'comment', 'processing-instruction'];
var ASXML = /** @class */ (function (_super) {
__extends(ASXML, _super);
function ASXML(value) {
var _this = _super.call(this) || this;
_this._parent = null;
if (isNullOrUndefined(value)) {
value = '';
}
if (typeof value === 'string' && value.length === 0) {
_this._kind = 3 /* ASXMLKind.Text */;
_this._value = '';
return _this;
}
var x = toXML(value, _this.