diff --git a/component-model/src/design/component-model-concepts.md b/component-model/src/design/component-model-concepts.md index d5c6789c..76d738fa 100644 --- a/component-model/src/design/component-model-concepts.md +++ b/component-model/src/design/component-model-concepts.md @@ -1,30 +1,110 @@ ## Component Model Concepts -This section introduces the core concepts and [rationale](./why-component-model.md) of the component model. - -* A [WebAssembly Component](./components.md) is the next evolution of core WebAssembly binaries. - * WebAssembly components are *nestable* -- they may contain one or more core modules and/or sub-components composed together. -* The Component Model extends core WebAssembly by introducing higher level types and interface-driven development - * [WebAssembly Interface Types (WIT)][wit] is the [IDL (Interface Definition Language)][wiki-idl] used to formally define functionality for WebAssembly modules. - * With WIT, WebAssembly components gain the ability to conform an language-agnostic and encode that support, so any WebAssembly component binary can be interrogated *and* executed. - * An [Interface](./interfaces.md) describes the types and functions used for a specific, focused bit of functionality. - * A [World](./worlds.md) assembles interfaces to express what features a component offers, and what features it depends on. - * A [Package](./packages.md) is a set of WIT files containing a related set of interfaces and worlds. -* The Component Model introduces the idea of a "platform" to core WebAssembly -- enabling the structured, standardized use of "host" functionality for WebAssembly "guest"s. - * The WebAssembly System Interface (WASI) defines in WIT a family of interfaces for common system-level functions. - * WASI defines common execution environments such as the command line (`wasi:cli`) or a HTTP server (`wasi:http`). -* The Component Model makes core WebAssembly composable -- components that provide functionality and those that use them can be composed together into *one* resulting component +The WebAssembly Component Model extends core WebAssembly in several ways. +The Component Model: +* Adds consistent representation of higher-level types +* Enables interface-driven development +* Makes core WebAssembly composable: +components that provide functionality and those that use them +can be composed together into *one* resulting component. + +This section introduces the core concepts behind the component model. +For the rationale behind the component model, see [the previous section](./why-component-model.md). + +### Components + +A [WebAssembly Component](./components.md) is a binary that +conforms to the [Canonical ABI](../advanced/canonical-abi.md); +often a WebAssembly core module extended with the features +of the Component Model +(higher-level types, interfaces). +WebAssembly components are *nestable*: +they may contain zero or more core modules and/or sub-components composed together. +For example, a component implementing a simple calculator might be written +by composing together a component that parses strings to floating-point numbers +with a component that does the main arithmetic. + +### WebAssembly Interface Types (WIT) + +[WebAssembly Interface Types (WIT)][wit] is the [Interface Definition Language (IDL)][wiki-idl] +used to formally define functionality for WebAssembly components. +WIT gives WebAssembly components the ability to express type signatures +in a language-agnostic way, +so any component binary can be checked, composed and executed. + +#### Interfaces + +An [_interface_](./interfaces.md) is a collection of type definitions +and function declarations (function names accompanied by type signatures). +Typically, a single interface describes a specific, focused bit +of functionality. + +For example, in [wasi-cli][wasi-cli-stdio], +three separate interfaces are used to implement `stdin`, `stdout`, and `stderr` +(streams typically available in command-line-like environments) + +### Worlds + +A [_world_](./worlds.md) is a collection of interfaces and types +that expresses what features a component offers +and what features it depends on. + +For example, wasi-cli includes the [`command` world][wasi-cli-command], +which depends on interfaces +that represent the `stdin`, `stdout`, and `stderr` streams, +among other things. +A component implementing the `command` world +must be invoked in an environment that implements those interfaces. + +### Packages + + A [_package_](./packages.md) is a set of WIT files +containing a related set of interfaces and worlds. + +For example, the [wasi-http](https://github.com/WebAssembly/wasi-http/blob/main/wit/proxy.wit) package includes +an `imports` world encapsulating the interfaces that an HTTP proxy depends on, +and a `proxy` world that depends on `imports`. + +### Platforms + +In the context of WebAssembly, a _host_ refers to a WebAssembly runtime +capable of executing WebAssembly binaries. +The runtime can be inside a browser or can stand alone. +A _guest_ refers to the WebAssembly binary that is executed by the host. +(These terms borrow from their analogs in [virtualization](https://en.wikipedia.org/wiki/Virtualization), where a guest is +a software-based virtual machine that runs on physical hardware, +which is the "host") + +The Component Model introduces the idea of a _platform_ +to core WebAssembly—enabling the structured, standardized use +of host functionality for WebAssembly guests. +Components may import functionality that is provided +by the platform on which they are executed. + +### WASI + +The WebAssembly System Interface ([WASI][wasi]) defines in WIT +a family of interfaces for common system-level functions. +WASI defines a platform for component writers that mimics +existing programs that developers are familiar with +(for example, `wasi-cli` or `wasi-http`), +standardizing the functionality components depend on. > [!NOTE] -> The Component Model is stewarded by the Bytecode Alliance and designed [in the open][cm-repo]. +> The Component Model is stewarded by the [Bytecode Alliance](https://bytecodealliance.org/) and designed [in the open][cm-repo]. > -> See the [`WebAssembly/component-model`][cm-repo] repository for [Goals][goals],[use cases][use-cases], and [high level design choices][design-choices]. +> See the [`WebAssembly/component-model`][cm-repo] repository for [goals][goals], [use cases][use-cases], and [high level design choices][design-choices]. [cm-repo]: https://github.com/WebAssembly/component-model -[wiki-idl]: https://en.wikipedia.org/wiki/Web_IDL +[wiki-idl]: https://en.wikipedia.org/wiki/Interface_description_language [goals]: https://github.com/WebAssembly/component-model/blob/main/design/high-level/Goals.md [use-cases]: https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md [design-choices]: https://github.com/WebAssembly/component-model/blob/main/design/high-level/Choices.md [wit]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md +[wasi]: https://wasi.dev/ +[wasi-cli]: https://github.com/WebAssembly/wasi-cli/ +[wasi-cli-stdio]: https://github.com/WebAssembly/wasi-cli/blob/main/wit/stdio.wit +[wasi-cli-command]: https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit +[wasi-http]: https://github.com/WebAssembly/wasi-http [!NOTE]: # diff --git a/component-model/src/design/components.md b/component-model/src/design/components.md index 53cfb1a4..c4a800b6 100644 --- a/component-model/src/design/components.md +++ b/component-model/src/design/components.md @@ -1,9 +1,60 @@ # Components -* Logically, components are containers for modules - or other components - which express their [interfaces](./interfaces.md) and dependencies via [WIT](./wit.md). -* Conceptually, components are self-describing units of code that interact only through interfaces instead of shared memory. -* Physically, a **component** is a specially-formatted WebAssembly file. Internally, the component could include multiple traditional ("core") WebAssembly modules, and sub-components, composed via their imports and exports. +Conceptually, a component is a self-describing WebAssembly binary +that interacts only through interfaces +instead of shared memory. +Let's break down what each of these terms means: -The external interface of a component - its imports and exports - corresponds to a [world](./worlds.md). The component, however, internally defines how that world is implemented. +* _Self-describing_: Like a WebAssembly core module, + a component includes import and export declarations + that declare both the names and types of + imported and exported functions. + Compared to core modules, components use a richer type system + to describe these types, so it's easier to understand + what functionality a module provides + and what functionality it relies on. +* _Interacts_: When a component interacts with other components, + that means either that it calls a function defined in a different component, + or that another component calls a function defined in it. + Interfaces specify what kinds of function calls are valid. +* _Shared memory_: In the ["Why the Component Model?"](./why-component-model.md) section, + we showed how WebAssembly core modules can only exchange compound data + through shared memory. + Components use memory in the same way that core modules do, + except that in components, memories are never exported or imported; + they are not shared. -> For a more formal definition of what a component is, take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). +Logically, a component is a structure +that may contain core modules and/or other components. +The component encodes the interfaces of these contained +modules and sub-components using [WebAssembly Interface Types (WIT)](./wit.md). + +> For a more formal definition of a component, +> take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). + +The on-disk representation of a component +is [a specially-formatted WebAssembly binary](../advanced/canonical-abi.md). +Internally, this file could include representations +of one or many traditional ("core") WebAssembly modules and sub-components, +composed together via their imports and exports. +Two modules or components can be composed if the +imports of one are satisfied by the exports of another. +Composition can be repeated arbitarily, composing a +single component out of many interlocking modules and components. +[Interfaces](./interfaces.md) enable checking that +a particular composition makes sense. + +Each component is described by a [world](./worlds.md), +which potentially collects together multiple interfaces +to describe all the imports and exports of the component. +The world only describes the types of imported and exported functions; +the component internally defines the code to implement the world. + +## Composition + +Two modules or components can be composed if the +imports of one are satisfied by the exports of another. +Composition can be repeated arbitarily, composing a +single component out of many interlocking modules and components. +[Interfaces](./interfaces.md) enable checking that +a particular composition makes sense. diff --git a/component-model/src/design/interfaces.md b/component-model/src/design/interfaces.md index 69f3c573..42991729 100644 --- a/component-model/src/design/interfaces.md +++ b/component-model/src/design/interfaces.md @@ -1,10 +1,58 @@ # Interfaces -An **interface** describes a single-focus, composable contract, through which components can interact with each other and with hosts. Interfaces describe the types and functions used to carry out that interaction. For example: +Interfaces are based on the idea of [design by contract][wp-contract]. +In software design, a _contract_ is a specification +of how a unit of code should behave. -* A "receive HTTP requests" interface might have only a single "handle request" function, but contain types representing incoming requests, outgoing responses, HTTP methods and headers, and so on. -* A "wall clock" interface might have two functions, one to get the current time and one to get the granularity of the timer. It would also include a type to represent an instant in time. +Concretely, an interface is a collection of type definitions +and function declarations. +Conceptually, an _interface_ describes a single-focus, composable contract +through which components can interact with each other +and with hosts. +* _Single-focus_: By convention, an interface describes + types and functions that are related to each other + and collectively provide a relatively small unit of + functionality, + such as reading from the standard input stream + in a command-line environment. +* _Composable_: Interfaces can be imported and exported. + One component's interfaces can be built + on top of interfaces defined in a different component. + Interfaces enable typechecking so that interfaces can + be composed only when it makes sense to do so. + +The types and functions in an interface +are used to enable interactions between components and hosts. +For example: + +* A "receive HTTP requests" interface might declare + a single "handle request" function, + along with definitions of types representing + incoming requests, outgoing responses, + HTTP methods and headers, and other data structures. + This might look like the `incoming-handler` interface + in [wasi-http][wasi-http-handler] +* A "wall clock" interface might declare two functions, + one to get the current time + and one to get the granularity of the timer (whether time + is measured in seconds, milliseconds, nanoseconds, or another unit). + It would also define a type to represent an instant in time. + This might look like the `wall-clock` interface + in [wasi-clocks][wasi-clocks-wall-clock]. + +As an example of composing interfaces together, +imagine defining a "timer" interface that declares two functions, +one to start a timer and one to query whether the timeout +has been exceeded. +This interface could be defined by importing the "wall clock" +interface. +The result is an interface that exports the timer functionality, +and imports anything imported by the "wall clock" interface. Interfaces are defined using [the WIT language](./wit.md). -> For a more formal definition of what an interface is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +[wp-contract]: https://en.wikipedia.org/wiki/Design_by_contract +[wasi-http-handler]: https://github.com/WebAssembly/wasi-http/blob/main/wit/handler.wit +[wasi-clocks-wall-clock]: https://github.com/WebAssembly/wasi-clocks/blob/main/wit/wall-clock.wit + +> For a more formal definition of an interface, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/packages.md b/component-model/src/design/packages.md index 295c96a0..f66056f8 100644 --- a/component-model/src/design/packages.md +++ b/component-model/src/design/packages.md @@ -1,9 +1,23 @@ # WIT Packages -A **WIT package** is a set of one or more [WIT (Wasm Interface Type)](./wit.md) files containing a related set of interfaces and worlds. WIT is an IDL (interface definition language) for the Component Model. Packages provide a way for worlds and interfaces to refer to each other, and thus for an ecosystem of components to share common definitions. +A **WIT package** is a set of one or more [WebAssembly Interface Type](./wit.md) (WIT) files +that, taken together, contain a set of interfaces and worlds that are related to each other. +WIT is an [interface definition language][wp-idl] (IDL) for the component model. +Packages provide a way for worlds and interfaces to refer to each other, +and thus for an ecosystem of components to share common definitions. -A WIT package is not a [world](./worlds.md). It's a way of grouping related interfaces and worlds together for ease of discovery and reference, more like a namespace. +A WIT package groups related interfaces and worlds together +for ease of discovery and reference. +A package is not a [world](./worlds.md): a package maps to one or more files +and contains worlds. +A world is a bundle of imported and exported types and interfaces. -* The WebAssembly System Interface (WASI) defines a number of packages, including one named `wasi:clocks`. Our HTTP proxy world could import the `wall-clock` interface from the `wasi:clocks` package, rather than having to define a custom clock interface. +* The WebAssembly System Interface (WASI) defines a number of packages, + including one named `wasi:clocks`. + Our HTTP proxy world could import the `wasi:clocks/wall-clock` interface + (read as "the `wall-clock` interface from the `wasi:clocks` package"), + rather than having to define a custom clock interface. > For a more formal definition of what a WIT package is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). + +[wp-idl]: https://en.wikipedia.org/wiki/Interface_description_language diff --git a/component-model/src/design/why-component-model.md b/component-model/src/design/why-component-model.md index af0a57b9..6b675efa 100644 --- a/component-model/src/design/why-component-model.md +++ b/component-model/src/design/why-component-model.md @@ -55,7 +55,9 @@ Kinds of definitions include: * And others; see [the Core Specification](https://webassembly.github.io/spec/core/syntax/modules.html) for the complete list. -Core modules can be run in the browser, +A compiled core module is sometimes called a "WebAssembly binary", +and usually corresponds to a single `.wasm` file. +These modules can be run in the browser, or via a separate runtime such as [Wasmtime](https://wasmtime.dev/) or [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime). diff --git a/component-model/src/design/worlds.md b/component-model/src/design/worlds.md index e708c68f..dcb3b5bc 100644 --- a/component-model/src/design/worlds.md +++ b/component-model/src/design/worlds.md @@ -1,20 +1,99 @@ # WIT Worlds -A **WIT world** is a higher-level contract that describes a component's capabilities and needs. +A **WIT world** (or just "world") is a contract with a broader scope +than a single interface. +A world describes the functionality a component provides, +and the functionality it requires in order to work. -On one hand, a world describes the shape of a component - it says which interfaces the component exposes for other code to call (its exports), and which interfaces the component depends on (its imports). A world only defines the surface of a component, not the internal behaviour. If you're an application or library developer creating a component, you'll specify the world your component targets. This world describes the functionality your component exposes and declares the functionality your component depends on in order to be able to run. Your component may target a custom world definition you have created with a unique set of imports and exports tailored just for your use case, or it may target an existing world definition that someone else has already specified. +A world can be used to describe a component, +and a hosting environment for other components, +depending on which imports and exports are specified. +Worlds can represent either a component or host environment +because components can be composed: +a component can provide functionality required by another component, +just like a host environment can. -On the other hand though, a world defines a _hosting environment_ for components (i.e., an environment in which a component can be instantiated and its functionality can be invoked). An environment supports a world by providing implementations for all of the imports and by optionally invoking one or more of the exports. +## Fulfilling worlds with components versus hosts -For example, WASI (the WebAssembly System Interface) defines a "command line" world which imports interfaces that command line programs typically expect to have available to them such as file I/O, random number generation, clocks and so on. This world has a single export for running the command line tool. Components targeting this world must provide an implementation for this single export, and they may optionally call any of the imports. On the other hand, environments supporting this world must provide implementations for all of the imports and may invoke the single export. +On the one hand, a world describes how a component relates to other components: +it describes the functionality the component exposes +and declares the functionality it depends on in order to be able to run. +Functionality is exposed by defining interfaces to export, +and dependencies are declared by importing interfaces. +A world only defines the surface of a component, not its internal behaviour. -A world is composed of interfaces, but each interface is _directional_ - it indicates whether the interface is available for outside code to call (an "export"), or whether outside code must fulfill the interface for the component to call (an "import"). These interfaces strictly bound the component. A component cannot interact with anything outside itself except by having its exports called, or by it calling its imports. This provides very strong sandboxing; for example, if a component does not have an import for a secret store, then it _cannot_ access that secret store, even if the store is running in the same process. +On the other hand, a world defines a hosting environment for components: +that is, an environment in which a component can be instantiated +and its functionality can be invoked. +* In WebAssembly, _instantiation_ means turning a static description of a module + into a dynamic structure in memory. + It's analogous to [loading](https://en.wikipedia.org/wiki/Loader_(computing)) + an executable file. -For a component to run, its imports must be fulfilled, by a host or by other components. Connecting up some or all of a component's imports to other components' matching exports is called _composition_. +A hosting environment supports a world by providing implementations +for all of the imports +and by optionally invoking one or more of the exports. +If you're an application or library developer creating a component, +you'll specify the world your component targets. +Your component may target a custom world definition you have created +with a unique set of imports and exports tailored just for your use case, +or it may target an existing world definition that someone else has already specified. +In either case, the world specifies all the external functionality your component needs. +Targeting a world is analogous to relying on a particular version of a standard library, +except that components give you the ability to precisely specify +exactly what functions your code depends on. -## Example Worlds +## Example: the `wasi:cli` world -* A (trivial) "HTTP proxy" world would export a "handle HTTP requests" interface, and import a "send HTTP requests" interface. A host, or another component, would call the exported "handle" interface, passing an HTTP request; the component would forward it on via the imported "send" interface. To be a _useful_ proxy, the component may also need to import interfaces such as I/O and clock time - without those imports the component could not perform, for example, on-disk caching. -* A "regex parser" world would export a "parse regex" function, and would import nothing. This declares not only that the component implementing this world can parse regular expressions, but also that it calls no other APIs. A user of such a parser could know, without looking at the implementation, that is does not access the file system, or send the user's regexes to a network service. +For example, WASI (the WebAssembly System Interface) defines a "command line" world +that imports interfaces that command-line programs typically expect to have available to them: +for example, file input/output, random number generation, and clocks. +This world has a single export for running the command-line tool. +Components targeting this world must provide an implementation for this single export, +and they may optionally call any of the imports. +For example, a component that prints out a summary of the sizes of files +in a particular directory (like the Unix `du` command) +could target the "command line" world, and would depend on +the file input/output interfaces imported by the world. +A hosting environment that supports this world +must provide implementations for all of the imports +and may invoke the single export. +Running your example disk usage component +would mean invoking it in a hosting environment +that supports the "command line" world. + +## Worlds and interfaces + +A world is a collection of interfaces, where each interface is _directional_. +Each interface is explicitly labeled as either an export or an import. +Exported interfaces are available for outside code to call, +whereas imported interfaces must be fulfilled by outside code. +These interfaces define a strict boundary for a component. +The only ways a component can interact with anything outside itself +are by having its exports called, +or by calling its imports. +This boundary provides very strong sandboxing: +for example, if a component does not have an import for a secret store, +then it _cannot_ access that secret store, +even if the store is running in the same process. + +For a component to run, its imports must be fulfilled, by a host or by other components. +Connecting up some or all of a component's imports to other components' matching exports is called _composition_. + +A world is defined in a WIT file; a single WIT files can contain multiple worlds. + +## Example worlds + +* A (trivial) "HTTP proxy" world would export a "handle HTTP requests" interface +and import a "send HTTP requests" interface. +A host, or another component, would call the exported "handle" interface, passing an HTTP request; +the component would forward it on via the imported "send" interface. +To be a _useful_ proxy, the component may also need to import interfaces such as I/O and clock time: +without those imports the component could not perform on-disk caching or other needed features. +* A "regex parser" world would export a "parse regex" function, and would import nothing. +This declares not only that the component implementing this world can parse regular expressions, +but also that it calls no other APIs. +A user of such a parser could know, without looking at the implementation, +that it does not access the file system or send the user's regexes to a network service. > For a more formal definition of what a WIT world is, take a look at the [WIT world specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#wit-worlds).