├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── assembly ├── buffer │ └── index.ts ├── fs │ └── index.ts ├── index.ts ├── node.d.ts └── tsconfig.json ├── package-lock.json ├── package.json └── tests ├── .gitignore ├── buffer.spec.ts ├── env.d.ts ├── fs.spec.ts ├── fs.spec.wasi.js ├── node.js ├── sandbox └── test.txt └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.* 2 | node_modules/ 3 | .history 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | notifications: 3 | email: false 4 | before_install: npm config set progress=false && npm i -g npm@latest --no-audit 5 | install: npm ci --no-audit 6 | jobs: 7 | include: 8 | - node_js: lts/* 9 | script: 10 | - npm test 11 | env: Runs the tests on node.js LTS. 12 | - node_js: node 13 | script: 14 | - npm test 15 | env: Runs the tests on node.js Stable. 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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 {yyyy} {name of copyright owner} 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![AS](https://avatars1.githubusercontent.com/u/28916798?s=48) node 2 | ====================== 3 | 4 | Implementations of the node.js APIs for AssemblyScript, utilizing [WASI](https://wasi.dev). 5 | 6 | Introduction 7 | ------------ 8 | 9 | This library aims to provide a convenient node.js-like environment for AssemblyScript programs. 10 | Please note that it is still in its early stages and that both the library and WASI are not even 11 | close to be finalized. 12 | 13 | As always, if the idea sounds appealing to you, feel free to improve existing APIs or to contribute 14 | additional ones. 15 | 16 | Instructions 17 | ------------ 18 | 19 | Install the library components as a dependency of your project 20 | 21 | ``` 22 | $> npm install --save-dev AssemblyScript/node 23 | ``` 24 | 25 | and include it in your build step to gain access to the implementations it provides: 26 | 27 | ``` 28 | $> asc --lib ./node_modules/@assemblyscript/node/assembly [...] 29 | ``` 30 | 31 | Doing so will automatically register common globals like the `Buffer` class and enables requiring 32 | for example the filesystem module through `import * as fs from "fs"`. 33 | 34 | Documentation 35 | ------------- 36 | 37 | * [Status and API documentation on the wiki](https://github.com/AssemblyScript/node/wiki) 38 | * [Implementation sources](./assembly) 39 | 40 | Building 41 | -------- 42 | 43 | To run the tests, first make sure that development dependencies are installed, then run: 44 | 45 | ``` 46 | $> npm test 47 | ``` 48 | 49 | One of the dependencies is [node-wasi](https://github.com/devsnek/node-wasi), which is a native 50 | module. If you are running into issues when compiling it (on Windows), make sure that node-wasi 51 | supports your version of node.js, that your machine can build native modules in the first place 52 | and that your version of npm is recent (`npm install npm@latest -g`). 53 | -------------------------------------------------------------------------------- /assembly/buffer/index.ts: -------------------------------------------------------------------------------- 1 | import { BLOCK_MAXSIZE, BLOCK, BLOCK_OVERHEAD } from "rt/common"; 2 | import { E_INVALIDLENGTH, E_INDEXOUTOFRANGE } from "util/error"; 3 | import { Uint8Array } from "typedarray"; 4 | 5 | export class Buffer extends Uint8Array { 6 | [key: number]: u8; 7 | 8 | constructor(size: i32) { 9 | super(size); 10 | } 11 | 12 | static alloc(size: i32): Buffer { 13 | return new Buffer(size); 14 | } 15 | 16 | @unsafe static allocUnsafe(size: i32): Buffer { 17 | // range must be valid 18 | if (size > BLOCK_MAXSIZE) throw new RangeError(E_INVALIDLENGTH); 19 | let buffer = __alloc(size, idof()); 20 | let result = __alloc(offsetof(), idof()); 21 | 22 | // set the properties 23 | store(result, __retain(buffer), offsetof("buffer")); 24 | store(result, buffer, offsetof("dataStart")); 25 | store(result, size, offsetof("byteLength")); 26 | 27 | // return and retain 28 | return changetype(result); 29 | } 30 | 31 | static isBuffer(value: T): bool { 32 | return value instanceof Buffer; 33 | } 34 | 35 | // Adapted from https://github.com/AssemblyScript/assemblyscript/blob/master/std/assembly/typedarray.ts 36 | subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Buffer { 37 | var len = this.byteLength; 38 | begin = begin < 0 ? max(len + begin, 0) : min(begin, len); 39 | end = end < 0 ? max(len + end, 0) : min(end, len); 40 | end = max(end, begin); 41 | 42 | var out = __alloc(offsetof(), idof()); // retains 43 | store(out, __retain(changetype(this.buffer)), offsetof("buffer")); 44 | store(out, this.dataStart + begin, offsetof("dataStart")); 45 | store(out, end - begin, offsetof("byteLength")); 46 | 47 | // retains 48 | return changetype(out); 49 | } 50 | 51 | readInt8(offset: i32 = 0): i8 { 52 | if (i32(offset < 0) | i32(offset >= this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 53 | return load(this.dataStart + offset); 54 | } 55 | 56 | readUInt8(offset: i32 = 0): u8 { 57 | if (i32(offset < 0) | i32(offset >= this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 58 | return load(this.dataStart + offset); 59 | } 60 | 61 | writeInt8(value: i8, offset: i32 = 0): i32 { 62 | if (i32(offset < 0) | i32(offset >= this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 63 | store(this.dataStart + offset, value); 64 | return offset + 1; 65 | } 66 | 67 | writeUInt8(value: u8, offset: i32 = 0): i32 { 68 | if (i32(offset < 0) | i32(offset >= this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 69 | store(this.dataStart + offset, value); 70 | return offset + 1; 71 | } 72 | 73 | readInt16LE(offset: i32 = 0): i16 { 74 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 75 | return load(this.dataStart + offset); 76 | } 77 | 78 | readInt16BE(offset: i32 = 0): i16 { 79 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 80 | return bswap(load(this.dataStart + offset)); 81 | } 82 | 83 | readUInt16LE(offset: i32 = 0): u16 { 84 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 85 | return load(this.dataStart + offset); 86 | } 87 | 88 | readUInt16BE(offset: i32 = 0): u16 { 89 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 90 | return bswap(load(this.dataStart + offset)); 91 | } 92 | 93 | writeInt16LE(value: i16, offset: i32 = 0): i32 { 94 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 95 | store(this.dataStart + offset, value); 96 | return offset + 2; 97 | } 98 | 99 | writeInt16BE(value: i16, offset: i32 = 0): i32 { 100 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 101 | store(this.dataStart + offset, bswap(value)); 102 | return offset + 2; 103 | } 104 | 105 | writeUInt16LE(value: u16, offset: i32 = 0): i32 { 106 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 107 | store(this.dataStart + offset, value); 108 | return offset + 2; 109 | } 110 | 111 | writeUInt16BE(value: u16, offset: i32 = 0): i32 { 112 | if (i32(offset < 0) | i32(offset + 2 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 113 | store(this.dataStart + offset, bswap(value)); 114 | return offset + 2; 115 | } 116 | 117 | readInt32LE(offset: i32 = 0): i32 { 118 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 119 | return load(this.dataStart + offset); 120 | } 121 | 122 | readInt32BE(offset: i32 = 0): i32 { 123 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 124 | return bswap(load(this.dataStart + offset)); 125 | } 126 | 127 | readUInt32LE(offset: i32 = 0): u32 { 128 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 129 | return load(this.dataStart + offset); 130 | } 131 | 132 | readUInt32BE(offset: i32 = 0): u32 { 133 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 134 | return bswap(load(this.dataStart + offset)); 135 | } 136 | 137 | writeInt32LE(value: i32, offset: i32 = 0): i32 { 138 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 139 | store(this.dataStart + offset, value); 140 | return offset + 4; 141 | } 142 | 143 | writeInt32BE(value: i32, offset: i32 = 0): i32 { 144 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 145 | store(this.dataStart + offset, bswap(value)); 146 | return offset + 4; 147 | } 148 | 149 | writeUInt32LE(value: u32, offset: i32 = 0): i32 { 150 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 151 | store(this.dataStart + offset, value); 152 | return offset + 4; 153 | } 154 | 155 | writeUInt32BE(value: u32, offset: i32 = 0): i32 { 156 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 157 | store(this.dataStart + offset, bswap(value)); 158 | return offset + 4; 159 | } 160 | 161 | readFloatLE(offset: i32 = 0): f32 { 162 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 163 | return load(this.dataStart + offset); 164 | } 165 | 166 | readFloatBE(offset: i32 = 0): f32 { 167 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 168 | return reinterpret(bswap(load(this.dataStart + offset))); 169 | } 170 | 171 | writeFloatLE(value: f32, offset: i32 = 0): i32 { 172 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 173 | store(this.dataStart + offset, value); 174 | return offset + 4; 175 | } 176 | 177 | writeFloatBE(value: f32, offset: i32 = 0): i32 { 178 | if (i32(offset < 0) | i32(offset + 4 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 179 | store(this.dataStart + offset, bswap(reinterpret(value))); 180 | return offset + 4; 181 | } 182 | 183 | readBigInt64LE(offset: i32 = 0): i64 { 184 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 185 | return load(this.dataStart + offset); 186 | } 187 | 188 | readBigInt64BE(offset: i32 = 0): i64 { 189 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 190 | return bswap(load(this.dataStart + offset)); 191 | } 192 | 193 | readBigUInt64LE(offset: i32 = 0): u64 { 194 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 195 | return load(this.dataStart + offset); 196 | } 197 | 198 | readBigUInt64BE(offset: i32 = 0): u64 { 199 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 200 | return bswap(load(this.dataStart + offset)); 201 | } 202 | 203 | writeBigInt64LE(value: i64, offset: i32 = 0): i32 { 204 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 205 | store(this.dataStart + offset, value); 206 | return offset + 8; 207 | } 208 | 209 | writeBigInt64BE(value: i64, offset: i32 = 0): i32 { 210 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 211 | store(this.dataStart + offset, bswap(value)); 212 | return offset + 8; 213 | } 214 | 215 | writeBigUInt64LE(value: u64, offset: i32 = 0): i32 { 216 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 217 | store(this.dataStart + offset, value); 218 | return offset + 8; 219 | } 220 | 221 | writeBigUInt64BE(value: u64, offset: i32 = 0): i32 { 222 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 223 | store(this.dataStart + offset, bswap(value)); 224 | return offset + 8; 225 | } 226 | 227 | readDoubleLE(offset: i32 = 0): f64 { 228 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 229 | return load(this.dataStart + offset); 230 | } 231 | 232 | readDoubleBE(offset: i32 = 0): f64 { 233 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 234 | return reinterpret(bswap(load(this.dataStart + offset))); 235 | } 236 | 237 | writeDoubleLE(value: f64, offset: i32 = 0): i32 { 238 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 239 | store(this.dataStart + offset, value); 240 | return offset + 8; 241 | } 242 | 243 | writeDoubleBE(value: f64, offset: i32 = 0): i32 { 244 | if (i32(offset < 0) | i32(offset + 8 > this.byteLength)) throw new RangeError(E_INDEXOUTOFRANGE); 245 | store(this.dataStart + offset, bswap(reinterpret(value))); 246 | return offset + 8; 247 | } 248 | 249 | swap16(): Buffer { 250 | let byteLength = this.byteLength; 251 | // Make sure byteLength is even 252 | if (byteLength & 1) throw new RangeError(E_INVALIDLENGTH); 253 | let dataStart = this.dataStart; 254 | byteLength += dataStart; 255 | while (dataStart < byteLength) { 256 | store(dataStart, bswap(load(dataStart))); 257 | dataStart += 2; 258 | } 259 | return this; 260 | } 261 | 262 | swap32(): Buffer { 263 | let byteLength = this.byteLength; 264 | // Make sure byteLength is divisible by 4 265 | if (byteLength & 3) throw new RangeError(E_INVALIDLENGTH); 266 | let dataStart = this.dataStart; 267 | byteLength += dataStart; 268 | while (dataStart < byteLength) { 269 | store(dataStart, bswap(load(dataStart))); 270 | dataStart += 4; 271 | } 272 | return this; 273 | } 274 | 275 | swap64(): Buffer { 276 | let byteLength = this.byteLength; 277 | // Make sure byteLength is divisible by 8 278 | if (byteLength & 7) throw new RangeError(E_INVALIDLENGTH); 279 | let dataStart = this.dataStart; 280 | byteLength += dataStart; 281 | while (dataStart < byteLength) { 282 | store(dataStart, bswap(load(dataStart))); 283 | dataStart += 8; 284 | } 285 | return this; 286 | } 287 | } 288 | 289 | export namespace Buffer { 290 | export namespace ASCII { 291 | export function encode(str: string): ArrayBuffer { 292 | let length = str.length; 293 | let output = __alloc(length, idof()); 294 | for (let i = 0; i < length; i++) { 295 | let char = load(changetype(str) + (i << 1)); 296 | store(output + i, char & 0x7F); 297 | } 298 | return changetype(output); 299 | } 300 | 301 | export function decode(buffer: ArrayBuffer): String { 302 | return decodeUnsafe(changetype(buffer), buffer.byteLength); 303 | } 304 | 305 | // @ts-ignore: decorator 306 | @unsafe export function decodeUnsafe(pointer: usize, length: i32): String { 307 | let result = __alloc(length << 1, idof()); 308 | 309 | for (let i = 0; i < length; i++) { 310 | let byte = load(pointer + i); 311 | store(result + (i << 1), byte & 0x7F); 312 | } 313 | 314 | return changetype(result); 315 | } 316 | } 317 | 318 | export namespace HEX { 319 | /** Calculates the byte length of the specified string when encoded as HEX. */ 320 | export function byteLength(str: string): i32 { 321 | let ptr = changetype(str); 322 | let byteCount = changetype(changetype(str) - BLOCK_OVERHEAD).rtSize; 323 | let length = byteCount >>> 2; 324 | // The string length must be even because the bytes come in pairs of characters two wide 325 | if (byteCount & 3) return 0; // encoding fails and returns an empty ArrayBuffer 326 | 327 | byteCount += ptr; 328 | while (ptr < byteCount) { 329 | var char = load(ptr); 330 | if ( ((char - 0x30) <= 9) 331 | || ((char - 0x61) <= 5) 332 | || ((char - 0x41) <= 5)) { 333 | ptr += 2; 334 | continue; 335 | } else { 336 | return 0; 337 | } 338 | } 339 | return length; 340 | } 341 | 342 | /** Creates an ArrayBuffer from a given string that is encoded in the HEX format. */ 343 | export function encode(str: string): ArrayBuffer { 344 | let bufferLength = byteLength(str); 345 | // short path: string is not a valid hex string, return a new empty ArrayBuffer 346 | if (bufferLength == 0) return changetype(__alloc(0, idof())); 347 | 348 | // long path: loop over each enociding pair and perform the conversion 349 | let ptr = changetype(str); 350 | let byteEnd = ptr + changetype(changetype(str) - BLOCK_OVERHEAD).rtSize; 351 | let result = __alloc(bufferLength, idof()); 352 | let b: u32 = 0; 353 | let outChar = 0; 354 | for (let i: usize = 0; ptr < byteEnd; i++) { 355 | if (i & 1) { 356 | outChar <<= 4; 357 | b >>>= 16; 358 | if ((b - 0x30) <= 9) { 359 | outChar |= b - 0x30; 360 | } else if ((b - 0x61) <= 5) { 361 | outChar |= b - 0x57; 362 | } else if (b - 0x41 <= 5) { 363 | outChar |= b - 0x37; 364 | } 365 | store(result + (i >> 1), (outChar & 0xFF)); 366 | ptr += 4; 367 | } else { 368 | b = load(ptr); 369 | outChar <<= 4; 370 | let c = b & 0xFF; 371 | if ((c - 0x30) <= 9) { 372 | outChar |= c - 0x30; 373 | } else if ((c - 0x61) <= 5) { 374 | outChar |= c - 0x57; 375 | } else if (c - 0x41 <= 5) { 376 | outChar |= c - 0x37; 377 | } 378 | } 379 | } 380 | return changetype(result); 381 | } 382 | 383 | /** Creates a string from a given ArrayBuffer that is decoded into hex format. */ 384 | export function decode(buff: ArrayBuffer): string { 385 | return decodeUnsafe(changetype(buff), buff.byteLength); 386 | } 387 | 388 | /** Decodes a chunk of memory to a utf16le encoded string in hex format. */ 389 | // @ts-ignore: decorator 390 | @unsafe export function decodeUnsafe(ptr: usize, length: i32): string { 391 | let stringByteLength = length << 2; // length * (2 bytes per char) * (2 chars per input byte) 392 | let result = __alloc(stringByteLength, idof()); 393 | let i = 0; 394 | let inputByteLength = length + ptr; 395 | 396 | // loop over each byte and store a `u32` for each one 397 | while (ptr < inputByteLength) { 398 | store(result + i, charsFromByte(load(ptr++))); 399 | i += 4; 400 | } 401 | 402 | return changetype(result); 403 | } 404 | 405 | /** Calculates the two char combination from the byte. */ 406 | // @ts-ignore: decorator 407 | @inline function charsFromByte(byte: u32): u32 { 408 | let hi = (byte >>> 4) & 0xF; 409 | let lo = byte & 0xF; 410 | hi += select(0x57, 0x30, hi > 9); 411 | lo += select(0x57, 0x30, lo > 9); 412 | return (lo << 16) | hi; 413 | } 414 | } 415 | } 416 | -------------------------------------------------------------------------------- /assembly/fs/index.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from "../buffer"; 2 | 3 | /** 4 | * TODO: Look at https://nodejs.org/dist/latest-v12.x/docs/api/fs.html#fs_fs_readfilesync_path_options 5 | * 6 | * Path can be ` | | | `. 7 | * 8 | * This will require a `` parameter to handle all these cases. In this particular case, I think 9 | * it's okay to default to only ``. 10 | */ 11 | export function readFileSync(): Buffer { 12 | return new Buffer(0); 13 | } 14 | -------------------------------------------------------------------------------- /assembly/index.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export { Buffer } from "./buffer"; 4 | -------------------------------------------------------------------------------- /assembly/node.d.ts: -------------------------------------------------------------------------------- 1 | declare class Buffer extends Uint8Array { 2 | /** This method allocates a new Buffer of indicated size. All of the data is zeroed. */ 3 | static alloc(size: i32): Buffer; 4 | /** This method allocates a new Buffer of indicated size. This is unsafe because the data is not zeroed. */ 5 | static allocUnsafe(size: i32): Buffer; 6 | /** This method asserts a value is a Buffer object via `value instanceof Buffer`. */ 7 | static isBuffer(value: T): bool; 8 | /** Reads a signed integer at the designated offset. */ 9 | readInt8(offset?: i32): i8; 10 | /** Reads an unsigned integer at the designated offset. */ 11 | readUInt8(offset?: i32): u8; 12 | /** Writes an inputted value to the buffer, at the desired offset. */ 13 | writeInt8(value:i8, offset?:i32): i32; 14 | /** Writes an inputted u8 value to the buffer, at the desired offset. */ 15 | writeUInt8(value:u8, offset?:i32): i32; 16 | /** Reads a signed 16-bit integer, stored in Little Endian format at the designated offset. */ 17 | readInt16LE(offset?: i32): i16; 18 | /** Reads a signed 16-bit integer, stored in Big Endian format at the designated offset. */ 19 | readInt16BE(offset?: i32): i16; 20 | /** Reads an unsigned 16-bit integer, stored in Little Endian format at the designated offset. */ 21 | readUInt16LE(offset?: i32): u16; 22 | /** Reads an unsigned 16-bit integer, stored in Big Endian format at the designated offset. */ 23 | readUInt16BE(offset?: i32): u16; 24 | /** Writes an inputted 16-bit integer at the designated offset, stored in Little Endian format */ 25 | writeInt16LE(value: i16, offset?: i32): i32; 26 | /** Writes an inputted 16-bit integer at the designated offset, stored in Big Endian format */ 27 | writeInt16BE(value: i16, offset?: i32): i32; 28 | /** Writes an inputted unsigned 16-bit integer at the designated offset, stored in Little Endian format */ 29 | writeUInt16LE(value: u16, offset?: i32): i32; 30 | /** Writes an inputted unsigned 16-bit integer at the designated offset, stored in Big Endian format */ 31 | writeUInt16BE(value: u16, offset?: i32): i32; 32 | /** Reads a signed 32-bit integer, stored in Little Endian format at the designated offset. */ 33 | readInt32LE(offset?: i32): i32; 34 | /** Reads a signed 32-bit integer, stored in Big Endian format at the designated offset. */ 35 | readInt32BE(offset?: i32): i32; 36 | /** Reads an unsigned 32-bit integer, stored in Little Endian format at the designated offset. */ 37 | readUInt32LE(offset?: i32): u32; 38 | /** Reads an unsigned 32-bit integer, stored in Big Endian format at the designated offset. */ 39 | readUInt32BE(offset?: i32): u32; 40 | /** Writes an inputted 32-bit integer at the designated offset, stored in Little Endian format */ 41 | writeInt32LE(value: i32, offset?: i32): i32; 42 | /** Writes an inputted 32-bit integer at the designated offset, stored in Big Endian format */ 43 | writeInt32BE(value: i32, offset?: i32): i32; 44 | /** Writes an inputted unsigned 32-bit integer at the designated offset, stored in Little Endian format */ 45 | writeUInt32LE(value: u32, offset?: i32): i32; 46 | /** Writes an inputted unsigned 32-bit integer at the designated offset, stored in Big Endian format */ 47 | writeUInt32BE(value: u32, offset?: i32): i32; 48 | /** Reads a signed 32-bit float, stored in Little Endian format at the designated offset. */ 49 | readFloatLE(offset?: i32): f32; 50 | /** Reads a signed 32-bit float, stored in Big Endian format at the designated offset. */ 51 | readFloatBE(offset?: i32): f32; 52 | /** Writes an inputted 32-bit float at the designated offset, stored in Little Endian format */ 53 | writeFloatLE(value: f32, offset?: i32): i32; 54 | /** Writes an inputted 32-bit float at the designated offset, stored in Big Endian format */ 55 | writeFloatBE(value: f32, offset?: i32): i32; 56 | /** Reads a signed 64-bit integer, stored in Little Endian format at the designated offset. */ 57 | readBigInt64LE(offset?: i32): i64; 58 | /** Reads a signed 64-bit integer, stored in Big Endian format at the designated offset. */ 59 | readBigInt64BE(offset?: i32): i64; 60 | /** Reads an unsigned 64-bit integer, stored in Little Endian format at the designated offset. */ 61 | readBigUInt64LE(offset?: i32): u64; 62 | /** Reads an unsigned 64-bit integer, stored in Big Endian format at the designated offset. */ 63 | readBigUInt64BE(offset?: i32): u64; 64 | /** Writes an inputted 64-bit integer at the designated offset, stored in Little Endian format */ 65 | writeBigInt64LE(value: i64, offset?: i32): i32; 66 | /** Writes an inputted 64-bit integer at the designated offset, stored in Big Endian format */ 67 | writeBigInt64BE(value: i64, offset?: i32): i32; 68 | /** Writes an inputted unsigned 64-bit integer at the designated offset, stored in Little Endian format */ 69 | writeBigUInt64LE(value: u64, offset?: i32): i32; 70 | /** Writes an inputted unsigned 64-bit integer at the designated offset, stored in Big Endian format */ 71 | writeBigUInt64BE(value: u64, offset?: i32): i32; 72 | /** Reads a signed 64-bit double, stored in Little Endian format at the designated offset. */ 73 | readDoubleLE(offset?: i32): f64; 74 | /** Reads a signed 64-bit double, stored in Big Endian format at the designated offset. */ 75 | readDoubleBE(offset?: i32): f64; 76 | /** Writes an inputted 64-bit double at the designated offset, stored in Little Endian format */ 77 | writeDoubleLE(value: f64, offset?: i32): i32; 78 | /** Writes an inputted 64-bit double at the designated offset, stored in Big Endian format */ 79 | writeDoubleBE(value: f64, offset?: i32): i32; 80 | /** Swaps every group of two bytes in a Buffer in-place */ 81 | swap16(): Buffer; 82 | /** Swaps every group of four bytes in a Buffer in-place */ 83 | swap32(): Buffer; 84 | /** Swaps every group of eight bytes in a Buffer in-place */ 85 | swap64(): Buffer; 86 | } 87 | 88 | declare namespace Buffer { 89 | /** The HEX encoding and decoding namespace. */ 90 | export namespace HEX { 91 | /** Creates an ArrayBuffer from a given string that is encoded in the hex format. */ 92 | export function encode(str: string): ArrayBuffer; 93 | /** Creates a string from a given ArrayBuffer that is decoded into hex format. */ 94 | export function decode(buffer: ArrayBuffer): string; 95 | /** Decodes a chunk of memory to a utf16le encoded string in hex format. */ 96 | export function decodeUnsafe(ptr: usize, byteLength: i32): string; 97 | } 98 | /** The ASCII encoding and decoding namespace. */ 99 | export namespace ASCII { 100 | /** Creates an ArrayBuffer from a given string that is encoded in the ASCII format. */ 101 | export function encode(str: string): ArrayBuffer; 102 | /** Creates a string from a given ArrayBuffer that is decoded into ASCII format. */ 103 | export function decode(buffer: ArrayBuffer): string; 104 | /** Decodes a chunk of memory to a utf16le encoded string in ASCII format. */ 105 | export function decodeUnsafe(ptr: usize, byteLength: i32): string; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /assembly/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../node_modules/assemblyscript/std/assembly.json", 3 | "include": [ 4 | "./**/*.ts" 5 | ] 6 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@assemblyscript/node", 3 | "version": "0.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@as-pect/assembly": { 8 | "version": "3.2.1", 9 | "resolved": "https://registry.npmjs.org/@as-pect/assembly/-/assembly-3.2.1.tgz", 10 | "integrity": "sha512-qok+WPvKV1BLQ+nnpn+hc0PLSZ69Pim4eT72PruA1C+hvMu6HCbNKDFcj4lrL7XNMKuibPf0633SW14asC0//w==", 11 | "dev": true 12 | }, 13 | "@as-pect/core": { 14 | "version": "3.2.2", 15 | "resolved": "https://registry.npmjs.org/@as-pect/core/-/core-3.2.2.tgz", 16 | "integrity": "sha512-Gr6ha3WGS/omSLvquDC6WPqZt1vP/hxvWovxgUuqNJ1APymMTjbvP2W86pjKLqvSaZj1gETAr5703PxhnnoL4g==", 17 | "dev": true, 18 | "requires": { 19 | "@as-pect/assembly": "^3.2.1", 20 | "@as-pect/snapshots": "^3.2.2", 21 | "chalk": "^4.0.0", 22 | "long": "^4.0.0" 23 | } 24 | }, 25 | "@as-pect/snapshots": { 26 | "version": "3.2.2", 27 | "resolved": "https://registry.npmjs.org/@as-pect/snapshots/-/snapshots-3.2.2.tgz", 28 | "integrity": "sha512-uJQwwbgX0gGRVD4Au8r3g9TbPCseBuChSDVjfaNAZifaQ0JKrrzB4tga2PVDrWrZHIgYvajTph5tsN3x9pJ5nA==", 29 | "dev": true, 30 | "requires": { 31 | "diff": "^4.0.2", 32 | "nearley": "^2.19.3" 33 | } 34 | }, 35 | "@types/color-name": { 36 | "version": "1.1.1", 37 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 38 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", 39 | "dev": true 40 | }, 41 | "ansi-styles": { 42 | "version": "4.2.1", 43 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 44 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 45 | "dev": true, 46 | "requires": { 47 | "@types/color-name": "^1.1.1", 48 | "color-convert": "^2.0.1" 49 | } 50 | }, 51 | "assemblyscript": { 52 | "version": "0.10.0", 53 | "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.10.0.tgz", 54 | "integrity": "sha512-ErUNhHboD+zsB4oG6X1YICDAIo27Gq7LeNX6jVe+Q0W5cI51/fHwC8yJ68IukqvupmZgYPdp1JqqRXlS+BrUfA==", 55 | "dev": true, 56 | "requires": { 57 | "binaryen": "93.0.0-nightly.20200514", 58 | "long": "^4.0.0" 59 | } 60 | }, 61 | "balanced-match": { 62 | "version": "1.0.0", 63 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 64 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 65 | "dev": true 66 | }, 67 | "binaryen": { 68 | "version": "93.0.0-nightly.20200514", 69 | "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-93.0.0-nightly.20200514.tgz", 70 | "integrity": "sha512-SRRItmNvhRVfoWWbRloO4i8IqkKH8rZ7/0QWRgLpM3umupK8gBpo9MY7Zp3pDysRSp+rVoqxvM5x4tFyCSa9zw==", 71 | "dev": true 72 | }, 73 | "brace-expansion": { 74 | "version": "1.1.11", 75 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 76 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 77 | "dev": true, 78 | "requires": { 79 | "balanced-match": "^1.0.0", 80 | "concat-map": "0.0.1" 81 | } 82 | }, 83 | "chalk": { 84 | "version": "4.0.0", 85 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", 86 | "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", 87 | "dev": true, 88 | "requires": { 89 | "ansi-styles": "^4.1.0", 90 | "supports-color": "^7.1.0" 91 | } 92 | }, 93 | "color-convert": { 94 | "version": "2.0.1", 95 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 96 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 97 | "dev": true, 98 | "requires": { 99 | "color-name": "~1.1.4" 100 | } 101 | }, 102 | "color-name": { 103 | "version": "1.1.4", 104 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 105 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 106 | "dev": true 107 | }, 108 | "commander": { 109 | "version": "2.20.3", 110 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 111 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 112 | "dev": true 113 | }, 114 | "concat-map": { 115 | "version": "0.0.1", 116 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 117 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 118 | "dev": true 119 | }, 120 | "diff": { 121 | "version": "4.0.2", 122 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 123 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 124 | "dev": true 125 | }, 126 | "discontinuous-range": { 127 | "version": "1.0.0", 128 | "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", 129 | "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", 130 | "dev": true 131 | }, 132 | "fs.realpath": { 133 | "version": "1.0.0", 134 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 135 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 136 | "dev": true 137 | }, 138 | "glob": { 139 | "version": "7.1.6", 140 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 141 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 142 | "dev": true, 143 | "requires": { 144 | "fs.realpath": "^1.0.0", 145 | "inflight": "^1.0.4", 146 | "inherits": "2", 147 | "minimatch": "^3.0.4", 148 | "once": "^1.3.0", 149 | "path-is-absolute": "^1.0.0" 150 | } 151 | }, 152 | "has-flag": { 153 | "version": "4.0.0", 154 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 155 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 156 | "dev": true 157 | }, 158 | "inflight": { 159 | "version": "1.0.6", 160 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 161 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 162 | "dev": true, 163 | "requires": { 164 | "once": "^1.3.0", 165 | "wrappy": "1" 166 | } 167 | }, 168 | "inherits": { 169 | "version": "2.0.4", 170 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 171 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 172 | "dev": true 173 | }, 174 | "long": { 175 | "version": "4.0.0", 176 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 177 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", 178 | "dev": true 179 | }, 180 | "minimatch": { 181 | "version": "3.0.4", 182 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 183 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 184 | "dev": true, 185 | "requires": { 186 | "brace-expansion": "^1.1.7" 187 | } 188 | }, 189 | "moo": { 190 | "version": "0.5.1", 191 | "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", 192 | "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", 193 | "dev": true 194 | }, 195 | "nearley": { 196 | "version": "2.19.3", 197 | "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.19.3.tgz", 198 | "integrity": "sha512-FpAy1PmTsUpOtgxr23g4jRNvJHYzZEW2PixXeSzksLR/ykPfwKhAodc2+9wQhY+JneWLcvkDw6q7FJIsIdF/aQ==", 199 | "dev": true, 200 | "requires": { 201 | "commander": "^2.19.0", 202 | "moo": "^0.5.0", 203 | "railroad-diagrams": "^1.0.0", 204 | "randexp": "0.4.6", 205 | "semver": "^5.4.1" 206 | } 207 | }, 208 | "once": { 209 | "version": "1.4.0", 210 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 211 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 212 | "dev": true, 213 | "requires": { 214 | "wrappy": "1" 215 | } 216 | }, 217 | "path-is-absolute": { 218 | "version": "1.0.1", 219 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 220 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 221 | "dev": true 222 | }, 223 | "railroad-diagrams": { 224 | "version": "1.0.0", 225 | "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", 226 | "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", 227 | "dev": true 228 | }, 229 | "randexp": { 230 | "version": "0.4.6", 231 | "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", 232 | "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", 233 | "dev": true, 234 | "requires": { 235 | "discontinuous-range": "1.0.0", 236 | "ret": "~0.1.10" 237 | } 238 | }, 239 | "ret": { 240 | "version": "0.1.15", 241 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", 242 | "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", 243 | "dev": true 244 | }, 245 | "semver": { 246 | "version": "5.7.1", 247 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 248 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 249 | "dev": true 250 | }, 251 | "supports-color": { 252 | "version": "7.1.0", 253 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 254 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 255 | "dev": true, 256 | "requires": { 257 | "has-flag": "^4.0.0" 258 | } 259 | }, 260 | "wrappy": { 261 | "version": "1.0.2", 262 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 263 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 264 | "dev": true 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@assemblyscript/node", 3 | "description": "Implementations of the node.js APIs for AssemblyScript, utilizing WASI.", 4 | "version": "0.1.0", 5 | "license": "Apache-2.0", 6 | "types": "assembly/node.d.ts", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/AssemblyScript/node.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/AssemblyScript/node/issues" 13 | }, 14 | "devDependencies": { 15 | "@as-pect/core": "^3.2.2", 16 | "assemblyscript": "0.10.0", 17 | "glob": "^7.1.6" 18 | }, 19 | "scripts": { 20 | "test": "node --experimental-wasi-unstable-preview1 --experimental-wasm-bigint tests/node" 21 | }, 22 | "dependencies": {} 23 | } 24 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.wat -------------------------------------------------------------------------------- /tests/buffer.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This is the buffer test suite. For each prototype function, put a single test 3 | * function call here. 4 | * 5 | * @example 6 | * describe("buffer", () => { 7 | * test("#alloc", () => { 8 | * // put any expectations related to #alloc here 9 | * }); 10 | * }); 11 | */ 12 | import { BLOCK_MAXSIZE } from "rt/common"; 13 | 14 | // Helper function to quickly create a Buffer from an array. 15 | //@ts-ignore 16 | function create(values: valueof[]): T { 17 | let result = instantiate(values.length); 18 | //@ts-ignore 19 | for (let i = 0; i < values.length; i++) result[i] = values[i]; 20 | return result; 21 | } 22 | 23 | describe("buffer", () => { 24 | test("#constructor", () => { 25 | expect(new Buffer(0)).toBeTruthy(); 26 | expect(new Buffer(10)).toHaveLength(10); 27 | let myBuffer = new Buffer(10); 28 | expect(myBuffer.buffer).toBeTruthy(); 29 | expect(myBuffer.buffer).toHaveLength(10); 30 | expect(() => { new Buffer(-1); }).toThrow(); 31 | // TODO: figure out how to test block maxsize 32 | // expect(() => { new Buffer(1 + BLOCK_MAXSIZE); }).toThrow(); 33 | }); 34 | 35 | test("#alloc", () => { 36 | expect(Buffer.alloc(10)).toBeTruthy(); 37 | expect(Buffer.alloc(10)).toHaveLength(10); 38 | let buff = Buffer.alloc(100); 39 | for (let i = 0; i < buff.length; i++) expect(buff[i]).toBe(0); 40 | expect(buff.buffer).not.toBeNull(); 41 | expect(buff.byteLength).toBe(100); 42 | expect(() => { Buffer.alloc(-1); }).toThrow(); 43 | // TODO: figure out how to test block maxsize 44 | // expect(() => { Buffer.alloc(1 + BLOCK_MAXSIZE); }).toThrow(); 45 | }); 46 | 47 | test("#allocUnsafe", () => { 48 | expect(Buffer.allocUnsafe(10)).toBeTruthy(); 49 | expect(Buffer.allocUnsafe(10)).toHaveLength(10); 50 | let buff = Buffer.allocUnsafe(100); 51 | expect(buff.buffer).not.toBeNull(); 52 | expect(buff.byteLength).toBe(100); 53 | expect(() => { Buffer.allocUnsafe(-1); }).toThrow(); 54 | // TODO: figure out how to test block maxsize 55 | // expect(() => { Buffer.allocUnsafe(BLOCK_MAXSIZE + 1); }).toThrow(); 56 | }); 57 | 58 | test("#isBuffer", () => { 59 | let a = ""; 60 | let b = new Uint8Array(0); 61 | let c = 0; 62 | let d = 1.1; 63 | let e = new Buffer(0); 64 | let f: Buffer | null = null; 65 | 66 | expect(Buffer.isBuffer(a)).toBeFalsy(); 67 | expect(Buffer.isBuffer(b)).toBeFalsy(); 68 | expect(Buffer.isBuffer(c)).toBeFalsy(); 69 | expect(Buffer.isBuffer(d)).toBeFalsy(); 70 | expect(Buffer.isBuffer(e)).toBeTruthy(); 71 | expect(Buffer.isBuffer(f)).toBeFalsy(); 72 | }); 73 | 74 | test("#readInt8", () => { 75 | let buff = create([0x5,0x0,0x0,0x0,0xFF]); 76 | expect(buff.readInt8()).toBe(5); 77 | // Testing offset, and casting between u8 and i8. 78 | expect(buff.readInt8(4)).toBe(-1); 79 | expect(() => { 80 | let newBuff = new Buffer(1); 81 | newBuff.readInt8(5); 82 | }).toThrow(); 83 | }); 84 | 85 | test("#readUInt8", () => { 86 | let buff = create([0xFE,0x0,0x0,0x0,0x2F]); 87 | // Testing casting between u8 and i8. 88 | expect(buff.readUInt8()).toBe(254); 89 | // Testing offset 90 | expect(buff.readUInt8(4)).toBe(47); 91 | expect(() => { 92 | let newBuff = new Buffer(1); 93 | newBuff.readUInt8(5); 94 | }).toThrow(); 95 | }); 96 | 97 | test("#writeInt8", () => { 98 | let buff = new Buffer(5); 99 | expect(buff.writeInt8(9)).toBe(1); 100 | expect(buff.writeInt8(-3,4)).toBe(5); 101 | let result = create([0x09, 0x0, 0x0, 0x0, 0xFD]); 102 | expect(buff).toStrictEqual(result); 103 | // TODO: 104 | expect(() => { 105 | let newBuff = new Buffer(1); 106 | newBuff.writeInt8(5,10); 107 | }).toThrow(); 108 | }); 109 | 110 | test("#writeUInt8", () => { 111 | let buff = new Buffer(5); 112 | expect(buff.writeUInt8(4)).toBe(1); 113 | expect(buff.writeUInt8(252,4)).toBe(5); 114 | let result = create([0x04, 0x0, 0x0, 0x0, 0xFC]); 115 | expect(buff).toStrictEqual(result); 116 | expect(() => { 117 | let newBuff = new Buffer(1); 118 | newBuff.writeUInt8(5,10); 119 | }).toThrow(); 120 | }); 121 | 122 | test("#readInt16LE", () => { 123 | let buff = create([0x0,0x05,0x0]); 124 | expect(buff.readInt16LE()).toBe(1280); 125 | expect(buff.readInt16LE(1)).toBe(5); 126 | expect(() => { 127 | let newBuff = new Buffer(1); 128 | newBuff.readInt16LE(0); 129 | }).toThrow(); 130 | }); 131 | 132 | test("#readInt16BE", () => { 133 | let buff = create([0x0,0x05,0x0]); 134 | expect(buff.readInt16BE()).toBe(5); 135 | expect(buff.readInt16BE(1)).toBe(1280); 136 | expect(() => { 137 | let newBuff = new Buffer(1); 138 | newBuff.readInt16BE(0); 139 | }).toThrow(); 140 | }); 141 | 142 | test("#readUInt16LE", () => { 143 | let buff = create([0x0,0x05,0x0]); 144 | expect(buff.readUInt16LE()).toBe(1280); 145 | expect(buff.readUInt16LE(1)).toBe(5); 146 | expect(() => { 147 | let newBuff = new Buffer(1); 148 | newBuff.readUInt16LE(0); 149 | }).toThrow(); 150 | }); 151 | 152 | test("#readUInt16BE", () => { 153 | let buff = create([0x0,0x05,0x0]); 154 | expect(buff.readUInt16BE()).toBe(5); 155 | expect(buff.readUInt16BE(1)).toBe(1280); 156 | expect(() => { 157 | let newBuff = new Buffer(1); 158 | newBuff.readUInt16BE(0); 159 | }).toThrow(); 160 | }); 161 | 162 | test("#writeInt16LE", () => { 163 | let buff = new Buffer(4); 164 | expect(buff.writeInt16LE(5)).toBe(2); 165 | expect(buff.writeInt16LE(1280,2)).toBe(4); 166 | let result = create([0x05, 0x0, 0x0, 0x5]); 167 | expect(buff).toStrictEqual(result); 168 | expect(() => { 169 | let newBuff = new Buffer(1); 170 | newBuff.writeInt16LE(0); 171 | }).toThrow(); 172 | }); 173 | 174 | test("#writeInt16BE", () => { 175 | let buff = new Buffer(4); 176 | expect(buff.writeInt16BE(1280)).toBe(2); 177 | expect(buff.writeInt16BE(5,2)).toBe(4); 178 | let result = create([0x05, 0x0, 0x0, 0x5]); 179 | expect(buff).toStrictEqual(result); 180 | expect(() => { 181 | let newBuff = new Buffer(1); 182 | newBuff.writeInt16BE(0); 183 | }).toThrow(); 184 | }); 185 | 186 | test("#writeUInt16LE", () => { 187 | let buff = new Buffer(4); 188 | expect(buff.writeUInt16LE(5)).toBe(2); 189 | expect(buff.writeUInt16LE(1280,2)).toBe(4); 190 | let result = create([0x05, 0x0, 0x0, 0x5]); 191 | expect(buff).toStrictEqual(result); 192 | expect(() => { 193 | let newBuff = new Buffer(1); 194 | newBuff.writeUInt16LE(0); 195 | }).toThrow(); 196 | }); 197 | 198 | test("#writeUInt16BE", () => { 199 | let buff = new Buffer(4); 200 | expect(buff.writeUInt16BE(1280)).toBe(2); 201 | expect(buff.writeUInt16BE(5,2)).toBe(4); 202 | let result = create([0x05, 0x0, 0x0, 0x5]); 203 | expect(buff).toStrictEqual(result); 204 | expect(() => { 205 | let newBuff = new Buffer(1); 206 | newBuff.writeUInt16BE(0); 207 | }).toThrow(); 208 | }); 209 | 210 | test("#readInt32LE", () => { 211 | let buff = create([0xEF,0xBE,0xAD,0xDE,0x0d,0xc0,0xde,0x10]); 212 | expect(buff.readInt32LE()).toBe(-559038737); 213 | expect(buff.readInt32LE(4)).toBe(283033613); 214 | expect(() => { 215 | let newBuff = new Buffer(1); 216 | newBuff.readInt32LE(0); 217 | }).toThrow(); 218 | }); 219 | 220 | test("#readInt32BE", () => { 221 | let buff = create([0xDE,0xAD,0xBE,0xEF,0x10,0xde,0xc0,0x0d]); 222 | expect(buff.readInt32BE()).toBe(-559038737); 223 | expect(buff.readInt32BE(4)).toBe(283033613); 224 | expect(() => { 225 | let newBuff = new Buffer(1); 226 | newBuff.readInt32BE(0); 227 | }).toThrow(); 228 | }); 229 | 230 | test("#readUInt32LE", () => { 231 | let buff = create([0xEF,0xBE,0xAD,0xDE,0x0d,0xc0,0xde,0x10]); 232 | expect(buff.readUInt32LE()).toBe(3735928559); 233 | expect(buff.readUInt32LE(4)).toBe(283033613); 234 | expect(() => { 235 | let newBuff = new Buffer(1); 236 | newBuff.readUInt32LE(0); 237 | }).toThrow(); 238 | }); 239 | 240 | test("#readUInt32BE", () => { 241 | let buff = create([0xDE,0xAD,0xBE,0xEF,0x10,0xde,0xc0,0x0d]); 242 | expect(buff.readUInt32BE()).toBe(3735928559); 243 | expect(buff.readUInt32BE(4)).toBe(283033613); 244 | expect(() => { 245 | let newBuff = new Buffer(1); 246 | newBuff.readUInt32BE(0); 247 | }).toThrow(); 248 | }); 249 | 250 | test("#writeInt32LE", () => { 251 | let buff = new Buffer(8); 252 | expect(buff.writeInt32LE(-559038737)).toBe(4); 253 | expect(buff.writeInt32LE(283033613,4)).toBe(8); 254 | let result = create([0xEF,0xBE,0xAD,0xDE,0x0d,0xc0,0xde,0x10]); 255 | expect(buff).toStrictEqual(result); 256 | expect(() => { 257 | let newBuff = new Buffer(1); 258 | newBuff.writeInt32LE(0); 259 | }).toThrow(); 260 | }); 261 | 262 | test("#writeInt32BE", () => { 263 | let buff = new Buffer(8); 264 | expect(buff.writeInt32BE(-559038737)).toBe(4); 265 | expect(buff.writeInt32BE(283033613,4)).toBe(8); 266 | let result = create([0xDE,0xAD,0xBE,0xEF,0x10,0xde,0xc0,0x0d]); 267 | expect(buff).toStrictEqual(result); 268 | expect(() => { 269 | let newBuff = new Buffer(1); 270 | newBuff.writeInt32BE(0); 271 | }).toThrow(); 272 | }); 273 | 274 | test("#writeUInt32LE", () => { 275 | let buff = new Buffer(8); 276 | expect(buff.writeUInt32LE(3735928559)).toBe(4); 277 | expect(buff.writeUInt32LE(283033613,4)).toBe(8); 278 | let result = create([0xEF,0xBE,0xAD,0xDE,0x0d,0xc0,0xde,0x10]);; 279 | expect(buff).toStrictEqual(result); 280 | expect(() => { 281 | let newBuff = new Buffer(1); 282 | newBuff.writeUInt32LE(0); 283 | }).toThrow(); 284 | }); 285 | 286 | test("#writeUInt32BE", () => { 287 | let buff = new Buffer(8); 288 | expect(buff.writeUInt32BE(3735928559)).toBe(4); 289 | expect(buff.writeUInt32BE(283033613,4)).toBe(8); 290 | let result = create([0xDE,0xAD,0xBE,0xEF,0x10,0xde,0xc0,0x0d]); 291 | expect(buff).toStrictEqual(result); 292 | expect(() => { 293 | let newBuff = new Buffer(1); 294 | newBuff.writeUInt32BE(0); 295 | }).toThrow(); 296 | }); 297 | 298 | test("#readFloatLE", () => { 299 | let buff = create([0xbb,0xfe,0x4a,0x4f,0x01,0x02,0x03,0x04]); 300 | expect(buff.readFloatLE()).toBe(0xcafebabe); 301 | expect(buff.readFloatLE(4)).toBe(1.539989614439558e-36); 302 | expect(() => { 303 | let newBuff = new Buffer(1); 304 | newBuff.readFloatLE(0); 305 | }).toThrow(); 306 | }); 307 | 308 | test("#readFloatBE", () => { 309 | let buff = create([0x4f,0x4a,0xfe,0xbb,0x01,0x02,0x03,0x04]); 310 | expect(buff.readFloatBE()).toBe(0xcafebabe); 311 | expect(buff.readFloatBE(4)).toBe(2.387939260590663e-38); 312 | expect(() => { 313 | let newBuff = new Buffer(1); 314 | newBuff.readFloatBE(0); 315 | }).toThrow(); 316 | }); 317 | 318 | test("#writeFloatLE", () => { 319 | let buff = new Buffer(8); 320 | expect(buff.writeFloatLE(0xcafebabe)).toBe(4); 321 | expect(buff.writeFloatLE(1.539989614439558e-36,4)).toBe(8); 322 | let result = create([0xbb,0xfe,0x4a,0x4f,0x01,0x02,0x03,0x04]); 323 | expect(buff).toStrictEqual(result); 324 | expect(() => { 325 | let newBuff = new Buffer(1); 326 | newBuff.writeFloatLE(0); 327 | }).toThrow(); 328 | }); 329 | 330 | test("#writeFloatBE", () => { 331 | let buff = new Buffer(8); 332 | expect(buff.writeFloatBE(0xcafebabe)).toBe(4); 333 | expect(buff.writeFloatBE(2.387939260590663e-38,4)).toBe(8); 334 | let result = create([0x4f,0x4a,0xfe,0xbb,0x01,0x02,0x03,0x04]); 335 | expect(buff).toStrictEqual(result); 336 | expect(() => { 337 | let newBuff = new Buffer(1); 338 | newBuff.writeFloatBE(0); 339 | }).toThrow(); 340 | }); 341 | 342 | test("#readBigInt64LE", () => { 343 | let buff = create([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]); 344 | expect(buff.readBigInt64LE()).toBe(-4294967296); 345 | expect(buff.readBigInt64LE(8)).toBe(4294967295); 346 | expect(() => { 347 | let newBuff = new Buffer(1); 348 | newBuff.readBigInt64LE(0); 349 | }).toThrow(); 350 | }); 351 | 352 | test("#readBigInt64BE", () => { 353 | let buff = create([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]); 354 | expect(buff.readBigInt64BE()).toBe(4294967295); 355 | expect(buff.readBigInt64BE(8)).toBe(-4294967296); 356 | expect(() => { 357 | let newBuff = new Buffer(1); 358 | newBuff.readBigInt64BE(0); 359 | }).toThrow(); 360 | }); 361 | 362 | test("#readBigUInt64LE", () => { 363 | let buff = create([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]); 364 | expect(buff.readBigUInt64LE()).toBe(18446744069414584320); 365 | expect(buff.readBigUInt64LE(8)).toBe(4294967295); 366 | expect(() => { 367 | let newBuff = new Buffer(1); 368 | newBuff.readBigUInt64LE(0); 369 | }).toThrow(); 370 | }); 371 | 372 | test("#readBigUInt64BE", () => { 373 | let buff = create([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]); 374 | expect(buff.readBigUInt64BE()).toBe(4294967295); 375 | expect(buff.readBigUInt64BE(8)).toBe(18446744069414584320); 376 | expect(() => { 377 | let newBuff = new Buffer(1); 378 | newBuff.readBigUInt64BE(0); 379 | }).toThrow(); 380 | }); 381 | 382 | test("#writeBigInt64LE", () => { 383 | let buff = new Buffer(16); 384 | expect(buff.writeBigInt64LE(-559038737)).toBe(8); 385 | expect(buff.writeBigInt64LE(283033613,8)).toBe(16); 386 | let result = create([0xEF,0xBE,0xAD,0xDE,0xFF,0xFF,0xFF,0xFF,0x0d,0xc0,0xde,0x10,0x00,0x00,0x00,0x00]); 387 | expect(buff).toStrictEqual(result); 388 | expect(() => { 389 | let newBuff = new Buffer(1); 390 | newBuff.writeBigInt64LE(0); 391 | }).toThrow(); 392 | }); 393 | 394 | test("#writeBigInt64BE", () => { 395 | let buff = new Buffer(16); 396 | expect(buff.writeBigInt64BE(-559038737)).toBe(8); 397 | expect(buff.writeBigInt64BE(283033613,8)).toBe(16); 398 | let result = create([0xFF,0xFF,0xFF,0xFF,0xDE,0xAD,0xBE,0xEF,0x00,0x00,0x00,0x00,0x10,0xde,0xc0,0x0d]); 399 | expect(buff).toStrictEqual(result); 400 | expect(() => { 401 | let newBuff = new Buffer(1); 402 | newBuff.writeBigInt64BE(0); 403 | }).toThrow(); 404 | }); 405 | 406 | test("#writeBigUInt64LE", () => { 407 | let buff = new Buffer(16); 408 | expect(buff.writeBigUInt64LE(3735928559)).toBe(8); 409 | expect(buff.writeBigUInt64LE(283033613,8)).toBe(16); 410 | let result = create([0xEF,0xBE,0xAD,0xDE,0x00,0x00,0x00,0x00,0x0d,0xc0,0xde,0x10,0x00,0x00,0x00,0x00]); 411 | expect(buff).toStrictEqual(result); 412 | expect(() => { 413 | let newBuff = new Buffer(1); 414 | newBuff.writeBigUInt64LE(0); 415 | }).toThrow(); 416 | }); 417 | 418 | test("#writeBigUInt64BE", () => { 419 | let buff = new Buffer(16); 420 | expect(buff.writeBigUInt64BE(3735928559)).toBe(8); 421 | expect(buff.writeBigUInt64BE(283033613,8)).toBe(16); 422 | let result = create([0x00,0x00,0x00,0x00,0xDE,0xAD,0xBE,0xEF,0x00,0x00,0x00,0x00,0x10,0xde,0xc0,0x0d]); 423 | expect(buff).toStrictEqual(result); 424 | expect(() => { 425 | let newBuff = new Buffer(1); 426 | newBuff.writeBigUInt64BE(0); 427 | }).toThrow(); 428 | }); 429 | 430 | test("#readDoubleLE", () => { 431 | let buff = create([0x77, 0xbe, 0x9f, 0x1a, 0x2f, 0xdd, 0x5e, 0x40, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); 432 | expect(buff.readDoubleLE()).toBe(123.456); 433 | expect(buff.readDoubleLE(8)).toBe(5.447603722011605e-270); 434 | expect(() => { 435 | let newBuff = new Buffer(1); 436 | newBuff.readDoubleLE(0); 437 | }).toThrow(); 438 | }); 439 | 440 | test("#readDoubleBE", () => { 441 | let buff = create([0x40, 0x5e, 0xdd, 0x2f, 0x1a, 0x9f, 0xbe, 0x77, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); 442 | expect(buff.readDoubleBE()).toBe(123.456); 443 | expect(buff.readDoubleBE(8)).toBe(8.20788039913184e-304); 444 | expect(() => { 445 | let newBuff = new Buffer(1); 446 | newBuff.readDoubleBE(0); 447 | }).toThrow(); 448 | }); 449 | 450 | test("#writeDoubleLE", () => { 451 | let buff = new Buffer(16); 452 | expect(buff.writeDoubleLE(123.456)).toBe(8); 453 | expect(buff.writeDoubleLE(5.447603722011605e-270,8)).toBe(16); 454 | let result = create([0x77, 0xbe, 0x9f, 0x1a, 0x2f, 0xdd, 0x5e, 0x40, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); 455 | expect(buff).toStrictEqual(result); 456 | expect(() => { 457 | let newBuff = new Buffer(1); 458 | newBuff.writeDoubleLE(0); 459 | }).toThrow(); 460 | }); 461 | 462 | test("#writeDoubleBE", () => { 463 | let buff = new Buffer(16); 464 | expect(buff.writeDoubleBE(123.456)).toBe(8); 465 | expect(buff.writeDoubleBE(8.20788039913184e-304,8)).toBe(16); 466 | let result = create([0x40, 0x5e, 0xdd, 0x2f, 0x1a, 0x9f, 0xbe, 0x77, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); 467 | expect(buff).toStrictEqual(result); 468 | expect(() => { 469 | let newBuff = new Buffer(1); 470 | newBuff.writeDoubleBE(0); 471 | }).toThrow(); 472 | }); 473 | 474 | test("#subarray", () => { 475 | let example = create([1, 2, 3, 4, 5, 6, 7, 8]); 476 | 477 | // no parameters means copy the Buffer 478 | let actual = example.subarray(); 479 | expect(actual).toStrictEqual(example); 480 | expect(actual.buffer).toBe(example.buffer); // should use the same buffer 481 | 482 | // start at offset 5 483 | actual = example.subarray(5); 484 | let expected = create([6, 7, 8]); 485 | // trace("length", 1, expected.length); 486 | expect(actual).toStrictEqual(expected); 487 | 488 | // negative start indicies, start at (8 - 5) 489 | actual = example.subarray(-5); 490 | expected = create([4, 5, 6, 7, 8]); 491 | expect(actual).toStrictEqual(expected); 492 | 493 | // two parameters 494 | actual = example.subarray(2, 6); 495 | expected = create([3, 4, 5, 6]); 496 | expect(actual).toStrictEqual(expected); 497 | 498 | // negative end index 499 | actual = example.subarray(4, -1); 500 | expected = create([5, 6, 7]); 501 | expect(actual).toStrictEqual(expected); 502 | }); 503 | 504 | test("#swap16", () => { 505 | let actual = create([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); 506 | let expected = create([0x2, 0x1, 0x4, 0x3, 0x6, 0x5, 0x8, 0x7]); 507 | let swapped = actual.swap16(); 508 | expect(actual).toStrictEqual(expected); 509 | expect(swapped).toBe(actual); 510 | expect(() => { 511 | let newBuff = create([0x1, 0x2, 0x3]); 512 | newBuff.swap16(); 513 | }).toThrow(); 514 | }); 515 | 516 | test("#swap32", () => { 517 | let actual = create([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); 518 | let expected = create([0x4, 0x3, 0x2, 0x1, 0x8, 0x7, 0x6, 0x5]); 519 | let swapped = actual.swap32(); 520 | expect(actual).toStrictEqual(expected); 521 | expect(swapped).toBe(actual); 522 | expect(() => { 523 | let newBuff = create([0x1, 0x2, 0x3]); 524 | newBuff.swap64(); 525 | }).toThrow(); 526 | }); 527 | 528 | test("#swap64", () => { 529 | let actual = create([0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf]); 530 | let expected = create([0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8]); 531 | let swapped = actual.swap64(); 532 | expect(actual).toStrictEqual(expected); 533 | expect(swapped).toBe(actual); 534 | expect(() => { 535 | let newBuff = create([0x1, 0x2, 0x3]); 536 | newBuff.swap64(); 537 | }).toThrow(); 538 | }); 539 | 540 | test("#Hex.encode", () => { 541 | let actual = "000102030405060708090a0b0c0d0e0f102030405060708090a0b0c0d0e0f0"; 542 | let exampleBuffer = create([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0]); 543 | let encoded = Buffer.HEX.encode(actual); 544 | expect(encoded).toStrictEqual(exampleBuffer.buffer); 545 | }); 546 | 547 | test("#Hex.decode", () => { 548 | let expected = "000102030405060708090a0b0c0d0e0f102030405060708090a0b0c0d0e0f0"; 549 | let exampleBuffer = create([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0]); 550 | let decoded = Buffer.HEX.decode(exampleBuffer.buffer); 551 | expect(decoded).toStrictEqual(expected); 552 | }); 553 | 554 | test("#ASCII.encode", () => { 555 | let actual = "D34dB3eF"; 556 | let exampleBuffer = create([0x44, 0x33, 0x34, 0x64, 0x42, 0x33, 0x65, 0x46]); 557 | let encoded = Buffer.ASCII.encode(actual); 558 | expect(encoded).toStrictEqual(exampleBuffer.buffer); 559 | }); 560 | 561 | test("#ASCII.decode", () => { 562 | let expected = create([0x44, 0x33, 0x34, 0x64, 0x42, 0x33, 0x65, 0x46]); 563 | let example = "D34dB3eF"; 564 | let encoded = Buffer.ASCII.decode(expected.buffer); 565 | expect(encoded).toStrictEqual(example); 566 | }); 567 | }); 568 | -------------------------------------------------------------------------------- /tests/env.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is for typescript editors like vscode. Do not delete this. 3 | */ 4 | /// 5 | /// 6 | /// 7 | -------------------------------------------------------------------------------- /tests/fs.spec.ts: -------------------------------------------------------------------------------- 1 | test("an empty test", () => { 2 | 3 | }); 4 | -------------------------------------------------------------------------------- /tests/fs.spec.wasi.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: process.env, 3 | argv: process.argv, 4 | preopens: { 5 | "./tests/sandbox": "./tests/sandbox" 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /tests/node.js: -------------------------------------------------------------------------------- 1 | const { TestContext, VerboseReporter } = require("@as-pect/core"); 2 | const glob = require("glob"); 3 | const { instantiateSync } = require("assemblyscript/lib/loader"); 4 | const { main } = require("assemblyscript/cli/asc"); 5 | const { parse } = require("assemblyscript/cli/util/options"); 6 | const path = require("path"); 7 | const fssync = require("fs"); 8 | const fs = fssync.promises; 9 | const { WASI } = require("wasi"); 10 | 11 | const promises = []; 12 | let pass = true; 13 | 14 | const options = parse(process.argv.slice(2), { 15 | "help": { 16 | "description": "Prints this message and exits.", 17 | "type": "b", 18 | "alias": "h" 19 | }, 20 | "updateFixtures": { 21 | "description": "Update the test fixtures.", 22 | "type": "b", 23 | "alias": "u" 24 | }, 25 | "preopens": { 26 | "description": "A set of preopened directories for wasi. Ex. ./dir=./dir", 27 | "type": "S", 28 | "alias": "p", 29 | "default": [], 30 | }, 31 | }); 32 | 33 | if (options.unknown.length > 1) { 34 | console.error("Unknown options arguments: " + options.unknown.join(" ")); 35 | process.exit(1); 36 | } 37 | 38 | // calculate default preopens from cli 39 | const preopens = options.options.preopens.reduce( 40 | (obj, value) => { 41 | const [_, dir1, dir2] = /([^=])*=(.*)/.exec(value); 42 | obj[dir1] = dir2; 43 | return obj; 44 | }, 45 | {} 46 | ); 47 | 48 | const reporter = new VerboseReporter(); 49 | reporter.stderr = process.stderr; 50 | reporter.stdout = process.stdout; 51 | 52 | function relativeFromCwd(location) { 53 | return path.relative(process.cwd(), location); 54 | } 55 | 56 | const ascOptions = [ 57 | relativeFromCwd(require.resolve("@as-pect/assembly/assembly/index.ts")), 58 | "--use", "ASC_RTRACE=1", 59 | "--explicitStart", 60 | "--measure", 61 | "--lib", "assembly", 62 | "--transform", require.resolve("@as-pect/core/lib/transform/index.js"), 63 | ]; 64 | 65 | const files = glob.sync("tests/**/*.spec.ts") 66 | .map(relativeFromCwd); 67 | 68 | const untouchedBinaryMap = new Map(); 69 | const optimizedBinaryMap = new Map(); 70 | 71 | const untouchedWatMap = new Map(); 72 | const optimizedWatMap = new Map(); 73 | 74 | const untouchedAscOptions = { 75 | writeFile(name, contents) { 76 | const ext = path.extname(name); 77 | if (ext === ".wasm") untouchedBinaryMap.set(name, contents); 78 | if (ext === ".wat") untouchedWatMap.set(name, contents); 79 | } 80 | }; 81 | 82 | const optimizedAscOptions = { 83 | writeFile(name, contents) { 84 | const ext = path.extname(name); 85 | if (ext === ".wasm") optimizedBinaryMap.set(name, contents); 86 | if (ext === ".wat") optimizedWatMap.set(name, contents); 87 | } 88 | }; 89 | 90 | const errors = []; 91 | 92 | for (const file of files) { 93 | const ext = path.extname(file); 94 | const wasmFileName = path.join(path.dirname(file), path.basename(file, ext)) + ".wasm"; 95 | const watFileName = path.join(path.dirname(file), path.basename(file, ext)) + ".wat"; 96 | 97 | const cliOptions = ascOptions.concat([ 98 | file, 99 | "--binaryFile", wasmFileName, 100 | "--textFile", watFileName, 101 | ]); 102 | 103 | process.stdout.write("Test File : " + file + " (untouched)\n"); 104 | main(cliOptions.concat(["--debug"]), untouchedAscOptions, (err) => { 105 | if (err) { 106 | console.error(err); 107 | errors.push(err); 108 | } else { 109 | const binary = untouchedBinaryMap.get(wasmFileName); 110 | const wat = untouchedWatMap.get(watFileName); 111 | runTest(file, "untouched", binary, wat); 112 | } 113 | }); 114 | 115 | process.stdout.write("\n"); 116 | process.stdout.write("Test File : " + file + " (optimized)\n"); 117 | main(cliOptions.concat(["-O3"]), optimizedAscOptions, (err) => { 118 | if (err) { 119 | console.error(err); 120 | errors.push(err); 121 | } else { 122 | const binary = optimizedBinaryMap.get(wasmFileName); 123 | const wat = optimizedWatMap.get(watFileName); 124 | runTest(file, "optimized", binary, wat); 125 | } 126 | }); 127 | 128 | process.stdout.write("\n"); 129 | } 130 | 131 | function runTest(fileName, type, binary, wat) { 132 | const dirname = path.dirname(fileName); 133 | const basename = path.basename(fileName, ".ts"); 134 | const fullName = path.join(dirname, basename) 135 | const watPath = `${fullName}.${type}.wat`; 136 | const wasiPath = `${fullName}.wasi.js`; 137 | const fileNamePath = `${fullName}.${type}.ts`; 138 | 139 | // use either a custom wasi configuration, or the default one 140 | const wasiOptions = fssync.existsSync(wasiPath) 141 | ? require(path.resolve(wasiPath)) 142 | : { 143 | args: process.argv, 144 | env: process.env, 145 | preopens, 146 | }; 147 | 148 | // should not block testing 149 | promises.push(fs.writeFile(watPath, wat)); 150 | 151 | const wasi = new WASI(wasiOptions); 152 | 153 | const context = new TestContext({ 154 | fileName: fileNamePath, // set the fileName 155 | reporter, // use verbose reporter 156 | binary, // pass the binary to get function names 157 | wasi, 158 | }); 159 | 160 | const imports = context.createImports({ 161 | wasi_snapshot_preview1: wasi.wasiImport, 162 | }); 163 | 164 | const instance = instantiateSync(binary, imports); 165 | 166 | process.stdout.write("\n"); 167 | context.run(instance); 168 | 169 | if (!context.pass) pass = false; 170 | } 171 | 172 | // await for all the file writes to occur for the wat files 173 | Promise.all(promises) 174 | .then(() => { 175 | // if the file writes were successful, inspect errors and pass 176 | process.exit(pass && errors.length === 0 ? 0 : 1); 177 | }) 178 | .catch((error) => { 179 | // report the file write error and exit 1 180 | console.error(error); 181 | process.exit(1); 182 | }); 183 | 184 | -------------------------------------------------------------------------------- /tests/sandbox/test.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AssemblyScript/node/bbd353ffbf2a7180ad6979a5f9a5bd91e677acb6/tests/sandbox/test.txt -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../node_modules/assemblyscript/std/assembly.json", 3 | "include": [ 4 | "./**/*.ts" 5 | ] 6 | } --------------------------------------------------------------------------------