@perspective-dev/client 4.0.0
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.
- package/LICENSE.md +193 -0
- package/README.md +3 -0
- package/dist/cdn/perspective-server.worker.js +2 -0
- package/dist/cdn/perspective-server.worker.js.map +7 -0
- package/dist/cdn/perspective.js +3 -0
- package/dist/cdn/perspective.js.map +7 -0
- package/dist/esm/perspective-server.worker.d.ts +1 -0
- package/dist/esm/perspective.browser.d.ts +14 -0
- package/dist/esm/perspective.inline.js +3 -0
- package/dist/esm/perspective.inline.js.map +7 -0
- package/dist/esm/perspective.js +3 -0
- package/dist/esm/perspective.js.map +7 -0
- package/dist/esm/perspective.node.d.ts +60 -0
- package/dist/esm/perspective.node.js +2431 -0
- package/dist/esm/perspective.node.js.map +7 -0
- package/dist/esm/ts-rs/Aggregate.d.ts +1 -0
- package/dist/esm/ts-rs/ColumnWindow.d.ts +4 -0
- package/dist/esm/ts-rs/DeleteOptions.d.ts +6 -0
- package/dist/esm/ts-rs/Expressions.d.ts +3 -0
- package/dist/esm/ts-rs/Filter.d.ts +2 -0
- package/dist/esm/ts-rs/FilterReducer.d.ts +1 -0
- package/dist/esm/ts-rs/FilterTerm.d.ts +2 -0
- package/dist/esm/ts-rs/OnUpdateMode.d.ts +9 -0
- package/dist/esm/ts-rs/OnUpdateOptions.d.ts +7 -0
- package/dist/esm/ts-rs/Scalar.d.ts +5 -0
- package/dist/esm/ts-rs/Sort.d.ts +2 -0
- package/dist/esm/ts-rs/SortDir.d.ts +1 -0
- package/dist/esm/ts-rs/SystemInfo.d.ts +40 -0
- package/dist/esm/ts-rs/TableInitOptions.d.ts +22 -0
- package/dist/esm/ts-rs/TableReadFormat.d.ts +7 -0
- package/dist/esm/ts-rs/UpdateOptions.d.ts +8 -0
- package/dist/esm/ts-rs/ViewConfigUpdate.d.ts +90 -0
- package/dist/esm/ts-rs/ViewOnUpdateResp.d.ts +4 -0
- package/dist/esm/ts-rs/ViewWindow.d.ts +23 -0
- package/dist/esm/wasm/browser.d.ts +21 -0
- package/dist/esm/wasm/decompress.d.ts +1 -0
- package/dist/esm/wasm/emscripten_api.d.ts +5 -0
- package/dist/esm/wasm/engine.d.ts +40 -0
- package/dist/esm/wasm/perspective-server.poly.d.ts +1 -0
- package/dist/esm/websocket.d.ts +4 -0
- package/dist/wasm/perspective-js.d.ts +712 -0
- package/dist/wasm/perspective-js.js +1934 -0
- package/dist/wasm/perspective-js.wasm +0 -0
- package/dist/wasm/perspective-js.wasm.d.ts +75 -0
- package/package.json +68 -0
- package/src/rust/client.rs +483 -0
- package/src/rust/lib.rs +70 -0
- package/src/rust/table.rs +364 -0
- package/src/rust/table_data.rs +159 -0
- package/src/rust/utils/browser.rs +39 -0
- package/src/rust/utils/console_logger.rs +236 -0
- package/src/rust/utils/errors.rs +288 -0
- package/src/rust/utils/futures.rs +174 -0
- package/src/rust/utils/json.rs +252 -0
- package/src/rust/utils/local_poll_loop.rs +63 -0
- package/src/rust/utils/mod.rs +32 -0
- package/src/rust/utils/serde.rs +46 -0
- package/src/rust/utils/trace_allocator.rs +98 -0
- package/src/rust/view.rs +355 -0
- package/src/ts/perspective-server.worker.ts +54 -0
- package/src/ts/perspective.browser.ts +132 -0
- package/src/ts/perspective.cdn.ts +22 -0
- package/src/ts/perspective.inline.ts +27 -0
- package/src/ts/perspective.node.ts +315 -0
- package/src/ts/ts-rs/Aggregate.ts +3 -0
- package/src/ts/ts-rs/ColumnWindow.ts +3 -0
- package/src/ts/ts-rs/DeleteOptions.ts +6 -0
- package/src/ts/ts-rs/Expressions.ts +3 -0
- package/src/ts/ts-rs/Filter.ts +4 -0
- package/src/ts/ts-rs/FilterReducer.ts +3 -0
- package/src/ts/ts-rs/FilterTerm.ts +4 -0
- package/src/ts/ts-rs/OnUpdateData.ts +8 -0
- package/src/ts/ts-rs/OnUpdateMode.ts +11 -0
- package/src/ts/ts-rs/OnUpdateOptions.ts +7 -0
- package/src/ts/ts-rs/Scalar.ts +7 -0
- package/src/ts/ts-rs/Sort.ts +4 -0
- package/src/ts/ts-rs/SortDir.ts +3 -0
- package/src/ts/ts-rs/SystemInfo.ts +41 -0
- package/src/ts/ts-rs/TableInitOptions.ts +21 -0
- package/src/ts/ts-rs/TableReadFormat.ts +9 -0
- package/src/ts/ts-rs/UpdateOptions.ts +7 -0
- package/src/ts/ts-rs/ViewConfigUpdate.ts +87 -0
- package/src/ts/ts-rs/ViewOnUpdateResp.ts +3 -0
- package/src/ts/ts-rs/ViewWindow.ts +17 -0
- package/src/ts/wasm/browser.ts +123 -0
- package/src/ts/wasm/decompress.ts +64 -0
- package/src/ts/wasm/emscripten_api.ts +63 -0
- package/src/ts/wasm/engine.ts +271 -0
- package/src/ts/wasm/perspective-server.poly.ts +244 -0
- package/src/ts/websocket.ts +95 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
//! A JSON generating macro which mirrors the format's classic syntax in Rust
|
|
14
|
+
//! via an incremental TT munching macro. This code was stolen from the
|
|
15
|
+
//! `serde-json` crate (licensed under Apache 2.0), and modified to create
|
|
16
|
+
//! `js_sys::*` types directly instead of serde types. Thanks `serde-json`!
|
|
17
|
+
//!
|
|
18
|
+
//! License: https://github.com/serde-rs/json/blob/master/LICENSE-APACHE
|
|
19
|
+
//! Repo: https://github.com/serde-rs/json
|
|
20
|
+
|
|
21
|
+
#[macro_export]
|
|
22
|
+
#[doc(hidden)]
|
|
23
|
+
macro_rules! json {
|
|
24
|
+
// Hide distracting implementation details from the generated rustdoc.
|
|
25
|
+
($($json:tt)+) => {
|
|
26
|
+
$crate::json_internal!($($json)+)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#[macro_export]
|
|
31
|
+
#[doc(hidden)]
|
|
32
|
+
macro_rules! json_internal {
|
|
33
|
+
|
|
34
|
+
// TT muncher for parsing the inside of an array [...]. Produces a vec![...]
|
|
35
|
+
// of the elements.
|
|
36
|
+
//
|
|
37
|
+
// Must be invoked as: json_internal!(@array [] $($tt)*)
|
|
38
|
+
|
|
39
|
+
// Done with trailing comma.
|
|
40
|
+
(@array [$($elems:expr,)*]) => {
|
|
41
|
+
vec![$($elems,)*]
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Done without trailing comma.
|
|
45
|
+
(@array [$($elems:expr),*]) => {
|
|
46
|
+
vec![$($elems),*]
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Next element is `null`.
|
|
50
|
+
(@array [$($elems:expr,)*] null $($rest:tt)*) => {
|
|
51
|
+
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!(null)] $($rest)*)
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Next element is `true`.
|
|
55
|
+
(@array [$($elems:expr,)*] true $($rest:tt)*) => {
|
|
56
|
+
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!(true)] $($rest)*)
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Next element is `false`.
|
|
60
|
+
(@array [$($elems:expr,)*] false $($rest:tt)*) => {
|
|
61
|
+
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!(false)] $($rest)*)
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Next element is an array.
|
|
65
|
+
(@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
|
|
66
|
+
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!([$($array)*])] $($rest)*)
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Next element is a map.
|
|
70
|
+
(@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
|
|
71
|
+
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!({$($map)*})] $($rest)*)
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Next element is an expression followed by comma.
|
|
75
|
+
(@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
|
|
76
|
+
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!($next),] $($rest)*)
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Last element is an expression with no trailing comma.
|
|
80
|
+
(@array [$($elems:expr,)*] $last:expr) => {
|
|
81
|
+
$crate::json_internal!(@array [$($elems,)* $crate::json_internal!($last)])
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Comma after the most recent element.
|
|
85
|
+
(@array [$($elems:expr),*] , $($rest:tt)*) => {
|
|
86
|
+
$crate::json_internal!(@array [$($elems,)*] $($rest)*)
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Unexpected token after most recent element.
|
|
90
|
+
(@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
|
|
91
|
+
$crate::json_unexpected!($unexpected)
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
//////////////////////////////////////////////////////////////////////////
|
|
95
|
+
// TT muncher for parsing the inside of an object {...}. Each entry is
|
|
96
|
+
// inserted into the given map variable.
|
|
97
|
+
//
|
|
98
|
+
// Must be invoked as: json_internal!(@object $map () ($($tt)*) ($($tt)*))
|
|
99
|
+
//
|
|
100
|
+
// We require two copies of the input tokens so that we can match on one
|
|
101
|
+
// copy and trigger errors on the other copy.
|
|
102
|
+
//////////////////////////////////////////////////////////////////////////
|
|
103
|
+
|
|
104
|
+
// Done.
|
|
105
|
+
(@object $object:ident () () ()) => {};
|
|
106
|
+
|
|
107
|
+
// Insert the current entry followed by trailing comma.
|
|
108
|
+
(@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
|
|
109
|
+
let k = js_intern::js_intern!($($key)+);
|
|
110
|
+
js_sys::Reflect::set(&$object, k, &$value).unwrap();
|
|
111
|
+
$crate::json_internal!(@object $object () ($($rest)*) ($($rest)*));
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Current entry followed by unexpected token.
|
|
115
|
+
(@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
|
|
116
|
+
$crate::json_unexpected!($unexpected);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Insert the last entry without trailing comma.
|
|
120
|
+
(@object $object:ident [$($key:tt)+] ($value:expr)) => {
|
|
121
|
+
let k = js_intern::js_intern!($($key)+);
|
|
122
|
+
js_sys::Reflect::set(&$object, k, &$value).unwrap();
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Next value is `null`.
|
|
126
|
+
(@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
|
|
127
|
+
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!(null)) $($rest)*);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// Next value is `true`.
|
|
131
|
+
(@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
|
|
132
|
+
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!(true)) $($rest)*);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Next value is `false`.
|
|
136
|
+
(@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
|
|
137
|
+
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!(false)) $($rest)*);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Next value is an array.
|
|
141
|
+
(@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
|
|
142
|
+
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!([$($array)*])) $($rest)*);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// Next value is a map.
|
|
146
|
+
(@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
|
|
147
|
+
$crate::json_internal!(@object $object [$($key)+] (JsValue::from($crate::json_internal!({$($map)*}))) $($rest)*);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Next value is an expression followed by comma.
|
|
151
|
+
(@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
|
|
152
|
+
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!($value)) , $($rest)*);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Last value is an expression with no trailing comma.
|
|
156
|
+
(@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
|
|
157
|
+
$crate::json_internal!(@object $object [$($key)+] ($crate::json_internal!($value)));
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Missing value for last entry. Trigger a reasonable error message.
|
|
161
|
+
(@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
|
|
162
|
+
// "unexpected end of macro invocation"
|
|
163
|
+
$crate::json_internal!();
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Missing colon and value for last entry. Trigger a reasonable error
|
|
167
|
+
// message.
|
|
168
|
+
(@object $object:ident ($($key:tt)+) () $copy:tt) => {
|
|
169
|
+
// "unexpected end of macro invocation"
|
|
170
|
+
$crate::json_internal!();
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Misplaced colon. Trigger a reasonable error message.
|
|
174
|
+
(@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
|
|
175
|
+
// Takes no arguments so "no rules expected the token `:`".
|
|
176
|
+
$crate::json_unexpected!($colon);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Found a comma inside a key. Trigger a reasonable error message.
|
|
180
|
+
(@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
|
|
181
|
+
// Takes no arguments so "no rules expected the token `,`".
|
|
182
|
+
$crate::json_unexpected!($comma);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Key is fully parenthesized. This avoids clippy double_parens false
|
|
186
|
+
// positives because the parenthesization may be necessary here.
|
|
187
|
+
(@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
|
|
188
|
+
$crate::json_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Refuse to absorb colon token into key expression.
|
|
192
|
+
(@object $object:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
|
|
193
|
+
$crate::json_expect_expr_comma!($($unexpected)+);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Munch a token into the current key.
|
|
197
|
+
(@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
|
|
198
|
+
$crate::json_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// The main implementation.
|
|
202
|
+
//
|
|
203
|
+
// Must be invoked as: json_internal!($($json)+)
|
|
204
|
+
|
|
205
|
+
(null) => {
|
|
206
|
+
$crate::Value::Null
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
(true) => {
|
|
210
|
+
::wasm_bindgen::JsValue::from(true)
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
(false) => {
|
|
214
|
+
::wasm_bindgen::JsValue::from(false)
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
([]) => {
|
|
218
|
+
js_sys::Array::new()
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
([ $($tt:tt)+ ]) => {
|
|
222
|
+
$crate::json_internal!(@array [] $($tt)+).iter().collect::<js_sys::Array>()
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
({}) => {
|
|
226
|
+
js_sys::Object::new()
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
({ $($tt:tt)+ }) => {{
|
|
230
|
+
let object = js_sys::Object::new();
|
|
231
|
+
$crate::json_internal!(@object object () ($($tt)+) ($($tt)+));
|
|
232
|
+
object
|
|
233
|
+
}};
|
|
234
|
+
|
|
235
|
+
// Any Serialize type: numbers, strings, struct literals, variables etc.
|
|
236
|
+
// Must be below every other rule.
|
|
237
|
+
($other:expr) => {
|
|
238
|
+
::wasm_bindgen::JsValue::from($other)
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
#[macro_export]
|
|
243
|
+
#[doc(hidden)]
|
|
244
|
+
macro_rules! json_unexpected {
|
|
245
|
+
() => {};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
#[macro_export]
|
|
249
|
+
#[doc(hidden)]
|
|
250
|
+
macro_rules! json_expect_expr_comma {
|
|
251
|
+
($e:expr, $($tt:tt)*) => {};
|
|
252
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
use futures::channel::mpsc::{UnboundedSender, unbounded};
|
|
14
|
+
use futures::{Future, SinkExt, StreamExt};
|
|
15
|
+
use wasm_bindgen::JsValue;
|
|
16
|
+
use wasm_bindgen_futures::spawn_local;
|
|
17
|
+
|
|
18
|
+
/// A useful abstraction for connecting `!Sync + !Send` callbacks (like
|
|
19
|
+
/// `js_sys::Function`) to `Send + Sync` contexts (like the client loop).
|
|
20
|
+
#[derive(Clone)]
|
|
21
|
+
pub struct LocalPollLoop<R: Send + Sync + 'static>(UnboundedSender<R>);
|
|
22
|
+
|
|
23
|
+
impl<R: Send + Sync + 'static> LocalPollLoop<R> {
|
|
24
|
+
/// Create a new loop which accepts a `R: Send + Sync` intermediate state
|
|
25
|
+
/// argument and calls the `!Send + !Sync` callback.
|
|
26
|
+
pub fn new<F: Fn(R) -> Result<JsValue, JsValue> + 'static>(send: F) -> Self {
|
|
27
|
+
let (emit, mut receive) = unbounded::<R>();
|
|
28
|
+
spawn_local(async move {
|
|
29
|
+
while let Some(resp) = receive.next().await {
|
|
30
|
+
let resp = send(resp);
|
|
31
|
+
if let Err(err) = resp {
|
|
32
|
+
web_sys::console::error_2(&"Failed to serialize".into(), &err);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
Self(emit)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Create a new loop which accepts a `R: Send + Sync` intermediate state
|
|
41
|
+
/// argument and calls the `!Send + !Sync` callback.
|
|
42
|
+
pub fn new_async<F: Fn(R) -> FUT + 'static, FUT: Future<Output = Result<JsValue, JsValue>>>(
|
|
43
|
+
send: F,
|
|
44
|
+
) -> Self {
|
|
45
|
+
let (emit, mut receive) = unbounded::<R>();
|
|
46
|
+
spawn_local(async move {
|
|
47
|
+
while let Some(resp) = receive.next().await {
|
|
48
|
+
let resp = send(resp).await;
|
|
49
|
+
if let Err(err) = resp {
|
|
50
|
+
web_sys::console::error_2(&"Failed to serialize".into(), &err);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
Self(emit)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Send a new `R` to the poll loop.
|
|
59
|
+
pub fn poll(&self, msg: R) -> impl Future<Output = ()> + Send + Sync + 'static + use<R> {
|
|
60
|
+
let mut emit = self.0.clone();
|
|
61
|
+
async move { emit.send(msg).await.unwrap() }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
#![doc(hidden)]
|
|
14
|
+
|
|
15
|
+
mod browser;
|
|
16
|
+
mod console_logger;
|
|
17
|
+
pub mod errors;
|
|
18
|
+
mod futures;
|
|
19
|
+
mod json;
|
|
20
|
+
mod local_poll_loop;
|
|
21
|
+
mod serde;
|
|
22
|
+
#[cfg(feature = "trace-allocator")]
|
|
23
|
+
mod trace_allocator;
|
|
24
|
+
|
|
25
|
+
pub use browser::*;
|
|
26
|
+
pub use console_logger::*;
|
|
27
|
+
pub use errors::*;
|
|
28
|
+
pub use futures::*;
|
|
29
|
+
pub use local_poll_loop::*;
|
|
30
|
+
pub use serde::*;
|
|
31
|
+
#[cfg(feature = "trace-allocator")]
|
|
32
|
+
pub(crate) use trace_allocator::get_used;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
use wasm_bindgen::JsValue;
|
|
14
|
+
|
|
15
|
+
pub trait JsValueSerdeExt {
|
|
16
|
+
fn from_serde_ext<T>(t: &T) -> Result<JsValue, serde_wasm_bindgen::Error>
|
|
17
|
+
where
|
|
18
|
+
T: serde::ser::Serialize + ?Sized;
|
|
19
|
+
|
|
20
|
+
fn into_serde_ext<T>(self) -> Result<T, serde_wasm_bindgen::Error>
|
|
21
|
+
where
|
|
22
|
+
T: for<'a> serde::de::Deserialize<'a>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
impl<U> JsValueSerdeExt for U
|
|
26
|
+
where
|
|
27
|
+
U: Into<JsValue>,
|
|
28
|
+
{
|
|
29
|
+
fn from_serde_ext<T>(t: &T) -> Result<JsValue, serde_wasm_bindgen::Error>
|
|
30
|
+
where
|
|
31
|
+
T: serde::ser::Serialize + ?Sized,
|
|
32
|
+
{
|
|
33
|
+
t.serialize(
|
|
34
|
+
&serde_wasm_bindgen::Serializer::new()
|
|
35
|
+
.serialize_maps_as_objects(true)
|
|
36
|
+
.serialize_missing_as_null(true),
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn into_serde_ext<T>(self) -> Result<T, serde_wasm_bindgen::Error>
|
|
41
|
+
where
|
|
42
|
+
T: for<'a> serde::de::Deserialize<'a>,
|
|
43
|
+
{
|
|
44
|
+
serde_wasm_bindgen::from_value(self.into())
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
//! A wrapper around the default allocator which counts allocations, useful for
|
|
14
|
+
//! instrumenting the `Client` as an alternative to switching to `talc`.
|
|
15
|
+
//!
|
|
16
|
+
//! Lifted from https://stackoverflow.com/questions/78246635/how-do-i-log-wasm-heap-memory-usage-from-rust
|
|
17
|
+
//! or as its popular to refer to these days, "AI".
|
|
18
|
+
|
|
19
|
+
use std::alloc::{GlobalAlloc, Layout, System};
|
|
20
|
+
use std::sync::atomic::{AtomicIsize, Ordering};
|
|
21
|
+
|
|
22
|
+
use wasm_bindgen::JsCast;
|
|
23
|
+
use wasm_bindgen::prelude::wasm_bindgen;
|
|
24
|
+
|
|
25
|
+
#[wasm_bindgen]
|
|
26
|
+
extern "C" {
|
|
27
|
+
type Memory;
|
|
28
|
+
#[wasm_bindgen(method, getter)]
|
|
29
|
+
fn buffer(this: &Memory) -> MaybeSharedArrayBuffer;
|
|
30
|
+
|
|
31
|
+
type MaybeSharedArrayBuffer;
|
|
32
|
+
#[wasm_bindgen(method, getter = byteLength)]
|
|
33
|
+
fn byte_length(this: &MaybeSharedArrayBuffer) -> f64;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
struct CountingAllocator<A> {
|
|
37
|
+
inner: A,
|
|
38
|
+
allocated_now: AtomicIsize,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
impl<A> CountingAllocator<A> {
|
|
42
|
+
const fn new(inner: A) -> Self {
|
|
43
|
+
Self {
|
|
44
|
+
inner,
|
|
45
|
+
allocated_now: AtomicIsize::new(0),
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fn allocated_now(&self) -> usize {
|
|
50
|
+
self.allocated_now
|
|
51
|
+
.load(Ordering::Relaxed)
|
|
52
|
+
.try_into()
|
|
53
|
+
.unwrap_or(0)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
unsafe impl<A: GlobalAlloc> GlobalAlloc for CountingAllocator<A> {
|
|
58
|
+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
|
59
|
+
self.allocated_now
|
|
60
|
+
.fetch_add(layout.size() as isize, Ordering::Relaxed);
|
|
61
|
+
unsafe { self.inner.alloc(layout) }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
|
65
|
+
self.allocated_now
|
|
66
|
+
.fetch_sub(layout.size() as isize, Ordering::Relaxed);
|
|
67
|
+
unsafe { self.inner.dealloc(ptr, layout) };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
|
71
|
+
self.allocated_now
|
|
72
|
+
.fetch_add(layout.size() as isize, Ordering::Relaxed);
|
|
73
|
+
unsafe { self.inner.alloc_zeroed(layout) }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
|
77
|
+
self.allocated_now.fetch_add(
|
|
78
|
+
new_size as isize - layout.size() as isize,
|
|
79
|
+
Ordering::Relaxed,
|
|
80
|
+
);
|
|
81
|
+
unsafe { self.inner.realloc(ptr, layout, new_size) }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#[global_allocator]
|
|
86
|
+
static ALLOCATOR: CountingAllocator<System> = CountingAllocator::new(System);
|
|
87
|
+
|
|
88
|
+
pub(crate) fn get_used() -> (usize, usize) {
|
|
89
|
+
let client_heap = wasm_bindgen::memory()
|
|
90
|
+
.unchecked_into::<Memory>()
|
|
91
|
+
.buffer()
|
|
92
|
+
.byte_length() as u64;
|
|
93
|
+
|
|
94
|
+
(ALLOCATOR.allocated_now(), client_heap as usize)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
#[cfg(all(feature = "talc-allocator", feature = "trace-allocator"))]
|
|
98
|
+
compile_error!("Cannot enable both `talc-allocator` and `trace-allocator` features");
|