Comparing version 2.0.0-beta2 to 2.0.0-beta3
{ | ||
"name": "nwsapi", | ||
"version": "2.0.0beta2", | ||
"version": "2.0.0beta3", | ||
"homepage": "https://github.com/dperini/nwsapi", | ||
@@ -5,0 +5,0 @@ "authors": [ |
{ | ||
"name": "nwsapi", | ||
"version": "2.0.0beta2", | ||
"version": "2.0.0beta3", | ||
"description": "Fast CSS Selectors API Engine", | ||
@@ -38,3 +38,9 @@ "homepage": "http://javascript.nwbox.com/nwsapi/", | ||
"url": "git://github.com/dperini/nwsapi.git" | ||
}, | ||
"scripts": { | ||
"lint": "eslint ./src/nwsapi.js" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^4.19.1" | ||
} | ||
} |
@@ -8,5 +8,5 @@ /* | ||
* Author: Diego Perini <diego.perini at gmail com> | ||
* Version: 2.0.0beta2 | ||
* Version: 2.0.0beta3 | ||
* Created: 20070722 | ||
* Release: 20180417 | ||
* Release: 20180514 | ||
* | ||
@@ -25,3 +25,3 @@ * License: | ||
module.exports = factory; | ||
} else if (typeof define === 'function' && define['amd']) { | ||
} else if (typeof define == 'function' && define['amd']) { | ||
define(factory); | ||
@@ -35,39 +35,21 @@ } else { | ||
var version = 'nwsapi-2.0.0beta2', | ||
var version = 'nwsapi-2.0.0beta3', | ||
doc = global.document, | ||
nav = global.navigator, | ||
root = doc.documentElement, | ||
COM = '>+~', | ||
ESC = '\\\\', | ||
HEX = '[0-9a-fA-F]', | ||
SPC = ' \\t\\r\\n\\f', | ||
WSP = '[' + SPC + ']', | ||
WSP = '[\\x20\\t\\r\\n\\f]', | ||
CFG = { | ||
operators: '[~*^$|]=|=', | ||
combinators: '[' + SPC + COM + '](?=[^' + COM + '])' | ||
combinators: '[\\x20\\t\\r\\n\\f>+~](?=[^>+~])' | ||
}, | ||
STR = { | ||
alphalodash: '[_a-zA-Z]', | ||
pseudoparms: '[-+]?\\d*', | ||
doublequote: '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"', | ||
singlequote: "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'", | ||
any_esc_chr: ESC + '.', | ||
non_asc_chr: '[^\\x00-\\x9f]', | ||
escaped_chr: ESC + '[^\\r\\n\\f0-9a-fA-F]', | ||
unicode_chr: ESC + HEX + '{1,6}(?:\\r\\n|' + WSP + ')?' | ||
}, | ||
REX = { | ||
HasEscapes: RegExp(ESC), | ||
HexNumbers: RegExp('^' + HEX), | ||
SplitComma: RegExp('\\s?,\\s?'), | ||
HasEscapes: RegExp('\\\\'), | ||
HexNumbers: RegExp('^[0-9a-fA-F]'), | ||
EscOrQuote: RegExp('^\\\\|[\\x22\\x27]'), | ||
RegExpChar: RegExp('(?:(?!\\\\)[\\\\^$.*+?()[\\]{}|\\/])' ,'g'), | ||
TrimSpaces: RegExp('[\\r\\n\\f]|^' + WSP + '+|' + WSP + '+$', 'g'), | ||
FixEscapes: RegExp('\\\\(' + HEX + '{1,6}' + WSP + '?|.)|([\\x22\\x27])', 'g'), | ||
FixEscapes: RegExp('\\\\([0-9a-fA-F]{1,6}' + WSP + '?|.)|([\\x22\\x27])', 'g'), | ||
SplitGroup: RegExp(WSP + '*,' + WSP + '*(?![^\\[]*\\]|[^\\(]*\\)|[^\\{]*\\})', 'g') | ||
@@ -78,4 +60,2 @@ }, | ||
reSimpleNot, | ||
reSimpleMul, | ||
reSimpleUni, | ||
reValidator, | ||
@@ -87,3 +67,3 @@ | ||
pseudo_2 = 'checked|disabled|enabled|selected|local-link(?:\\(\\d*\\))?|lang\\(([-\\w]{2,})\\)', | ||
pseudo_3 = 'default|indeterminate|optional|required|valid|invalid|in-range|out-of-range|read-only|read-write', | ||
pseudo_3 = 'default|indeterminate|optional|required|valid|invalid|in-range|out-of-range|read-only|read-write|placeholder-shown', | ||
pseudo_4 = 'after|before|first-letter|first-line', | ||
@@ -112,5 +92,21 @@ pseudo_5 = 'selection|backdrop|placeholder', | ||
// special handling flags | ||
Config = { | ||
BUGFIX_ID: true, | ||
FASTCOMMA: true, | ||
SIMPLENOT: true, | ||
USE_HTML5: true, | ||
LOGERRORS: true, | ||
VERBOSITY: true | ||
}, | ||
MIXED_NS, | ||
NAMESPACE, | ||
QUIRKS_MODE, | ||
HAS_DUPE_IDS, | ||
HTML_DOCUMENT, | ||
NAMESPACE_URI, | ||
CASE_SENSITIVE, | ||
@@ -183,7 +179,10 @@ ATTR_ID = 'e.id', | ||
if (force || oldDoc !== doc) { | ||
// force a new check for each document change | ||
// performed before the next select operation | ||
HAS_DUPE_IDS = undefined; | ||
root = doc.documentElement; | ||
HTML_DOCUMENT = isHTML(doc); | ||
NAMESPACE_URI = root.namespaceURI; | ||
QUIRKS_MODE = HTML_DOCUMENT && | ||
doc.compatMode.indexOf('CSS') < 0; | ||
NAMESPACE = root && root.namespaceURI; | ||
ATTR_ID = Config.BUGFIX_ID ? FIX_ID : 'e.id'; | ||
@@ -276,31 +275,99 @@ Snapshot.doc = doc; | ||
compat = { | ||
'#': function(c, n, z) { return function(e, f) { return byId(n, c); }; }, | ||
'*': function(c, n, z) { return function(e, f) { return byTag(n, c); }; }, | ||
'.': function(c, n, z) { return function(e, f) { return byClass(n, c); }; } | ||
set_compat = | ||
function() { | ||
return !Config.FASTCOMMA ? { | ||
'#': function(c, n, z) { return function(e, f) { return byId(n, c); }; }, | ||
'*': function(c, n, z) { return function(e, f) { return byTag(n, c); }; }, | ||
'.': function(c, n, z) { return function(e, f) { return byClass(n, c); }; } | ||
} : { | ||
'#': function(c, n, z) { return function(e, f) { return validate(c, n, z, '#') ? z : (z = byId(n, c)); }; }, | ||
'*': function(c, n, z) { return function(e, f) { return validate(c, n, z, '*') ? z : (z = byTag(n, c)); }; }, | ||
'.': function(c, n, z) { return function(e, f) { return validate(c, n, z, '.') ? z : (z = byClass(n, c)); }; } | ||
}; | ||
}, | ||
domapi = { | ||
'#': function(c, n, z) { return function(e, f) { if (e && z) return z; z = c.getElementById(n); return z = z ? [ z ] : none; };}, | ||
'*': function(c, n, z) { return function(e, f) { if (e && z) return z; z = c.getElementsByTagName(n); return f ? concatCall(z, f) : toArray(z); };}, | ||
'.': function(c, n, z) { return function(e, f) { if (e && z) return z; z = c.getElementsByClassName(n); return f ? concatCall(z, f) : toArray(z); };} | ||
compat = set_compat(), | ||
set_domapi = | ||
function() { | ||
var mapped = { | ||
'@': function(c, n, z) { return function(e, f) { return byId(n, c); }; }, | ||
'#': function(c, n, z) { return function(e, f) { if (e && z) return z; z = c.getElementById(n); return z = z ? [ z ] : none; };}, | ||
'*': function(c, n, z) { return function(e, f) { if (e && z) return z; z = c.getElementsByTagName(n); return f ? concatCall(z, f) : toArray(z); };}, | ||
'.': function(c, n, z) { return function(e, f) { if (e && z) return z; z = c.getElementsByClassName(n); return f ? concatCall(z, f) : toArray(z); };} | ||
}, | ||
natives = mapped; | ||
if (HAS_DUPE_IDS) natives['#'] = mapped['@']; | ||
delete natives['@']; | ||
return natives; | ||
}, | ||
domapi = set_domapi(), | ||
// check context for duplicate Ids | ||
hasDuplicateId = | ||
function(id, context) { | ||
var i = 0, cloned, element, fragment; | ||
function(context) { | ||
var i = 0, e, r = Object(); | ||
e = byTag('*', context); | ||
while (e[i]) { | ||
if (e[i].id) { | ||
if (!r[e[i].id]) { | ||
r[e[i].id] = true; | ||
} else return true; | ||
} | ||
++i; | ||
} | ||
return false; | ||
}, | ||
cloned = context.firstElementChild.cloneNode(true); | ||
fragment = doc.createDocumentFragment(); | ||
fragment.appendChild(cloned); | ||
// detect case sensitivity of the nodeName property | ||
// for elements created in the context owner document | ||
isCaseSensitive = | ||
function(context) { | ||
var d = context.ownerDocument || context; | ||
return d.createElement('div').nodeName == | ||
d.createElement('DIV').nodeName; | ||
}, | ||
while ((element = fragment.getElementById(id))) { | ||
element.parentNode.removeChild(element); ++i; | ||
if (i > 1) { break; } | ||
// check context for mixed content | ||
hasMixedNamespace = | ||
function(context) { | ||
var d = context.ownerDocument || context, | ||
dns, all_nodes, dns_nodes; | ||
if (root) { | ||
// the root element namespace | ||
dns = root.namespaceURI; | ||
} else { | ||
// default html/xhtml namespace | ||
dns = 'http://www.w3.org/1999/xhtml'; | ||
} | ||
return i > 1; | ||
// check to see if all nodes are in the same namespace | ||
all_nodes = d.getElementsByTagNameNS('*', '*').length; | ||
dns_nodes = d.getElementsByTagNameNS(dns, '*').length; | ||
return (all_nodes - dns_nodes) > 0; | ||
}, | ||
// validate memoized HTMLCollections | ||
validate = | ||
function(context, ident, list, type) { | ||
var c, i, j, k, l, m, els, test; | ||
if (!list) { return false; } | ||
l = list.length; | ||
k = ident.length; | ||
m = method[type]; | ||
for (i = 0; k > i; ++i) { | ||
els = context[m](ident[i]); | ||
if (!els) continue; | ||
test = toArray(els); | ||
for (j = 0, c = 0; l > j; ++j) { | ||
if (list[j] === test[c]) { ++c; } | ||
} | ||
if (c === 0 || test.length !== c) { return false; } | ||
} | ||
return true; | ||
}, | ||
// recursive DOM LTR traversal, configurable by replacing | ||
@@ -316,3 +383,3 @@ // the conditional part (@) to accept returned elements | ||
// cross document methods: byId, byTag, byCls, byTagCls | ||
idTest = 't==' + FIX_ID, | ||
idTest = 't.test(' + FIX_ID + ')', | ||
tagMatch = 'a||t.test(e.nodeName)', | ||
@@ -324,21 +391,17 @@ clsMatch = 'c.test(e.getAttribute?' + | ||
byId = | ||
function(id, context) { | ||
var element, elements, resolver; | ||
function(ids, context) { | ||
var element, elements, nIds = '', reIds, resolver; | ||
// ensure a default context | ||
context || (context = doc); | ||
if (typeof ids == 'string') { ids = [ ids ]; } | ||
// unescape special chars in | ||
// identifier if is necessary | ||
id = unescapeIdentifier(id); | ||
id = id.replace(/\x00|\\$/g, '\ufffd'); | ||
// check if the duplicate config option is enabled | ||
if (!(Config.DUPLICATE && hasDuplicateId(id, context))) { | ||
// if available use the DOM API to collect the nodes | ||
if ('getElementById' in context) { | ||
return (element = context.getElementById(id)) ? [ element ] : none; | ||
} | ||
// if duplicates are disallowed use DOM API to collect the nodes | ||
if (!HAS_DUPE_IDS && ids.length < 2 && method['#'] in context) { | ||
element = context.getElementById(unescapeIdentifier(ids[0])); | ||
return element ? [ element ] : none; | ||
} | ||
// multiple ids names | ||
ids.map(function(e) { nIds += '|' + e.replace(REX.RegExpChar, '\\$&'); }); | ||
reIds = RegExp('^(?:' + nIds.slice(1) + ')$', 'i'); | ||
// for non-elements contexts start from first element child | ||
@@ -348,6 +411,6 @@ context.nodeType != 1 && (context = context.firstElementChild); | ||
// build the resolver and execute it | ||
resolver = Function('t', walk.replace('@', idTest))(id); | ||
resolver = Function('t', walk.replace('@', idTest))(reIds); | ||
elements = resolver(context); | ||
return Config.DUPLICATE ? elements : elements[0] || null; | ||
return elements; | ||
}, | ||
@@ -366,3 +429,3 @@ | ||
if (tag.length < 2 && method['*'] in context) { | ||
return context[method['*']](tag[0]); | ||
return context[method['*'] + 'NS']('*', tag[0]); | ||
} | ||
@@ -398,3 +461,3 @@ | ||
if (cls.length < 2 && method['.'] in context) { | ||
return context[method['.']](cls[0]); | ||
return context[method['.']](unescapeIdentifier(cls[0])); | ||
} | ||
@@ -406,5 +469,3 @@ | ||
// multiple class names | ||
cls.map(function(e) { | ||
nCls += '|' + e.replace(REX.RegExpChar, '\\$&'); | ||
}); | ||
cls.map(function(e) { nCls += '|' + e.replace(REX.RegExpChar, '\\$&'); }); | ||
reCls = RegExp('(^|\\s)' + nCls.slice(1) + '(\\s|$)', cs); | ||
@@ -445,16 +506,37 @@ | ||
nthElement = (function() { | ||
var parents = Array(), elements = Array(); | ||
var idx, len, set, parent, parents = Array(), nodes = Array(); | ||
return function(element, dir) { | ||
var e, i, j, k, l; | ||
// ensure caches are emptied after each run, invoking with dir = 2 | ||
if (dir == 2) { parents.length = 0; elements.length = 0; return -1; } | ||
var e, i, j, l, parent = element.parentNode; | ||
if ((i = parents.indexOf(parent)) < 0) { | ||
i = parents.length; | ||
parents[i] = parent; | ||
elements[i] = Array(); | ||
e = parent.firstElementChild; | ||
while (e) { elements[i].push(e); e = e.nextElementSibling; } | ||
if (dir == 2) { nodes.length = 0; parents.length = 0; parent = null; return -1; } | ||
if (parent === element.parentNode) { | ||
i = set; j = idx; l = len; | ||
} else { | ||
l = parents.length; | ||
parent = element.parentNode; | ||
for (i = -1, j = 0, k = l - 1; l > j; ++j, --k) { | ||
if (parents[j] === parent) { i = j; break; } | ||
if (parents[k] === parent) { i = k; break; } | ||
} | ||
if (i < 0) { | ||
parents[i = l] = parent; | ||
l = 0; nodes[i] = Array(); | ||
e = parent.firstElementChild; | ||
while (e) { nodes[i][l] = e; if (e === element) j = l; e = e.nextElementSibling; ++l; } | ||
set = i; idx = 0; len = l; | ||
if (l < 2) return l; | ||
} else { | ||
l = nodes[i].length; | ||
set = i; | ||
} | ||
} | ||
for (j = 0, l = elements[i].length; l > j; ++j) { if (elements[i][j] === element) break; } | ||
return dir ? l - j : j + 1; | ||
if (element !== nodes[i][j] && element !== nodes[i][j = 0]) { | ||
for (j = 0, e = nodes[i], k = l - 1; l > j; ++j, --k) { | ||
if (e[j] === element) { break; } | ||
if (e[k] === element) { j = k; break; } | ||
} | ||
} | ||
idx = j + 1; len = l; | ||
return dir ? l - j : idx; | ||
}; | ||
@@ -465,17 +547,37 @@ })(), | ||
nthOfType = (function() { | ||
var parents = Array(), elements = Array(); | ||
var idx, len, set, parent, parents = Array(), nodes = Array(); | ||
return function(element, dir) { | ||
// ensure caches are emptied after each run, invoking with dir = 2 | ||
if (dir == 2) { parents.length = 0; elements.length = 0; return -1; } | ||
var e, i, j, l, name = element.nodeName, parent = element.parentNode; | ||
if ((i = parents.indexOf(parent)) < 0 || !(elements[i] && elements[i][name])) { | ||
i = parents.length; | ||
parents[i] = parent; | ||
elements[i] = Object(); | ||
elements[i][name] = Array(); | ||
e = parent.firstElementChild; | ||
while (e) { if (e.nodeName == name) elements[i][name].push(e); e = e.nextElementSibling; } | ||
if (dir == 2) { nodes.length = 0; parents.length = 0; parent = null; return -1; } | ||
var e, i, j, k, l, name = element.nodeName; | ||
if (nodes[set] && nodes[set][name] && parent === element.parentNode) { | ||
i = set; j = idx; l = len; | ||
} else { | ||
l = parents.length; | ||
parent = element.parentNode; | ||
for (i = -1, j = 0, k = l - 1; l > j; ++j, --k) { | ||
if (parents[j] === parent) { i = j; break; } | ||
if (parents[k] === parent) { i = k; break; } | ||
} | ||
if (i < 0 || !nodes[i][name]) { | ||
parents[i = l] = parent; | ||
nodes[i] || (nodes[i] = Object()); | ||
l = 0; nodes[i][name] = Array(); | ||
e = parent.firstElementChild; | ||
while (e) { if (e === element) j = l; if (e.nodeName == name) { nodes[i][name][l] = e; ++l; } e = e.nextElementSibling; } | ||
set = i; idx = j; len = l; | ||
if (l < 2) return l; | ||
} else { | ||
l = nodes[i][name].length; | ||
set = i; | ||
} | ||
} | ||
for (j = 0, l = elements[i][name].length; l > j; ++j) { if (elements[i][name][j] === element) break; } | ||
return dir ? l - j : j + 1; | ||
if (element !== nodes[i][name][j] && element !== nodes[i][name][j = 0]) { | ||
for (j = 0, e = nodes[i][name], k = l - 1; l > j; ++j, --k) { | ||
if (e[j] === element) { break; } | ||
if (e[k] === element) { j = k; break; } | ||
} | ||
} | ||
idx = j + 1; len = l; | ||
return dir ? l - j : idx; | ||
}; | ||
@@ -499,5 +601,6 @@ })(), | ||
function(node) { | ||
var doc = node.ownerDocument || node, root = doc.documentElement; | ||
return doc.nodeType == 9 && ('body' in doc) && root.nodeName == 'HTML' && | ||
doc.createElement('DiV').nodeName != 'DiV' && doc.contentType.indexOf('/html'); | ||
var doc = node.ownerDocument || node; | ||
return doc.nodeType == 9 && | ||
doc.contentType.indexOf('/html') > 0 && | ||
doc.createElement('DiV').nodeName == 'DIV'; | ||
}, | ||
@@ -515,2 +618,4 @@ | ||
selectResolvers = { }; | ||
} else if (i == 'FASTCOMMA') { | ||
set_compat(); | ||
} | ||
@@ -539,20 +644,2 @@ } | ||
// special handling flags | ||
Config = { | ||
ESCAPECHR: true, | ||
NON_ASCII: true, | ||
SELECTOR3: true, | ||
UNICODE16: true, | ||
BUGFIX_ID: true, | ||
DUPLICATE: true, | ||
SIMPLENOT: true, | ||
USE_HTML5: true, | ||
LOGERRORS: true, | ||
VERBOSITY: true | ||
}, | ||
// execute the engine initialization code | ||
@@ -562,5 +649,3 @@ initialize = | ||
setIdentifierSyntax(); | ||
lastMatchContext = doc; | ||
lastSelectContext = doc; | ||
switchContext(doc, true); | ||
lastContext = switchContext(doc, true); | ||
}, | ||
@@ -572,28 +657,27 @@ | ||
var identifier, | ||
extendedValidator, | ||
standardValidator, | ||
attrparser, attrvalues, | ||
attributes, attrmatcher, | ||
pseudoclass, pseudoparms, | ||
syntax = '', start = Config['SELECTOR3'] ? '-{2}|' : ''; | ||
var identifier = | ||
// doesn't start with a digit | ||
'(?=[^0-9])' + | ||
// can start with double dash | ||
'(?:-{2}' + | ||
// may include ascii chars | ||
'|[a-zA-Z0-9-_]' + | ||
// non-ascii chars | ||
'|[^\\x00-\\x9f]' + | ||
// escaped chars | ||
'|\\\\[^\\r\\n\\f0-9a-fA-F]' + | ||
// unicode chars | ||
'|\\\\[0-9a-fA-F]{1,6}(?:\\r\\n|\\s)?' + | ||
// any escaped chars | ||
'|\\\\.' + | ||
')+', | ||
Config['NON_ASCII'] && (syntax += '|' + STR.non_asc_chr); | ||
Config['UNICODE16'] && (syntax += '|' + STR.unicode_chr); | ||
Config['ESCAPECHR'] && (syntax += '|' + STR.escaped_chr); | ||
pseudoparms = '(?:[-+]?\\d*)(?:n[-+]?\\d*)', | ||
doublequote = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"', | ||
singlequote = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'", | ||
syntax += ( | ||
Config['UNICODE16'] || | ||
Config['ESCAPECHR']) ? '' : '|' + STR.any_esc_chr; | ||
attrparser = identifier + '|' + doublequote + '|' + singlequote, | ||
identifier = '\\-?' + | ||
'(?:' + start + STR.alphalodash + syntax + ')' + | ||
'(?:-|[0-9]|' + STR.alphalodash + syntax + ')*'; | ||
attrvalues = '([\\x22\\x27]?)((?!\\3)*|(?:\\\\?.)*?)\\3', | ||
attrparser = identifier + | ||
'|' + STR.doublequote + | ||
'|' + STR.singlequote; | ||
attrvalues = '([\\x22\\x27]?)((?!\\3)*|(?:\\\\?.)*?)\\3'; | ||
attributes = | ||
@@ -615,10 +699,6 @@ '\\[' + | ||
// needed to pass current WP tests and mimic browsers behavior 'a[href=#' | ||
'(?:\\]|$)'; | ||
'(?:\\]|$)', | ||
attrmatcher = attributes.replace(attrparser, attrvalues); | ||
attrmatcher = attributes.replace(attrparser, attrvalues), | ||
pseudoparms = | ||
'(?:' + STR.pseudoparms + ')' + | ||
'(?:n' + STR.pseudoparms + ')' ; | ||
pseudoclass = | ||
@@ -636,3 +716,3 @@ '(?:\\(' + | ||
'(?:' + attributes + ')' + | ||
')+\\))*'; | ||
')+\\))*', | ||
@@ -650,4 +730,6 @@ standardValidator = | ||
'(?:' + WSP + '?,' + WSP + '?)' + | ||
')+'; | ||
')+', | ||
extendedValidator = standardValidator.replace(pseudoclass, '.*'); | ||
reSimpleNot = RegExp( | ||
@@ -665,7 +747,4 @@ '^(' + | ||
reOptimizer = RegExp('(?:([.:#*]?)(' + identifier + ')(?:(?:\\[.*\\])|:[-\\w]+(?:\\(.*\\))?)*)$'); | ||
reOptimizer = RegExp('(?:([.:#*]?)(' + identifier + ')(?::[-\\w]+|\\[.+\\]|\\(.+\\))*)$'); | ||
reSimpleUni = RegExp('^([.#]?)(-?(?:-{2}|[_a-zA-Z]|[^\x00-\x9f])(?:-|[0-9]|[_a-zA-Z]|[^\x00-\x9f])*)$'); | ||
reSimpleMul = RegExp('^(\\.?)(-?(?:-{2}|[_a-zA-Z]|[^\x00-\x9f])(?:-|[0-9]|[_a-zA-Z]|[^\x00-\x9f])*)$'); | ||
Patterns.id = RegExp('^#(' + identifier + ')(.*)'); | ||
@@ -676,4 +755,2 @@ Patterns.tagName = RegExp('^(' + identifier + ')(.*)'); | ||
extendedValidator = standardValidator.replace(pseudoclass, '.*'); | ||
reValidator = RegExp(Config.SIMPLENOT ? | ||
@@ -711,9 +788,14 @@ standardValidator : extendedValidator, 'g'); | ||
// make sure that the input string is an array | ||
// 'groups' may be a string, convert it to array | ||
if (typeof groups == 'string') groups = [groups]; | ||
// detect case sensitivity of element nodeName | ||
CASE_SENSITIVE = isCaseSensitive(lastContext); | ||
selector = groups.join(', '); | ||
key = selector + '_' + (mode ? '1' : '0') + (callback ? '1' : '0'); | ||
switch (mode) { | ||
// ensure 'mode' type is boolean | ||
// true = select / false = match | ||
switch (!!mode) { | ||
case true: | ||
@@ -735,7 +817,11 @@ if (selectLambdas[key]) { return selectLambdas[key]; } | ||
for (i = 0, l = groups.length; l > i; ++i) { | ||
token = groups[i]; | ||
if (!seen[token] && (seen[token] = true)) { | ||
source += compileSelector(token, macro, mode, callback, false); | ||
if (groups.length > 1) { | ||
for (i = 0, l = groups.length; l > i; ++i) { | ||
token = groups[i]; | ||
if (!seen[token] && (seen[token] = true)) { | ||
source += compileSelector(token, macro, mode, callback, false); | ||
} | ||
} | ||
} else { | ||
source += compileSelector(groups[0], macro, mode, callback, false); | ||
} | ||
@@ -758,3 +844,3 @@ | ||
factory = Function('s', F_INIT + '{' + head + vars + loop + 'return r; }')(Snapshot); | ||
factory = Function('s', F_INIT + '{' + head + vars + loop + 'return r;}')(Snapshot); | ||
@@ -770,3 +856,3 @@ return mode ? (selectLambdas[key] = factory) : (matchLambdas[key] = factory); | ||
// D is the default inverted negation flag | ||
var a, b, n, x_error = '', NS, | ||
var a, b, n, f, name, x_error = '', NS, | ||
N = not ? '!' : '', D = not ? '' : '!', pseudo, | ||
@@ -788,3 +874,3 @@ compat, expr, match, result, status, symbol, test, | ||
// get namespace prefix if present or get first char of selector | ||
symbol = /^(?:\w+|\*)\|/.test(selector) ? '|' : selector.charAt(0); | ||
symbol = /^(?:\w+|\*)\|/.test(selector) ? '|' : selector[0]; | ||
@@ -816,8 +902,6 @@ switch (symbol) { | ||
match = selector.match(Patterns.tagName); | ||
compat = HTML_DOCUMENT ? match[1].toUpperCase() : match[1]; | ||
source = 'if(' + N + '(' + | ||
(NS === void 0 ? 'e.nodeName=="' + convertEscapes(compat) + '"' : | ||
(NS === '*' ? '/' + match[1] + '/i.test(e.nodeName)' : | ||
(NS === null ? 'e.nodeName==e.localName' : | ||
'e.namespaceURI=="' + NAMESPACE_URI + '"'))) + | ||
(!HTML_DOCUMENT || CASE_SENSITIVE ? | ||
'/^' + match[1] + '$/i.test(e.nodeName)' : | ||
'e.nodeName=="' + match[1].toUpperCase() + '"') + | ||
')){' + source + '}'; | ||
@@ -828,3 +912,3 @@ break; | ||
match = selector.match(Patterns.namespace); | ||
NS = match[1] || null; | ||
match.pop(); | ||
if (match[1] == '*') { | ||
@@ -835,3 +919,3 @@ source = 'if(' + N + 'true){' + source + '}'; | ||
} else if (typeof match[1] == 'string' && root.prefix == match[1]) { | ||
source = 'if(' + N + '(e.namespaceURI=="' + NAMESPACE_URI + '")){' + source + '}'; | ||
source = 'if(' + N + '(e.namespaceURI=="' + NAMESPACE + '")){' + source + '}'; | ||
} else { | ||
@@ -844,3 +928,5 @@ emit('\'' + selector_string + '\' is not a valid selector'); | ||
match = selector.match(Patterns.attribute); | ||
expr = match[1].split(':'); | ||
NS = !MIXED_NS && match[0].match(/(\*|\w+)\|[-\w]+/); | ||
name = match[1]; | ||
expr = name.split(':'); | ||
expr = expr.length == 2 ? expr[1] : expr[0]; | ||
@@ -856,19 +942,14 @@ if (match[2] && !(test = Operators[match[2]])) { | ||
{ p1: '^', p2: '$', p3: 'true' } : test; | ||
} else { | ||
} else if (match[2] == '~=' && match[4].indexOf(' ') > -1) { | ||
// whitespace separated list but value contains space | ||
if (match[2] == '~=' && match[4].indexOf(' ') > -1) { | ||
source = 'if(' + N + 'false){' + source + '}'; | ||
break; | ||
} | ||
source = 'if(' + N + 'false){' + source + '}'; | ||
break; | ||
} else if (match[4]) { | ||
match[4] = convertEscapes(match[4]).replace(REX.RegExpChar, '\\$&'); | ||
} | ||
type = !HTML_DOCUMENT || !HTML_TABLE[expr.toLowerCase()] ? '' : 'i'; | ||
type = HTML_DOCUMENT && HTML_TABLE[expr.toLowerCase()] ? 'i' : ''; | ||
source = 'if(' + N + '(' + (!match[2] ? | ||
'(e.namespaceURI!="' + NAMESPACE_URI + '")?' + | ||
's.hasAttributeNS(e,"' + match[1] + '"):' + | ||
'e.hasAttribute("' + match[1] + '")' : | ||
(!match[4] && match[2] in ATTR_STD_OPS && match[2] != '~=' ? | ||
'e.getAttribute("' + match[1] + '")==""' : | ||
'(/' + test.p1 + convertEscapes(match[4]). | ||
replace(REX.RegExpChar, '\\$&') + test.p2 + '/' + type + | ||
').test(e.getAttribute("' + match[1] + '"))===' + test.p3)) + | ||
(MIXED_NS && NS ? 's.hasAttributeNS(e,"' + name + '")' : 'e.hasAttribute("' + name + '")') : | ||
!match[4] && ATTR_STD_OPS[match[2]] && match[2] != '~=' ? 'e.getAttribute("' + name + '")==""' : | ||
'(/' + test.p1 + match[4] + test.p2 + '/' + type + ').test(e.getAttribute("' + name + '"))==' + test.p3) + | ||
')){' + source + '}'; | ||
@@ -881,3 +962,3 @@ break; | ||
match = selector.match(Patterns.relative); | ||
source = 'if(' + N + '(e.previousElementSibling)){n=e;e=e.parentNode.firstElementChild;while(e&&e!==n){' + source + 'e=e.nextElementSibling;}e=n;}'; | ||
source = 'n=e;while((e=e.previousElementSibling)){' + source + '}e=n;'; | ||
break; | ||
@@ -888,3 +969,3 @@ // *** Adjacent sibling combinator | ||
match = selector.match(Patterns.adjacent); | ||
source = 'if(' + N + '(e.previousElementSibling)){n=e;if(e=e.previousElementSibling){' + source + '}e=n;}'; | ||
source = 'n=e;if((e=e.previousElementSibling)){' + source + '}e=n;'; | ||
break; | ||
@@ -896,3 +977,3 @@ // *** Descendant combinator | ||
match = selector.match(Patterns.ancestor); | ||
source = 'n=e;while(e=e.parentElement){' + source + '}e=n;'; | ||
source = 'n=e;while((e=e.parentElement)){' + source + '}e=n;'; | ||
break; | ||
@@ -903,3 +984,3 @@ // *** Child combinator | ||
match = selector.match(Patterns.children); | ||
source = 'n=e;if(e=e.parentElement){' + source + '}e=n;'; | ||
source = 'n=e;if((e=e.parentElement)){' + source + '}e=n;'; | ||
break; | ||
@@ -974,3 +1055,3 @@ | ||
test = 'n%2==0'; | ||
} else if (match[2] === 'odd' || match[2] == '2n1' || match[2] == '2n+1') { | ||
} else if (match[2] == 'odd' || match[2] == '2n1' || match[2] == '2n+1') { | ||
test = 'n%2==1'; | ||
@@ -1019,4 +1100,4 @@ } else { | ||
case 'checked': | ||
source = 'if(' + N + '((/^input$/i.test(e.nodeName)&&' + | ||
'(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)||' + | ||
source = 'if(' + N + '(/^input$/i.test(e.nodeName)&&' + | ||
'("|radio|checkbox|".includes("|"+e.type+"|")&&e.checked)||' + | ||
'(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' + | ||
@@ -1094,5 +1175,5 @@ ')){' + source + '}'; | ||
'}' + | ||
'if(' + N + '(e.form&&(e===n[x]&&/^image|submit$/i.test(e.type))||' + | ||
'if(' + N + '(e.form&&(e===n[x]&&"|image|submit|".includes("|"+e.type+"|"))||' + | ||
'((/^option$/i.test(e.nodeName))&&e.defaultSelected)||' + | ||
'((/^(radio|checkbox)$/i.test(e.type))&&e.defaultChecked)' + | ||
'(("|radio|checkbox|".includes("|"+e.type+"|"))&&e.defaultChecked)' + | ||
')){' + source + '}'; | ||
@@ -1103,4 +1184,4 @@ break; | ||
'if(' + N + '(/^progress$/i.test(e.nodeName)&&!e.hasAttribute("value"))||' + | ||
'(/^input$/i.test(e.nodeName)&&(/^checkbox$/i.test(e.type)&&e.indeterminate)||' + | ||
'(/^radio$/i.test(e.type)&&e.name&&!s.first("input[name="+e.name+"]:checked",e.form))' + | ||
'(/^input$/i.test(e.nodeName)&&("checkbox"==e.type&&e.indeterminate)||' + | ||
'("radio"==e.type&&e.name&&!s.first("input[name="+e.name+"]:checked",e.form))' + | ||
')){' + source + '}'; | ||
@@ -1124,3 +1205,3 @@ break; | ||
'((/^textarea$/i.test(e.nodeName)&&!e.readOnly&&!e.disabled)||' + | ||
'(/^password|text$/i.test(e.type)&&!e.readOnly&&!e.disabled))||' + | ||
'("|password|text|".includes("|"+e.type+"|")&&!e.readOnly&&!e.disabled))||' + | ||
'(e.hasAttribute("contenteditable")||(s.doc.designMode=="on"))' + | ||
@@ -1133,3 +1214,3 @@ ')){' + source + '}'; | ||
'(/^textarea$/i.test(e.nodeName)&&(e.readOnly||e.disabled))||' + | ||
'(/^password|text$/i.test(e.type)&&e.readOnly)' + | ||
'("|password|text|".includes("|"+e.type+"|")&&e.readOnly)' + | ||
')){' + source + '}'; | ||
@@ -1159,4 +1240,4 @@ break; | ||
'(!e.validity.rangeUnderflow&&!e.validity.rangeOverflow)&&' + | ||
'(/^date|datetime-local|month|number|range|time|week$/i.test(e.type))&&' + | ||
'(/^range$/i.test(e.type)||e.getAttribute("min")||e.getAttribute("max"))' + | ||
'("|date|datetime-local|month|number|range|time|week|".includes("|"+e.type+"|"))&&' + | ||
'("range"==e.type||e.getAttribute("min")||e.getAttribute("max"))' + | ||
'){' + source + '}'; | ||
@@ -1170,6 +1251,14 @@ break; | ||
'(e.validity.rangeUnderflow||e.validity.rangeOverflow)&&' + | ||
'(/^date|datetime-local|month|number|range|time|week$/i.test(e.type))&&' + | ||
'(/^range$/i.test(e.type)||e.getAttribute("min")||e.getAttribute("max"))' + | ||
'("|date|datetime-local|month|number|range|time|week|".includes("|"+e.type+"|"))&&' + | ||
'("range"==e.type||e.getAttribute("min")||e.getAttribute("max"))' + | ||
'){' + source + '}'; | ||
break; | ||
case 'placeholder-shown': | ||
source = | ||
'if(' + N + '(' + | ||
'(/^input|textarea$/i.test(e.nodeName))&&e.hasAttribute("placeholder")&&' + | ||
'("|textarea|password|number|search|email|text|tel|url".includes("|"+e.type+"|"))&&' + | ||
'(!s.match(":focus",e))' + | ||
')){' + source + '}'; | ||
break; | ||
default: | ||
@@ -1247,13 +1336,2 @@ emit('\'' + selector_string + '\' is not a valid selector' + x_error); | ||
// optimize selectors removing already checked components | ||
optimize = | ||
function(expression, token) { | ||
var index = token.index, | ||
length = token[1].length + token[2].length; | ||
return expression.slice(0, index) + | ||
(' >+~'.indexOf(expression.charAt(index - 1)) > -1 ? | ||
(':['.indexOf(expression.charAt(index + length + 1)) > -1 ? | ||
'*' : '') : '') + expression.slice(index + length); | ||
}, | ||
// parse selector groups in an array | ||
@@ -1287,6 +1365,4 @@ parseGroup = | ||
var expression, groups; | ||
var groups; | ||
lastMatched = selector; | ||
if (element && matchResolvers[selector]) { | ||
@@ -1296,2 +1372,4 @@ return !!matchResolvers[selector](element, callback); | ||
lastMatched = selector; | ||
// arguments validation | ||
@@ -1312,9 +1390,9 @@ if (arguments.length === 0) { | ||
// normalize selector | ||
expression = selector. | ||
selector = selector. | ||
replace(/\x00|\\$/g, '\ufffd'). | ||
replace(REX.TrimSpaces, ''); | ||
// parse and validate expression and split possible selector groups | ||
if ((groups = expression.match(reValidator)) && groups.join('') == expression) { | ||
groups = /\,/.test(expression) ? parseGroup(expression) : [expression]; | ||
// parse, validate and split possible selector groups | ||
if ((groups = selector.match(reValidator)) && groups.join('') == selector) { | ||
groups = /\,/.test(selector) ? parseGroup(selector) : [selector]; | ||
if (groups.indexOf('') > -1) { | ||
@@ -1358,4 +1436,14 @@ emit('invalid or illegal string specified'); | ||
var expression, groups, resolver, token; | ||
var groups, resolver, token; | ||
if (selector) { | ||
if ((resolver = selectResolvers[selector])) { | ||
if (resolver.context === context && resolver.usrcall === callback) { | ||
return resolver.factory(resolver.builder, callback, context); | ||
} | ||
} | ||
} | ||
lastSelected = selector; | ||
@@ -1365,6 +1453,6 @@ | ||
if (selector && !callback && (resolver = selectResolvers[selector])) { | ||
if (resolver.context === context) { | ||
return resolver.factory(resolver.builder, callback, context); | ||
} | ||
if (HAS_DUPE_IDS === undefined) { | ||
HAS_DUPE_IDS = hasDuplicateId(context); | ||
MIXED_NS = hasMixedNamespace(context); | ||
domapi = set_domapi(); | ||
} | ||
@@ -1379,4 +1467,4 @@ | ||
return Config.VERBOSITY ? undefined : none; | ||
} else if (lastSelectContext !== context) { | ||
lastSelectContext = switchContext(context); | ||
} else if (lastContext !== context) { | ||
lastContext = switchContext(context); | ||
} | ||
@@ -1390,9 +1478,9 @@ | ||
// normalize selector | ||
expression = selector. | ||
selector = selector. | ||
replace(/\x00|\\$/g, '\ufffd'). | ||
replace(REX.TrimSpaces, ''); | ||
// parse and validate expression and split possible selector groups | ||
if ((groups = expression.match(reValidator)) && groups.join('') == expression) { | ||
groups = /\,/.test(expression) ? parseGroup(expression) : [expression]; | ||
// parse, validate and split possible selector groups | ||
if ((groups = selector.match(reValidator)) && groups.join('') == selector) { | ||
groups = /\,/.test(selector) ? parseGroup(selector) : [selector]; | ||
if (groups.indexOf('') > -1) { | ||
@@ -1409,10 +1497,11 @@ emit('invalid or illegal string specified'); | ||
resolver = collect( | ||
groups.length < 2 ? expression : groups, context, callback, | ||
groups.length < 2 ? selector : groups, context, callback, | ||
HTML_DOCUMENT && context.nodeType != 11 ? domapi : compat); | ||
// save/reuse factory and closure collection | ||
if (!selectResolvers[selector] && !callback) { | ||
if (!selectResolvers[selector]) { | ||
selectResolvers[selector] = { | ||
builder: resolver.builder, | ||
factory: resolver.factory, | ||
usrcall: callback, | ||
context: context | ||
@@ -1425,33 +1514,40 @@ }; | ||
// optimize selectors removing already checked components | ||
optimize = | ||
function(selector, token) { | ||
var index = token.index, | ||
length = token[1].length + token[2].length; | ||
return selector.slice(0, index) + | ||
(' >+~'.indexOf(selector[index - 1]) > -1 ? | ||
(':['.indexOf(selector[index + length + 1]) > -1 ? | ||
'*' : '') : '') + selector.slice(index + length - (token[1] == '*' ? 1 : 0)); | ||
}, | ||
// prepare factory resolvers and closure collections | ||
collect = | ||
function(expression, context, callback, resolvers) { | ||
var builder, factory, ident, symbol, token; | ||
if (typeof expression == 'string') { | ||
if ((token = expression.match(reOptimizer)) && (ident = token[2])) { | ||
symbol = token[1] || '*'; | ||
ident = unescapeIdentifier(ident); | ||
if (!(symbol == '#' && context.nodeType == 1)) { | ||
if ('.#*'.indexOf(symbol) > -1) { | ||
builder = resolvers[symbol](context, ident); | ||
if (HTML_DOCUMENT && context.nodeType != 11) { | ||
expression = optimize(expression, token); | ||
} | ||
} | ||
function(selector, context, callback, resolvers) { | ||
var i, j, l, done, items, prev, builder, ident, symbol, token; | ||
if (typeof selector == 'string') { | ||
if ((token = selector.match(reOptimizer)) && (ident = token[2])) { | ||
if ((symbol = token[1] || '*') && context[method[symbol]]) { | ||
builder = resolvers[symbol](context, unescapeIdentifier(ident)); | ||
if (HTML_DOCUMENT) { selector = optimize(selector, token); } | ||
} | ||
} | ||
} else { | ||
var tn = Array(), ts = Object(), cn = Array(), cs = Object(); | ||
for (var i = 0, l = expression.length; l > i; ++i) { | ||
if ((token = expression[i].match(reOptimizer)) && (ident = token[2])) { | ||
items = { '#': Array(), '.': Array(), '*': Array() }; | ||
for (i = 0, l = selector.length; l > i; ++i) { | ||
if ((token = selector[i].match(reOptimizer)) && (ident = token[2])) { | ||
symbol = token[1] || '*'; | ||
ident = unescapeIdentifier(ident); | ||
if (prev == ident) { | ||
j = i - 1; | ||
selector[j] = optimize(selector[j], token); | ||
selector[i] = optimize(selector[i], token); | ||
} | ||
if (!done && (done = true)) { prev = ident; } | ||
} | ||
if (symbol == '*') { if (!ts[ident] && (ts[ident] = true)) { tn.push(ident); }} | ||
if (symbol == '.') { if (!cs[ident] && (cs[ident] = true)) { cn.push(ident); }} | ||
if (items[symbol]) items[symbol].push(ident); | ||
} | ||
if (tn.length == l) { | ||
builder = compat['*'](context, tn); | ||
} else if (cn.length == l) { | ||
builder = compat['.'](context, cn); | ||
if (items[symbol] && items[symbol].length == l) { | ||
builder = compat[symbol](context, items[symbol]); | ||
} else { | ||
@@ -1463,3 +1559,3 @@ builder = compat['*'](context, '*'); | ||
builder: builder || resolvers['*'](context, '*'), | ||
factory: factory || compile(expression, true, callback) | ||
factory: compile(selector, true, callback) | ||
}; | ||
@@ -1553,2 +1649,5 @@ }, | ||
// context | ||
lastContext, | ||
// selector | ||
@@ -1558,6 +1657,2 @@ lastMatched, | ||
// last context | ||
lastMatchContext, | ||
lastSelectContext, | ||
// cached lambdas | ||
@@ -1649,4 +1744,4 @@ matchLambdas = { }, | ||
for (; l > i; ++i) { | ||
if (combinator.charAt(i) != '=') { | ||
symbol = combinator.charAt(i); | ||
if (combinator[i] != '=') { | ||
symbol = combinator[i]; | ||
break; | ||
@@ -1670,4 +1765,4 @@ } | ||
for (; l > i; ++i) { | ||
if (operator.charAt(i) != '=') { | ||
symbol = operator.charAt(i); | ||
if (operator[i] != '=') { | ||
symbol = operator[i]; | ||
break; | ||
@@ -1674,0 +1769,0 @@ } |
@@ -70,5 +70,5 @@ // Require selectors.js to be included before this. | ||
if (obj.ownerDocument) { // The object is not a Document | ||
// assert_true(list instanceof obj.ownerDocument.defaultView.NodeList, "The result should be an instance of a NodeList") | ||
assert_true(list instanceof obj.ownerDocument.defaultView.NodeList, "The result should be an instance of a NodeList") | ||
} else { // The object is a Document | ||
// assert_true(list instanceof obj.defaultView.NodeList, "The result should be an instance of a NodeList") | ||
assert_true(list instanceof obj.defaultView.NodeList, "The result should be an instance of a NodeList") | ||
} | ||
@@ -75,0 +75,0 @@ }, type + ".querySelectorAll returns NodeList instance") |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
15853037
1
263
45633
7
13