1 | let shouldSkip;
|
2 | let shouldAbort;
|
3 |
|
4 | export default function walk ( ast, { enter, leave }) {
|
5 | shouldAbort = false;
|
6 | visit( ast, null, enter, leave );
|
7 | }
|
8 |
|
9 | let context = {
|
10 | skip: () => shouldSkip = true,
|
11 | abort: () => shouldAbort = true
|
12 | };
|
13 |
|
14 | let childKeys = {};
|
15 |
|
16 | let toString = Object.prototype.toString;
|
17 |
|
18 | function isArray ( thing ) {
|
19 | return toString.call( thing ) === '[object Array]';
|
20 | }
|
21 |
|
22 | function visit ( node, parent, enter, leave ) {
|
23 | if ( !node || shouldAbort ) return;
|
24 |
|
25 | if ( enter ) {
|
26 | shouldSkip = false;
|
27 | enter.call( context, node, parent );
|
28 | if ( shouldSkip || shouldAbort ) return;
|
29 | }
|
30 |
|
31 | let keys = childKeys[ node.type ] || (
|
32 | childKeys[ node.type ] = Object.keys( node ).filter( key => typeof node[ key ] === 'object' )
|
33 | );
|
34 |
|
35 | let key, value, i, j;
|
36 |
|
37 | i = keys.length;
|
38 | while ( i-- ) {
|
39 | key = keys[i];
|
40 | value = node[ key ];
|
41 |
|
42 | if ( isArray( value ) ) {
|
43 | j = value.length;
|
44 | while ( j-- ) {
|
45 | visit( value[j], node, enter, leave );
|
46 | }
|
47 | }
|
48 |
|
49 | else if ( value && value.type ) {
|
50 | visit( value, node, enter, leave );
|
51 | }
|
52 | }
|
53 |
|
54 | if ( leave && !shouldAbort ) {
|
55 | leave( node, parent );
|
56 | }
|
57 | } |
\ | No newline at end of file |