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

Parcel Bundler Error - fs.findAncestorFile #16460

Closed
rawkakani opened this issue Oct 28, 2022 · 25 comments
Closed

Parcel Bundler Error - fs.findAncestorFile #16460

rawkakani opened this issue Oct 28, 2022 · 25 comments
Assignees
Labels
needs investigation requires further investigation before determining if it is an issue or not node compat node native extension related to the node-api (.node)

Comments

@rawkakani
Copy link

rawkakani commented Oct 28, 2022

Hi
I am currently running into an issue where I am following the Parcel API documentation, and currently running into a Type error as below

error: Uncaught TypeError: fs.findAncestorFile is not a function

Currently using Deno 1.27.0, I would like to find out if there is another way to use parcel with Deno ?

I am importing @parcel/core and not parcel

System
Apple M1
macOS Ventura

@rawkakani rawkakani changed the title Parcel Bundler Error, ( fs.findAncestorFile) Parcel Bundler Error - fs.findAncestorFile Oct 28, 2022
@rawkakani
Copy link
Author

I got as far as napi_add_finalizer is not yet supported. could I please be guided in where this would be implemented, or a PR where it is currently in progress

@bartlomieju
Copy link
Member

I've opened an issue in deno_std to add the missing API.

@rawkakani
Copy link
Author

I've opened an issue in deno_std to add the missing API.

awesome thank you so much

@Seally
Copy link

Seally commented Oct 28, 2022

This function seems to be defined in Parcel (probably this one: https://github.com/parcel-bundler/parcel/blob/27bf5963322ba124b4878a0e4cfd6d60979b0d02/packages/core/fs/src/find.js#L35) and not in Node. I did a text search in the Node codebase and Node docs and couldn't find any results for findAncestorFile.

I haven't investigated why it's not on the fs object in this case, however. Since it seems Parcel has several different implementations of fs involved, I'm not sure which fs the code is referring to. Are you using Node/Deno's fs and not Parcel's variants?

Edit: There's a native implementation for the function with napi as well, but I'm not well-versed enough to know if it's relevant.

@dsherret dsherret added bug Something isn't working node compat needs investigation requires further investigation before determining if it is an issue or not and removed bug Something isn't working labels Oct 31, 2022
@BoltDoggy
Copy link

BoltDoggy commented Nov 4, 2022

https://github.com/parcel-bundler/parcel/blob/411d4c2e81f2dd9aa25be4fab82623e39f9ca49a/packages/core/fs/src/NodeFS.js#L50

这里的 searchNative 即 @parcel/fs-search 只有

{
  writeSnapshot: [Function],
  getEventsSince: [Function],
  subscribe: [Function],
  unsubscribe: [Function]
}

也许是在 deno 环境下加载 node 插件异常

@rawkakani
Copy link
Author

rawkakani commented Nov 12, 2022

awesome thank you for the feedback attemped to implement a custom fs.findAncestorFile using @BoltDoggy comment and got a new error Error: Not implemented: v8.setFlagsFromString

Screenshot 2022-11-12 at 15 03 07

can someone guide me to what this is, or is there a way for me to inplement this manually

@bartlomieju how can I start contributing to Deno

@lilnasy
Copy link

lilnasy commented Nov 17, 2022

Are you using parcel-bundler, which is deprecated?

@rawkakani
Copy link
Author

Are you using parcel-bundler, which is deprecated?

oh no I am using @parcel/core

@rawkakani
Copy link
Author

rawkakani commented Nov 18, 2022

Are you using parcel-bundler, which is deprecated?

@lilnasy does the npm:parcel work now for you?

@lilnasy
Copy link

lilnasy commented Nov 19, 2022

I ran the canary build and sadly, it does not work. It does not panic anymore, but now I get the same error as you: fs.findAncestorFile is not a function.

On a different note, it's interesting that it says that specifically, not that it's undefined.

@lilnasy
Copy link

lilnasy commented Nov 19, 2022

I added console.log's to deno's cached files and turns out fs.findAncestorFile really is undefined, along with the rest of parcel's custom fs, which gets shared around as a function parameter (ran the cli before vscode could save the file).

I couldn't find anything more because deno wouldn't wait for me attach a debugger before it throws this error.

@rawkakani are you able to attach a debugger with the --inspect-brk flag.

@lilnasy
Copy link

lilnasy commented Nov 19, 2022

The issue seems to be with the experimental Node API support. @parcel/fs re-exports a few functions from @parcel/fs-search which is an NAPI library. At least 3 of the functions that @parcel/fs expects from require("@parcel/fs-search") are missing, including findAncestorFile.

@bartlomieju bartlomieju added the node native extension related to the node-api (.node) label Nov 20, 2022
@bartlomieju
Copy link
Member

@littledivy please take a look

@rawkakani
Copy link
Author

The issue seems to be with the experimental Node API support. @parcel/fs re-exports a few functions from @parcel/fs-search which is an NAPI library. At least 3 of the functions that @parcel/fs expects from require("@parcel/fs-search") are missing, including findAncestorFile.

@lilnasy I extended the deno fs like this

import * as searchNative from 'npm:@parcel/fs-search';
// import defaultConfig from 'npm:@parcel/config-default' 
let inputFS = Deno;
inputFS.findAncestorFile = searchNative.default.findAncestorFile

and changed the FS that parcel core uses

let bundler = new Parcel({
  entries: 'a.js',
  defaultConfig: '@parcel/config-default',
  inputFS
});

and got the error above I mentioned

I will attempt to attach the debugger

@lilnasy
Copy link

lilnasy commented Nov 22, 2022

@rawkakani That specific error has to do with Node's V8 API. V8 is what Node and Deno use under the hood to run javascript, and for now Deno does not have a compatibility layer to directly interact with it. v8.setFlagsFromString makes changes to V8, you can't manually implement it from within javascript land.

The fact that you are directly able to import findAncestorFile from @parcel/fs-search is interesting though, because @parcel/fs could not. I fiddled around a bit more and it turns out Deno imports different functions from @parcel/fs-search depending on how/where it is imported.

Via another npm package

Screenshot (11)

Directly via an npm specifier

Screenshot (12)

@marvinhagemeister
Copy link
Contributor

I think I found a clue. Was logging all exports when a native addon is loaded and noticed that @parcel/watcher/prebuilds/darwin-arm64/node.napi.glibc.node is loaded just before the one that has wrong exports. The load order is:

  1. @parcel/source-map/parcel_sourcemap_node/artifacts/index.darwin-arm64.node - Correct
  2. @parcel/hash/parcel-hash.darwin-arm64.node - Correct
  3. @parcel/watcher/prebuilds/darwin-arm64/node.napi.glibc.node - Correct
  4. @parcel/fs-search/fs-search.darwin-arm64.node - WRONG, returns exports from node.napi.glibc.node

Screenshot of the exports:

Screenshot 2023-05-24 at 23 57 00

Logging out the v8 pointer confirms that both node.napi.glibc.node and fs-search.darwin-arm64.node share the same address. Somehow it seems that deno returns the same pointer for two different modules. Comparing the exports and the packages confirms that the returned API belongs to @parcel/watcher and not @parcel/fs-search.

@bartlomieju
Copy link
Member

Nice investigation @marvinhagemeister. Can you share the code where you dump the pointers?

@marvinhagemeister
Copy link
Contributor

marvinhagemeister commented May 25, 2023

@bartlomieju Upon second look I think I got the pointer bit wrong. Printed out the exports NapiValue inside the match statement of op_napi_open on this line. But I now realize that it's the same for all of them. Maybe I was too tired yesterday evening (or it's way over my head as a frontend dev :P ).

Either way, as far as I can tell the modules which run into the bug described here go through the Some(nm) case of the surrounding match expression. The ones falling through None seem fine. That's as far as I can debug it though. My knowledge on native stuff is too limited.

deno/ext/napi/lib.rs

Lines 628 to 656 in 935071d

Some(nm) => {
// SAFETY: napi_register_module guarantees that `nm` is valid.
let nm = unsafe { &*nm };
assert_eq!(nm.nm_version, 1);
// SAFETY: we are going blind, calling the register function on the other side.
let maybe_exports = unsafe {
(nm.nm_register_func)(
env_ptr,
std::mem::transmute::<v8::Local<v8::Value>, napi_value>(
exports.into(),
),
)
};
let exports = maybe_exports
.as_ref()
.map(|_| unsafe {
// SAFETY: v8::Local is a pointer to a value and napi_value is also a pointer
// to a value, they have the same layout
std::mem::transmute::<napi_value, v8::Local<v8::Value>>(
maybe_exports,
)
})
.unwrap_or_else(|| {
// If the module didn't return anything, we use the exports object.
exports.into()
});
Ok(serde_v8::Value { v8_value: exports })

Made an isolated reproduction case.

Steps to reproduce

  1. Clone https://github.com/marvinhagemeister/deno-parcel-bug
  2. Run deno task dev

@bartlomieju
Copy link
Member

Thanks @marvinhagemeister! I just spotted the error here, will fix it at first convenience.

littledivy added a commit that referenced this issue May 26, 2023
This commit fixes problem with loading N-API modules that use 
the "old" way of registration (using "napi_module_register" API).
The slot was not cleared after loading modules, causing subsequent
calls that use the new way of registration (using 
"napi_register_module_v1" API) to try and load the previous module.

Ref #16460

---------

Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
@rawkakani
Copy link
Author

are these changes available in 1.34?

@bartlomieju
Copy link
Member

@rawkakani, no, they will be available in v1.34.1 to be release later this week.

@rawkakani
Copy link
Author

@rawkakani, no, they will be available in v1.34.1 to be release later this week.

@bartlomieju thank you

@rawkakani
Copy link
Author

rawkakani commented May 30, 2023

I have upgraded to 1.34.1, and have gotten the below error trying to implement Parcel API

error: Uncaught (in worker "$DENO_STD_NODE_WORKER_THREAD") TypeError: Cannot read properties of undefined (reading 'startsWith')
    at Array.get (ext:deno_node/process.ts:486:33)
    at Array.indexOf (<anonymous>)
    at module.exports (file:///Users/rawkakani/Documents/rnd/node_modules/.deno/has-flag@4.0.0/node_modules/has-flag/index.js:5:24)
    at Object.<anonymous> (file:///Users/rawkakani/Documents/rnd/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:9:5)
    at Object.<anonymous> (file:///Users/rawkakani/Documents/rnd/node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js:137:4)
    at Module._compile (ext:deno_node/01_require.js:974:34)
    at Object.Module._extensions..js (ext:deno_node/01_require.js:1007:10)
    at Module.load (ext:deno_node/01_require.js:885:32)
    at Function.Module._load (ext:deno_node/01_require.js:719:12

this occurs when I use the below script and install @parcel/config-default locally using npm

import {Parcel} from 'npm:@parcel/core';

let bundler = new Parcel({
    entries: './a.js',
    defaultConfig: '@parcel/config-default'
});

if anyone does get this right can you please let me know

however the fs.findAncestorFile error is gone thank you @bartlomieju

@bartlomieju
Copy link
Member

I believe the error you are seeing is the same problem as #18334 is trying to fix.

@rawkakani
Copy link
Author

rawkakani commented May 30, 2023

I believe the error you are seeing is the same problem as #18334 is trying to fix.

okay awesome thank you, is it cool to close this issue and watch the PR you mentioned

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation requires further investigation before determining if it is an issue or not node compat node native extension related to the node-api (.node)
Projects
None yet
Development

No branches or pull requests

8 participants