Files
upload-google-play/node_modules/acorn-globals/index.js
Drew Heavner bdde081050 Fixed #1 - Fixed the whatsnew-** script for loading release notes into builds
Added test to ensure that release notes are parsed properly
Updated to latest dependencies to fix security vulnerability
Updated GH Actions Workflow to run test before updating tag
Updated README.md to reflect proper whatsnew documentation.
2020-01-30 11:14:51 -05:00

180 lines
5.4 KiB
JavaScript

'use strict';
var acorn = require('acorn');
var walk = require('acorn-walk');
function isScope(node) {
return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression' || node.type === 'Program';
}
function isBlockScope(node) {
return node.type === 'BlockStatement' || isScope(node);
}
function declaresArguments(node) {
return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration';
}
function declaresThis(node) {
return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration';
}
function reallyParse(source, options) {
var parseOptions = Object.assign({}, options,
{
allowReturnOutsideFunction: true,
allowImportExportEverywhere: true,
allowHashBang: true
}
);
return acorn.parse(source, parseOptions);
}
module.exports = findGlobals;
module.exports.parse = reallyParse;
function findGlobals(source, options) {
options = options || {};
var globals = [];
var ast;
// istanbul ignore else
if (typeof source === 'string') {
ast = reallyParse(source, options);
} else {
ast = source;
}
// istanbul ignore if
if (!(ast && typeof ast === 'object' && ast.type === 'Program')) {
throw new TypeError('Source must be either a string of JavaScript or an acorn AST');
}
var declareFunction = function (node) {
var fn = node;
fn.locals = fn.locals || Object.create(null);
node.params.forEach(function (node) {
declarePattern(node, fn);
});
if (node.id) {
fn.locals[node.id.name] = true;
}
};
var declareClass = function (node) {
node.locals = node.locals || Object.create(null);
if (node.id) {
node.locals[node.id.name] = true;
}
};
var declarePattern = function (node, parent) {
switch (node.type) {
case 'Identifier':
parent.locals[node.name] = true;
break;
case 'ObjectPattern':
node.properties.forEach(function (node) {
declarePattern(node.value || node.argument, parent);
});
break;
case 'ArrayPattern':
node.elements.forEach(function (node) {
if (node) declarePattern(node, parent);
});
break;
case 'RestElement':
declarePattern(node.argument, parent);
break;
case 'AssignmentPattern':
declarePattern(node.left, parent);
break;
// istanbul ignore next
default:
throw new Error('Unrecognized pattern type: ' + node.type);
}
};
var declareModuleSpecifier = function (node, parents) {
ast.locals = ast.locals || Object.create(null);
ast.locals[node.local.name] = true;
};
walk.ancestor(ast, {
'VariableDeclaration': function (node, parents) {
var parent = null;
for (var i = parents.length - 1; i >= 0 && parent === null; i--) {
if (node.kind === 'var' ? isScope(parents[i]) : isBlockScope(parents[i])) {
parent = parents[i];
}
}
parent.locals = parent.locals || Object.create(null);
node.declarations.forEach(function (declaration) {
declarePattern(declaration.id, parent);
});
},
'FunctionDeclaration': function (node, parents) {
var parent = null;
for (var i = parents.length - 2; i >= 0 && parent === null; i--) {
if (isScope(parents[i])) {
parent = parents[i];
}
}
parent.locals = parent.locals || Object.create(null);
if (node.id) {
parent.locals[node.id.name] = true;
}
declareFunction(node);
},
'Function': declareFunction,
'ClassDeclaration': function (node, parents) {
var parent = null;
for (var i = parents.length - 2; i >= 0 && parent === null; i--) {
if (isBlockScope(parents[i])) {
parent = parents[i];
}
}
parent.locals = parent.locals || Object.create(null);
if (node.id) {
parent.locals[node.id.name] = true;
}
declareClass(node);
},
'Class': declareClass,
'TryStatement': function (node) {
if (node.handler === null) return;
node.handler.locals = node.handler.locals || Object.create(null);
declarePattern(node.handler.param, node.handler);
},
'ImportDefaultSpecifier': declareModuleSpecifier,
'ImportSpecifier': declareModuleSpecifier,
'ImportNamespaceSpecifier': declareModuleSpecifier
});
function identifier(node, parents) {
var name = node.name;
if (name === 'undefined') return;
for (var i = 0; i < parents.length; i++) {
if (name === 'arguments' && declaresArguments(parents[i])) {
return;
}
if (parents[i].locals && name in parents[i].locals) {
return;
}
}
node.parents = parents.slice();
globals.push(node);
}
walk.ancestor(ast, {
'VariablePattern': identifier,
'Identifier': identifier,
'ThisExpression': function (node, parents) {
for (var i = 0; i < parents.length; i++) {
if (declaresThis(parents[i])) {
return;
}
}
node.parents = parents.slice();
globals.push(node);
}
});
var groupedGlobals = Object.create(null);
globals.forEach(function (node) {
var name = node.type === 'ThisExpression' ? 'this' : node.name;
groupedGlobals[name] = (groupedGlobals[name] || []);
groupedGlobals[name].push(node);
});
return Object.keys(groupedGlobals).sort().map(function (name) {
return {name: name, nodes: groupedGlobals[name]};
});
}