kentcdodds / kentcdodds/babel-plugin-macros

Initialization, scopes and assignments - possible bugs / possible improvements

Open
#167 10 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.