| "use strict"; |
| |
| Object.defineProperty(exports, "__esModule", { |
| value: true |
| }); |
| exports.default = void 0; |
| |
| var _debug = _interopRequireDefault(require("debug")); |
| |
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
| |
| const debug = (0, _debug.default)('requireExportJsdoc'); |
| |
| const createNode = function createNode() { |
| return { |
| props: {} |
| }; |
| }; |
| |
| const getSymbolValue = function getSymbolValue(symbol) { |
| /* istanbul ignore next */ |
| if (!symbol) { |
| /* istanbul ignore next */ |
| return null; |
| } |
| /* istanbul ignore next */ |
| |
| |
| if (symbol.type === 'literal') { |
| return symbol.value.value; |
| } |
| /* istanbul ignore next */ |
| |
| |
| return null; |
| }; |
| |
| const getIdentifier = function getIdentifier(node, globals, scope, opts) { |
| if (opts.simpleIdentifier) { |
| // Type is Identier for noncomputed properties |
| const identifierLiteral = createNode(); |
| identifierLiteral.type = 'literal'; |
| identifierLiteral.value = { |
| value: node.name |
| }; |
| return identifierLiteral; |
| } |
| /* istanbul ignore next */ |
| |
| |
| const block = scope || globals; // As scopes are not currently supported, they are not traversed upwards recursively |
| |
| if (block.props[node.name]) { |
| return block.props[node.name]; |
| } // Seems this will only be entered once scopes added and entered |
| |
| /* istanbul ignore next */ |
| |
| |
| if (globals.props[node.name]) { |
| return globals.props[node.name]; |
| } |
| |
| return null; |
| }; |
| |
| let _createSymbol = null; |
| |
| const getSymbol = function getSymbol(node, globals, scope, opt) { |
| const opts = opt || {}; |
| |
| switch (node.type) { |
| case 'Identifier': |
| { |
| return getIdentifier(node, globals, scope, opts); |
| } |
| |
| case 'MemberExpression': |
| { |
| const obj = getSymbol(node.object, globals, scope, opts); |
| const propertySymbol = getSymbol(node.property, globals, scope, { |
| simpleIdentifier: !node.computed |
| }); |
| const propertyValue = getSymbolValue(propertySymbol); |
| /* istanbul ignore next */ |
| |
| if (obj && propertyValue && obj.props[propertyValue]) { |
| const block = obj.props[propertyValue]; |
| return block; |
| } |
| /* |
| if (opts.createMissingProps && propertyValue) { |
| obj.props[propertyValue] = createNode(); |
| return obj.props[propertyValue]; |
| } |
| */ |
| |
| /* istanbul ignore next */ |
| |
| |
| debug(`MemberExpression: Missing property ${node.property.name}`); |
| /* istanbul ignore next */ |
| |
| return null; |
| } |
| |
| case 'ClassDeclaration': |
| case 'ClassExpression': |
| case 'FunctionExpression': |
| case 'FunctionDeclaration': |
| case 'ArrowFunctionExpression': |
| { |
| const val = createNode(); |
| val.props.prototype = createNode(); |
| val.props.prototype.type = 'object'; |
| val.type = 'object'; |
| val.value = node; |
| return val; |
| } |
| |
| case 'AssignmentExpression': |
| { |
| return _createSymbol(node.left, globals, node.right, scope, opts); |
| } |
| |
| case 'ClassBody': |
| { |
| const val = createNode(); |
| node.body.forEach(method => { |
| val.props[method.key.name] = createNode(); |
| val.props[method.key.name].type = 'object'; |
| val.props[method.key.name].value = method.value; |
| }); |
| val.type = 'object'; |
| val.value = node; |
| return val; |
| } |
| |
| case 'ObjectExpression': |
| { |
| const val = createNode(); |
| val.type = 'object'; |
| node.properties.forEach(prop => { |
| if ([// @typescript-eslint/parser, espree, acorn, etc. |
| 'SpreadElement', // babel-eslint |
| 'ExperimentalSpreadProperty'].includes(prop.type)) { |
| return; |
| } |
| |
| const propVal = getSymbol(prop.value, globals, scope, opts); |
| /* istanbul ignore next */ |
| |
| if (propVal) { |
| val.props[prop.key.name] = propVal; |
| } |
| }); |
| return val; |
| } |
| |
| case 'Literal': |
| { |
| const val = createNode(); |
| val.type = 'literal'; |
| val.value = node; |
| return val; |
| } |
| } |
| /* istanbul ignore next */ |
| |
| |
| return null; |
| }; |
| |
| const createBlockSymbol = function createBlockSymbol(block, name, value, globals, isGlobal) { |
| block.props[name] = value; |
| |
| if (isGlobal && globals.props.window && globals.props.window.special) { |
| globals.props.window.props[name] = value; |
| } |
| }; |
| |
| _createSymbol = function createSymbol(node, globals, value, scope, isGlobal) { |
| const block = scope || globals; |
| let symbol; |
| |
| switch (node.type) { |
| case 'FunctionDeclaration': // Fallthrough |
| |
| case 'ClassDeclaration': |
| { |
| if (node.id && node.id.type === 'Identifier') { |
| return _createSymbol(node.id, globals, node, globals); |
| } |
| |
| break; |
| } |
| |
| case 'Identifier': |
| { |
| if (value) { |
| const valueSymbol = getSymbol(value, globals, block); |
| /* istanbul ignore next */ |
| |
| if (valueSymbol) { |
| createBlockSymbol(block, node.name, valueSymbol, globals, isGlobal); |
| return block.props[node.name]; |
| } |
| /* istanbul ignore next */ |
| |
| |
| debug('Identifier: Missing value symbol for %s', node.name); |
| } else { |
| createBlockSymbol(block, node.name, createNode(), globals, isGlobal); |
| return block.props[node.name]; |
| } |
| /* istanbul ignore next */ |
| |
| |
| break; |
| } |
| |
| case 'MemberExpression': |
| { |
| symbol = getSymbol(node.object, globals, block); |
| const propertySymbol = getSymbol(node.property, globals, block, { |
| simpleIdentifier: !node.computed |
| }); |
| const propertyValue = getSymbolValue(propertySymbol); |
| |
| if (symbol && propertyValue) { |
| createBlockSymbol(symbol, propertyValue, getSymbol(value, globals, block), globals, isGlobal); |
| return symbol.props[propertyValue]; |
| } |
| /* istanbul ignore next */ |
| |
| |
| debug('MemberExpression: Missing symbol: %s', node.property.name); |
| break; |
| } |
| } |
| |
| return null; |
| }; // Creates variables from variable definitions |
| |
| |
| const initVariables = function initVariables(node, globals, opts) { |
| switch (node.type) { |
| case 'Program': |
| { |
| node.body.forEach(childNode => { |
| initVariables(childNode, globals, opts); |
| }); |
| break; |
| } |
| |
| case 'ExpressionStatement': |
| { |
| initVariables(node.expression, globals, opts); |
| break; |
| } |
| |
| case 'VariableDeclaration': |
| { |
| node.declarations.forEach(declaration => { |
| // let and const |
| const symbol = _createSymbol(declaration.id, globals, null, globals); |
| |
| if (opts.initWindow && node.kind === 'var' && globals.props.window) { |
| // If var, also add to window |
| globals.props.window.props[declaration.id.name] = symbol; |
| } |
| }); |
| break; |
| } |
| |
| case 'ExportNamedDeclaration': |
| { |
| if (node.declaration) { |
| initVariables(node.declaration, globals, opts); |
| } |
| |
| break; |
| } |
| } |
| }; // Populates variable maps using AST |
| |
| |
| const mapVariables = function mapVariables(node, globals, opt, isExport) { |
| /* istanbul ignore next */ |
| const opts = opt || {}; |
| /* istanbul ignore next */ |
| |
| switch (node.type) { |
| case 'Program': |
| { |
| if (opts.ancestorsOnly) { |
| return false; |
| } |
| |
| node.body.forEach(childNode => { |
| mapVariables(childNode, globals, opts); |
| }); |
| break; |
| } |
| |
| case 'ExpressionStatement': |
| { |
| mapVariables(node.expression, globals, opts); |
| break; |
| } |
| |
| case 'AssignmentExpression': |
| { |
| _createSymbol(node.left, globals, node.right); |
| |
| break; |
| } |
| |
| case 'VariableDeclaration': |
| { |
| node.declarations.forEach(declaration => { |
| const isGlobal = opts.initWindow && node.kind === 'var' && globals.props.window; |
| |
| const symbol = _createSymbol(declaration.id, globals, declaration.init, globals, isGlobal); |
| |
| if (symbol && isExport) { |
| symbol.exported = true; |
| } |
| }); |
| break; |
| } |
| |
| case 'FunctionDeclaration': |
| { |
| /* istanbul ignore next */ |
| if (node.id.type === 'Identifier') { |
| _createSymbol(node.id, globals, node, globals, true); |
| } |
| |
| break; |
| } |
| |
| case 'ExportDefaultDeclaration': |
| { |
| const symbol = _createSymbol(node.declaration, globals, node.declaration); |
| |
| if (symbol) { |
| symbol.exported = true; |
| } else if (!node.id) { |
| globals.ANONYMOUS_DEFAULT = node.declaration; |
| } |
| |
| break; |
| } |
| |
| case 'ExportNamedDeclaration': |
| { |
| if (node.declaration) { |
| if (node.declaration.type === 'VariableDeclaration') { |
| mapVariables(node.declaration, globals, opts, true); |
| } else { |
| const symbol = _createSymbol(node.declaration, globals, node.declaration); |
| /* istanbul ignore next */ |
| |
| |
| if (symbol) { |
| symbol.exported = true; |
| } |
| } |
| } |
| |
| node.specifiers.forEach(specifier => { |
| mapVariables(specifier, globals, opts); |
| }); |
| break; |
| } |
| |
| case 'ExportSpecifier': |
| { |
| const symbol = getSymbol(node.local, globals, globals); |
| /* istanbul ignore next */ |
| |
| if (symbol) { |
| symbol.exported = true; |
| } |
| |
| break; |
| } |
| |
| case 'ClassDeclaration': |
| { |
| _createSymbol(node.id, globals, node.body, globals); |
| |
| break; |
| } |
| |
| default: |
| { |
| /* istanbul ignore next */ |
| return false; |
| } |
| } |
| |
| return true; |
| }; |
| |
| const findNode = function findNode(node, block, cache) { |
| let blockCache = cache || []; |
| /* istanbul ignore next */ |
| |
| if (!block || blockCache.includes(block)) { |
| return false; |
| } |
| |
| blockCache = blockCache.slice(); |
| blockCache.push(block); |
| |
| if (block.type === 'object') { |
| if (block.value === node) { |
| return true; |
| } |
| } |
| |
| const props = block.props; |
| |
| for (const prop in props) { |
| /* istanbul ignore next */ |
| if (Object.prototype.hasOwnProperty.call(props, prop)) { |
| const propval = props[prop]; // Only check node if it had resolvable value |
| |
| if (propval && findNode(node, propval, blockCache)) { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| }; |
| |
| const findExportedNode = function findExportedNode(block, node, cache) { |
| if (block.ANONYMOUS_DEFAULT === node) { |
| return true; |
| } |
| /* istanbul ignore next */ |
| |
| |
| if (block === null) { |
| return false; |
| } |
| |
| const blockCache = cache || []; |
| const props = block.props; |
| |
| for (const key in props) { |
| /* istanbul ignore next */ |
| if (Object.prototype.hasOwnProperty.call(props, key)) { |
| blockCache.push(props[key]); |
| |
| if (props[key].exported) { |
| if (node === props[key].value || findNode(node, props[key].value)) { |
| return true; |
| } |
| } // No need to check `props[key]` for exported nodes as ESM |
| // exports are only global |
| |
| } |
| } |
| |
| return false; |
| }; |
| |
| const isNodeExported = function isNodeExported(node, globals, opt) { |
| if (opt.initModuleExports && globals.props.module && globals.props.module.props.exports) { |
| if (findNode(node, globals.props.module.props.exports)) { |
| return true; |
| } |
| } |
| |
| if (opt.initWindow && globals.props.window) { |
| if (findNode(node, globals.props.window)) { |
| return true; |
| } |
| } |
| |
| if (opt.esm && findExportedNode(globals, node)) { |
| return true; |
| } |
| |
| return false; |
| }; |
| |
| const parseRecursive = function parseRecursive(node, globalVars, opts) { |
| // Iterate from top using recursion - stop at first processed node from top |
| if (node.parent) { |
| if (parseRecursive(node.parent, globalVars, opts)) { |
| return true; |
| } |
| } |
| |
| return mapVariables(node, globalVars, opts); |
| }; |
| |
| const parse = function parse(ast, node, opt) { |
| /* istanbul ignore next */ |
| const opts = opt || { |
| ancestorsOnly: false, |
| esm: true, |
| initModuleExports: true, |
| initWindow: true |
| }; |
| const globalVars = createNode(); |
| |
| if (opts.initModuleExports) { |
| globalVars.props.module = createNode(); |
| globalVars.props.module.props.exports = createNode(); |
| globalVars.props.exports = globalVars.props.module.props.exports; |
| } |
| |
| if (opts.initWindow) { |
| globalVars.props.window = createNode(); |
| globalVars.props.window.special = true; |
| } |
| |
| if (opts.ancestorsOnly) { |
| parseRecursive(node, globalVars, opts); |
| } else { |
| initVariables(ast, globalVars, opts); |
| mapVariables(ast, globalVars, opts); |
| } |
| |
| return { |
| globalVars |
| }; |
| }; |
| |
| const isExported = function isExported(node, parseResult, opt) { |
| return isNodeExported(node, parseResult.globalVars, opt); |
| }; |
| |
| var _default = { |
| isExported, |
| parse |
| }; |
| exports.default = _default; |
| module.exports = exports.default; |
| //# sourceMappingURL=exportParser.js.map |