Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helper-hoist-variables docs #2500

Merged
merged 3 commits into from Apr 26, 2021
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 44 additions & 3 deletions docs/helper-hoist-variables.md
Expand Up @@ -10,11 +10,52 @@ npm install @babel/helper-hoist-variables --save

## API

```javascript
declare export default hoistVariables(path: NodePath, emit: Function, kind: "var" | "let" = "var");
```typescript
type EmitFunction = (
id: t.Identifier,
idName: string,
hasInit: boolean,
) => any;

declare export default hoistVariables(path: NodePath, emit: EmitFunction, kind: "var" | "let" = "var");
```

## Usage

TODO
`hoistVariables` traverses a given `path` and replaces variable declarations (`var x = 1`) to assignment expressions (`x = 1`). It can also replace left hand side expressions `for (x of []);` like in `for (var x of []);`). The binding identifiers (`x`) from the declarations will be emitted via the `EmitFunction` callback. `hoistVariables` is applied only to those declarations within the same scope of `path`, in other words, it will not hoist variables defined inside a function body nested inside `path`. If `kind` is `"let"`, it will hoist `let` declarations.
JLHwung marked this conversation as resolved.
Show resolved Hide resolved

Generally an `EmitFunction` will declare such variables in outer `scope`.

## Example

```javascript
import hoistVariables from "@babel/helper-hoist-variables";

// a naive plugin transforms
// `(function myEval(){ var x = 1; })()`
// to
// `var x;(function myEval(){ x = 1; })()`

module.exports = api => {
return {
visitor: {
Function(path) {
if (path.node.id.name === "myEval") {
const outerScope = path.scope.parent;
hoistVariables(
path.get("body"),
id => {
// Use Scope#push to register a `var` binding in
// the outer scope
outerScope.push({ id });
},
"var"
);
}
},
},
};
};
```

`@babel/plugin-proposal-do-expressions` also uses the same technique to hoist the `var` declarations in do blocks to the containing function scope.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add the link to implementations when babel/babel#13122 is merged.