rusteerio 1.1.3 → 1.1.4
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/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/native/src/snapshot.rs +153 -45
- package/package.json +1 -1
- package/rusteerio.darwin-arm64.node +0 -0
- package/rusteerio.darwin-x64.node +0 -0
- package/rusteerio.linux-arm64-gnu.node +0 -0
- package/rusteerio.linux-arm64-musl.node +0 -0
- package/rusteerio.linux-x64-gnu.node +0 -0
- package/rusteerio.linux-x64-musl.node +0 -0
- package/rusteerio.win32-arm64-msvc.node +0 -0
- package/rusteerio.win32-x64-msvc.node +0 -0
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -4,7 +4,7 @@ This file preserves third-party license and attribution notices for the Rust nat
|
|
|
4
4
|
|
|
5
5
|
Generated by `node scripts/generate-notices.mjs` from `cargo metadata --locked`, crate license files, and the pinned supplemental sources recorded in `scripts/notices/sources.json`. It includes build dependencies and dependencies for all target platforms; a particular binary may use a subset. Identical notice texts are reproduced once and referenced below. The html5ever, markup5ever and html5gum crates contain local observer-hook and opt-in UTF-16 transport patches; their complete patched source and original notices are included in `native/vendor`. Other dependency source files are unmodified.
|
|
6
6
|
|
|
7
|
-
Cargo.lock SHA-256: `
|
|
7
|
+
Cargo.lock SHA-256: `a2ff4645db9ecfd1110ed1ae3af80a43ffaf87ab3c192ce24bee23065684331c`.
|
|
8
8
|
|
|
9
9
|
## Source availability
|
|
10
10
|
|
package/native/src/snapshot.rs
CHANGED
|
@@ -49,41 +49,128 @@ const KINDS: [&str; 8] = [
|
|
|
49
49
|
const SHORT_NAME_SLOTS: usize = 256;
|
|
50
50
|
|
|
51
51
|
pub(crate) struct NodeSnapshot {
|
|
52
|
+
/// Consecutive ranges of nodes, encoded separately (in parallel for
|
|
53
|
+
/// large trees) with references local to each chunk.
|
|
54
|
+
chunks: Vec<Chunk>,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
struct Chunk {
|
|
52
58
|
is_encoded: bool,
|
|
53
59
|
nodes: Vec<u32>,
|
|
54
60
|
children: Vec<u32>,
|
|
55
61
|
attributes: Vec<u32>,
|
|
56
62
|
strings: Vec<u32>,
|
|
57
63
|
text: String,
|
|
64
|
+
units: u32,
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
impl NodeSnapshot {
|
|
61
68
|
pub(crate) fn into_js(self, env: &Env) -> Result<JsObject> {
|
|
62
|
-
let
|
|
63
|
-
let lengths =
|
|
69
|
+
let total = |part: fn(&Chunk) -> usize| self.chunks.iter().map(part).sum::<usize>();
|
|
70
|
+
let lengths = [
|
|
71
|
+
total(|chunk| chunk.nodes.len()),
|
|
72
|
+
total(|chunk| chunk.children.len()),
|
|
73
|
+
total(|chunk| chunk.attributes.len()),
|
|
74
|
+
total(|chunk| chunk.strings.len()),
|
|
75
|
+
];
|
|
64
76
|
let header = [
|
|
65
|
-
lengths[0],
|
|
66
|
-
lengths[1],
|
|
67
|
-
lengths[2],
|
|
68
|
-
lengths[3],
|
|
69
|
-
u32::from(self.is_encoded),
|
|
77
|
+
lengths[0] as u32,
|
|
78
|
+
lengths[1] as u32,
|
|
79
|
+
lengths[2] as u32,
|
|
80
|
+
lengths[3] as u32,
|
|
81
|
+
u32::from(self.chunks.iter().any(|chunk| chunk.is_encoded)),
|
|
70
82
|
];
|
|
71
|
-
let length = header.len() +
|
|
83
|
+
let length = header.len() + lengths.iter().sum::<usize>();
|
|
72
84
|
let data = uninitialized_words(env, length, |words| {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
85
|
+
words[..header.len()].copy_from_slice(&header);
|
|
86
|
+
let (nodes, rest) = words[header.len()..].split_at_mut(lengths[0]);
|
|
87
|
+
let (children, rest) = rest.split_at_mut(lengths[1]);
|
|
88
|
+
let (attributes, strings) = rest.split_at_mut(lengths[2]);
|
|
89
|
+
let mut bases = Bases::default();
|
|
90
|
+
for chunk in &self.chunks {
|
|
91
|
+
bases.copy(chunk, nodes, children, attributes, strings);
|
|
78
92
|
}
|
|
79
93
|
})?;
|
|
94
|
+
let text = if self.chunks.len() == 1 {
|
|
95
|
+
crate::codec::js_string(env, &self.chunks[0].text)?
|
|
96
|
+
} else {
|
|
97
|
+
let mut text =
|
|
98
|
+
String::with_capacity(self.chunks.iter().map(|chunk| chunk.text.len()).sum());
|
|
99
|
+
for chunk in &self.chunks {
|
|
100
|
+
text.push_str(&chunk.text);
|
|
101
|
+
}
|
|
102
|
+
crate::codec::js_string(env, &text)?
|
|
103
|
+
};
|
|
80
104
|
let mut object = env.create_object()?;
|
|
81
105
|
object.set_named_property("data", data)?;
|
|
82
|
-
object.set_named_property("text",
|
|
106
|
+
object.set_named_property("text", text)?;
|
|
83
107
|
Ok(object)
|
|
84
108
|
}
|
|
85
109
|
}
|
|
86
110
|
|
|
111
|
+
/// Where the next chunk's entries start in each combined list.
|
|
112
|
+
#[derive(Default)]
|
|
113
|
+
struct Bases {
|
|
114
|
+
nodes: usize,
|
|
115
|
+
children: usize,
|
|
116
|
+
attributes: usize,
|
|
117
|
+
strings: usize,
|
|
118
|
+
units: u32,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
impl Bases {
|
|
122
|
+
/// Copies `chunk` after the chunks before it, shifting its references to
|
|
123
|
+
/// children, attribute pairs, strings and text by theirs.
|
|
124
|
+
fn copy(
|
|
125
|
+
&mut self,
|
|
126
|
+
chunk: &Chunk,
|
|
127
|
+
nodes: &mut [u32],
|
|
128
|
+
children: &mut [u32],
|
|
129
|
+
attributes: &mut [u32],
|
|
130
|
+
strings: &mut [u32],
|
|
131
|
+
) {
|
|
132
|
+
let string_base = (self.strings / 2) as u32;
|
|
133
|
+
let child_base = self.children as u32;
|
|
134
|
+
let pair_base = (self.attributes / 2) as u32;
|
|
135
|
+
let target = &mut nodes[self.nodes..self.nodes + chunk.nodes.len()];
|
|
136
|
+
target.copy_from_slice(&chunk.nodes);
|
|
137
|
+
if self.nodes != 0 {
|
|
138
|
+
for fields in target.as_chunks_mut::<STRIDE>().0 {
|
|
139
|
+
let flags = fields[10];
|
|
140
|
+
if flags & RELEASED != 0 {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
fields[0] += string_base;
|
|
144
|
+
fields[4] += child_base;
|
|
145
|
+
fields[8] += pair_base;
|
|
146
|
+
for field in [6, 7, 14] {
|
|
147
|
+
if fields[field] != 0 {
|
|
148
|
+
fields[field] += string_base;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if flags & HAS_NAMESPACE != 0 {
|
|
152
|
+
fields[13] += string_base;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
children[self.children..self.children + chunk.children.len()]
|
|
157
|
+
.copy_from_slice(&chunk.children);
|
|
158
|
+
let target = &mut attributes[self.attributes..self.attributes + chunk.attributes.len()];
|
|
159
|
+
for (slot, reference) in target.iter_mut().zip(&chunk.attributes) {
|
|
160
|
+
*slot = reference + string_base;
|
|
161
|
+
}
|
|
162
|
+
let target = &mut strings[self.strings..self.strings + chunk.strings.len()];
|
|
163
|
+
for (slot, offset) in target.iter_mut().zip(&chunk.strings) {
|
|
164
|
+
*slot = offset + self.units;
|
|
165
|
+
}
|
|
166
|
+
self.nodes += chunk.nodes.len();
|
|
167
|
+
self.children += chunk.children.len();
|
|
168
|
+
self.attributes += chunk.attributes.len();
|
|
169
|
+
self.strings += chunk.strings.len();
|
|
170
|
+
self.units += chunk.units;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
87
174
|
/// A `Uint32Array` of `length` words that `fill` writes. A Node buffer is
|
|
88
175
|
/// used for its storage because, unlike an `ArrayBuffer`, it is not
|
|
89
176
|
/// zero-filled first; `fill` writes every word before JavaScript can read it.
|
|
@@ -167,43 +254,34 @@ struct Builder {
|
|
|
167
254
|
is_encoded: bool,
|
|
168
255
|
}
|
|
169
256
|
|
|
257
|
+
/// Nodes per chunk worth encoding on another thread.
|
|
258
|
+
const PARALLEL_CHUNK_NODES: usize = 8192;
|
|
259
|
+
|
|
170
260
|
pub(crate) fn build(document: &NativeDocument) -> NodeSnapshot {
|
|
171
261
|
let codec = document.options.get("__utf16Codec") == Some(&Value::Bool(true))
|
|
172
262
|
|| document.options.get("__losslessUnicode") == Some(&Value::Bool(true));
|
|
173
|
-
let count = document.slot_count() as usize;
|
|
174
|
-
let mut builder = Builder {
|
|
175
|
-
nodes: Vec::with_capacity(count * STRIDE),
|
|
176
|
-
children: Vec::with_capacity(count),
|
|
177
|
-
attributes: Vec::new(),
|
|
178
|
-
strings: Vec::with_capacity(count * 2),
|
|
179
|
-
text: String::with_capacity(document.content_bytes.get()),
|
|
180
|
-
units: 0,
|
|
181
|
-
interned: IdMap::with_capacity_and_hasher(32, Default::default()),
|
|
182
|
-
kinds: [None; KINDS.len()],
|
|
183
|
-
short_names: Box::new([(0, 0, 0); SHORT_NAME_SLOTS]),
|
|
184
|
-
local_names: IdMap::with_capacity_and_hasher(32, Default::default()),
|
|
185
|
-
namespaces: IdMap::default(),
|
|
186
|
-
codec,
|
|
187
|
-
is_encoded: false,
|
|
188
|
-
};
|
|
189
263
|
if let Some(arena) = document.arena.borrow().as_ref() {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
264
|
+
let chunks =
|
|
265
|
+
crate::runtime::chunked_map(arena.nodes.len(), PARALLEL_CHUNK_NODES, |range| {
|
|
266
|
+
let mut builder = Builder::new(range.len(), 0, codec);
|
|
267
|
+
for id in range {
|
|
268
|
+
match arena.node(id as u32) {
|
|
269
|
+
Some(node) => builder.encode(node),
|
|
270
|
+
None => builder.released(),
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
vec![builder.finish()]
|
|
274
|
+
});
|
|
275
|
+
return NodeSnapshot { chunks };
|
|
199
276
|
}
|
|
277
|
+
let mut builder = Builder::new(
|
|
278
|
+
document.slot_count() as usize,
|
|
279
|
+
document.content_bytes.get(),
|
|
280
|
+
codec,
|
|
281
|
+
);
|
|
282
|
+
builder.encode_immutable(document);
|
|
200
283
|
NodeSnapshot {
|
|
201
|
-
|
|
202
|
-
nodes: builder.nodes,
|
|
203
|
-
children: builder.children,
|
|
204
|
-
attributes: builder.attributes,
|
|
205
|
-
strings: builder.strings,
|
|
206
|
-
text: builder.text,
|
|
284
|
+
chunks: vec![builder.finish()],
|
|
207
285
|
}
|
|
208
286
|
}
|
|
209
287
|
|
|
@@ -232,6 +310,36 @@ fn pointer(value: Option<u32>) -> u32 {
|
|
|
232
310
|
}
|
|
233
311
|
|
|
234
312
|
impl Builder {
|
|
313
|
+
fn new(count: usize, text_bytes: usize, codec: bool) -> Self {
|
|
314
|
+
Self {
|
|
315
|
+
nodes: Vec::with_capacity(count * STRIDE),
|
|
316
|
+
children: Vec::with_capacity(count),
|
|
317
|
+
attributes: Vec::new(),
|
|
318
|
+
strings: Vec::with_capacity(count * 2),
|
|
319
|
+
text: String::with_capacity(text_bytes),
|
|
320
|
+
units: 0,
|
|
321
|
+
interned: IdMap::with_capacity_and_hasher(32, Default::default()),
|
|
322
|
+
kinds: [None; KINDS.len()],
|
|
323
|
+
short_names: Box::new([(0, 0, 0); SHORT_NAME_SLOTS]),
|
|
324
|
+
local_names: IdMap::with_capacity_and_hasher(32, Default::default()),
|
|
325
|
+
namespaces: IdMap::default(),
|
|
326
|
+
codec,
|
|
327
|
+
is_encoded: false,
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
fn finish(self) -> Chunk {
|
|
332
|
+
Chunk {
|
|
333
|
+
is_encoded: self.is_encoded,
|
|
334
|
+
nodes: self.nodes,
|
|
335
|
+
children: self.children,
|
|
336
|
+
attributes: self.attributes,
|
|
337
|
+
strings: self.strings,
|
|
338
|
+
text: self.text,
|
|
339
|
+
units: self.units,
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
235
343
|
fn string(&mut self, value: &str) -> u32 {
|
|
236
344
|
let start = self.units;
|
|
237
345
|
self.text.push_str(value);
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|