callstack / linaria

Zero-runtime CSS in JS library
https://linaria.dev
MIT License
11.68k stars 417 forks source link

Build flaky with Typescript enum: throws EvalError not defined #1360

Open PierreGUI opened 1 year ago

PierreGUI commented 1 year ago

Environment

Description

Something is off with some enums. I use enums in many places, they mostly work fine. But in some cases the build fails on one of them:

ERROR in ./src/components/clients/discover/Presenter.view.tsx
Module build failed (from ./node_modules/babel-loader/lib/index.js):
/node_modules/@linaria/babel-preset/lib/module.js:224
      throw new EvalError(`${e.message} in${this.callstack.join('\n| ')}\n`);
      ^

EvalError: ContentWidth is not defined in /src/constants/style.ts

Also, I call it flaky because this happened:

  1. I encountered a similar error on my first build
  2. I replaced with an object the enum which caused the error
  3. Built sucessfully
  4. Subsequent builds error on a different enum (see above)

This is ContentWidth from /src/constants/style.ts

export enum ContentWidth {
    xs = 360,
    sm = 540,
    md = 720,
    lg = 900,
    xl = 1140,
}

Reproducible Demo

As I can't determine exactly how the problem occurs, I'll start with some debug logs:

2023-09-28T09:33:45.953Z linaria:transform:00026#1 >> evaluate __linariaPreval
2023-09-28T09:33:45.953Z linaria:transform:00026#1:module init /src/components/clients/pages/Checkout.tsx
2023-09-28T09:33:45.953Z linaria:cache:entrypoints get /src/components/clients/pages/Checkout.tsx hit
2023-09-28T09:33:45.953Z linaria:transform:00026#1 create EvaluatedEntrypoint for [ '__linariaPreval' ]
2023-09-28T09:33:45.953Z linaria:cache:entrypoints 00026:add /src/components/clients/pages/Checkout.tsx "updated"
2023-09-28T09:33:45.953Z linaria:transform:00026#1:module evaluate
2023-09-28T09:33:45.954Z linaria:transform:00026#1 set __linariaPreval: undefined
2023-09-28T09:33:45.954Z linaria:transform:00026#1:module require ../../../constants/style -> /src/constants/style.ts
2023-09-28T09:33:45.954Z linaria:cache:entrypoints get /src/constants/style.ts hit
2023-09-28T09:33:45.954Z linaria:transform:00026#1:module ✅ ready for evaluation
2023-09-28T09:33:45.954Z linaria:transform:00026#1->00046#3:module init /src/constants/style.ts
2023-09-28T09:33:45.954Z linaria:cache:entrypoints get /src/constants/style.ts hit
2023-09-28T09:33:45.954Z linaria:transform:00026#1->00046#3 create EvaluatedEntrypoint for [ 'Breakpoint', 'CHECKOUT_DUAL_BREAK_SIZE', 'CHECKOUT_WIDTH', 'ImageRatio' ]
2023-09-28T09:33:45.954Z linaria:cache:entrypoints 00046:add /src/constants/style.ts "updated"
2023-09-28T09:33:45.954Z linaria:transform:00026#1->00046#3:module evaluate
2023-09-28T09:33:45.954Z linaria:transform:00020#1->00046#1 set CHECKOUT_DUAL_BREAK_SIZE: undefined
2023-09-28T09:33:45.954Z linaria:transform:00020#1->00046#1 set CHECKOUT_WIDTH: undefined
2023-09-28T09:33:45.954Z linaria:transform:00020#1->00046#1 set Size: undefined
2023-09-28T09:33:45.954Z linaria:transform:00020#1->00046#1 set ZIndex: undefined
2023-09-28T09:33:45.954Z linaria:transform:00020#1->00046#1 set Size: { xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', xl: 'xl', xxl: 'xxl' }
2023-09-28T09:33:45.954Z linaria:transform:00020#1->00046#1 set CHECKOUT_DUAL_BREAK_SIZE: 'md'
2023-09-28T09:33:45.955Z linaria:cache:entrypoints 00046:add /src/constants/style.ts "updated"
2023-09-28T09:33:45.955Z linaria:transform:00026#1->00046#3:module /src/constants/style.ts:37
const CHECKOUT_WIDTH = exports.CHECKOUT_WIDTH = ContentWidth.xs;
                                                ^

ReferenceError: ContentWidth is not defined
at /src/constants/style.ts:37:49
at /src/constants/style.ts:64:3
at Script.runInContext (node:vm:135:12)
at Module.evaluate (/node_modules/@linaria/babel-preset/lib/module.js:209:14)
at require.Object.assign.ensure (/node_modules/@linaria/babel-preset/lib/module.js:121:7)
at /src/components/clients/pages/Checkout.tsx:7:14
at /src/components/clients/pages/Checkout.tsx:65:3
at Script.runInContext (node:vm:135:12)
at Module.evaluate (/node_modules/@linaria/babel-preset/lib/module.js:209:14)
at evaluate (/node_modules/@linaria/babel-preset/lib/evaluators/index.js:15:5)
[
'/src/constants/style.ts',
'/src/components/clients/pages/Checkout.tsx'
]
2023-09-28T09:33:45.955Z linaria:cache:entrypoints 00026:add /src/components/clients/pages/Checkout.tsx "updated"
2023-09-28T09:33:45.955Z linaria:transform:00026#1:module /node_modules/@linaria/babel-preset/lib/module.js:224
  throw new EvalError(`${e.message} in${this.callstack.join('\n| ')}\n`);
  ^

EvalError: ContentWidth is not defined in/src/constants/style.ts
| /src/components/clients/pages/Checkout.tsx

None of the variables from this module should be undefined

Anber commented 1 year ago

Could you please try with the latest version? We have just released a few fixes for issues that can be related to yours.

PierreGUI commented 1 year ago

I just tried the new version and have the same error

Anber commented 1 year ago

Ok, thank you! Just wanted to be sure that this is not related to the bag with pluginOptions. We will take a look soon.

PierreGUI commented 1 year ago

FYI I fixed the error and got a successful build by replacing these 2 enums (out of 170 total) with their object+type counterpart. I have no clue what makes these enums error in particular.

Anber commented 1 year ago

Could you please add to your webpack config the next plugin:

const { LinariaDebugPlugin } = require('@linaria/webpack5-loader');
// … 
  plugins: [
    new LinariaDebugPlugin({
      dir: 'linaria-debug',
      print: true,
    }),
    // …
  }

It will create a build report in the linaria-debug folder. I understand that it may reveal some critical information about the project (it includes file names and information about imports), so if sharing such info about the whole project is not appropriate for you, let's do some grep:

  1. First we need to find all entrypoints' ids for the broken file. It can be found by the name of such file in entrypoint.jsonl. We are looking for the first number in line with "filename":"/path/to/file/wehere/enum/is/defined.ts". In the next case, for /linaria/website/src/index.jsx, it will be [0, 3, 4]:
    
    [0,713.2929162979126,{"class":"Entrypoint","evaluatedOnly":[],"filename":"/linaria/website/src/index.jsx","generation":1,"idx":"00001","isExportsInherited":false,"only":["__linariaPreval"],"parentId":null,"type":"created"}]
    …
    [3,1016.1742076873779,{"class":"EvaluatedEntrypoint","evaluatedOnly":["__linariaPreval"],"filename":"/linaria/website/src/index.jsx","generation":2,"idx":"00001","isExportsInherited":true,"only":["__linariaPreval"],"parentId":null,"type":"created"}]
    …
    [4,1104.999457359314,{"class":"EvaluatedEntrypoint","evaluatedOnly":["__linariaPreval"],"filename":"/linaria/website/src/index.jsx","generation":2,"idx":"00001","isExportsInherited":true,"only":["__linariaPreval"],"parentId":null,"type":"created"}]

2. Then we need all lines from `entrypoint.jsonl` with the same ids. Like:

[0,713.2929162979126,{"class":"Entrypoint","evaluatedOnly":[],"filename":"/Users/anber/Sources/linaria/website/src/index.jsx","generation":1,"idx":"00001","isExportsInherited":false,"only":["linariaPreval"],"parentId":null,"type":"created"}] [0,965.2337913513184,{"type":"actionCreated","actionType":"workflow","actionIdx":"000001"}] [0,965.7795829772949,{"type":"actionCreated","actionType":"processEntrypoint","actionIdx":"000002"}] [0,965.9743747711182,{"type":"actionCreated","actionType":"explodeReexports","actionIdx":"000003"}] [0,968.8894577026367,{"type":"actionCreated","actionType":"transform","actionIdx":"000004"}] [0,1004.6903743743896,{"type":"actionCreated","actionType":"resolveImports","actionIdx":"000005"}] [0,1006.9242496490479,{"type":"actionCreated","actionType":"processImports","actionIdx":"000006"}] [3,1016.1742076873779,{"class":"EvaluatedEntrypoint","evaluatedOnly":["linariaPreval"],"filename":"/Users/anber/Sources/linaria/website/src/index.jsx","generation":2,"idx":"00001","isExportsInherited":true,"only":["linariaPreval"],"parentId":null,"type":"created"}] [4,1104.999457359314,{"class":"EvaluatedEntrypoint","evaluatedOnly":["linariaPreval"],"filename":"/Users/anber/Sources/linaria/website/src/index.jsx","generation":2,"idx":"00001","isExportsInherited":true,"only":["__linariaPreval"],"parentId":null,"type":"created"}]


3. And finally, we need all actions that were applied to extracted entrypoints. Actions can be found in `actions.jsonl` by their indexes from `actionIdx` field in `entrypoint.jsonl`.

{"actionId":0,"entrypointRef":"00001#1","idx":"000001:1","startedAt":965.6203746795654,"type":"workflow"} {"actionId":1,"entrypointRef":"00001#1","idx":"000002:1","startedAt":965.8404998779297,"type":"processEntrypoint"} {"actionId":3,"entrypointRef":"00001#1","idx":"000002:2","startedAt":968.8673324584961,"type":"processEntrypoint"} {"actionId":15,"entrypointRef":"00001#1","idx":"000002:3","startedAt":1015.7590827941895,"type":"processEntrypoint"} {"actionId":16,"entrypointRef":"00001#1","idx":"000001:2","startedAt":1015.7772493362427,"type":"workflow"} {"actionId":36,"entrypointRef":"00001#1","idx":"000001:3","startedAt":1115.6526670455933,"type":"workflow"} {"actionId":38,"entrypointRef":"00001#1","idx":"000001:4","startedAt":1120.666666984558,"type":"workflow"} {"actionId":40,"entrypointRef":"00001#1","idx":"000001:5","startedAt":1122.278582572937,"type":"workflow"} …



Fortunately, it all can be done with jq:
1. `jq -r -c --arg ids "$(jq 'select(.[2].filename | . and endswith("/src/index.jsx"))[0]' ./entrypoint.jsonl | jq --slurp -c)" 'select(.[0] | tostring as $id | $ids | index($id))' ./entrypoint.jsonl > ./broken-file-entrypoints.jsonl` generates a new file with the broken file related entrypoints.
2. `jq -c --arg actions "$(jq '.[2].actionIdx | select(.)' ./broken-file-entrypoints.jsonl | jq --slurp -c)" '. | select(.idx[0:6] as $idx | $idx and ($actions | index($idx)))' ./actions.jsonl > ./broken-file-actions.jsonl` generates a new file with the broken file related actions.
PierreGUI commented 1 year ago

Ok thanks I have the debug report I'll send it privately

namoko commented 1 year ago

Is there any update on this? I have the similar problem, when migrating from Linaria 3 to 4 or 5 (Current version 5.0.2 core, 5.0.3 React)