Update bare reference (#174)

* Update `api.md` & `overview.md` w/ `bare`'s `README.md`

Adjusted to account for the extra modules section & the `api.md`
breaking out `Bare`'s API.

* Update `bare-module` docs w/ `bare-module`'s `README.md`
This commit is contained in:
Sean Zellmer
2025-03-14 03:38:51 -05:00
committed by rafapaezbas
parent ab9e188234
commit e8cd9cc6e5
3 changed files with 663 additions and 89 deletions

View File

@@ -12,7 +12,11 @@ The identifier of the operating system for which Bare was compiled. The possible
### `Bare.arch`
The identifier of the processor architecture for which Bare was compiled. The possible values are `arm`, `arm64`, `ia32`, and `x64`.
The identifier of the processor architecture for which Bare was compiled. The possible values are `arm`, `arm64`, `ia32`, `mips`, `mipsel`, and `x64`.
### `Bare.simulator`
Whether or not Bare was compiled for a simulator.
### `Bare.argv`
@@ -46,7 +50,7 @@ An object containing the version strings of Bare and its dependencies.
Immediately terminate the process or current thread with an exit status of `code` which defaults to `Bare.exitCode`.
### `Bare.suspend()`
### `Bare.suspend([linger])`
Suspend the process and all threads. This will emit a `suspend` event signalling that all work should stop immediately. When all work has stopped and the process would otherwise exit, an `idle` event will be emitted. If the process is not resumed from an `idle` event listener and no additional work is scheduled, the loop will block until the process is resumed. If additional work is scheduled from an `idle` event, the `idle` event will be emitted again once all work has stopped unless the process was resumed.
@@ -70,23 +74,23 @@ If the process is exited explicitly, such as by calling `Bare.exit()` or as the
### `Bare.on('exit', code)`
Emitted just before the process or current thread terminates. Additional work scheduled from an `exit` event listener will be given a chance to run after which the process will terminate. If the process is forcefully terminated from an `exit` event listener, the remaining listeners will not run.
> [!IMPORTANT]
> Only cleanup work may be scheduled from an `exit` event listener. All I/O, including timers, will be closed on `exit` and can therefore not be used.
Emitted before the process or current thread terminates. Additional work must not be scheduled from an `exit` event listener. If the process is forcefully terminated from an `exit` event listener, the remaining listeners will not run.
### `Bare.on('teardown')`
Emitted after the process or current thread has terminated and just before the JavaScript environment is torn down. Additional work must not be scheduled from a `teardown` event listener. Bare itself will register `teardown` event listeners to join dangling threads and unload native addons.
Emitted after the process or current thread has terminated and before the JavaScript environment is torn down. Additional work must not be scheduled from a `teardown` event listener. Bare itself will register `teardown` event listeners to join dangling threads and unload native addons.
> [!IMPORTANT]
> `teardown` listeners should generally be prepended to have the listeners run in last in, first out order:
>
> ##### Teardown ordering
>
> `teardown` listeners **SHOULD** be prepended to have the listeners run in last in, first out order:
>
> ```js
> Bare.prependListener('teardown', () => { ... })
> ```
### `Bare.on('suspend')`
### `Bare.on('suspend', linger)`
Emitted when the process or current thread is suspended. Any in-progress or outstanding work, such as network activity or file system access, should be deferred, cancelled, or paused when the `suspend` event is emitted and no additional work may be scheduled.
@@ -102,30 +106,23 @@ Emitted when the process or current thread resumes after suspension. Deferred an
The `Bare.Addon` namespace provides support for loading native addons, which are typically written in C/C++ and distributed as shared libraries.
### `const addon = Addon.load(url)`
### `const addon = Addon.load(url[, options])`
Load a static or dynamic native addon identified by `url`. If `url` is not a static native addon, Bare will instead look for a matching dynamic object library.
### `const unloaded = Addon.unload(url)`
Options are reserved.
### `const unloaded = Addon.unload(url[, options])`
Unload a dynamic native addon identified by `url`. If the function returns `true`, the addon was unloaded from memory. If it instead returns `false`, the addon is still in use by one or more threads and will only be unloaded from memory when those threads either exit or explicitly unload the addon.
Options are reserved.
### `const url = Addon.resolve(specifier, parentURL[, options])`
Resolve a native addon specifier by searching for a static native addon or dynamic object library matching `specifier` imported from `parentURL`.
Options include:
```js
{
// The name of the addon. If `null`, it will instead be read from the
// resolved `package.json`.
name: null,
// The version of the addon. If `null`, it will instead be read from the
// resolved `package.json`.
version: null
}
```
Options are reserved.
## `Bare.Thread`
@@ -152,7 +149,7 @@ Options include:
```js
{
// Optional data to pass to the thread
data: Buffer | ArrayBuffer | SharedArrayBuffer | External,
data: null,
// Optional file source, will be read from `filename` if neither `source` nor `callback` are provided
source: string | Buffer,
// Optional source encoding if `source` is a string

View File

@@ -1,6 +1,6 @@
# Bare Modules
# bare-module
Bare modules provide a robust system for managing code dependencies within Bare applications. This section delves into the details of Bare's module system.
Module support for JavaScript.
```
npm i bare-module
@@ -10,40 +10,65 @@ npm i bare-module
```js
const Module = require('bare-module')
````
```
## External Modules for Bare
Supported Modules |
:--- |
<https://github.com/holepunchto/bare-abort>
<https://github.com/holepunchto/bare-assert>
<https://github.com/holepunchto/bare-atomics>
<https://github.com/holepunchto/bare-buffer>
<https://github.com/holepunchto/bare-bundle>
<https://github.com/holepunchto/bare-channel>
<https://github.com/holepunchto/bare-console>
<https://github.com/holepunchto/bare-env>
<https://github.com/holepunchto/bare-events>
<https://github.com/holepunchto/bare-fs>
<https://github.com/holepunchto/bare-hrtime>
<https://github.com/holepunchto/bare-http1>
<https://github.com/holepunchto/bare-inspect>
<https://github.com/holepunchto/bare-module>
<https://github.com/holepunchto/bare-os>
<https://github.com/holepunchto/bare-path>
<https://github.com/holepunchto/bare-pipe>
<https://github.com/holepunchto/bare-process>
<https://github.com/holepunchto/bare-readline>
<https://github.com/holepunchto/bare-repl>
<https://github.com/holepunchto/bare-signals>
<https://github.com/holepunchto/bare-subprocess>
<https://github.com/holepunchto/bare-timers>
<https://github.com/holepunchto/bare-tty>
<https://github.com/holepunchto/bare-url>
Bare provides no standard library beyond the core JavaScript API available through the `Bare` namespace. Instead, we maintain a comprehensive collection of external modules built specifically for Bare:
| Module |
| :----------------------------------------------------- |
| <https://github.com/holepunchto/bare-abort> |
| <https://github.com/holepunchto/bare-assert> |
| <https://github.com/holepunchto/bare-atomics> |
| <https://github.com/holepunchto/bare-buffer> |
| <https://github.com/holepunchto/bare-bundle> |
| <https://github.com/holepunchto/bare-channel> |
| <https://github.com/holepunchto/bare-console> |
| <https://github.com/holepunchto/bare-crypto> |
| <https://github.com/holepunchto/bare-dgram> |
| <https://github.com/holepunchto/bare-dns> |
| <https://github.com/holepunchto/bare-env> |
| <https://github.com/holepunchto/bare-events> |
| <https://github.com/holepunchto/bare-fetch> |
| <https://github.com/holepunchto/bare-format> |
| <https://github.com/holepunchto/bare-fs> |
| <https://github.com/holepunchto/bare-hrtime> |
| <https://github.com/holepunchto/bare-http1> |
| <https://github.com/holepunchto/bare-https> |
| <https://github.com/holepunchto/bare-inspect> |
| <https://github.com/holepunchto/bare-inspector> |
| <https://github.com/holepunchto/bare-ipc> |
| <https://github.com/holepunchto/bare-module> |
| <https://github.com/holepunchto/bare-net> |
| <https://github.com/holepunchto/bare-os> |
| <https://github.com/holepunchto/bare-path> |
| <https://github.com/holepunchto/bare-pipe> |
| <https://github.com/holepunchto/bare-process> |
| <https://github.com/holepunchto/bare-querystring> |
| <https://github.com/holepunchto/bare-readline> |
| <https://github.com/holepunchto/bare-realm> |
| <https://github.com/holepunchto/bare-repl> |
| <https://github.com/holepunchto/bare-rpc> |
| <https://github.com/holepunchto/bare-semver> |
| <https://github.com/holepunchto/bare-signals> |
| <https://github.com/holepunchto/bare-stream> |
| <https://github.com/holepunchto/bare-structured-clone> |
| <https://github.com/holepunchto/bare-subprocess> |
| <https://github.com/holepunchto/bare-tcp> |
| <https://github.com/holepunchto/bare-timers> |
| <https://github.com/holepunchto/bare-tls> |
| <https://github.com/holepunchto/bare-tty> |
| <https://github.com/holepunchto/bare-type> |
| <https://github.com/holepunchto/bare-url> |
| <https://github.com/holepunchto/bare-vm> |
| <https://github.com/holepunchto/bare-worker> |
| <https://github.com/holepunchto/bare-ws> |
| <https://github.com/holepunchto/bare-zlib> |
## Packages
A package is directory with a `package.json` file.
A package is a directory with a `package.json` file.
### Fields
@@ -75,7 +100,7 @@ The current version of the package. This is used for [addon resolution](https://
}
```
The module format used for `.js` files. If not defined, `.js` files are interpreted as CommonJS. If set to `"module"` the `.js` files are instead interpreted as ES modules.
The module format used for `.js` files. If not defined, `.js` files are interpreted as CommonJS. If set to `"module"`, `.js` files are instead interpreted as ES modules.
#### `"exports"`
@@ -106,7 +131,7 @@ When importing the package by name, `require('my-package')` will resolve to `<mo
##### Conditional exports
Conditional exports allow packages to provide different exports for different conditions, such as the module format of the importing module:
Conditional exports allow packages to provide different exports for different conditions, such as the loading method the importing module uses (e.g. `require()` vs `import`):
```json
{
@@ -150,13 +175,33 @@ To provide a fallback for when no other conditions match, the `"default"` condit
The following conditions are supported, listed in order from most specific to least specific as conditions should be defined:
Condition | Description
:-- | :--
`"bare"` | This applies when the module is being imported from another Bare module.
`"node"` | This applies when the module is being imported within a Node.js environment.
`"import"` | This applies when the module is being imported using an ES module import statement.
`"require"` | This applies when the module is being imported using the CommonJS require() function.
`"default"` | This serves as a fallback export if none of the more specific conditions (bare, node, import, require) are met.
| Condition | Description |
| :------------- | :---------------------------------------------------------------------------------------------------------------------------------- |
| `"import"` | Matches when the package is loaded via `import` or `import()`. |
| `"require"` | Matches when the package is loaded via `require()`. |
| `"asset"` | Matches when the package is loaded via `require.asset()`. |
| `"addon"` | Matches when the package is loaded via `require.addon()`. |
| `"bare"` | Matches for any [Bare](https://github.com/holepunchto/bare) environment. |
| `"node"` | Matches for any Node.js environment. |
| `"<platform>"` | Matches when equal to `Bare.platform`. See [`Bare.platform`](https://github.com/holepunchto/bare#bareplatform) for possible values. |
| `"<arch>"` | Matches when equal to `Bare.arch`. See [`Bare.arch`](https://github.com/holepunchto/bare#barearch) for possible values. |
| `"simulator"` | Matches when Bare was compiled for a simulator, i.e. when `Bare.simulator` is `true`. |
| `"default"` | The fallback that always matches. This condition should always be last. |
Export conditions are evaluated in the order they are defined in the `"exports"` field. This means that less specific conditionals defined first will override more specific conditions define later. For example, the following will always call `./fallback.js` because `"default"` always matches and is defined first.
```json
{
"exports": {
".": {
"default": "./fallback.js",
"bare": "./bare.js"
}
}
}
```
This is why the general rule is that conditions should be from most specific to least specific when defined.
##### Self-referencing
@@ -184,3 +229,484 @@ If a package defines only a single export, `"."`, it may leave out the subpath e
}
```
#### `"imports"`
A private mapping for import specifiers within the package itself. Similar to `"exports"`, the `"imports"` field can be used to conditional import other packages within the package. But unlike `"exports"`, `"imports"` permits mapping to external packages.
The rules are otherwise analogous to the [`"exports"`](#conditional-exports) field.
##### Subpath imports
Just like exports, subpaths can be used when importing a module internally.
```json
{
"imports": {
".": "./index.js",
"./submodule": "./lib/submodule.js"
}
}
```
##### Conditional imports
Adding conditional imports allows importing different packages based on the configured conditions. As an example:
```json
{
"imports": {
"bar": {
"require": "./baz.cjs",
"import": "./baz.mjs"
}
}
}
```
When importing the package `bar` as `require('bar')` will resolve to `./baz.cjs`, but when importing with `import('bar')` will resolve to `./baz.mjs`.
To provide a fallback for when no other conditions are met, the `"default"` condition can be configured like so:
```json
{
"imports": {
"bar": {
"require": "./baz.cjs",
"asset": "./baz.txt",
"default": "./baz.mjs"
}
}
}
```
The following conditions are supported, listed in order from most specific to least specific as conditions should be defined:
| Condition | Description |
| :------------- | :---------------------------------------------------------------------------------------------------------------------------------- |
| `"import"` | Matches when the package is loaded via `import` or `import()`. |
| `"require"` | Matches when the package is loaded via `require()`. |
| `"asset"` | Matches when the package is loaded via `require.asset()`. |
| `"addon"` | Matches when the package is loaded via `require.addon()`. |
| `"bare"` | Matches for any [Bare](https://github.com/holepunchto/bare) environment. |
| `"node"` | Matches for any Node.js environment. |
| `"<platform>"` | Matches when equal to `Bare.platform`. See [`Bare.platform`](https://github.com/holepunchto/bare#bareplatform) for possible values. |
| `"<arch>"` | Matches when equal to `Bare.arch`. See [`Bare.arch`](https://github.com/holepunchto/bare#barearch) for possible values. |
| `"simulator"` | Matches when Bare was compiled for a simulator, ie when `Bare.simulator` is `true`. |
| `"default"` | The fallback that always matches. This condition should always be last. |
The general rule is that conditions should be from most specific to least specific when defined.
##### `#` Prefix
All import maps are private to the package and allow mapping to external packages. Entries in `"imports"` may start with `#` to disambiguate from external packages, but it is not required unlike in Node.js.
#### `"engines"`
```json
{
"engines": {
"bare": ">=1.0.5"
}
}
```
The `"engines"` field defines the engine requirements of the package. During module resolution, the versions declared by `Bare.versions` will be tested against the requirements declared by the package and resolution fail if they're not satisfied.
## API
#### `Module.constants.states`
The flags for the current state of a module.
| Constant | Description |
| :------------ | :------------------------------------------- |
| `EVALUATED` | The module has been evaluated. |
| `SYNTHESIZED` | The module named exports have been detected. |
| `DESTROYED` | The module has been unloaded. |
#### `Module.constants.types`
| Constant | Description |
| :------- | :--------------------------------------------------------------------------- |
| `SCRIPT` | The module is a CommonJS module. |
| `MODULE` | The module is a ECMAScript module. |
| `JSON` | The module is a JSON file. |
| `BUNDLE` | The module is a [`bare-bundle`](https://github.com/holepunchto/bare-bundle). |
| `ADDON` | The module is a native addon. |
| `BINARY` | The module is a binary file. |
| `TEXT` | The module is a text file. |
#### `Module.protocol`
The default `ModuleProtocol` class for resolving, reading and loading modules. See [Protocols](#protocols) for usage.
#### `Module.cache`
The global cache of loaded modules.
#### `const url = Module.resolve(specifier, parentURL[, options])`
Resolve the module `specifier` relative to the `parentURL`. `specifier` is a string and `parentURL` is a WHATWG `URL`.
Options include:
```js
options = {
// Whether the module is called via `import` or `import()`.
isImport: false,
// The referring module.
referrer: null,
// The type of the module. See Module.constants.types for possible values. The
// default is the equivalent constant of the `attributes`'s `type` property.
type,
// A list of file extensions to look for. The default is based on the `type`
// option.
extensions: [],
// The ModuleProtocol to resolve the specifier. Defaults to referrer's
// protocol if defined, otherwise defaults to Module.protocol
protocol,
// A default "imports" map to apply to all specifiers. Follows the same
// syntax and rules as the "imports" property defined in `package.json`.
imports,
// A map of preresolved imports with keys being serialized parent URLs and
// values being "imports" maps.
resolutions,
// A map of builtin module specifiers to loaded modules. If matched by the
// default resolver, the protocol of the resolved URL will be `builtin:`.
builtins,
// The supported import conditions. "default" is always recognized.
conditions: [],
// The import attributes, e.g. the `{ type: "json" }` in:
// `import foo from 'foo' with { type: "json" }`
// or in:
// `require('foo', { with: { type: "json" } })`
attributes
}
```
#### `const module = Module.load(url[, source][, options])`
Load a module with the provided `url`. `url` is a WHATWG `URL`. If provided, the `source` will be passed to the matching `extension` for the `url`.
Options include:
```js
options = {
// Whether the module is called via `import` or `import()`.
isImport: false,
// Whether the module is called via `import()`.
isDynamicImport: false,
// The referring module.
referrer: null,
// The type of the module. See Module.constants.types for possible values. The
// default is the equivalent constant of the `attributes`'s `type` property.
type,
// The assumed type of a module without a type using an ambiguous extension
// such as `.js`. See Module.constants.types. Inherited from `referrer` if it
// is defined.
defaultType: Module.constants.types.SCRIPT,
// Cache to use to load the Module. Defaults to `Module.cache`.
cache,
// The module representing the entry script where the program was launched.
main,
// The ModuleProtocol to use resolve the specifier. Defaults to referrer's
// `protocol` if defined, otherwise defaults to `Module.protocol`.
protocol,
// A default "imports" map to apply to all specifiers. Follows the same
// syntax and rules as the "imports" property defined in `package.json`.
imports,
// A map of preresolved imports with keys being serialized parent URLs and
// values being "imports" maps.
resolutions,
// A map of builtin module specifiers to loaded modules. If the `url`'s
// protocol is `builtin:`, the module's exports will be set to the matching
// value in the map for `url.pathname`.
builtins,
// The supported import conditions. "default" is always recognized.
conditions,
// The import attributes, e.g. the `{ type: "json" }` in:
// `import foo from 'foo' with { type: "json" }`
// or in:
// `require('foo', { with: { type: "json" } })`
attributes
}
```
#### `const url = Module.asset(specifier, parentURL[, options])`
Get the asset URL by resolving `specifier` relative to `parentURL`. `specifier` is a string and `parentURL` is a WHATWG `URL`.
Options include:
```js
options = {
// The referring module.
referrer: null,
// The ModuleProtocol to use resolve the specifier. Defaults to referrer's
// protocol if defined, otherwise defaults to Module.protocol
protocol,
// A default "imports" map to apply to all specifiers. Follows the same
// syntax and rules as the "imports" property defined in `package.json`.
imports,
// A map of preresolved imports with keys being serialized parent URLs and
// values being "imports" maps.
resolutions,
// The supported import conditions. "default" is always recognized.
conditions
}
```
#### `module.url`
The WHATWG `URL` instance for the module.
#### `module.filename`
The pathname of the `module.url`.
#### `module.dirname`
The directory name of the module.
#### `module.type`
The type of the module. See [`Module.constants.types`](#module.constants.types) for possible values.
#### `module.defaultType`
The assumed type of a module without a `type` using an ambiguous extension, such as `.js`. See [`Module.constants.types`](#module.constants.types) for possible values.
#### `module.cache`
A cache of loaded modules for this module. Defaults to `Module.cache`.
#### `module.main`
The module representing the entry script where the program was launched.
#### `module.exports`
The exports from the module.
#### `module.imports`
The import map when the module was loaded.
#### `module.resolutions`
A map of preresolved imports with keys being serialized parent URLs and values being `"imports"` maps.
#### `module.builtins`
A map of builtin module specifiers mapped to the loaded module.
#### `module.conditions`
An array of conditions used to resolve dependencies while loading the module. See [Conditional Exports](#conditional-exports) for possible values.
#### `module.protocol`
The `ModuleProtocol` class used for resolving, reading and loading modules. See [Protocols](#protocols).
#### `module.destroy()`
Unloads the module.
### CommonJS modules
#### `require(specifier[, options])`
Used to import JavaScript or JSON modules and local files. Relative paths such as `./`, `./foo`, `./bar/baz`, and `../foo` will be resolved against the directory named by `__dirname`. POSIX style paths are resolved in an OS independent fashion, meaning that the examples above will work on Windows in the same way they would on POSIX systems.
Returns the exported module contents.
Options include:
```js
options = {
// The import attributes which instruct how the file or module should be loaded.
// Possible values for `type` are `script`, `module`, `json`, `bundle`,
// `addon`, `binary` and `text`.
with: { type: 'json' }
}
```
#### `require.main`
The module representing the entry script where the program was launched. The same value as [`module.main`](#modulemain) for the current module.
#### `require.cache`
A cache of loaded modules for this module. The same value as `module.cache` for the current module.
#### `const path = require.resolve(specifier[, parentURL])`
Use the internal machinery of `require()` to resolve the `specifier` string relative to the URL `parentURL` and return the path string.
#### `require.addon([specifier][, parentURL])`
Also used to import modules but specifically loads only addon modules. `specifier` is resolved relative to `parentURL` using the [addon resolution](https://github.com/holepunchto/bare-addon-resolve#algorithm) algorithm.
Returns the exported module contents.
A common pattern for writing an addon module is to use `require.addon()` as the JavaScript module exports:
```js
module.exports = require.addon()
```
See [`bare-addon`](https://github.com/holepunchto/bare-addon) for a template of building native addon modules.
#### `require.addon.host`
Returns the string representation of the platform and architecture used when resolving addons with the pattern `<platform>-<arch>[-simulator]`. Returns the same value as `Bare.Addon.host`.
#### `const path = require.addon.resolve([specifier][, parentURL])`
Resolve the `specifier` string relative to the URL `parentURL` as an addon and returns the path string. The `specifier` is resolved using the [addon resolution algorithm](https://github.com/holepunchto/bare-addon-resolve#algorithm).
#### `const path = require.asset(specifier[, parentURL])`
Resolve the `specifier` relative to the `parentURL` and return the path of the asset as a string.
Can be used to load assets, for example the following loads `./foo.txt` from the local files:
```js
const fs = require('bare-fs')
const contents = fs.readFileSync(require.asset('./foo.txt'))
```
### ECMAScript modules
#### `import defaultExport, * as name, { export1, export2 as alias2, ... } from 'specifier' with { type: 'json' }`
The static `import` declaration is used to import read-only live bindings that are exported by another module. The imported bindings are called _live_ bindings because they are updated by the module that exported the binding, but cannot be re-assigned by the importing module. In brief, you can import what is exported from another module.
For more information on `import` syntax, see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).
#### `import.meta.url`
The string representation of the URL for the current module.
#### `import.meta.main`
A boolean representing whether the current module is the entry script where the program was launched.
#### `import.meta.cache`
A cache of loaded modules for this module. The same value as `module.cache` for the current module.
#### `const href = import.meta.resolve(specifier[, parentURL])`
A module-relative resolution function which returns the URL string for the module. The `specifier` is a string which is resolved relative to the `parentURL` which is a WHATWG URL.
#### `import.meta.addon([specifier][, parentURL])`
Also used to import modules but specifically loads only addon modules. `specifier` is resolved relative to `parentURL` using the [addon resolution](https://github.com/holepunchto/bare-addon-resolve#algorithm) algorithm.
Returns the exported module contents.
#### `import.meta.addon.host`
Returns the string representation of the platform and architecture used when resolving addons with the pattern `<platform>-<arch>[-simulator]`. Returns the same value as `Bare.Addon.host`.
#### `const href = import.meta.addon.resolve([specifier][, parentURL])`
Resolve the `specifier` string relative to the URL `parentURL` as an addon and returns the URL string. The `specifier` is resolved using the [addon resolution algorithm](https://github.com/holepunchto/bare-addon-resolve#algorithm).
#### `const href = import.meta.asset(specifier[, parentURL])`
Resolve the `specifier` relative to the `parentURL` and return the URL of the asset as a string.
### Custom `require()`
Creating a custom require allows one to create a preconfigured `require()`. This can be useful in scenarios such as a Read-Evaluate-Print-Loop (REPL) where the parent URL is set to a directory so requiring relative paths to work correctly.
#### `const require = Module.createRequire(parentURL[, options])`
Options include:
```js
options = {
// The module to become the `referrer` for the returned `require()`. Defaults
// to creating a new module instance from the `parentURL` with the same
// options.
module: null,
// The referring module.
referrer: null,
// The type of the module. See Module.constants.types for possible values.
type: Module.constants.types.SCRIPT,
// The assumed type of a module without a type using an ambiguous extension
// such as `.js`. See Module.constants.types. Inherited from `referrer` if it
// is defined, otherwise defaults to SCRIPT.
defaultType: Module.constants.types.SCRIPT,
// A cache of loaded modules. Inherited from `referrer` if it is defined,
// otherwise defaults to `Module.cache`
cache,
// The module representing the entry script where the program was launched.
main,
// The ModuleProtocol to use resolve the specifier and/or the module. Defaults to
// referrer's protocol if defined, otherwise defaults to Module.protocol
protocol,
// A default "imports" map to apply to all specifiers. Follows the same
// syntax and rules as the "imports" property defined in `package.json`.
imports,
// A map of preresolved imports with keys being serialized parent URLs and
// values being "imports" maps.
resolutions,
// A map of builtin module specifiers to loaded modules.
builtins,
// The supported import conditions. "default" is always recognized.
conditions
}
```
### Protocols
Protocols define how to resolve, access and load modules. Custom protocols can be defined to extend or replace how module are resolved and loaded to support things like loading modules via a [`Hyperdrive`](https://github.com/holepunchto/hyperdrive).
#### `const protocol = new Module.Protocol(methods, context = null)`
Methods include:
```js
methods = {
// function (specifier, parentURL): string
// A function to preprocess the `specifier` and `parentURL` before the resolve
// algorithm is called.
preresolve,
// function (url): string
// A function to process the resolved URL. Can be used to convert file paths,
// etc.
postresolve,
// function* (specifier, parentURL, imports): [URL]
// A generator to resolve the `specifier` to a URL.
resolve,
// function (url): boolean
// A function that returns whether the URL exists as a boolean.
exists,
// function (url): string | Buffer
// A function that returns the source code of a URL represented as a string or
// buffer.
read,
// function (url): object
// A function that returns the evaluated exports for the url. This is
// only called for Javascript modules (extensions `.js`, `.cjs` & `.mjs`)
// by default. If defined, this function will skip calling `read()` and
// evaluating the source method for the default implementations of the
// Javascript extensions.
load,
// function (url): URL
// A function used to post process URLs for addons before `postresolve()`.
addon,
// function (url): URL
// A function used to post process URLs for assets before `postresolve()`.
asset
}
```
### Bundles
#### `const bundle = new Module.Bundle()`
See <https://github.com/holepunchto/bare-bundle>.

View File

@@ -1,32 +1,41 @@
# Bare
[Bare](https://github.com/holepunchto/bare) is a small and modular JavaScript runtime for desktop and mobile. Like Node.js, it provides an asynchronous, event-driven architecture for writing applications in the lingua franca of modern software. Unlike Node.js, it makes embedding and cross-device support core use cases, aiming to run well on any system whether that is a phone or desktop. The result is a runtime ideal for networked, peer-to-peer applications that can run on a wide selection of hardware.
## Installation
Prebuilt binaries are provided by [Bare Runtime](https://github.com/holepunchto/bare-runtime) and can be installed using `npm`:
Small and modular JavaScript runtime for desktop and mobile. Like Node.js, it provides an asynchronous, event-driven architecture for writing applications in the lingua franca of modern software. Unlike Node.js, it makes embedding and cross-device support core use cases, aiming to run just as well on your phone as on your laptop. The result is a runtime ideal for networked, peer-to-peer applications that can run on a wide selection of hardware.
```sh
npm i -g bare-runtime
npm i -g bare
```
## Usage
```sh
bare [-e, --eval <script>] [-p, --print <script>] [<filename>]
```console
bare [flags] <filename> [...args]
Evaluate a script or start a REPL session if no script is provided.
Arguments:
<filename> The name of a script to evaluate
[...args] Additional arguments made available to the script
Flags:
--version|-v Print the Bare version
--eval|-e <script> Evaluate an inline script
--print|-p <script> Evaluate an inline script and print the result
--inspect Activate the inspector
--help|-h Show help
```
The specified `<script>` or `<filename>` is run using `Module.load()`. For more information on the module system and the supported formats, see [Bare Modules](./bare-modules.md).
The specified `<script>` or `<filename>` is run using `Module.load()`. For more information on the module system and the supported formats, see <https://github.com/holepunchto/bare-module>.
## Architecture
Bare is built on top of [libjs](https://github.com/holepunchto/libjs), which provides low-level bindings to V8, and [libuv](https://github.com/libuv/libuv), which provides an asynchronous I/O event loop. Bare itself only adds a few missing pieces on top to support a wider ecosystem of modules:
Bare is built on top of <https://github.com/holepunchto/libjs>, which provides low-level bindings to V8 in an engine independent manner, and <https://github.com/libuv/libuv>, which provides an asynchronous I/O event loop. Bare itself only adds a few missing pieces on top to support a wider ecosystem of modules:
1. A module system supporting both CJS and ESM with bidirectional interoperability between the two.
2. A native addon system supporting both statically and dynamically linked addons.
3. Light-weight thread support with synchronous joins and shared array buffer support.
All additional features are implemented by userland modules using these primitives, keeping the runtime itself lean and _bare_.
Everything else if left to userland modules to implement using these primitives, keeping the runtime itself succint and _bare_. By abstracting over both the underlying JavaScript engine using `libjs` and platform I/O operations using `libuv`, Bare allows module authors to implement native addons that can run on any JavaScript engine that implements the `libjs` ABI and any system that `libuv` supports.
## API
@@ -36,7 +45,6 @@ Bare makes it easy to craft applications that can run effectively across a broad
Bare provides no standard library beyond the core JavaScript API available through the `Bare` namespace. Instead, there is a comprehensive collection of external modules built specifically for Bare, see [Bare Modules](./bare-modules.md)
### Embedding
Bare can easily be embedded using the C API defined in [`include/bare.h`](https://github.com/holepunchto/bare/blob/main/include/bare.h):
@@ -46,9 +54,11 @@ Bare can easily be embedded using the C API defined in [`include/bare.h`](https:
#include <uv.h>
bare_t *bare;
bare_setup(uv_default_loop(), platform, &env, argc, argv, options, &bare);
bare_setup(uv_default_loop(), platform, &env /* Optional */, argc, argv, options, &bare);
bare_run(bare, filename, source);
bare_load(bare, filename, source, &module /* Optional */);
bare_run(bare);
int exit_code;
bare_teardown(bare, &exit_code);
@@ -60,31 +70,72 @@ If `source` is `NULL`, the contents of `filename` will instead be read at runtim
Bare provides a mechanism for implementing process suspension, which is needed for platforms with strict application lifecycle constraints, such as mobile platforms. When suspended, a `suspend` event will be emitted on the `Bare` namespace. Then, when the loop has no work left and would otherwise exit, an `idle` event will be emitted and the loop blocked, keeping it from exiting. When the process is later resumed, a `resume` event will be emitted and the loop unblocked, allowing it to exit when no work is left.
The suspension API is available through `bare_suspend()` and `bare_resume()` from C and `Bare.suspend()` and `Bare.resume()` from JavaScript. See [`test/suspend-resume.js`](https://github.com/holepunchto/bare/blob/main/test/suspend-resume.js) for an example of using the suspension API from JavaScript.
The suspension API is available through `bare_suspend()` and `bare_resume()` from C and `Bare.suspend()` and `Bare.resume()` from JavaScript.
## Building
The `bare-dev` toolkit, which we'll be invoking with `npx`, is used for building Bare and acts as a convenient wrapper around CMake and other tools. After cloning the repository, start by synchronizing the vendored dependencies such as git submodules:
<https://github.com/holepunchto/bare-make> is used for compiling Bare. Start by installing the tool globally:
```sh
npx bare-dev vendor sync
```console
npm i -g bare-make
```
Then, configure the build tree before performing the first build:
Next, install the required build and runtime dependencies:
```sh
npx bare-dev configure [--debug]
```console
npm i
```
Finally, perform the build:
Then, generate the build system:
```sh
npx bare-dev build
```console
bare-make generate
```
When completed, the `bare` binary will be available in the `build/bin` directory and the `libbare.(a|lib)` and `(lib)bare.(dylib|dll)` libraries will be available in the root of the `build` directory.
This only has to be run once per repository checkout. When updating `bare-make` or your compiler toolchain it might also be necessary to regenerate the build system. To do so, run the command again with the `--no-cache` flag set to disregard the existing build system cache:
```console
bare-make generate --no-cache
```
With a build system generated, Bare can be compiled:
```console
bare-make build
```
When completed, the `bare(.exe)` binary will be available in the `build/bin` directory and the `libbare.(a|lib)` and `(lib)bare.(dylib|dll|lib)` libraries will be available in the root of the `build` directory.
### Linking
When linking against the static `libbare.(a|lib)` library, make sure to use whole archive linking as Bare relies on constructor functions for registering native addons. Without whole archive linking, the linker will remove the constructor functions as they aren't referenced by anything.
## Platform support
Bare uses a tiered support system to manage expectations for the platforms that it targets. Targets may move between tiers between minor releases and as such a change in tier will not be considered a breaking change.
**Tier 1:** Platform targets for which prebuilds are provided as defined by the [`.github/workflows/prebuild.yml`](https://github.com/holepunchto/bare/blob/main/.github/workflows/prebuild.yml) workflow. Compilation and test failures for these targets will cause workflow runs to go red.
**Tier 2:** Platform targets for which Bare is known to work, but without automated compilation and testing. Regressions may occur between releases and will be considered bugs.
> [!NOTE]
> Development happens primarily on Apple hardware with Linux and Windows systems running as virtual machines.
| Platform | Architecture | Version | Tier | Notes |
| :-------- | :----------- | :----------------------------------- | :--- | :-------------------------- |
| GNU/Linux | `arm64` | >= Linux 5.15, >= GNU C Library 2.35 | 1 | Ubuntu 22.04, OpenWrt 23.05 |
| GNU/Linux | `x64` | >= Linux 5.15, >= GNU C Library 2.35 | 1 | Ubuntu 22.04, OpenWrt 23.05 |
| GNU/Linux | `arm64` | >= Linux 5.10, >= musl 1.2 | 2 | Alpine 3.13, OpenWrt 22.03 |
| GNU/Linux | `x64` | >= Linux 5.10, >= musl 1.2 | 2 | Alpine 3.13, OpenWrt 22.03 |
| GNU/Linux | `mips` | >= Linux 5.10, >= musl 1.2 | 2 | OpenWrt 22.03 |
| GNU/Linux | `mipsel` | >= Linux 5.10, >= musl 1.2 | 2 | OpenWrt 22.03 |
| Android | `arm` | >= 9 | 1 |
| Android | `arm64` | >= 9 | 1 |
| Android | `ia32` | >= 9 | 1 |
| Android | `x64` | >= 9 | 1 |
| macOS | `arm64` | >= 11.0 | 1 |
| macOS | `x64` | >= 11.0 | 1 |
| iOS | `arm64` | >= 14.0 | 1 |
| iOS | `x64` | >= 14.0 | 1 | Simulator only |
| Windows | `arm64` | >= Windows 11 | 1 |
| Windows | `x64` | >= Windows 10 | 1 |