rsms / estrella

Lightweight and versatile build tool based on the esbuild compiler
ISC License
1.1k stars 38 forks source link

TypeError: t is not a function on Windows #48

Open thekevinbrown opened 2 years ago

thekevinbrown commented 2 years ago

When we try to run this script:

// We're using require here because this is a JS file that Node loads directly.
/* eslint-disable @typescript-eslint/no-var-requires */
const { build, file, glob } = require('estrella');
const { join, resolve } = require('path');

const makeAllPackagesExternalPlugin = {
    name: 'make-all-packages-external',
    setup(build) {
        const filter = /^[^./]|^\.[^./]|^\.\.[^/]/; // Must not start with "/" or "./" or "../"
        build.onResolve({ filter }, ({ path }) => ({ path, external: true }));
    },
};

const common = {
    // Anything in node_modules should be marked as external.
    plugins: [makeAllPackagesExternalPlugin],

    minify: false,
    bundle: true,
    sourcemap: true,
    platform: 'node',
    target: ['node12'],

    // We are not going to run tslint in dev
    tslint: false,
};

const tasks = glob('./packages/*').map(async (dir) => {
    // Ignore .DS_Store files.
    if (dir.indexOf('/.DS_Store') >= 0) return;

    const { source, main } = JSON.parse(await file.read(join(dir, 'package.json'), 'utf-8'));

    // If source and/or main aren't defined, we don't need to build this package.
    if (source && main) {
        build({
            ...common,

            entry: resolve(dir, source),
            outfile: resolve(dir, main),
        });
    }
});

Promise.all(tasks).catch((error) => {
    console.error(error);
    process.exit(1);
});

on Windows, we get:

Unhandled exception: TypeError: t is not a function
    at C:\[project folder]\node_modules\estrella\node_modules\miniglob\src\miniglob.js:59:18
    at Je (C:\[project folder]\node_modules\estrella\node_modules\miniglob\src\miniglob.js:269:23)
    at ln (C:\[project folder]\node_modules\estrella\node_modules\miniglob\src\miniglob.js:24:12)
    at Object.<anonymous> (C:\[project folder]\transpile.js:28:15)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47
error Command failed with exit code 2.

When we look for C:\[project folder]\node_modules\estrella\node_modules\miniglob\src\miniglob.js the file doesn't exist. How can we help debug this?

thekevinbrown commented 2 years ago

Ok, I created an unminified build of both miniglob and estrella. Here's the actual error:

Unhandled exception: TypeError: volumeNameLen2 is not a function
    at C:\[project folder]\node_modules\estrella\node_modules\miniglob\src\miniglob.js:59:18
    at glob0 (C:\[project folder]\node_modules\estrella\node_modules\miniglob\src\miniglob.js:269:23)
    at glob (C:\[project folder]\node_modules\estrella\node_modules\miniglob\src\miniglob.js:24:12)
    at Object.<anonymous> (C:\[project folder]\transpile.js:28:15)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47
error Command failed with exit code 2.

That seems to be this bit of code:

var cleanGlobPath = WIN32 ? (path, volumeNameLen2) => {
  let vollen = volumeNameLen2(path); // <= Error here
  if (path == "") {
    return [0, "."];
  }
  // ...
}

Which is odd. When I check the code, it looks like the non-win32 path thinks that volumeNameLen there should be a number. So why does this line treat it like a function? https://github.com/rsms/js-miniglob/blob/master/src/miniglob.js#L59 when down the other path it's a number that gets returned in the result? https://github.com/rsms/js-miniglob/blob/master/src/miniglob.js#L76

Has this ever worked on Windows? What's the intent of this code?

I'd be happy to PR back to miniglob to fix the windows path if that's helpful, just would be good to understand what that's trying to do.

Also I'm happy to move this issue over to that repo, but I notice you're the same person behind both projects so I didn't want to spam you with notifications. If this is better over there just let me know.

thekevinbrown commented 2 years ago

I've made a little more progress by editing cleanGlobPath to:

var cleanGlobPath = WIN32 ? (path, volumeNameLen2) => {
  let vollen = volumeNameLen2;

This now gets me to the place where it runs, but the glob function with the pattern ./packages/* doesn't pick up anything, even though there are things in that directory. I also tried changing it to packages/* with the same result. Estrella never finds anything to build.

pjeby commented 2 years ago

The bigger problem here is that the miniglob library does not support cross-platform glob patterns: estrella should use something that does (e.g. node-glob), as to work correctly on Windows you would have to replace all your glob patterns' slashes with backslashes, and even then I'm not sure it would work right.