From c21594961019ef3dabc19968b411b1754a6a7079 Mon Sep 17 00:00:00 2001 From: Jakub Gieryluk Date: Fri, 3 May 2019 17:43:49 +0200 Subject: [PATCH] Check if base visitor is defined (fix #829) --- acorn-walk/README.md | 17 +++++++++++++++++ acorn-walk/src/index.js | 23 +++++++++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/acorn-walk/README.md b/acorn-walk/README.md index e192baced..0c6a7c343 100644 --- a/acorn-walk/README.md +++ b/acorn-walk/README.md @@ -124,3 +124,20 @@ the given position. **findNodeAfter**`(node, pos, test, base, state)` is similar to `findNodeAround`, but will match all nodes *after* the given position (testing outer nodes before inner nodes). + + +## Walking with a plugin + +When you use a parser plugin, e.g. `acorn-jsx`, you might see an error +message like `Base visitor for type JSXElement not found`. +In such case, you need to pass an additional `base` parameter, +in which you define the base visitors for all the types defined +by the plugin. For example, you can extend the default base in the +following way: + +```js +walk.simple(parsedJsx, {}, { + ...walk.base, + JSXElement: () => {} +}) +```` diff --git a/acorn-walk/src/index.js b/acorn-walk/src/index.js index 25f5166f1..e5ce5e5a9 100644 --- a/acorn-walk/src/index.js +++ b/acorn-walk/src/index.js @@ -1,5 +1,12 @@ // AST walker module for Mozilla Parser API compatible trees +function assertBaseVisitor(baseVisitor, type) { + if (typeof baseVisitor[type] !== "function") { + throw new Error(`Base visitor for type ${type} not found. You should define it in the 'base' parameter.`) + } + return true +} + // A simple walk is one where you simply specify callbacks to be // called on specific nodes. The last two arguments are optional. A // simple use would be @@ -20,7 +27,7 @@ export function simple(node, visitors, baseVisitor, state, override) { if (!baseVisitor) baseVisitor = base ;(function c(node, st, override) { let type = override || node.type, found = visitors[type] - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) if (found) found(node, st) })(node, state, override) } @@ -35,7 +42,7 @@ export function ancestor(node, visitors, baseVisitor, state) { let type = override || node.type, found = visitors[type] let isNew = node !== ancestors[ancestors.length - 1] if (isNew) ancestors.push(node) - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) if (found) found(node, st || ancestors, ancestors) if (isNew) ancestors.pop() })(node, state) @@ -71,7 +78,7 @@ export function full(node, callback, baseVisitor, state, override) { if (!baseVisitor) baseVisitor = base ;(function c(node, st, override) { let type = override || node.type - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) if (!override) callback(node, st, type) })(node, state, override) } @@ -85,7 +92,7 @@ export function fullAncestor(node, callback, baseVisitor, state) { let type = override || node.type let isNew = node !== ancestors[ancestors.length - 1] if (isNew) ancestors.push(node) - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) if (!override) callback(node, st || ancestors, ancestors, type) if (isNew) ancestors.pop() })(node, state) @@ -102,7 +109,7 @@ export function findNodeAt(node, start, end, test, baseVisitor, state) { let type = override || node.type if ((start == null || node.start <= start) && (end == null || node.end >= end)) - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) if ((start == null || node.start === start) && (end == null || node.end === end) && test(type, node)) @@ -123,7 +130,7 @@ export function findNodeAround(node, pos, test, baseVisitor, state) { (function c(node, st, override) { let type = override || node.type if (node.start > pos || node.end < pos) return - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) if (test(type, node)) throw new Found(node, st) })(node, state) } catch (e) { @@ -141,7 +148,7 @@ export function findNodeAfter(node, pos, test, baseVisitor, state) { if (node.end < pos) return let type = override || node.type if (node.start >= pos && test(type, node)) throw new Found(node, st) - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) })(node, state) } catch (e) { if (e instanceof Found) return e @@ -159,7 +166,7 @@ export function findNodeBefore(node, pos, test, baseVisitor, state) { let type = override || node.type if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node)) max = new Found(node, st) - baseVisitor[type](node, st, c) + assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c) })(node, state) return max }