Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/ajv/lib/compile/util.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
239 lines (192 sloc)
6.81 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
module.exports = { | |
copy: copy, | |
checkDataType: checkDataType, | |
checkDataTypes: checkDataTypes, | |
coerceToTypes: coerceToTypes, | |
toHash: toHash, | |
getProperty: getProperty, | |
escapeQuotes: escapeQuotes, | |
equal: require('fast-deep-equal'), | |
ucs2length: require('./ucs2length'), | |
varOccurences: varOccurences, | |
varReplace: varReplace, | |
schemaHasRules: schemaHasRules, | |
schemaHasRulesExcept: schemaHasRulesExcept, | |
schemaUnknownRules: schemaUnknownRules, | |
toQuotedString: toQuotedString, | |
getPathExpr: getPathExpr, | |
getPath: getPath, | |
getData: getData, | |
unescapeFragment: unescapeFragment, | |
unescapeJsonPointer: unescapeJsonPointer, | |
escapeFragment: escapeFragment, | |
escapeJsonPointer: escapeJsonPointer | |
}; | |
function copy(o, to) { | |
to = to || {}; | |
for (var key in o) to[key] = o[key]; | |
return to; | |
} | |
function checkDataType(dataType, data, strictNumbers, negate) { | |
var EQUAL = negate ? ' !== ' : ' === ' | |
, AND = negate ? ' || ' : ' && ' | |
, OK = negate ? '!' : '' | |
, NOT = negate ? '' : '!'; | |
switch (dataType) { | |
case 'null': return data + EQUAL + 'null'; | |
case 'array': return OK + 'Array.isArray(' + data + ')'; | |
case 'object': return '(' + OK + data + AND + | |
'typeof ' + data + EQUAL + '"object"' + AND + | |
NOT + 'Array.isArray(' + data + '))'; | |
case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND + | |
NOT + '(' + data + ' % 1)' + | |
AND + data + EQUAL + data + | |
(strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')'; | |
case 'number': return '(typeof ' + data + EQUAL + '"' + dataType + '"' + | |
(strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')'; | |
default: return 'typeof ' + data + EQUAL + '"' + dataType + '"'; | |
} | |
} | |
function checkDataTypes(dataTypes, data, strictNumbers) { | |
switch (dataTypes.length) { | |
case 1: return checkDataType(dataTypes[0], data, strictNumbers, true); | |
default: | |
var code = ''; | |
var types = toHash(dataTypes); | |
if (types.array && types.object) { | |
code = types.null ? '(': '(!' + data + ' || '; | |
code += 'typeof ' + data + ' !== "object")'; | |
delete types.null; | |
delete types.array; | |
delete types.object; | |
} | |
if (types.number) delete types.integer; | |
for (var t in types) | |
code += (code ? ' && ' : '' ) + checkDataType(t, data, strictNumbers, true); | |
return code; | |
} | |
} | |
var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]); | |
function coerceToTypes(optionCoerceTypes, dataTypes) { | |
if (Array.isArray(dataTypes)) { | |
var types = []; | |
for (var i=0; i<dataTypes.length; i++) { | |
var t = dataTypes[i]; | |
if (COERCE_TO_TYPES[t]) types[types.length] = t; | |
else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t; | |
} | |
if (types.length) return types; | |
} else if (COERCE_TO_TYPES[dataTypes]) { | |
return [dataTypes]; | |
} else if (optionCoerceTypes === 'array' && dataTypes === 'array') { | |
return ['array']; | |
} | |
} | |
function toHash(arr) { | |
var hash = {}; | |
for (var i=0; i<arr.length; i++) hash[arr[i]] = true; | |
return hash; | |
} | |
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i; | |
var SINGLE_QUOTE = /'|\\/g; | |
function getProperty(key) { | |
return typeof key == 'number' | |
? '[' + key + ']' | |
: IDENTIFIER.test(key) | |
? '.' + key | |
: "['" + escapeQuotes(key) + "']"; | |
} | |
function escapeQuotes(str) { | |
return str.replace(SINGLE_QUOTE, '\\$&') | |
.replace(/\n/g, '\\n') | |
.replace(/\r/g, '\\r') | |
.replace(/\f/g, '\\f') | |
.replace(/\t/g, '\\t'); | |
} | |
function varOccurences(str, dataVar) { | |
dataVar += '[^0-9]'; | |
var matches = str.match(new RegExp(dataVar, 'g')); | |
return matches ? matches.length : 0; | |
} | |
function varReplace(str, dataVar, expr) { | |
dataVar += '([^0-9])'; | |
expr = expr.replace(/\$/g, '$$$$'); | |
return str.replace(new RegExp(dataVar, 'g'), expr + '$1'); | |
} | |
function schemaHasRules(schema, rules) { | |
if (typeof schema == 'boolean') return !schema; | |
for (var key in schema) if (rules[key]) return true; | |
} | |
function schemaHasRulesExcept(schema, rules, exceptKeyword) { | |
if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not'; | |
for (var key in schema) if (key != exceptKeyword && rules[key]) return true; | |
} | |
function schemaUnknownRules(schema, rules) { | |
if (typeof schema == 'boolean') return; | |
for (var key in schema) if (!rules[key]) return key; | |
} | |
function toQuotedString(str) { | |
return '\'' + escapeQuotes(str) + '\''; | |
} | |
function getPathExpr(currentPath, expr, jsonPointers, isNumber) { | |
var path = jsonPointers // false by default | |
? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')') | |
: (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\''); | |
return joinPaths(currentPath, path); | |
} | |
function getPath(currentPath, prop, jsonPointers) { | |
var path = jsonPointers // false by default | |
? toQuotedString('/' + escapeJsonPointer(prop)) | |
: toQuotedString(getProperty(prop)); | |
return joinPaths(currentPath, path); | |
} | |
var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/; | |
var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/; | |
function getData($data, lvl, paths) { | |
var up, jsonPointer, data, matches; | |
if ($data === '') return 'rootData'; | |
if ($data[0] == '/') { | |
if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data); | |
jsonPointer = $data; | |
data = 'rootData'; | |
} else { | |
matches = $data.match(RELATIVE_JSON_POINTER); | |
if (!matches) throw new Error('Invalid JSON-pointer: ' + $data); | |
up = +matches[1]; | |
jsonPointer = matches[2]; | |
if (jsonPointer == '#') { | |
if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl); | |
return paths[lvl - up]; | |
} | |
if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl); | |
data = 'data' + ((lvl - up) || ''); | |
if (!jsonPointer) return data; | |
} | |
var expr = data; | |
var segments = jsonPointer.split('/'); | |
for (var i=0; i<segments.length; i++) { | |
var segment = segments[i]; | |
if (segment) { | |
data += getProperty(unescapeJsonPointer(segment)); | |
expr += ' && ' + data; | |
} | |
} | |
return expr; | |
} | |
function joinPaths (a, b) { | |
if (a == '""') return b; | |
return (a + ' + ' + b).replace(/([^\\])' \+ '/g, '$1'); | |
} | |
function unescapeFragment(str) { | |
return unescapeJsonPointer(decodeURIComponent(str)); | |
} | |
function escapeFragment(str) { | |
return encodeURIComponent(escapeJsonPointer(str)); | |
} | |
function escapeJsonPointer(str) { | |
return str.replace(/~/g, '~0').replace(/\//g, '~1'); | |
} | |
function unescapeJsonPointer(str) { | |
return str.replace(/~1/g, '/').replace(/~0/g, '~'); | |
} |