kentcdodds / kentcdodds/babel-plugin-macros
Initialization, scopes and assignments - possible bugs / possible improvements
- Dominant language
- JavaScript
- Stars
- 2.6k
- Forks
- 138
- PR merge metrics
- No merged PRs in 30d
Description
- `babel-plugin-macros` version: 3.0.1
- `node` version: v14.15.1
- `npm` version: 6.14.8
## Relevant code or config
```javascript
// File: test.macro.js
const { createMacro } = require("babel-plugin-macros");
let callbackCounter = 0;
// Counts macro calls and adds comments to every detected macro usage
function macroCallback({ references, state, babel, source, config }) {
callbackCounter += 1;
for (const importName in references) {
for (const path of references[importName]) {
path.addComment("leading", callbackCounter);
}
}
}
module.exports = createMacro(macroCallback);
```
```javascript
// File: index.js
macro = 1;
macro;
macro("before require");
const macro = require("./test.macro");
macro("after require");
macro = "Direct assignment is always ignored";
macro.v = "This works";
{
macro("before require");
const macro = require("./test.macro");
macro("after require");
}
macro;
```
```javascript
// File: index-after-macro.js
"use strict";
macro = 1;
/*1*/
macro;
/*1*/
macro("before require");
/*1*/
macro("after require");
macro = "Direct assignment is always ignored";
/*1*/
macro.v = "This works";
{
/*2*/
macro("before require");
/*2*/
macro("after require");
}
/*1*/
macro;
```
## Problem description and suggested solutions:
I can see few issues here:
* You can access a macro in a scope before initialization. It's a bit unexpected and there are no warnings/errors. It may cause some issues especially if there are some global variables.
* When you do assignments, direct assignment is completely ignored.
Even if the macro was imported or required as const there is no error.
I assume that it has something to do with global variables, but I think
it would be nice, if a user could handle a scenario like this in a macro.
Either to just print an error message like 'usage like this is not allowed' or
to do something else.
* Babel-plugin-macros allows for scoping (awesome), but the way it's handled right now
makes it impossible to handle all macro usages within a single function (without some nasty tricks, atleast).
Maybe there is a way to handle scoping better? Sometimes user may want to do some global post-processing in a file after processing all macros. References could be organised like this for example:
```javascript
[
{
scope: 0, // id
importName: "default/*/name",
localName: "importName/as",
path: PathNode(),
},
/* .. */
];
```
I gives more context about the macro usage.
Of course, localName name currently can be easily checked with `Identifier` name prop.
The main issue are scopes.
Also two minor things.
* Syntax like this (similar to `require()`) is not recognized. Not that I need it, it's just something I noticed. It looks like a minor oversight, but maybe it's intentional.
```javascript
const macro = import('./test.macro');
```
* Syntax like this causes an 'Cannot read property 'name' of undefined' error. Again, just something I noticed.
```javascript
import * as macro from "./test.macro";
```
Contributor guide
Research direction
Start by reproducing the reported cases from test.macro.js, index.js, and index-after-macro.js, including pre-initialization access, assignments, nested scopes, dynamic import(), and namespace import syntax. Determine the intended behavior for each case before locating the relevant macro-processing entry points; done means the scope and assignment behavior are decided and the reported cases are covered by regression tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- babel, javascript
- Domain
- compilers, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100