feat: Scoped Packages (#7911)

* chore: move tns-core-modules to nativescript-core

* chore: preparing compat generate script

* chore: add missing definitions

* chore: no need for http-request to be private

* chore: packages chore

* test: generate tests for tns-core-modules

* chore: add anroid module for consistency

* chore: add .npmignore

* chore: added privateModulesWhitelist

* chore(webpack): added bundle-entry-points

* chore: scripts

* chore: tests changed to use @ns/core

* test: add scoped-packages test project

* test: fix types

* test: update test project

* chore: build scripts

* chore: update build script

* chore: npm scripts cleanup

* chore: make the compat pgk work with old wp config

* test: generate diff friendly tests

* chore: create barrel exports

* chore: move files after rebase

* chore: typedoc config

* chore: compat mode

* chore: review of barrels

* chore: remove tns-core-modules import after rebase

* chore: dev workflow setup

* chore: update developer-workflow

* docs: experiment with API extractor

* chore: api-extractor and barrel exports

* chore: api-extractor configs

* chore: generate d.ts rollup with api-extractor

* refactor: move methods inside Frame

* chore: fic tests to use Frame static methods

* refactor: create Builder class

* refactor: use Builder class in tests

* refactor: include Style in ui barrel

* chore: separate compat build script

* chore: fix tslint errors

* chore: update NATIVESCRIPT_CORE_ARGS

* chore: fix compat pack

* chore: fix ui-test-app build with linked modules

* chore: Application, ApplicationSettings, Connectivity and Http

* chore: export Trace, Profiling and Utils

* refactor: Static create methods for ImageSource

* chore: fix deprecated usages of ImageSource

* chore: move Span and FormattedString to ui

* chore: add events-args and ImageSource to index files

* chore: check for CLI >= 6.2 when building for IOS

* chore: update travis build

* chore: copy Pod file to compat package

* chore: update error msg ui-tests-app

* refactor: Apply suggestions from code review

Co-Authored-By: Martin Yankov <m.i.yankov@gmail.com>

* chore: typings and refs

* chore: add missing d.ts files for public API

* chore: adress code review FB

* chore: update api-report

* chore: dev-workflow for other apps

* chore: api update

* chore: update api-report
This commit is contained in:
Alexander Vakrilov
2019-10-17 00:45:33 +03:00
committed by GitHub
parent 6c7139477e
commit cc97a16800
880 changed files with 9090 additions and 2104 deletions

View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2012 Vopilovskii Constantine <flash.vkv@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,46 @@
EASYSAX - pure javascript sax-style parser for xml
==================================================
Простой и быстрый SAX парсер XML файлов.
Реализован по принципу парсить только то что нужно и как можно быстрее.
Парсер не потоковый, и не расчитан на гиганские файлы. Весь XML должен быть в памяти.
Встроенный уникальный механизм работы с пространсвами имен.
Парсер был написан для RSS ридера http://zzreader.com
На конец 2012 года остается самым быстрым SAX парсером под NODE.JS
BENCHMARK
---------------------------------------------------
**benchmark/test.js, parse file #1**
```
sax-js: 12671ms
libxmljs: 11311ms
expat: 6118ms
expat buffer: 5278ms
easysax : 1739ms // namespace--on, attr()--on , entity_decode--on
easysax: 1035ms // namespace--off, attr()--on , entity_decode--on
easysax: 740ms // namespace--off, attr()--off , entity_decode--off
```
**benchmark/test.js, parse file #2 (много атрибутов)**
```
sax-js: 84060ms
libxmljs: 48919ms
expat: 39444ms
expat buffer: 35375ms
easysax: 14655ms // namespace--on, attr()--on , entity_decode--on
easysax: 9874ms // namespace--off, attr()--on , entity_decode--on
easysax: 3531ms // namespace--off, attr()--off , entity_decode--on
easysax: 2954ms // namespace--off, attr()--off , entity_decode--off
```
**demo/example.js, parse file #2**
```
1,000 pages for: 13335ms - attr()--all
1,000 pages for: 7300ms - attr()--on_request
```

View File

@ -0,0 +1,13 @@
/**
* @module "js-libs/easysax"
* @private
*/ /** */
//@private
export class EasySAXParser {
constructor();
parse(xml: string): void;
on(name: string, cb: Function): void;
ns(root: string, ns: any): void;
public angularSyntax: boolean;
}

View File

@ -0,0 +1,782 @@
 /*
new function() {
var parser = new EasySAXParser();
parser.ns('rss', { // or false
rss: 'http://purl.org/rss/1.0/',
atom: 'http://www.w3.org/2005/Atom',
xhtml: 'http://www.w3.org/1999/xhtml',
media: 'http://search.yahoo.com/mrss/'
});
parser.on('error', function(msg) {
//console.log(msg)
});
parser.on('startNode', function(elem, attr, uq, tagend, getStrNode) {
attr();
return;
if (tagend) {
console.log(' '+str)
} else {
console.log('+ '+str)
};
});
parser.on('endNode', function(elem, uq, tagstart, str) {
return;
if (!tagstart) console.log('- ' + str)
});
parser.on('textNode', function(s, uq) {
uq(s);
return
console.log(' '+s)
});
parser.on('cdata', function(data) {
});
parser.on('comment', function(text) {
//console.log('--'+text+'--')
});
//parser.on('question', function() {}); // <? ... ?>
//parser.on('attention', function() {}); // <!XXXXX zzzz="eeee">
console.time('easysax');
for(var z=1000;z--;) {
parser.parse(xml)
};
console.timeEnd('easysax');
};
*/
// << ------------------------------------------------------------------------ >> //
if (typeof exports === 'object' /*&& this == exports*/) {
module.exports.EasySAXParser = EasySAXParser;
};
function EasySAXParser() {
'use strict';
if (!this) return null;
this.angularSyntax = false;
function nullFunc() {};
this.onTextNode = nullFunc;
this.onStartNode = nullFunc;
this.onEndNode = nullFunc;
this.onCDATA = nullFunc;
this.onError = nullFunc;
this.onComment = null;
this.onQuestion = null;
this.onAttention = null;
this.is_onComment = this.is_onQuestion = this.is_onAttention = false;
this.isNamespace = false;
this.useNS = null;
this.default_xmlns = null;
this.xmlns = null;
this.nsmatrix = {xmlns: this.xmlns};
this.hasSurmiseNS = false;
;
this.attr_string = ''; // строка атрибутов
this.attr_posstart = 0; //
this.attr_res; // закешированный результат разбора атрибутов , null - разбор не проводился, object - хеш атрибутов, true - нет атрибутов, false - невалидный xml
}
EasySAXParser.prototype.on = function(name, cb) {
if (typeof cb !== 'function') {
if (cb !== null) return;
};
switch(name) {
case 'error': this.onError = cb || nullFunc; break;
case 'startNode': this.onStartNode = cb || nullFunc; break;
case 'endNode': this.onEndNode = cb || nullFunc; break;
case 'textNode': this.onTextNode = cb || nullFunc; break;
case 'cdata': this.onCDATA = cb || nullFunc; break;
case 'comment': this.onComment = cb; this.is_onComment = !!cb; break;
case 'question': this.onQuestion = cb; this.is_onQuestion = !!cb; break; // <? .... ?>
case 'attention': this.onAttention = cb; this.is_onAttention = !!cb; break; // <!XXXXX zzzz="eeee">
};
};
EasySAXParser.prototype.ns = function(root, ns) {
if (!root || typeof root !== 'string' || !ns) {
return;
};
var u, x = {}, ok, v, i;
for(i in ns) {
v = ns[i];
if (typeof v === 'string') {
if (root === v) ok = true;
x[i] = v;
};
};
if (ok) {
this.isNamespace = true;
this.default_xmlns = root;
this.useNS = x;
};
};
EasySAXParser.prototype.parse = function(xml) {
if (typeof xml !== 'string') {
return;
};
if (this.isNamespace) {
this.nsmatrix = {xmlns: this.default_xmlns};
parse(xml);
this.nsmatrix = false;
} else {
parse(xml);
};
this.attr_res = true;
};
// -----------------------------------------------------
var xharsQuot={constructor: false, hasOwnProperty: false, isPrototypeOf: false, propertyIsEnumerable: false, toLocaleString: false, toString: false, valueOf: false
, quot: '"'
, QUOT: '"'
, amp: '&'
, AMP: '&'
, nbsp: '\u00A0'
, apos: '\''
, lt: '<'
, LT: '<'
, gt: '>'
, GT: '>'
, copy: '\u00A9'
, laquo: '\u00AB'
, raquo: '\u00BB'
, reg: '\u00AE'
, deg: '\u00B0'
, plusmn: '\u00B1'
, sup2: '\u00B2'
, sup3: '\u00B3'
, micro: '\u00B5'
, para: '\u00B6'
};
function rpEntities(s, d, x, z) {
if (z) {
return xharsQuot[z] || '\x01';
};
if (d) {
return String.fromCodePoint(d);
};
return String.fromCodePoint(parseInt(x, 16));
};
function unEntities(s, i) {
s = String(s);
if (s.length > 3 && s.indexOf('&') !== -1) {
if (s.indexOf('&gt;') !== -1) s = s.replace(/&gt;/g, '>');
if (s.indexOf('&lt;') !== -1) s = s.replace(/&lt;/g, '<');
if (s.indexOf('&quot;') !== -1) s = s.replace(/&quot;/g, '"');
if (s.indexOf('&') !== -1) {
s = s.replace(/&#(\d+);|&#x([0123456789abcdef]+);|&(\w+);/ig, rpEntities);
};
};
return s;
};
EasySAXParser.prototype.allowedAngularAttributeChars = function(w) {
if (!this.angularSyntax) {
return false;
} else {
return (
w === 40 || // (
w === 41 || // )
w === 91 || // [
w === 93 || // ]
w === 94 || // ^
w === 35 // #
);
}
};
/*
парсит атрибуты по требованию. Важно! - функция не генерирует исключения.
если была ошибка разбора возврашается false
если атрибутов нет и разбор удачен то возврашается true
если есть атрибуты то возврашается обьект(хеш)
*/
EasySAXParser.prototype.getAttrs = function() {
if (this.attr_res !== null) {
return this.attr_res;
};
/*
if (xxtest !== u && attr_string.indexOf(xxtest) === -1) {
/ *
// для ускорения
if (getAttrs('html').type == 'html') {
...
};
* /
return true;
};
*/
var u
, res = {}
, s = this.attr_string
, i = this.attr_posstart
, l = s.length
, attr_list = this.hasSurmiseNS ? [] : false
, name, value = ''
, ok = false
, noValueAttribute = false
, j, w, nn, n
, hasNewMatrix
, alias, newalias
;
aa:
for(; i < l; i++) {
w = s.charCodeAt(i);
if (w===32 || (w<14 && w > 8) ) { // \f\n\r\t\v
continue
};
// Check for valid attribute start char
if ((w < 65 && !this.allowedAngularAttributeChars(w)) ||
w > 122 || (w > 90 && w < 97 && !this.allowedAngularAttributeChars(w)) ) { // ожидаем символ
return this.attr_res = false; // error. invalid char
};
for(j = i + 1; j < l; j++) { // проверяем все символы имени атрибута
w = s.charCodeAt(j);
if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 95 || w === 46 /* https://github.com/telerik/xPlatCore/issues/179 */) {
if (noValueAttribute) {
j--; //Started next attribute. Get back and break out of the loop.
break;
} else {
continue;
}
};
if (this.allowedAngularAttributeChars(w)) {
continue;
}
if (w === 32 || (w > 8 && w < 14) ) { // \f\n\r\t\v пробел
noValueAttribute = true;
continue;
} else if (w === 61) { // "=" == 61
noValueAttribute = false;
break;
} else {
//console.log('error 2');
if (!noValueAttribute)
return this.attr_res = false; // error. invalid char
};
break;
};
name = s.substring(i, j).trim();
ok = true;
if (name === 'xmlns:xmlns') {
//console.log('error 6')
return this.attr_res = false; // error. invalid name
};
w = s.charCodeAt(j+1);
while (w = s.charCodeAt(j+1)) {
if (w===32 || (w > 8 && w<14) ) { // \f\n\r\t\v пробел
j++;
} else {
break;
}
}
if (!noValueAttribute) {
if (w === 34) { // '"'
j = s.indexOf('"', i = j+2 );
} else {
if (w === 39) {
j = s.indexOf('\'', i = j+2 );
} else { // "'"
return this.attr_res = false; // error. invalid char
};
};
}
if (j === -1) {
//console.log('error 4')
return this.attr_res = false; // error. invalid char
};
if (j+1 < l && !noValueAttribute) {
w = s.charCodeAt(j+1);
if (w > 32 || w < 9 || (w < 32 && w > 13)) {
// error. invalid char
//console.log('error 5')
return this.attr_res = false;
};
};
if (noValueAttribute) {
value = '';
} else {
value = s.substring(i, j);
}
//i = j + 1; // след. семвол уже проверен потому проверять нужно следуюший
i = j; // след. семвол уже проверен потому проверять нужно следуюший
if (this.isNamespace) { //
if (this.hasSurmiseNS) {
// есть подозрение что в атрибутах присутствует xmlns
if (newalias = name === 'xmlns' ? 'xmlns' : name.charCodeAt(0) === 120 && name.substr(0, 6) === 'xmlns:' && name.substr(6) ) {
alias = this.useNS[unEntities(value)];
if (alias) {
if (this.nsmatrix[newalias] !== alias) {
if (!hasNewMatrix) {
hasNewMatrix = true;
nn = {}; for (n in this.nsmatrix) nn[n] = this.nsmatrix[n];
this.nsmatrix = nn;
};
this.nsmatrix[newalias] = alias;
};
} else {
if (this.nsmatrix[newalias]) {
if (!hasNewMatrix) {
hasNewMatrix = true;
nn = {}; for (n in this.nsmatrix) nn[n] = this.nsmatrix[n];
this.nsmatrix = nn;
};
this.nsmatrix[newalias] = false;
};
};
res[name] = value;
continue;
};
attr_list.push(name, value);
continue;
};
w = name.length;
while(--w) {
if (name.charCodeAt(w) === 58) { // ':'
if (w = this.nsmatrix[name.substring(0, w)] ) {
res[w + name.substr(w)] = value;
};
continue aa;
// 'xml:base' ???
};
};
};
res[name] = value;
noValueAttribute = false;
};
if (!ok) {
return this.attr_res = true; // атрибутов нет, ошибок тоже нет
};
if (this.hasSurmiseNS) {
bb:
for (i = 0, l = attr_list.length; i < l; i++) {
name = attr_list[i++];
w = name.length;
while(--w) { // name.indexOf(':')
if (name.charCodeAt(w) === 58) { // ':'
if (w = this.nsmatrix[name.substring(0, w)]) {
res[w + name.substr(w)] = attr_list[i];
};
continue bb;
break;
};
};
res[name] = attr_list[i];
};
};
return this.attr_res = res;
};
// xml - string
EasySAXParser.prototype.parse = function(xml) {
var u
, xml = String(xml)
, nodestack = []
, stacknsmatrix = []
//, string_node
, elem
, tagend = false
, tagstart = false
, j = 0, i = 0, k = 0, len
, x, y, q, w
, xmlns
, stopIndex = 0
, stop // используется при разборе "namespace" . если встретился неизвестное пространство то события не генерируются
, _nsmatrix
, ok
, pos = 0, ln = 0, lnStart = -2, lnEnd = -1
;
len = xml.length;
function getStringNode() {
return xml.substring(i, j+1)
};
function findLineAndColumnFromPos() {
while (lnStart < lnEnd && lnEnd < pos) {
lnStart = lnEnd;
lnEnd = xml.indexOf("\n", lnEnd + 1);
++ln;
}
return { line: ln, column: pos - lnStart };
}
function position(p) {
pos = p;
return findLineAndColumnFromPos;
}
while(j !== -1) {
stop = stopIndex > 0;
if (xml.charCodeAt(j) === 60) { // "<"
i = j;
} else {
i = xml.indexOf('<', j);
};
if (i === -1) { // конец разбора
if (nodestack.length) {
this.onError('end file', position(j));
return;
};
return;
};
if (j !== i && !stop) {
ok = this.onTextNode(xml.substring(j, i), unEntities, position(j));
if (ok === false) return;
};
w = xml.charCodeAt(i+1);
if (w === 33) { // "!"
w = xml.charCodeAt(i+2);
if (w === 91 && xml.substr(i+3, 6) === 'CDATA[') { // 91 == "["
j = xml.indexOf(']]>', i);
if (j === -1) {
this.onError('cdata', position(i));
return;
};
//x = xml.substring(i+9, j);
if (!stop) {
ok = this.onCDATA(xml.substring(i+9, j), false, position(i));
if (ok === false) return;
};
j += 3;
continue;
};
if (w === 45 && xml.charCodeAt(i+3) === 45) { // 45 == "-"
j = xml.indexOf('-->', i);
if (j === -1) {
this.onError('expected -->', position(i));
return;
};
if (this.is_onComment && !stop) {
ok = this.onComment(xml.substring(i+4, j), unEntities, position(i));
if (ok === false) return;
};
j += 3;
continue;
};
j = xml.indexOf('>', i+1);
if (j === -1) {
this.onError('expected ">"', position(i + 1));
return;
};
if (this.is_onAttention && !stop) {
ok = this.onAttention(xml.substring(i, j+1), unEntities, position(i));
if (ok === false) return;
};
j += 1;
continue;
} else {
if (w === 63) { // "?"
j = xml.indexOf('?>', i);
if (j === -1) { // error
this.onError('...?>', position(i));
return;
};
if (this.is_onQuestion) {
ok = this.onQuestion(xml.substring(i, j+2), position(i));
if (ok === false) return;
};
j += 2;
continue;
};
};
var inside=false;
for (k=i,j=-1;k<len;k++) {
var c = xml.charCodeAt(k);
if (!inside) {
if (c === 34) { // '"'
inside = c;
}
else if (c === 39) { // "'"
inside = c;
}
else if (c === 62) { // <
j = k; break;
}
} else {
if (c === inside) { inside = false; }
}
}
if (j == -1) { // error
this.onError('...>', position(i + 1));
return;
};
this.attr_res = true; // атрибутов нет
//if (xml.charCodeAt(i+1) === 47) { // </...
if (w === 47) { // </...
tagstart = false;
tagend = true;
// проверяем что должен быть закрыт тотже тег что и открывался
x = elem = nodestack.pop();
q = i + 2 + x.length;
//console.log()
if (xml.substring(i+2, q) !== x) {
this.onError('close tagname', position(i + 2));
return;
};
// проверим что в закрываюшем теге нет лишнего
for(; q < j; q++) {
w = xml.charCodeAt(q);
if (w===32 || (w > 8 && w<14) ) { // \f\n\r\t\v пробел
continue;
};
this.onError('close tag', position(i + 2));
return;
};
} else {
if (xml.charCodeAt(j-1) === 47) { // .../>
x = elem = xml.substring(i+1, j-1);
tagstart = true;
tagend = true;
} else {
x = elem = xml.substring(i+1, j);
tagstart = true;
tagend = false;
};
if ( !(w > 96 && w < 123 || w > 64 && w <91) ) {
this.onError('first char nodeName', position(i + 1));
return;
};
for(q = 1, y = x.length; q < y; q++) {
w = x.charCodeAt(q);
if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 95 || w === 46 /* https://github.com/telerik/xPlatCore/issues/179 */) {
continue;
};
if (w===32 || (w<14 && w > 8)) { // \f\n\r\t\v пробел
elem = x.substring(0, q)
this.attr_res = null; // возможно есть атирибуты
break;
};
this.onError('invalid nodeName', position(i + 1));
return;
};
if (!tagend) {
nodestack.push(elem);
};
};
if (this.isNamespace) {
if (stop) {
if (tagend) {
if (!tagstart) {
if (--stopIndex === 0) {
this.nsmatrix = stacknsmatrix.pop();
};
};
} else {
stopIndex += 1;
};
j += 1;
continue;
};
_nsmatrix = this.nsmatrix;
if (!tagend) {
stacknsmatrix.push(this.nsmatrix);
if (this.attr_res !== true) {
if (this.hasSurmiseNS = x.indexOf('xmlns', q) !== -1) {
this.attr_string = x;
this.attr_posstart = q;
this.getAttrs();
this.hasSurmiseNS = false;
};
};
};
w = elem.indexOf(':');
if (w !== -1) {
xmlns = this.nsmatrix[elem.substring(0, w)];
elem = elem.substr(w+1);
} else {
xmlns = this.nsmatrix.xmlns;
};
if (!xmlns) {
if (tagend) {
if (tagstart) {
this.nsmatrix = _nsmatrix;
} else {
this.nsmatrix = stacknsmatrix.pop();
};
} else {
stopIndex = 1; // первый элемент для которого не определено пространство имен
this.attr_res = true;
};
j += 1;
continue;
};
elem = xmlns + ':' + elem;
};
//string_node = xml.substring(i, j+1); // текст ноды как есть
if (tagstart) { // is_onStartNode
this.attr_string = x;
this.attr_posstart = q;
var that = this;
ok = this.onStartNode(elem, function() { return that.getAttrs() }, unEntities, tagend
, getStringNode, position(i)
);
if (ok === false) {
return;
};
this.attr_res = true;
};
if (tagend) {
ok = this.onEndNode(elem, unEntities, tagstart
, getStringNode, position(i)
);
if (ok === false) {
return;
};
if (this.isNamespace) {
if (tagstart) {
this.nsmatrix = _nsmatrix;
} else {
this.nsmatrix = stacknsmatrix.pop();
};
};
};
j += 1;
};
};

View File

@ -0,0 +1,34 @@
{
"name": "easysax",
"description": "pure javascript xml parser",
"keywords": [
"xml",
"sax",
"parser",
"pure"
],
"version": "0.1.14",
"main": "easysax",
"types": "easysax.d.ts",
"bugs": {
"url": "https://github.com/vflash/easysax/issues"
},
"author": {
"name": "Vopilovskiy Konstantin",
"email": "flash.vkv@gmail.com",
"url": "http://vflash.ru"
},
"repository": {
"type": "git",
"url": "https://github.com/vflash/easysax"
},
"readme": "EASYSAX - pure javascript sax-style parser for xml\r\n==================================================\r\nПростой и быстрый SAX парсер XML файлов.\r\nРеализован по принципу парсить только то что нужно и как можно быстрее.\r\nПарсер не потоковый, и не расчитан на гиганские файлы. Весь XML должен быть в памяти.\r\nВстроенный уникальный механизм работы с пространсвами имен.\r\n\r\n\r\nПарсер был написан для RSS ридера http://zzreader.com\r\nНа конец 2012 года остается самым быстрым SAX парсером под NODE.JS\r\n\r\n\r\n\r\nBENCHMARK\r\n---------------------------------------------------\r\n\r\n**benchmark/test.js, parse file #1**\r\n```\r\nsax-js: 12671ms\r\nlibxmljs: 11311ms\r\nexpat: 6118ms\r\nexpat buffer: 5278ms\r\neasysax : 1739ms // namespace--on, attr()--on , entity_decode--on\r\neasysax: 1035ms // namespace--off, attr()--on , entity_decode--on\r\neasysax: 740ms // namespace--off, attr()--off , entity_decode--off\r\n```\r\n\r\n\r\n**benchmark/test.js, parse file #2 (много атрибутов)**\r\n```\r\nsax-js: 84060ms\r\nlibxmljs: 48919ms\r\nexpat: 39444ms\r\nexpat buffer: 35375ms\r\neasysax: 14655ms // namespace--on, attr()--on , entity_decode--on\r\neasysax: 9874ms // namespace--off, attr()--on , entity_decode--on\r\neasysax: 3531ms // namespace--off, attr()--off , entity_decode--on\r\neasysax: 2954ms // namespace--off, attr()--off , entity_decode--off\r\n```\r\n\r\n\r\n**demo/example.js, parse file #2**\r\n```\r\n1,000 pages for: 13335ms - attr()--all\r\n1,000 pages for: 7300ms - attr()--on_request\r\n```\n",
"readmeFilename": "README.md",
"homepage": "https://github.com/vflash/easysax",
"_id": "easysax@0.1.14",
"dist": {
"shasum": "ef7f6f92dfbbf68306ec3bfa1c707a9d8d959d1e"
},
"_from": "easysax@",
"_resolved": "https://registry.npmjs.org/easysax/-/easysax-0.1.14.tgz"
}

View File

@ -0,0 +1,19 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,24 @@
**Esprima** ([esprima.org](http://esprima.org), BSD license) is a high performance,
standard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
parser written in ECMAScript (also popularly known as
[JavaScript](http://en.wikipedia.org/wiki/JavaScript>JavaScript)).
Esprima is created and maintained by [Ariya Hidayat](http://twitter.com/ariyahidayat),
with the help of [many contributors](https://github.com/ariya/esprima/contributors).
### Features
- Full support for ECMAScript 5.1 ([ECMA-262](http://www.ecma-international.org/publications/standards/Ecma-262.htm))
- Sensible [syntax tree format](http://esprima.org/doc/index.html#ast) compatible with Mozilla
[Parser AST](https://developer.mozilla.org/en/SpiderMonkey/Parser_API)
- Optional tracking of syntax node location (index-based and line-column)
- Heavily tested (> 700 [unit tests](http://esprima.org/test/) with [full code coverage](http://esprima.org/test/coverage.html))
- [Partial support](http://esprima.org/doc/es6.html) for ECMAScript 6
Esprima serves as a **building block** for some JavaScript
language tools, from [code instrumentation](http://esprima.org/demo/functiontrace.html)
to [editor autocompletion](http://esprima.org/demo/autocomplete.html).
Esprima runs on many popular web browsers, as well as other ECMAScript platforms such as
[Rhino](http://www.mozilla.org/rhino), [Nashorn](http://openjdk.java.net/projects/nashorn/), and [Node.js](https://npmjs.org/package/esprima).
For more information, check the web site [esprima.org](http://esprima.org).

View File

@ -0,0 +1,276 @@
/**
* @module "js-libs/esprima"
*/ /** */
/* tslint:disable */
// Type definitions for Esprima v1.2.0
// Project: http://esprima.org
// Definitions by: teppeis <https://github.com/teppeis/>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
export const version: string;
export function parse(code: string, options?: Options): Syntax.Program;
export function tokenize(code: string, options?: Options): Array<Token>;
export interface Token {
type: string
value: string
}
export interface Options {
loc?: boolean
range?: boolean
raw?: boolean
tokens?: boolean
comment?: boolean
attachComment?: boolean
tolerant?: boolean
source?: boolean
}
export module Syntax {
// Node
interface Node {
type: string
loc?: LineLocation
range?: number[]
leadingComments?: Comment[]
trailingComments?: Comment[]
}
interface LineLocation {
start: Position
end: Position
}
interface Position {
line: number
column: number
}
// Comment
interface Comment extends Node {
value: string
}
// Program
interface Program extends Node {
body: SomeStatement[]
comments?: Comment[]
}
// Function
interface Function extends Node {
id: Identifier // | null
params: Identifier[]
defaults: SomeExpression[]
rest: Identifier // | null
body: BlockStatementOrExpression
generator: boolean
expression: boolean
}
interface BlockStatementOrExpression extends Array<SomeStatement>, BlockStatement, SomeExpression {
body: BlockStatementOrExpression
}
// Statement
interface Statement extends Node {
}
interface EmptyStatement extends Statement {
}
interface BlockStatement extends Statement {
body: SomeStatement[]
}
interface ExpressionStatement extends Statement {
expression: SomeExpression
}
interface IfStatement extends Statement {
test: SomeExpression
consequent: SomeStatement
alternate: SomeStatement
}
interface LabeledStatement extends Statement {
label: Identifier
body: SomeStatement
}
interface BreakStatement extends Statement {
label: Identifier // | null
}
interface ContinueStatement extends Statement {
label: Identifier // | null
}
interface WithStatement extends Statement {
object: SomeExpression
body: SomeStatement
}
interface SwitchStatement extends Statement {
discriminant: SomeExpression
cases: SwitchCase[]
lexical: boolean
}
interface ReturnStatement extends Statement {
argument: SomeExpression // | null
}
interface ThrowStatement extends Statement {
argument: SomeExpression
}
interface TryStatement extends Statement {
block: BlockStatement
handler: CatchClause // | null
guardedHandlers: CatchClause[]
finalizer: BlockStatement // | null
}
interface WhileStatement extends Statement {
test: SomeExpression
body: SomeStatement
}
interface DoWhileStatement extends Statement {
body: SomeStatement
test: SomeExpression
}
interface ForStatement extends Statement {
init: VariableDeclaratorOrExpression // | null
test: SomeExpression // | null
update: SomeExpression // | null
body: SomeStatement
}
interface ForInStatement extends Statement {
left: VariableDeclaratorOrExpression
right: SomeExpression
body: SomeStatement
each: boolean
}
interface VariableDeclaratorOrExpression extends VariableDeclarator, SomeExpression {
}
interface DebuggerStatement extends Statement {
}
interface SomeStatement extends
EmptyStatement, ExpressionStatement, BlockStatement, IfStatement,
LabeledStatement, BreakStatement, ContinueStatement, WithStatement,
SwitchStatement, ReturnStatement, ThrowStatement, TryStatement,
WhileStatement, DoWhileStatement, ForStatement, ForInStatement, DebuggerStatement {
body: SomeStatementOrList
}
interface SomeStatementOrList extends Array<SomeStatement>, SomeStatement {
}
// Declration
interface Declration extends Statement {
}
interface FunctionDeclration extends Declration {
id: Identifier
params: Identifier[] // Pattern
defaults: SomeExpression[]
rest: Identifier
body: BlockStatementOrExpression
generator: boolean
expression: boolean
}
interface VariableDeclaration extends Declration {
declarations: VariableDeclarator[]
kind: string // "var" | "let" | "const"
}
interface VariableDeclarator extends Node {
id: Identifier // Pattern
init: SomeExpression
}
// Expression
interface Expression extends Node { // | Pattern
}
interface SomeExpression extends
ThisExpression, ArrayExpression, ObjectExpression, FunctionExpression,
ArrowFunctionExpression, SequenceExpression, UnaryExpression, BinaryExpression,
AssignmentExpression, UpdateExpression, LogicalExpression, ConditionalExpression,
NewExpression, CallExpression, MemberExpression {
}
interface ThisExpression extends Expression {
}
interface ArrayExpression extends Expression {
elements: SomeExpression[] // [ Expression | null ]
}
interface ObjectExpression extends Expression {
properties: Property[]
}
interface Property extends Node {
key: LiteralOrIdentifier // Literal | Identifier
value: SomeExpression
kind: string // "init" | "get" | "set"
}
interface LiteralOrIdentifier extends Literal, Identifier {
}
interface FunctionExpression extends Function, Expression {
}
interface ArrowFunctionExpression extends Function, Expression {
}
interface SequenceExpression extends Expression {
expressions: SomeExpression[]
}
interface UnaryExpression extends Expression {
operator: string // UnaryOperator
prefix: boolean
argument: SomeExpression
}
interface BinaryExpression extends Expression {
operator: string // BinaryOperator
left: SomeExpression
right: SomeExpression
}
interface AssignmentExpression extends Expression {
operator: string // AssignmentOperator
left: SomeExpression
right: SomeExpression
}
interface UpdateExpression extends Expression {
operator: string // UpdateOperator
argument: SomeExpression
prefix: boolean
}
interface LogicalExpression extends Expression {
operator: string // LogicalOperator
left: SomeExpression
right: SomeExpression
}
interface ConditionalExpression extends Expression {
test: SomeExpression
alternate: SomeExpression
consequent: SomeExpression
}
interface NewExpression extends Expression {
callee: SomeExpression
arguments: SomeExpression[]
}
interface CallExpression extends Expression {
callee: SomeExpression
arguments: SomeExpression[]
}
interface MemberExpression extends Expression {
object: SomeExpression
property: IdentifierOrExpression // Identifier | Expression
computed: boolean
}
interface IdentifierOrExpression extends Identifier, SomeExpression {
}
// Pattern
// interface Pattern extends Node {
// }
// Clauses
interface SwitchCase extends Node {
test: SomeExpression
consequent: SomeStatement[]
}
interface CatchClause extends Node {
param: Identifier // Pattern
guard: SomeExpression
body: BlockStatement
}
// Misc
interface Identifier extends Node, Expression { // | Pattern
name: string
}
interface Literal extends Node, Expression {
value: any // string | boolean | null | number | RegExp
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
{
"name": "esprima",
"description": "ECMAScript parsing infrastructure for multipurpose analysis",
"homepage": "http://esprima.org",
"main": "esprima",
"types": "esprima.d.ts",
"bin": {
"esparse": "./bin/esparse.js",
"esvalidate": "./bin/esvalidate.js"
},
"version": "2.0.0-dev",
"engines": {
"node": ">=0.4.0"
},
"author": {
"name": "Ariya Hidayat",
"email": "ariya.hidayat@gmail.com"
},
"maintainers": [
{
"name": "Ariya Hidayat",
"email": "ariya.hidayat@gmail.com",
"web": "http://ariya.ofilabs.com"
}
],
"repository": {
"type": "git",
"url": "https://github.com/ariya/esprima.git"
},
"bugs": {
"url": "http://issues.esprima.org"
},
"licenses": [
{
"type": "BSD",
"url": "https://github.com/ariya/esprima/raw/master/LICENSE.BSD"
}
],
"devDependencies": {
"jslint": "~0.1.9",
"eslint": "~5.16.0",
"jscs": "~1.2.4",
"istanbul": "~0.2.6",
"complexity-report": "~0.6.1",
"regenerate": "~0.6.2",
"unicode-7.0.0": "~0.1.5",
"json-diff": "~0.3.1",
"optimist": "~0.6.0"
},
"keywords": [
"ast",
"ecmascript",
"javascript",
"parser",
"syntax"
],
"scripts": {
"generate-regex": "node tools/generate-identifier-regex.js",
"test": "npm run-script lint && node test/run.js && npm run-script coverage && npm run-script complexity",
"lint": "npm run-script check-version && npm run-script eslint && npm run-script jscs && npm run-script jslint",
"check-version": "node tools/check-version.js",
"eslint": "node node_modules/eslint/bin/eslint.js esprima.js",
"jscs": "node node_modules/jscs/bin/jscs esprima.js",
"jslint": "node node_modules/jslint/bin/jslint.js esprima.js",
"coverage": "npm run-script analyze-coverage && npm run-script check-coverage",
"analyze-coverage": "node node_modules/istanbul/lib/cli.js cover test/runner.js",
"check-coverage": "node node_modules/istanbul/lib/cli.js check-coverage --statement 100 --branch 100 --function 100",
"complexity": "npm run-script analyze-complexity && npm run-script check-complexity",
"analyze-complexity": "node tools/list-complexity.js",
"check-complexity": "node node_modules/complexity-report/src/cli.js --maxcc 15 --silent -l -w esprima.js",
"benchmark": "node test/benchmarks.js",
"benchmark-quick": "node test/benchmarks.js quick"
}
}

View File

@ -0,0 +1,27 @@
// Copyright (c) 2014 The Polymer Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,5 @@
{
"name": "polymer-expressions",
"main": "polymer-expressions",
"types": "polymer-expressions.d.ts"
}

View File

@ -0,0 +1,393 @@
/*
* Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
'use strict';
function detectEval() {
// Don't test for eval if we're running in a Chrome App environment.
// We check for APIs set that only exist in a Chrome App context.
if (typeof chrome !== 'undefined' && chrome.app && chrome.app.runtime) {
return false;
}
// Firefox OS Apps do not allow eval. This feature detection is very hacky
// but even if some other platform adds support for this function this code
// will continue to work.
if (typeof navigator != 'undefined' && navigator.getDeviceStorage) {
return false;
}
try {
var f = new Function('', 'return true;');
return f();
} catch (ex) {
return false;
}
}
var hasEval = detectEval();
function isIndex(s) {
return +s === s >>> 0 && s !== '';
}
function toNumber(s) {
return +s;
}
function isObject(obj) {
return obj === Object(obj);
}
var numberIsNaN = Number.isNaN || function (value) {
return typeof value === 'number' && isNaN(value);
}
function areSameValue(left, right) {
if (left === right)
return left !== 0 || 1 / left === 1 / right;
if (numberIsNaN(left) && numberIsNaN(right))
return true;
return left !== left && right !== right;
}
var createObject = ('__proto__' in {}) ?
function (obj) { return obj; } :
function (obj) {
var proto = obj.__proto__;
if (!proto)
return obj;
var newObject = Object.create(proto);
Object.getOwnPropertyNames(obj).forEach(function (name) {
Object.defineProperty(newObject, name,
Object.getOwnPropertyDescriptor(obj, name));
});
return newObject;
};
var identStart = '[\$_a-zA-Z]';
var identPart = '[\$_a-zA-Z0-9]';
var identRegExp = new RegExp('^' + identStart + '+' + identPart + '*' + '$');
function getPathCharType(char) {
if (char === undefined)
return 'eof';
var code = char.charCodeAt(0);
switch (code) {
case 0x5B: // [
case 0x5D: // ]
case 0x2E: // .
case 0x22: // "
case 0x27: // '
case 0x30: // 0
return char;
case 0x5F: // _
case 0x24: // $
return 'ident';
case 0x20: // Space
case 0x09: // Tab
case 0x0A: // Newline
case 0x0D: // Return
case 0xA0: // No-break space
case 0xFEFF: // Byte Order Mark
case 0x2028: // Line Separator
case 0x2029: // Paragraph Separator
return 'ws';
}
// a-z, A-Z
if ((0x61 <= code && code <= 0x7A) || (0x41 <= code && code <= 0x5A))
return 'ident';
// 1-9
if (0x31 <= code && code <= 0x39)
return 'number';
return 'else';
}
var pathStateMachine = {
'beforePath': {
'ws': ['beforePath'],
'ident': ['inIdent', 'append'],
'[': ['beforeElement'],
'eof': ['afterPath']
},
'inPath': {
'ws': ['inPath'],
'.': ['beforeIdent'],
'[': ['beforeElement'],
'eof': ['afterPath']
},
'beforeIdent': {
'ws': ['beforeIdent'],
'ident': ['inIdent', 'append']
},
'inIdent': {
'ident': ['inIdent', 'append'],
'0': ['inIdent', 'append'],
'number': ['inIdent', 'append'],
'ws': ['inPath', 'push'],
'.': ['beforeIdent', 'push'],
'[': ['beforeElement', 'push'],
'eof': ['afterPath', 'push']
},
'beforeElement': {
'ws': ['beforeElement'],
'0': ['afterZero', 'append'],
'number': ['inIndex', 'append'],
"'": ['inSingleQuote', 'append', ''],
'"': ['inDoubleQuote', 'append', '']
},
'afterZero': {
'ws': ['afterElement', 'push'],
']': ['inPath', 'push']
},
'inIndex': {
'0': ['inIndex', 'append'],
'number': ['inIndex', 'append'],
'ws': ['afterElement'],
']': ['inPath', 'push']
},
'inSingleQuote': {
"'": ['afterElement'],
'eof': ['error'],
'else': ['inSingleQuote', 'append']
},
'inDoubleQuote': {
'"': ['afterElement'],
'eof': ['error'],
'else': ['inDoubleQuote', 'append']
},
'afterElement': {
'ws': ['afterElement'],
']': ['inPath', 'push']
}
}
function noop() { }
function parsePath(path) {
var keys = [];
var index = -1;
var c, newChar, key, type, transition, action, typeMap, mode = 'beforePath';
var actions = {
push: function () {
if (key === undefined)
return;
keys.push(key);
key = undefined;
},
append: function () {
if (key === undefined)
key = newChar
else
key += newChar;
}
};
function maybeUnescapeQuote() {
if (index >= path.length)
return;
var nextChar = path[index + 1];
if ((mode == 'inSingleQuote' && nextChar == "'") ||
(mode == 'inDoubleQuote' && nextChar == '"')) {
index++;
newChar = nextChar;
actions.append();
return true;
}
}
while (mode) {
index++;
c = path[index];
if (c == '\\' && maybeUnescapeQuote(mode))
continue;
type = getPathCharType(c);
typeMap = pathStateMachine[mode];
transition = typeMap[type] || typeMap['else'] || 'error';
if (transition == 'error')
return; // parse error;
mode = transition[0];
action = actions[transition[1]] || noop;
newChar = transition[2] === undefined ? c : transition[2];
action();
if (mode === 'afterPath') {
return keys;
}
}
return; // parse error
}
function isIdent(s) {
return identRegExp.test(s);
}
var constructorIsPrivate = {};
function Path(parts, privateToken) {
if (privateToken !== constructorIsPrivate)
throw Error('Use Path.get to retrieve path objects');
for (var i = 0; i < parts.length; i++) {
this.push(String(parts[i]));
}
if (hasEval && this.length) {
this.getValueFrom = this.compiledGetValueFromFn();
}
}
// TODO(rafaelw): Make simple LRU cache
var pathCache = {};
function getPath(pathString) {
if (pathString instanceof Path)
return pathString;
if (pathString == null || pathString.length == 0)
pathString = '';
if (typeof pathString != 'string') {
if (isIndex(pathString.length)) {
// Constructed with array-like (pre-parsed) keys
return new Path(pathString, constructorIsPrivate);
}
pathString = String(pathString);
}
var path = pathCache[pathString];
if (path)
return path;
var parts = parsePath(pathString);
if (!parts)
return invalidPath;
var path = new Path(parts, constructorIsPrivate);
pathCache[pathString] = path;
return path;
}
Path.get = getPath;
function formatAccessor(key) {
if (isIndex(key)) {
return '[' + key + ']';
} else {
return '["' + key.replace(/"/g, '\\"') + '"]';
}
}
Path.prototype = createObject({
__proto__: [],
valid: true,
toString: function () {
var pathString = '';
for (var i = 0; i < this.length; i++) {
var key = this[i];
if (isIdent(key)) {
pathString += i ? '.' + key : key;
} else {
pathString += formatAccessor(key);
}
}
return pathString;
},
getValueFrom: function (obj, directObserver) {
for (var i = 0; i < this.length; i++) {
if (obj == null)
return;
obj = obj[this[i]];
}
return obj;
},
iterateObjects: function (obj, observe) {
for (var i = 0; i < this.length; i++) {
if (i)
obj = obj[this[i - 1]];
if (!isObject(obj))
return;
observe(obj, this[i]);
}
},
compiledGetValueFromFn: function () {
var str = '';
var pathString = 'obj';
str += 'if (obj != null';
var i = 0;
var key;
for (; i < (this.length - 1) ; i++) {
key = this[i];
pathString += isIdent(key) ? '.' + key : formatAccessor(key);
str += ' &&\n ' + pathString + ' != null';
}
str += ')\n';
var key = this[i];
pathString += isIdent(key) ? '.' + key : formatAccessor(key);
str += ' return ' + pathString + ';\nelse\n return undefined;';
return new Function('obj', str);
},
setValueFrom: function (obj, value) {
if (!this.length)
return false;
for (var i = 0; i < this.length - 1; i++) {
if (!isObject(obj))
return false;
obj = obj[this[i]];
}
if (!isObject(obj))
return false;
obj[this[i]] = value;
return true;
}
});
var invalidPath = new Path('', constructorIsPrivate);
invalidPath.valid = false;
invalidPath.getValueFrom = invalidPath.setValueFrom = function () { };
exports.Path = Path;

View File

@ -0,0 +1,19 @@
/**
* @module "js-libs/polymer-expressions"
* @private
*/ /** */
//@private
export class PolymerExpressions {
static getExpression(expression: string): Expression;
}
export class Expression {
/**
* Evaluates a value for an expression.
* @param model - Context of the expression.
* @param isBackConvert - Denotes if the convertion is forward (from model to ui) or back (ui to model).
* @param changedModel - A property bag which contains all changed properties (in case of two way binding).
*/
getValue(model, isBackConvert, changedModel);
}

View File

@ -0,0 +1,541 @@
// Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
// Code distributed by Google as part of the polymer project is also
// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
// Hack to resolve https://github.com/webpack/enhanced-resolve/issues/197 .
// This issue causes an require like this (`../esprima`) to be resolved to (`esprima`) by the Angular webpack plugin
var esprima = require("../../js-libs/esprima").esprima;
var Path = require("./path-parser").Path;
(function (global) {
'use strict';
// TODO(rafaelw): Implement simple LRU.
var expressionParseCache = Object.create(null);
function getExpression(expressionText) {
var expression = expressionParseCache[expressionText];
if (!expression) {
var delegate = new ASTDelegate();
esprima.parse(expressionText, delegate);
expression = new Expression(delegate);
expressionParseCache[expressionText] = expression;
}
return expression;
}
function Literal(value) {
this.value = value;
this.valueFn_ = undefined;
}
Literal.prototype = {
valueFn: function () {
if (!this.valueFn_) {
var value = this.value;
this.valueFn_ = function () {
return value;
}
}
return this.valueFn_;
}
}
function IdentPath(name) {
this.name = name;
this.path = Path.get(name);
}
IdentPath.prototype = {
valueFn: function () {
if (!this.valueFn_) {
var name = this.name;
var path = this.path;
this.valueFn_ = function (model, observer, changedModel) {
if (observer)
observer.addPath(model, path);
if (changedModel) {
var result = path.getValueFrom(changedModel);
if (result !== undefined) {
return result;
}
}
return path.getValueFrom(model);
}
}
return this.valueFn_;
},
setValue: function (model, newValue) {
if (this.path.length == 1) {
model = findScope(model, this.path[0]);
}
return this.path.setValueFrom(model, newValue);
}
};
function MemberExpression(object, property, accessor) {
this.computed = accessor == '[';
this.dynamicDeps = typeof object == 'function' ||
object.dynamicDeps ||
(this.computed && !(property instanceof Literal));
this.simplePath =
!this.dynamicDeps &&
(property instanceof IdentPath || property instanceof Literal) &&
(object instanceof MemberExpression || object instanceof IdentPath);
this.object = this.simplePath ? object : getFn(object);
this.property = !this.computed || this.simplePath ?
property : getFn(property);
}
MemberExpression.prototype = {
get fullPath() {
if (!this.fullPath_) {
var parts = this.object instanceof MemberExpression ?
this.object.fullPath.slice() : [this.object.name];
parts.push(this.property instanceof IdentPath ?
this.property.name : this.property.value);
this.fullPath_ = Path.get(parts);
}
return this.fullPath_;
},
valueFn: function () {
if (!this.valueFn_) {
var object = this.object;
if (this.simplePath) {
var path = this.fullPath;
this.valueFn_ = function (model, observer) {
if (observer)
observer.addPath(model, path);
return path.getValueFrom(model);
};
} else if (!this.computed) {
var path = Path.get(this.property.name);
this.valueFn_ = function (model, observer, filterRegistry) {
var context = object(model, observer, filterRegistry);
if (observer)
observer.addPath(context, path);
return path.getValueFrom(context);
}
} else {
// Computed property.
var property = this.property;
this.valueFn_ = function (model, observer, filterRegistry) {
var context = object(model, observer, filterRegistry);
var propName = property(model, observer, filterRegistry);
if (observer)
observer.addPath(context, [propName]);
return context ? context[propName] : undefined;
};
}
}
return this.valueFn_;
},
setValue: function (model, newValue) {
if (this.simplePath) {
this.fullPath.setValueFrom(model, newValue);
return newValue;
}
var object = this.object(model);
var propName = this.property instanceof IdentPath ? this.property.name :
this.property(model);
return object[propName] = newValue;
}
};
function Filter(name, args) {
this.name = name;
this.args = [];
for (var i = 0; i < args.length; i++) {
this.args[i] = getFn(args[i]);
}
}
Filter.prototype = {
transform: function (model, observer, filterRegistry, toModelDirection,
initialArgs) {
var fn = filterRegistry[this.name];
var context = model;
if (fn) {
context = undefined;
} else {
fn = context[this.name];
if (!fn) {
console.error('Cannot find function or filter: ' + this.name);
return;
}
}
// If toModelDirection is falsey, then the "normal" (dom-bound) direction
// is used. Otherwise, it looks for a 'toModel' property function on the
// object.
if (toModelDirection) {
fn = fn.toModel;
} else if (typeof fn.toView == 'function') {
fn = fn.toView;
}
if (typeof fn != 'function') {
console.error('Cannot find function or filter: ' + this.name);
return;
}
var args = initialArgs || [];
for (var i = 0; i < this.args.length; i++) {
args.push(getFn(this.args[i])(model, observer, filterRegistry));
}
return fn.apply(context, args);
}
};
function notImplemented() { throw Error('Not Implemented'); }
var unaryOperators = {
'+': function (v) { return +v; },
'-': function (v) { return -v; },
'!': function (v) { return !v; }
};
var binaryOperators = {
'+': function (l, r) { return l + r; },
'-': function (l, r) { return l - r; },
'*': function (l, r) { return l * r; },
'/': function (l, r) { return l / r; },
'%': function (l, r) { return l % r; },
'<': function (l, r) { return l < r; },
'>': function (l, r) { return l > r; },
'<=': function (l, r) { return l <= r; },
'>=': function (l, r) { return l >= r; },
'==': function (l, r) { return l == r; },
'!=': function (l, r) { return l != r; },
'===': function (l, r) { return l === r; },
'!==': function (l, r) { return l !== r; },
'&&': function (l, r) { return l && r; },
'||': function (l, r) { return l || r; },
};
function getFn(arg) {
return typeof arg == 'function' ? arg : arg.valueFn();
}
function ASTDelegate() {
this.expression = null;
this.filters = [];
this.deps = {};
this.currentPath = undefined;
this.scopeIdent = undefined;
this.indexIdent = undefined;
this.dynamicDeps = false;
}
ASTDelegate.prototype = {
createUnaryExpression: function (op, argument) {
if (!unaryOperators[op])
throw Error('Disallowed operator: ' + op);
argument = getFn(argument);
return function (model, observer, filterRegistry) {
return unaryOperators[op](argument(model, observer, filterRegistry));
};
},
createBinaryExpression: function (op, left, right) {
if (!binaryOperators[op])
throw Error('Disallowed operator: ' + op);
left = getFn(left);
right = getFn(right);
switch (op) {
case '||':
this.dynamicDeps = true;
return function (model, observer, filterRegistry) {
return left(model, observer, filterRegistry) ||
right(model, observer, filterRegistry);
};
case '&&':
this.dynamicDeps = true;
return function (model, observer, filterRegistry) {
return left(model, observer, filterRegistry) &&
right(model, observer, filterRegistry);
};
}
return function (model, observer, filterRegistry) {
return binaryOperators[op](left(model, observer, filterRegistry),
right(model, observer, filterRegistry));
};
},
createConditionalExpression: function (test, consequent, alternate) {
test = getFn(test);
consequent = getFn(consequent);
alternate = getFn(alternate);
this.dynamicDeps = true;
return function (model, observer, filterRegistry) {
return test(model, observer, filterRegistry) ?
consequent(model, observer, filterRegistry) :
alternate(model, observer, filterRegistry);
}
},
createIdentifier: function (name) {
var ident = new IdentPath(name);
ident.type = 'Identifier';
return ident;
},
createMemberExpression: function (accessor, object, property) {
var ex = new MemberExpression(object, property, accessor);
if (ex.dynamicDeps)
this.dynamicDeps = true;
return ex;
},
createCallExpression: function (expression, args) {
if (!(expression instanceof IdentPath))
throw Error('Only identifier function invocations are allowed');
var filter = new Filter(expression.name, args);
return function (model, observer, filterRegistry) {
return filter.transform(model, observer, filterRegistry, false);
};
},
createLiteral: function (token) {
return new Literal(token.value);
},
createArrayExpression: function (elements) {
for (var i = 0; i < elements.length; i++)
elements[i] = getFn(elements[i]);
return function (model, observer, filterRegistry) {
var arr = []
for (var i = 0; i < elements.length; i++)
arr.push(elements[i](model, observer, filterRegistry));
return arr;
}
},
createProperty: function (kind, key, value) {
return {
key: key instanceof IdentPath ? key.name : key.value,
value: value
};
},
createObjectExpression: function (properties) {
for (var i = 0; i < properties.length; i++)
properties[i].value = getFn(properties[i].value);
return function (model, observer, filterRegistry) {
var obj = {};
for (var i = 0; i < properties.length; i++)
obj[properties[i].key] =
properties[i].value(model, observer, filterRegistry);
return obj;
}
},
createFilter: function (name, args) {
this.filters.push(new Filter(name, args));
},
createAsExpression: function (expression, scopeIdent) {
this.expression = expression;
this.scopeIdent = scopeIdent;
},
createInExpression: function (scopeIdent, indexIdent, expression) {
this.expression = expression;
this.scopeIdent = scopeIdent;
this.indexIdent = indexIdent;
},
createTopLevel: function (expression) {
this.expression = expression;
},
createThisExpression: notImplemented
}
function Expression(delegate) {
this.scopeIdent = delegate.scopeIdent;
this.indexIdent = delegate.indexIdent;
if (!delegate.expression)
throw Error('No expression found.');
this.expression = delegate.expression;
getFn(this.expression); // forces enumeration of path dependencies
this.filters = delegate.filters;
this.dynamicDeps = delegate.dynamicDeps;
}
Expression.prototype = {
getValue: function (model, isBackConvert, changedModel, observer) {
var value = getFn(this.expression)(model.context, observer, changedModel);
for (var i = 0; i < this.filters.length; i++) {
value = this.filters[i].transform(model.context, observer, model.context, isBackConvert, [value]);
}
return value;
},
setValue: function (model, newValue, filterRegistry) {
var count = this.filters ? this.filters.length : 0;
while (count-- > 0) {
newValue = this.filters[count].transform(model, undefined,
filterRegistry, true, [newValue]);
}
if (this.expression.setValue)
return this.expression.setValue(model, newValue);
}
}
/**
* Converts a style property name to a css property name. For example:
* "WebkitUserSelect" to "-webkit-user-select"
*/
function convertStylePropertyName(name) {
return String(name).replace(/[A-Z]/g, function (c) {
return '-' + c.toLowerCase();
});
}
var parentScopeName = '@' + Math.random().toString(36).slice(2);
// Single ident paths must bind directly to the appropriate scope object.
// I.e. Pushed values in two-bindings need to be assigned to the actual model
// object.
function findScope(model, prop) {
while (model[parentScopeName] &&
!Object.prototype.hasOwnProperty.call(model, prop)) {
model = model[parentScopeName];
}
return model;
}
function isLiteralExpression(pathString) {
switch (pathString) {
case '':
return false;
case 'false':
case 'null':
case 'true':
return true;
}
if (!isNaN(Number(pathString)))
return true;
return false;
};
function PolymerExpressions() { }
PolymerExpressions.prototype = {
// "built-in" filters
styleObject: function (value) {
var parts = [];
for (var key in value) {
parts.push(convertStylePropertyName(key) + ': ' + value[key]);
}
return parts.join('; ');
},
tokenList: function (value) {
var tokens = [];
for (var key in value) {
if (value[key])
tokens.push(key);
}
return tokens.join(' ');
},
// binding delegate API
prepareInstancePositionChanged: function (template) {
var indexIdent = template.polymerExpressionIndexIdent_;
if (!indexIdent)
return;
return function (templateInstance, index) {
templateInstance.model[indexIdent] = index;
};
},
prepareInstanceModel: function (template) {
var scopeName = template.polymerExpressionScopeIdent_;
if (!scopeName)
return;
var parentScope = template.templateInstance ?
template.templateInstance.model :
template.model;
var indexName = template.polymerExpressionIndexIdent_;
return function (model) {
return createScopeObject(parentScope, model, scopeName, indexName);
};
}
};
var createScopeObject = ('__proto__' in {}) ?
function (parentScope, model, scopeName, indexName) {
var scope = {};
scope[scopeName] = model;
scope[indexName] = undefined;
scope[parentScopeName] = parentScope;
scope.__proto__ = parentScope;
return scope;
} :
function (parentScope, model, scopeName, indexName) {
var scope = Object.create(parentScope);
Object.defineProperty(scope, scopeName,
{ value: model, configurable: true, writable: true });
Object.defineProperty(scope, indexName,
{ value: undefined, configurable: true, writable: true });
Object.defineProperty(scope, parentScopeName,
{ value: parentScope, configurable: true, writable: true });
return scope;
};
global.PolymerExpressions = PolymerExpressions;
PolymerExpressions.getExpression = getExpression;
})(module.exports);