From b9a893aab68a6f6980b738a34d7345b5dbb7757d Mon Sep 17 00:00:00 2001 From: Amjad Masad Date: Wed, 2 Mar 2016 12:20:11 -0800 Subject: [PATCH] Move NodePath cache out of the AST As mentioned on the task https://phabricator.babeljs.io/T7179 having this cache on the AST leads to all sorts of portability and reuse bugs. This moves the cache into a clearable WeakMap which will fix the following: 1. Moving the AST between different babel versions or tools will not lead into sharing potentially outdated cached information 2. `.clear()` can be called on the cache by a plugin to clear potentially outdated information. This is helpful when implementing two seperate pipelines that should not share information. I think the next step (which is harder, I tried) is to isolate cache and make it live on a transform or pipeline level state (like the `hub`). The reason it is hard is because the `babel-traverse` main API -- although requires the state object to be passed -- not many callers do. To fix this we should release a patch version that warns about this and fix all the internal callers. Next couple of releases we can start throwing when no state is passed (or we can create our own state). --- packages/babel-traverse/src/index.js | 1 + packages/babel-traverse/src/path/cache.js | 25 +++++++++++++++++++ packages/babel-traverse/src/path/constants.js | 1 - packages/babel-traverse/src/path/index.js | 8 ++++-- .../babel-traverse/src/path/modification.js | 4 +-- 5 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 packages/babel-traverse/src/path/cache.js delete mode 100644 packages/babel-traverse/src/path/constants.js diff --git a/packages/babel-traverse/src/index.js b/packages/babel-traverse/src/index.js index 01a48112c4d9..099e6f0bf7d9 100644 --- a/packages/babel-traverse/src/index.js +++ b/packages/babel-traverse/src/index.js @@ -9,6 +9,7 @@ import * as t from "babel-types"; export { default as NodePath } from "./path"; export { default as Scope } from "./scope"; export { default as Hub } from "./hub"; +export { default as cache } from "./path/cache"; export { visitors }; export default function traverse( diff --git a/packages/babel-traverse/src/path/cache.js b/packages/babel-traverse/src/path/cache.js new file mode 100644 index 000000000000..a58ecc5f08de --- /dev/null +++ b/packages/babel-traverse/src/path/cache.js @@ -0,0 +1,25 @@ +let wm = new WeakMap(); + +// To implement clear we need to export a facade. +export default { + clear() { + wm = new WeakMap(); + }, + + delete(k) { + return wm.delete(k) + }, + + get(k) { + return wm.get(k) + }, + + has(k) { + return wm.has(k) + }, + + set(k, v) { + wm.set(k, v); + return wm; + }, +}; diff --git a/packages/babel-traverse/src/path/constants.js b/packages/babel-traverse/src/path/constants.js deleted file mode 100644 index 11431edfe431..000000000000 --- a/packages/babel-traverse/src/path/constants.js +++ /dev/null @@ -1 +0,0 @@ -export const PATH_CACHE_KEY = "_paths"; //Symbol(); diff --git a/packages/babel-traverse/src/path/index.js b/packages/babel-traverse/src/path/index.js index 4fa06c9b3033..fadb928ab6ae 100644 --- a/packages/babel-traverse/src/path/index.js +++ b/packages/babel-traverse/src/path/index.js @@ -4,12 +4,12 @@ import type Hub from "../hub"; import type TraversalContext from "../context"; import * as virtualTypes from "./lib/virtual-types"; import buildDebug from "debug"; -import { PATH_CACHE_KEY } from "./constants"; import invariant from "invariant"; import traverse from "../index"; import assign from "lodash/object/assign"; import Scope from "../scope"; import * as t from "babel-types"; +import cache from "./cache"; let debug = buildDebug("babel"); @@ -69,7 +69,11 @@ export default class NodePath { let targetNode = container[key]; - let paths = parent[PATH_CACHE_KEY] = parent[PATH_CACHE_KEY] || []; + let paths = cache.get(parent) || []; + if (!cache.has(parent)) { + cache.set(parent, paths); + } + let path; for (let i = 0; i < paths.length; i++) { diff --git a/packages/babel-traverse/src/path/modification.js b/packages/babel-traverse/src/path/modification.js index b2827613a3ac..c32745bb9c3a 100644 --- a/packages/babel-traverse/src/path/modification.js +++ b/packages/babel-traverse/src/path/modification.js @@ -1,7 +1,7 @@ /* eslint max-len: 0 */ // This file contains methods that modify the path/node in some ways. -import { PATH_CACHE_KEY } from "./constants"; +import cache from "./cache"; import PathHoister from "./lib/hoister"; import NodePath from "./index"; import * as t from "babel-types"; @@ -136,7 +136,7 @@ export function insertAfter(nodes) { export function updateSiblingKeys(fromIndex, incrementBy) { if (!this.parent) return; - let paths = this.parent[PATH_CACHE_KEY]; + let paths = cache.get(this.parent); for (let i = 0; i < paths.length; i++) { let path = paths[i]; if (path.key >= fromIndex) {