├── .gitignore ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── book.toml ├── examples ├── core-module │ ├── core-module.wasm │ └── core-module.wat ├── instance │ ├── instance.wasm │ └── instance.wat ├── out-alias │ ├── out-alias.wasm │ └── out-alias.wat ├── recursive-ids │ ├── recursive-ids.wasm │ └── recursive-ids.wat ├── recursive │ ├── recursive.wasm │ └── recursive.wat └── simple │ ├── simple.wasm │ └── simple.wat ├── spin.toml └── src ├── SUMMARY.md ├── encoding.md └── intro.md /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | .spin 3 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2010 The Rust Project Developers 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Components 2 | 3 | A high-level explanation of the low-level details of WebAssembly components 4 | 5 | You can find a deployed version of this book [here](https://wasm-components.fermyon.app/). 6 | 7 | ## Building 8 | 9 | This book is built using [`mdbook`](https://github.com/rust-lang/mdBook). 10 | 11 | ```bash 12 | mdbook build --open 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Ryan Levick"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "WebAssembly Components" 7 | -------------------------------------------------------------------------------- /examples/core-module/core-module.wasm: -------------------------------------------------------------------------------- 1 | asm Uasm Kasm``consolelog logIt 2 | A  namelog'asm`}two 3 | C@ -------------------------------------------------------------------------------- /examples/core-module/core-module.wat: -------------------------------------------------------------------------------- 1 | (component 2 | (component 3 | (core module 4 | (import "console" "log" (func $log (param i32))) 5 | (func (export "logIt") 6 | i32.const 13 7 | call $log) 8 | ) 9 | ) 10 | (core module (func (export "two") (result f32) (f32.const 2))) 11 | ) -------------------------------------------------------------------------------- /examples/instance/instance.wasm: -------------------------------------------------------------------------------- 1 | asm 5asm`one 2 | A namenumbers9asm` myNamespaceonename doSomething myNamespaceNcomponent-namenumbers doSomething" firstInstancesecondInstance -------------------------------------------------------------------------------- /examples/instance/instance.wat: -------------------------------------------------------------------------------- 1 | (component 2 | (core module $numbers 3 | (func (export "one") (result i32) (i32.const 1)) 4 | ) 5 | (core module $doSomething 6 | (func (import "myNamespace" "one") (result i32)) 7 | ) 8 | (core instance $firstInstance (instantiate $numbers)) 9 | (core instance $secondInstance (instantiate $doSomething (with "myNamespace" (instance $firstInstance)))) 10 | ) -------------------------------------------------------------------------------- /examples/out-alias/out-alias.wasm: -------------------------------------------------------------------------------- 1 | asm Aasm` onetwo 2 | A A namenumbers=asm` 3 | theNumbersmyNumbername doSomething twomyNumber 4 | theNumbersXcomponent-nametwonumbers doSomething" firstInstancesecondInstance -------------------------------------------------------------------------------- /examples/out-alias/out-alias.wat: -------------------------------------------------------------------------------- 1 | (component 2 | (core module $numbers 3 | (func (export "one") (result i32) (i32.const 1)) 4 | (func (export "two") (result i32) (i32.const 2)) 5 | ) 6 | (core module $doSomething 7 | (func (import "theNumbers" "myNumber") (result i32)) 8 | ) 9 | (core instance $firstInstance (instantiate $numbers)) 10 | 11 | ;; Here's where things get interesting... 12 | (core func $two (alias core export $firstInstance "two")) 13 | (core instance $secondInstance (instantiate $doSomething 14 | (with "theNumbers" (instance 15 | (export "myNumber" (func $two)) 16 | )) 17 | )) 18 | ) -------------------------------------------------------------------------------- /examples/recursive-ids/recursive-ids.wasm: -------------------------------------------------------------------------------- 1 | asm Iasm asm component-namebarcomponent-namefoobarasm component-namebazcomponent-name foobaz -------------------------------------------------------------------------------- /examples/recursive-ids/recursive-ids.wat: -------------------------------------------------------------------------------- 1 | 2 | (component 3 | (component $foo 4 | (component $bar) 5 | ) 6 | (component $baz) 7 | ) -------------------------------------------------------------------------------- /examples/recursive/recursive.wasm: -------------------------------------------------------------------------------- 1 | asm )asm asm component-namefooasm component-namefoo -------------------------------------------------------------------------------- /examples/recursive/recursive.wat: -------------------------------------------------------------------------------- 1 | (component 2 | (component 3 | (component) 4 | ) 5 | (component) 6 | ) 7 | -------------------------------------------------------------------------------- /examples/simple/simple.wasm: -------------------------------------------------------------------------------- 1 | asm  -------------------------------------------------------------------------------- /examples/simple/simple.wat: -------------------------------------------------------------------------------- 1 | (component) -------------------------------------------------------------------------------- /spin.toml: -------------------------------------------------------------------------------- 1 | spin_manifest_version = "1" 2 | name = "component-book" 3 | trigger = { type = "http", base = "/" } 4 | version = "0.1.0" 5 | 6 | [[component]] 7 | source = { url = "https://github.com/fermyon/spin-fileserver/releases/download/v0.0.2/spin_static_fs.wasm", digest = "sha256:65456bf4e84cf81b62075e761b2b0afaffaef2d0aeda521b245150f76b96421b" } 8 | id = "component-book" 9 | files = [{ source = "book", destination = "/" }] 10 | [component.trigger] 11 | route = "/..." 12 | [component.build] 13 | command = "mdbook build" 14 | -------------------------------------------------------------------------------- /src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](./intro.md) 4 | - [Encoding Components](./encoding.md) 5 | -------------------------------------------------------------------------------- /src/encoding.md: -------------------------------------------------------------------------------- 1 | # Encoding 2 | 3 | Much like WebAssembly core modules, WebAssembly components are encoded in wasm binaries files (`.wasm` files). These binary formats can also be represented 1 to 1 as WebAssembly text format (`.wat` files) which uses s-expressions to represent components. We'll largely be using wat to show examples of how components are constructed. 4 | 5 | > For a more formal explanation of this information, checkout the ["Component Model Explainer"](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md) from the component model spec repo. This document is inspired by and based off of that document. A big shout out to everyone working on the spec for their amazing work! 6 | 7 | ## Core WebAssembly modules 8 | 9 | WebAssembly components are backwards compatible with WebAssembly modules (often called "core modules") and core modules are embedded inside of WebAssembly components. In order to understand components, you must first understand core modules. We won't be providing a detailed explanation of core modules here. However, a good explainer can be [found on MDN](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format). Give that a read, and come back when you're done. 10 | 11 | ## The simplest component 12 | 13 | Let's create the simplest component we can (which you can find in `examples/simple/simple.wat`): 14 | 15 | ```wat 16 | (component) 17 | ``` 18 | 19 | We can validate this component is correct with `wasm-tools validate`: 20 | 21 | ```bash 22 | # Note: `-f component-model` turns on the component model feature of the validator. 23 | # If we don't turn this on we'll get an error. 24 | wasm-tools validate examples/simple/simple.wat -f component-model 25 | ``` 26 | 27 | We can produce the `.wasm` binary equivalent of this component using `wasm-tools parse`: 28 | 29 | ```bash 30 | wasm-tools parse examples/simple/simple.wat -o simple.wasm 31 | ``` 32 | 33 | While we can inspect this binary directly, we can also use another tool `wasm-tools dump` to view the binary format with helpful annotations on the side. 34 | 35 | ```bash 36 | wasm-tools dump examples/simple/simple.wat 37 | ``` 38 | 39 | Which produces the following output: 40 | 41 | ``` 42 | 0x0 | 00 61 73 6d | version 12 (Component) 43 | | 0c 00 01 00 44 | ``` 45 | 46 | The binary consists of three parts: 47 | 48 | * `00 61 73 6d` is the WebAssembly magic number which tells tooling we're looking at a WebAssembly binary. It spells "\0asm" in ASCII. 49 | * `0c 00` is the binary version. Before the component model is standardized this will keep increasing (to ensure that it's easy to coordinate which pre-standard version the binary is). This [will eventually be `01 00`](https://github.com/WebAssembly/component-model/blob/79c0614c55b06896af3349f5dadf644fb077922b/design/mvp/Binary.md?plain=1#L45) when the standard is finalized. 50 | * `01 00` is the "layer" which indicates that this is a WebAssembly component (as opposed to a core module). 51 | 52 | ## Recursive components 53 | 54 | Components contain a sequence of definitions of various kinds. In the case of our simple component, the sequence contained no items. We'll discover over time what these items are. The first one we'll take a look at is: `component`. That's right, components can contain components. 55 | 56 | Take the following component for example (which you can find in `examples/recursive/recursive.wat`): 57 | 58 | ```wat 59 | (component 60 | (component 61 | (component) 62 | ) 63 | (component) 64 | ) 65 | ``` 66 | 67 | We can do the same thing we did before with `wasm-tools validate`, `wasm-tools parse`, and `wasm-tools dump`. 68 | 69 | It's important to note that components definitions are acyclic: definitions can only refer to preceding definitions. However, unlike core modules, components can arbitrarily interleave different kinds of definitions. 70 | 71 | ## Indices and identifiers 72 | 73 | We notice something interesting when we parse our recursive example into a WebAssembly binary and then print it *back* out as wat: 74 | 75 | ```bash 76 | wasm-tools parse examples/recursive/recursive.wat -o recursive.wasm` 77 | wasm-tools print recursive.wasm` 78 | ``` 79 | 80 | This gives us: 81 | 82 | ```wat 83 | (component 84 | (component (;0;) 85 | (component (;0;)) 86 | ) 87 | (component (;1;)) 88 | ) 89 | ``` 90 | 91 | Each component (except for the top-level one) has a `(;N;)`. These are there to indicate the *index* of that definition. Definitions that come after a given definition can refer to that definition using its index. 92 | 93 | Indices are not global meaning that for each nested level a new index space starts. This explains why the first two nested components both have index 0. They are the first components at their respective nesting level. These indices are also separated by which *kind* of definition being referred to. We only have component definitions right now, so everything at the same nesting level lives in the same index space, but as we introduce new definition types, definitions will have different index spaces that they occupy depending on what type they are. If this is unclear, wait until the next section when we'll introduce our next definition type: core modules. 94 | 95 | However, to make reading `wat` files easier, `wasm-tools print` uses block comments (i.e., either between a "(;" and a ";)" which is ignored as a comment) to explicitly show what the index is. 96 | 97 | When writing wat ourselves, we can use identifiers (in the form of `$example-id`) instead to give these indices descriptive names. 98 | 99 | Let's modify our example to use identifiers (which you can find in `examples/recursive-ids/recursive-ids.wat`): 100 | 101 | ```wat 102 | (component 103 | (component $foo 104 | (component $bar) 105 | ) 106 | (component $baz) 107 | ) 108 | ``` 109 | 110 | If we do the same conversion as before (turning our component into a binary wasm file and then back to wat file), we can see that the identifiers are kept! 111 | 112 | This is done through a wasm custom section which encodes the name so that the `wasm-tools` tooling suite can use the more descriptive identifier names. However, these names are just for human consumption. At the end of the day, the identifiers are equivalent to the index numbers they refer to (i.e., $foo == 0, $bar == 0, and $baz == 1). This becomes clear when we use `wasm-tools dump` to dump the recursive-ids binary and see the custom sections: 113 | 114 | ``` 115 | # ... 116 | 0x89 | 00 03 66 6f | Naming { index: 0, name: "foo" } 117 | | 6f 118 | 0x8e | 01 03 62 61 | Naming { index: 1, name: "baz" } 119 | | 7a 120 | ``` 121 | 122 | ## Embedding core modules 123 | 124 | Besides recursively containing components, components can also contain core WebAssembly modules. For example (which you can find in `examples/core-module/core-module.wat`): 125 | 126 | ```wat 127 | (component 128 | (component 129 | (core module 130 | (import "console" "log" (func $log (param i32))) 131 | (func (export "logIt") 132 | i32.const 13 133 | call $log) 134 | ) 135 | ) 136 | (core module (func (export "two") (result f32) (f32.const 2))) 137 | ) 138 | ``` 139 | 140 | The wat above uses the short hand way of defining a core function type, the function definition, *and* exporting that function all at the same type. 141 | 142 | If we turn this wat into a WebAssembly binary and then back into wat, the tooling will use the more verbose syntax: 143 | 144 | ```wat 145 | (component 146 | (component (;0;) 147 | (core module (;0;) 148 | (type (;0;) (func (param i32))) 149 | (type (;1;) (func)) 150 | (import "console" "log" (func $log (;0;) (type 0))) 151 | (func (;1;) (type 1) 152 | i32.const 13 153 | call $log 154 | ) 155 | (export "logIt" (func 1)) 156 | ) 157 | ) 158 | (core module (;0;) 159 | (type (;0;) (func (result f32))) 160 | (func (;0;) (type 0) (result f32) 161 | f32.const 0x1p+1 (;=2;) 162 | ) 163 | (export "two" (func 0)) 164 | ) 165 | ) 166 | ``` 167 | 168 | In this equivalent version, we *first* define the function type, then the function definition, and *finally* we export it. Take your time to ensure you are comfortable with both equivalent styles and can convince yourself that these two are equivalent. 169 | 170 | It's important to note that there are two top-level definitions that this component has: the nested component which includes the core module *and* another core module that is not nested in a component. Because these definitions are of two different kinds (i.e., component and core module) they occupy two different index spaces and as such both have index 0. 171 | 172 | ## Instances 173 | 174 | Everything we've defined so far has been immutable dead code. We can also define "instances" which represent components or core modules which have had the imports they define satisfied. For example, a core module may import `memory` to use a mutable state needed during its execution. An instance can be used to supply that core module with the memory it requires. Of course, imports can be many other things besides memory including functions. 175 | 176 | Instances can allow us to "link" modules and components together with other modules and components by specifying that the imports one component or core module expects are satisfied by the exports of another component or core module. 177 | 178 | Let's take a look at an example (which you can find in `examples/instance/instance.wat`): 179 | 180 | ```wat 181 | (component 182 | (core module $numbers 183 | (func (export "one") (result i32) (i32.const 1)) 184 | ) 185 | (core module $doSomething 186 | (func (import "myNamespace" "one") (result i32)) 187 | ) 188 | (core instance $firstInstance (instantiate $numbers)) 189 | (core instance $secondInstance (instantiate $doSomething (with "myNamespace" (instance $firstInstance)))) 190 | ) 191 | ``` 192 | 193 | > *Note*: you may have noticed that instances have a `core` prefix associated with them. This is because, while instances are not a part of the existing ratified WebAssembly spec like core modules, they were a proposed extension to the core WebAssembly spec outside of components (i.e., they would also be useable in core modules). Instances were originally proposed as part of the [module linking](https://github.com/WebAssembly/module-linking) proposal, but that has been subsumed by the component model work. 194 | 195 | This component consists of 4 definitions: 196 | * Two core modules 197 | * Two core instances 198 | 199 | The first core module `$numbers` exports a function called "one". The second core module `$doSomething` wants to import a function called "one" in the namespace "myNamespace". 200 | 201 | The first core instance `$firstInstance` instantiates the `$numbers` core module. Since the `$numbers` core module expects no imports, we do not need to supply any. The second core instance `$secondInstance` instantiates the core module `$doSomething` with an instance that we're supplying under the namespace "myNamespace"). Since `$doSomething` is expecting an imported namespace "myNamespace" which contains a function named "one" and we're supplying `$firstInstance` under the namespace "myNamespace" and $firstInstance exports a function named "one", everything lines up and we form a valid component. 202 | 203 | ## Renaming with aliases 204 | 205 | At times it might be desireable to take an export that has been exported under a certain name and import into another component or core module as a different name. This eliminates the need for exports from one module to exactly match the imports another module is expecting. To accomplish this we'll use "aliases". There are a few kind of aliases so we'll look them in turn. 206 | 207 | ### Out of line aliases 208 | 209 | First, let's take a look at out of line aliases. Let's take a look at an example (which you can find at `examples/out-alias/out-alias.wat`): 210 | 211 | ```wat 212 | (component 213 | (core module $numbers 214 | (func (export "one") (result i32) (i32.const 1)) 215 | (func (export "two") (result i32) (i32.const 2)) 216 | ) 217 | (core module $doSomething 218 | (func (import "theNumbers" "myNumber") (result i32)) 219 | ) 220 | (core instance $firstInstance (instantiate $numbers)) 221 | 222 | ;; Here's where things get interesting... 223 | (core func $two (alias core export $firstInstance "two")) 224 | (core instance $secondInstance (instantiate $doSomething 225 | (with "theNumbers" (instance 226 | (export "myNumber" (func $two)) 227 | )) 228 | )) 229 | ) 230 | ``` 231 | 232 | We start much like our previous example by defining two core modules: `$numbers` which exports two functions and `$doSomething` which expects an import called "myNumber" under the namespace "theNumbers". We then instantiate `$numbers` as an instance called `$firstInstance`. 233 | 234 | After that is where things get interesting. Using an `alias export` we effectively reach into `$firstInstance` and grab the export named "two" and bind that export to the name `$two`. Without this alias function we had no way to refer to that export. Now we can refer to that export as the function `$two` as if it had been defined at the top level (even when in reality it was defined inside a nested core module). 235 | 236 | That by itself is not too interesting, but next we instantiate the core module `$doSomething` with an *inline* instance instead of providing `$firstInstance`. This inline instance exports a function called "myNumber" which is defined using the function definition `$two`. Effectively we now have a mechanism for supplying imports to an core module where we decide *at instantiation* which import to provide. 237 | 238 | > Out of line aliases are called such since they are not defined *in-line* with the inline instance. We'll see another type of alias that allows declaring aliases inline inside of inline instance definitions. 239 | 240 | This allows us to instantiate `$doSomething` many times where we supply the important "theNumber" "myNumber" with different definitions for each instantiation. 241 | 242 | There is also a second syntax for declaring an out of line alias: 243 | 244 | ```wat 245 | ;; This is equivalent to `(core func $two (alias core export $firstInstance "two"))` 246 | (alias core export $firstInstance "two" (core func $two)) 247 | ``` 248 | 249 | ### Inline aliases 250 | 251 | Instead of first declaring an alias any then using that alias within an inline instance definition, you can also just declare the alias directly. The following is equivalent to the example above just using an inline alias: 252 | 253 | ```wat 254 | (component 255 | (core module $numbers 256 | (func (export "one") (result i32) (i32.const 1)) 257 | (func (export "two") (result i32) (i32.const 2)) 258 | ) 259 | (core module $doSomething 260 | (func (import "theNumbers" "myNumber") (result i32)) 261 | ) 262 | (core instance $firstInstance (instantiate $numbers)) 263 | 264 | ;; Here's where things are different... 265 | (core instance $secondInstance (instantiate $doSomething 266 | (with "theNumbers" (instance 267 | (export "myNumber" (func $firstInstance "two")) 268 | )) 269 | )) 270 | ) 271 | ``` 272 | 273 | You'll notice that we are no longer first declaring an alias before instantiating `$secondInstance`. Instead we declare the alias in the same line as declaring the export of our inline instance with `(func $firstInstance "two")`. Just like before, this reaches into `$firstInstance` and brings the "two" function into scope for our use. 274 | 275 | > *Note*: We're only showing linking of *core modules*, because we need to introduce component-level type and function definitions before we can do that. 276 | 277 | **TODO**: Continue [here](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#type-definitions) 278 | -------------------------------------------------------------------------------- /src/intro.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This book is a high-level explanation of the low-level details of WebAssembly components. 4 | 5 | ## Who is this book for? 6 | 7 | This book is primarily intended for anyone who is working on implementation work of WebAssembly components such as low-level tooling that needs to interact directly with component binaries directly. Component authors and end users may find some information here useful (especially until resources more appropriate to those audiences are developed), but those audiences are not the focus of this book. 8 | 9 | ## What is this book not? 10 | 11 | This book does not attempt to explain what WebAssembly is, how it compares to other technology, or what use cases it has. This book is more concerned with *how* components are created rather than why or their usage in any particular context. 12 | 13 | This book is also not a formal specification or even the ground work for such a specification. While the hope is that this book's information is accurate, there is no attempt to eliminate all possible ambiguities or to provide formal definitions. Whenever possible, we will try to provide to link to resources where more formal definitions are being worked on. 14 | 15 | ## What do I need to get started? 16 | 17 | To get the most out of this book, you'll need the following tools installed on your machine: 18 | * [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools) 19 | --------------------------------------------------------------------------------