smoldot 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,10 +7,6 @@ export interface Config {
7
7
  * When `buffer_size` or `buffer_index` are called, the buffer is found here.
8
8
  */
9
9
  bufferIndices: Array<Uint8Array>;
10
- /**
11
- * Returns the number of milliseconds since an arbitrary epoch.
12
- */
13
- performanceNow: () => number;
14
10
  /**
15
11
  * Tries to open a new connection using the given configuration.
16
12
  *
@@ -71,7 +67,7 @@ export interface Connection {
71
67
  *
72
68
  * The connection and stream must currently be in the `Open` state.
73
69
  *
74
- * The number of bytes most never exceed the number of "writable bytes" of the stream.
70
+ * The number of bytes must never exceed the number of "writable bytes" of the stream.
75
71
  * `onWritableBytes` can be used in order to notify that more writable bytes are available.
76
72
  *
77
73
  * The `streamId` must be provided if and only if the connection is of type "multi-stream".
@@ -160,7 +156,8 @@ export interface ConnectionConfig {
160
156
  */
161
157
  onStreamReset: (streamId: number) => void;
162
158
  /**
163
- * Callback called when more data can be written on the stream.
159
+ * Callback called when some data sent using {@link Connection.send} has effectively been
160
+ * written on the stream, meaning that some buffer space is now free.
164
161
  *
165
162
  * Can only happen while the connection is in the `Open` state.
166
163
  *
@@ -168,6 +165,9 @@ export interface ConnectionConfig {
168
165
  *
169
166
  * The `streamId` parameter must be provided if and only if the connection is of type
170
167
  * "multi-stream".
168
+ *
169
+ * Only a number of bytes equal to the size of the data provided to {@link Connection.send}
170
+ * must be reported. In other words, the `initialWritableBytes` must never be exceeded.
171
171
  */
172
172
  onWritableBytes: (numExtra: number, streamId?: number) => void;
173
173
  /**
@@ -89,10 +89,6 @@ function default_1(config) {
89
89
  config.logCallback(level, target, message);
90
90
  }
91
91
  },
92
- // Must return the UNIX time in milliseconds.
93
- unix_time_ms: () => Date.now(),
94
- // Must return the value of a monotonic clock in milliseconds.
95
- monotonic_clock_ms: () => config.performanceNow(),
96
92
  // Must call `timer_finished` after the given number of milliseconds has elapsed.
97
93
  start_timer: (id, ms) => {
98
94
  if (killedTracked.killed)
@@ -5,6 +5,10 @@ export interface Config {
5
5
  * Fills the given buffer with randomly-generated bytes.
6
6
  */
7
7
  getRandomValues: (buffer: Uint8Array) => void;
8
+ /**
9
+ * Returns the number of milliseconds since an arbitrary epoch.
10
+ */
11
+ performanceNow: () => number;
8
12
  /**
9
13
  * List of environment variables to feed to the Rust program. An array of strings.
10
14
  * Example: `["RUST_BACKTRACE=1", "RUST_LOG=foo"];`
@@ -41,6 +41,36 @@ exports.default = (config) => {
41
41
  }
42
42
  return 0;
43
43
  },
44
+ clock_time_get: (clockId, _precision, outPtr) => {
45
+ // See <https://github.com/rust-lang/rust/blob/master/library/std/src/sys/wasi/time.rs>
46
+ // and <docs.rs/wasi/> for help.
47
+ const instance = config.instance;
48
+ const mem = new Uint8Array(instance.exports.memory.buffer);
49
+ outPtr >>>= 0;
50
+ // We ignore the precision, as it can't be implemented anyway.
51
+ switch (clockId) {
52
+ case 0: {
53
+ // Realtime clock.
54
+ const now = BigInt(Math.floor(Date.now())) * BigInt(1000000);
55
+ buffer.writeUInt64LE(mem, outPtr, now);
56
+ // Success.
57
+ return 0;
58
+ }
59
+ case 1: {
60
+ // Monotonic clock.
61
+ const nowMs = config.performanceNow();
62
+ const nowMsInt = Math.floor(nowMs);
63
+ const now = BigInt(nowMsInt) * BigInt(1000000) +
64
+ BigInt(Math.floor(((nowMs - nowMsInt) * 1000000)));
65
+ buffer.writeUInt64LE(mem, outPtr, now);
66
+ // Success.
67
+ return 0;
68
+ }
69
+ default:
70
+ // Return an `EINVAL` error.
71
+ return 28;
72
+ }
73
+ },
44
74
  // Writing to a file descriptor is used in order to write to stdout/stderr.
45
75
  fd_write: (fd, addr, num, outPtr) => {
46
76
  const instance = config.instance;
@@ -8,3 +8,4 @@ export declare function readUInt32LE(buffer: Uint8Array, offset: number): number
8
8
  */
9
9
  export declare function writeUInt8(buffer: Uint8Array, offset: number, value: number): void;
10
10
  export declare function writeUInt32LE(buffer: Uint8Array, offset: number, value: number): void;
11
+ export declare function writeUInt64LE(buffer: Uint8Array, offset: number, value: bigint): void;
@@ -3,7 +3,7 @@
3
3
  // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
4
4
  // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writeUInt32LE = exports.writeUInt8 = exports.readUInt32LE = exports.utf8BytesToString = void 0;
6
+ exports.writeUInt64LE = exports.writeUInt32LE = exports.writeUInt8 = exports.readUInt32LE = exports.utf8BytesToString = void 0;
7
7
  // This program is free software: you can redistribute it and/or modify
8
8
  // it under the terms of the GNU General Public License as published by
9
9
  // the Free Software Foundation, either version 3 of the License, or
@@ -45,6 +45,18 @@ function writeUInt32LE(buffer, offset, value) {
45
45
  buffer[offset] = value & 0xff;
46
46
  }
47
47
  exports.writeUInt32LE = writeUInt32LE;
48
+ function writeUInt64LE(buffer, offset, value) {
49
+ checkRange(buffer, offset, 8);
50
+ buffer[offset + 7] = Number((value >> BigInt(56)) & BigInt(0xff));
51
+ buffer[offset + 6] = Number((value >> BigInt(48)) & BigInt(0xff));
52
+ buffer[offset + 5] = Number((value >> BigInt(40)) & BigInt(0xff));
53
+ buffer[offset + 4] = Number((value >> BigInt(32)) & BigInt(0xff));
54
+ buffer[offset + 3] = Number((value >> BigInt(24)) & BigInt(0xff));
55
+ buffer[offset + 2] = Number((value >> BigInt(16)) & BigInt(0xff));
56
+ buffer[offset + 1] = Number((value >> BigInt(8)) & BigInt(0xff));
57
+ buffer[offset] = Number(value & BigInt(0xff));
58
+ }
59
+ exports.writeUInt64LE = writeUInt64LE;
48
60
  function checkRange(buffer, offset, length) {
49
61
  if (!Number.isInteger(offset) || offset < 0)
50
62
  throw new RangeError();
@@ -38,7 +38,7 @@ function startInstance(config, platformBindings) {
38
38
  let killAll;
39
39
  const bufferIndices = new Array;
40
40
  // Used to bind with the smoldot-light bindings. See the `bindings-smoldot-light.js` file.
41
- const smoldotJsConfig = Object.assign({ bufferIndices, performanceNow: platformBindings.performanceNow, connect: platformBindings.connect, onPanic: (message) => {
41
+ const smoldotJsConfig = Object.assign({ bufferIndices, connect: platformBindings.connect, onPanic: (message) => {
42
42
  killAll();
43
43
  config.onWasmPanic(message);
44
44
  throw new Error();
@@ -47,6 +47,7 @@ function startInstance(config, platformBindings) {
47
47
  const wasiConfig = {
48
48
  envVars: [],
49
49
  getRandomValues: platformBindings.getRandomValues,
50
+ performanceNow: platformBindings.performanceNow,
50
51
  onProcExit: (retCode) => {
51
52
  killAll();
52
53
  config.onWasmPanic(`proc_exit called: ${retCode}`);
@@ -77,10 +77,10 @@ export function start(options, platformBindings) {
77
77
  // For each chain object returned by `addChain`, the associated internal chain id.
78
78
  //
79
79
  // Immediately cleared when `remove()` is called on a chain.
80
- let chainIds = new WeakMap();
80
+ const chainIds = new WeakMap();
81
81
  // If `Client.terminate()̀ is called, this error is set to a value.
82
82
  // All the functions of the public API check if this contains a value.
83
- let alreadyDestroyedError = null;
83
+ const alreadyDestroyedError = { value: null };
84
84
  const instance = startInstance({
85
85
  // Maximum level of log entries sent by the client.
86
86
  // 0 = Logging disabled, 1 = Error, 2 = Warn, 3 = Info, 4 = Debug, 5 = Trace
@@ -94,8 +94,8 @@ export function start(options, platformBindings) {
94
94
  }, platformBindings);
95
95
  return {
96
96
  addChain: (options) => __awaiter(this, void 0, void 0, function* () {
97
- if (alreadyDestroyedError)
98
- throw alreadyDestroyedError;
97
+ if (alreadyDestroyedError.value)
98
+ throw alreadyDestroyedError.value;
99
99
  // Passing a JSON object for the chain spec is an easy mistake, so we provide a more
100
100
  // readable error.
101
101
  if (!(typeof options.chainSpec === 'string'))
@@ -120,8 +120,8 @@ export function start(options, platformBindings) {
120
120
  // Resolve the promise that `addChain` returned to the user.
121
121
  const newChain = {
122
122
  sendJsonRpc: (request) => {
123
- if (alreadyDestroyedError)
124
- throw alreadyDestroyedError;
123
+ if (alreadyDestroyedError.value)
124
+ throw alreadyDestroyedError.value;
125
125
  if (wasDestroyed.destroyed)
126
126
  throw new AlreadyDestroyedError();
127
127
  if (options.disableJsonRpc)
@@ -133,8 +133,8 @@ export function start(options, platformBindings) {
133
133
  instance.request(request, chainId);
134
134
  },
135
135
  nextJsonRpcResponse: () => {
136
- if (alreadyDestroyedError)
137
- return Promise.reject(alreadyDestroyedError);
136
+ if (alreadyDestroyedError.value)
137
+ return Promise.reject(alreadyDestroyedError.value);
138
138
  if (wasDestroyed.destroyed)
139
139
  return Promise.reject(new AlreadyDestroyedError());
140
140
  if (options.disableJsonRpc)
@@ -142,8 +142,8 @@ export function start(options, platformBindings) {
142
142
  return instance.nextJsonRpcResponse(chainId);
143
143
  },
144
144
  remove: () => {
145
- if (alreadyDestroyedError)
146
- throw alreadyDestroyedError;
145
+ if (alreadyDestroyedError.value)
146
+ throw alreadyDestroyedError.value;
147
147
  if (wasDestroyed.destroyed)
148
148
  throw new AlreadyDestroyedError();
149
149
  wasDestroyed.destroyed = true;
@@ -156,9 +156,9 @@ export function start(options, platformBindings) {
156
156
  return newChain;
157
157
  }),
158
158
  terminate: () => __awaiter(this, void 0, void 0, function* () {
159
- if (alreadyDestroyedError)
160
- throw alreadyDestroyedError;
161
- alreadyDestroyedError = new AlreadyDestroyedError();
159
+ if (alreadyDestroyedError.value)
160
+ throw alreadyDestroyedError.value;
161
+ alreadyDestroyedError.value = new AlreadyDestroyedError();
162
162
  instance.startShutdown();
163
163
  })
164
164
  };