# Deno Node.js compatibility

This module is meant to have a compatibility layer for the
[Node.js standard library](https://nodejs.org/docs/latest/api/).

**Warning**: Any function of this module should not be referred anywhere in the
Deno standard library as it's a compatibility module.

## Supported modules

- [x] assert
- [x] assert/strict _partly_
- [x] async_hooks _partly_
- [x] buffer
- [x] child_process _partly_
- [x] cluster _partly_
- [x] console _partly_
- [x] constants _partly_
- [x] crypto _partly_
- [x] dgram _partly_
- [x] diagnostics_channel _partly_
- [x] dns _partly_
- [x] events
- [x] fs _partly_
- [x] fs/promises _partly_
- [x] http _partly_
- [ ] http2
- [x] https _partly_
- [x] inspector _partly_
- [x] module
- [x] net
- [x] os _partly_
- [x] path
- [x] path/posix
- [x] path/win32
- [x] perf_hooks
- [x] process _partly_
- [x] punycode
- [x] querystring
- [x] readline
- [x] repl _partly_
- [x] stream
- [x] stream/promises
- [x] stream/web _partly_
- [x] string_decoder
- [x] sys
- [x] timers
- [x] timers/promises
- [ ] tls
- [ ] trace_events
- [x] tty _partly_
- [x] url
- [x] util _partly_
- [x] util/types _partly_
- [ ] v8
- [x] vm _partly_
- [x] wasi
- [ ] webcrypto
- [x] worker_threads
- [ ] zlib

* [x] node globals _partly_

### Deprecated

These modules are deprecated in Node.js and will probably not be polyfilled:

- domain
- freelist

### Experimental

These modules are experimental in Node.js and will not be polyfilled until they
are stable:

- diagnostics_channel
- async_hooks
- policies
- trace_events
- wasi
- webcrypto

## CommonJS modules loading

`createRequire(...)` is provided to create a `require` function for loading CJS
modules. It also sets supported globals.

```ts
import { createRequire } from "node:module";

const require = createRequire(import.meta.url);
// Loads native module polyfill.
const path = require("path");
// Loads extensionless module.
const cjsModule = require("./my_mod");
// Visits node_modules.
const leftPad = require("left-pad");
```

## Contributing

### Setting up the test runner and running tests

See [tests/node_compat/README.md](../../../tests/node_compat/README.md).

### Best practices

When converting from promise-based to callback-based APIs, the most obvious way
is like this:

```ts, ignore
promise.then((value) => callback(null, value)).catch(callback);
```

This has a subtle bug - if the callback throws an error, the catch statement
will also catch _that_ error, and the callback will be called twice. The correct
way to do it is like this:

```ts, ignore
promise.then((value) => callback(null, value), callback);
```

The second parameter of `then` can also be used to catch errors, but only errors
from the existing promise, not the new one created by the callback.

If the Deno equivalent is actually synchronous, there's a similar problem with
try/catch statements:

```ts, ignore
try {
  const value = process();
  callback(null, value);
} catch (err) {
  callback(err);
}
```

Since the callback is called within the `try` block, any errors from it will be
caught and call the callback again.

The correct way to do it is like this:

```ts, ignore
let err, value;
try {
  value = process();
} catch (e) {
  err = e;
}
if (err) {
  callback(err); // Make sure arguments.length === 1
} else {
  callback(null, value);
}
```

It's not as clean, but prevents the callback being called twice.

### Remaining Tests

Node compatibility can be measured by how many native Node tests pass. If you'd
like to know what you can work on, check the
[latest Node compatibility test results](https://node-test-viewer.deno.dev/results/latest).
