mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
style: 修 rustfmt 格式化差异
This commit is contained in:
@@ -467,11 +467,7 @@ pub fn shared_array_buffer_max_byte_length<H: VmHost>(vm: &mut H, args: &[u8]) -
|
|||||||
let payload_ptr = native_try!(shared_array_buffer_payload(vm, this_val));
|
let payload_ptr = native_try!(shared_array_buffer_payload(vm, this_val));
|
||||||
// SAFETY: payload_ptr 经 shared_array_buffer_payload 校验为合法 SAB 载荷。
|
// SAFETY: payload_ptr 经 shared_array_buffer_payload 校验为合法 SAB 载荷。
|
||||||
let payload = unsafe { &*payload_ptr };
|
let payload = unsafe { &*payload_ptr };
|
||||||
let value = if payload.growable {
|
let value = if payload.growable { payload.buffer.max_len() } else { payload.buffer.len() };
|
||||||
payload.buffer.max_len()
|
|
||||||
} else {
|
|
||||||
payload.buffer.len()
|
|
||||||
};
|
|
||||||
NativeResult::Ok(JsValue::int(value as i32))
|
NativeResult::Ok(JsValue::int(value as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ use oxide_types::value::JsValue;
|
|||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
|
|
||||||
use crate::array_buffer::{
|
use crate::array_buffer::{buffer_store, buffer_store_mut_ptr, buffer_store_ptr, BufferStore, BufferStoreMut};
|
||||||
buffer_store, buffer_store_mut_ptr, buffer_store_ptr, BufferStore, BufferStoreMut,
|
|
||||||
};
|
|
||||||
|
|
||||||
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
||||||
|
|
||||||
@@ -116,9 +114,7 @@ fn get_data_view_data<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<DataVi
|
|||||||
/// detach(AB 臂 detached 标志)、auto 视图 offset 超 live、定长视图
|
/// detach(AB 臂 detached 标志)、auto 视图 offset 超 live、定长视图
|
||||||
/// offset + 静态长超 live(含溢出)→ TypeError;通过时返回视图长
|
/// offset + 静态长超 live(含溢出)→ TypeError;通过时返回视图长
|
||||||
/// (auto 视图现算 live − offset,定长视图返静态长)。
|
/// (auto 视图现算 live − offset,定长视图返静态长)。
|
||||||
fn dv_view_bounds<H: VmHost>(
|
fn dv_view_bounds<H: VmHost>(vm: &mut H, store: &BufferStore, view: DataViewData) -> Result<usize, JsValue> {
|
||||||
vm: &mut H, store: &BufferStore, view: DataViewData,
|
|
||||||
) -> Result<usize, JsValue> {
|
|
||||||
if store.is_detached() {
|
if store.is_detached() {
|
||||||
return Err(crate::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
return Err(crate::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,10 +110,7 @@ pub fn drop_message_port_native(obj: &mut JsObject) -> u64 {
|
|||||||
/// - 构造器不占 BuiltinWorld P 字段(绑定层就地填充占位)。
|
/// - 构造器不占 BuiltinWorld P 字段(绑定层就地填充占位)。
|
||||||
pub fn message_channel_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
pub fn message_channel_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||||
if !vm.constructing_native() {
|
if !vm.constructing_native() {
|
||||||
return NativeResult::Err(crate::error::create_type_error(
|
return NativeResult::Err(crate::error::create_type_error(vm, "MessageChannel constructor requires new"));
|
||||||
vm,
|
|
||||||
"MessageChannel constructor requires new",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (a_to_b_tx, b_rx) = message_queue::channel::<MessageValue>();
|
let (a_to_b_tx, b_rx) = message_queue::channel::<MessageValue>();
|
||||||
@@ -135,19 +132,9 @@ pub fn message_channel_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> Nativ
|
|||||||
// SAFETY: a_ptr / b_ptr 是本函数刚 alloc_object 的端口对象,存活且本段无别名。
|
// SAFETY: a_ptr / b_ptr 是本函数刚 alloc_object 的端口对象,存活且本段无别名。
|
||||||
unsafe {
|
unsafe {
|
||||||
let a_obj = &mut *a_ptr;
|
let a_obj = &mut *a_ptr;
|
||||||
let _ = vm.define_data_property(
|
let _ = vm.define_data_property(a_obj, si_onmessage, JsValue::null(), PropAttributes::new(true, false, true));
|
||||||
a_obj,
|
|
||||||
si_onmessage,
|
|
||||||
JsValue::null(),
|
|
||||||
PropAttributes::new(true, false, true),
|
|
||||||
);
|
|
||||||
let b_obj = &mut *b_ptr;
|
let b_obj = &mut *b_ptr;
|
||||||
let _ = vm.define_data_property(
|
let _ = vm.define_data_property(b_obj, si_onmessage, JsValue::null(), PropAttributes::new(true, false, true));
|
||||||
b_obj,
|
|
||||||
si_onmessage,
|
|
||||||
JsValue::null(),
|
|
||||||
PropAttributes::new(true, false, true),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 结果对象:plain 对象(proto = %Object.prototype%),两枚可枚举 port1 / port2。
|
// 结果对象:plain 对象(proto = %Object.prototype%),两枚可枚举 port1 / port2。
|
||||||
@@ -156,27 +143,15 @@ pub fn message_channel_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> Nativ
|
|||||||
// SAFETY: result_ptr 是本函数刚 alloc_object 的对象,存活且本段无别名。
|
// SAFETY: result_ptr 是本函数刚 alloc_object 的对象,存活且本段无别名。
|
||||||
let result_obj = unsafe { &mut *result_ptr };
|
let result_obj = unsafe { &mut *result_ptr };
|
||||||
let si_port1 = vm.perm_intern("port1");
|
let si_port1 = vm.perm_intern("port1");
|
||||||
let _ = vm.define_data_property(
|
let _ = vm.define_data_property(result_obj, si_port1, JsValue::from_js_object(a_ptr), PropAttributes::DEFAULT_DATA);
|
||||||
result_obj,
|
|
||||||
si_port1,
|
|
||||||
JsValue::from_js_object(a_ptr),
|
|
||||||
PropAttributes::DEFAULT_DATA,
|
|
||||||
);
|
|
||||||
let si_port2 = vm.perm_intern("port2");
|
let si_port2 = vm.perm_intern("port2");
|
||||||
let _ = vm.define_data_property(
|
let _ = vm.define_data_property(result_obj, si_port2, JsValue::from_js_object(b_ptr), PropAttributes::DEFAULT_DATA);
|
||||||
result_obj,
|
|
||||||
si_port2,
|
|
||||||
JsValue::from_js_object(b_ptr),
|
|
||||||
PropAttributes::DEFAULT_DATA,
|
|
||||||
);
|
|
||||||
NativeResult::Ok(JsValue::from_js_object(result_ptr))
|
NativeResult::Ok(JsValue::from_js_object(result_ptr))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 建单枚端口对象:空形状对象挂载荷盒,`alloc_object` 入对象表。
|
/// 建单枚端口对象:空形状对象挂载荷盒,`alloc_object` 入对象表。
|
||||||
fn make_port_object<H: VmHost>(
|
fn make_port_object<H: VmHost>(
|
||||||
vm: &mut H,
|
vm: &mut H, proto_val: JsValue, peer: message_queue::Sender<MessageValue>,
|
||||||
proto_val: JsValue,
|
|
||||||
peer: message_queue::Sender<MessageValue>,
|
|
||||||
rx: message_queue::Receiver<MessageValue>,
|
rx: message_queue::Receiver<MessageValue>,
|
||||||
) -> (*mut JsObject, *mut MessagePortInner) {
|
) -> (*mut JsObject, *mut MessagePortInner) {
|
||||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, proto_val);
|
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, proto_val);
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ use oxide_types::private_key::{encode_symbol_key, int_key_value, is_int_key, WEL
|
|||||||
use oxide_types::value::JsValue;
|
use oxide_types::value::JsValue;
|
||||||
|
|
||||||
use crate::array_buffer::{
|
use crate::array_buffer::{
|
||||||
array_buffer_payload_ptr, buffer_store, buffer_store_mut_ptr, buffer_store_ptr,
|
array_buffer_payload_ptr, buffer_store, buffer_store_mut_ptr, buffer_store_ptr, default_array_buffer_proto,
|
||||||
default_array_buffer_proto, new_array_buffer, BufferStore, BufferStoreMut,
|
new_array_buffer, BufferStore, BufferStoreMut, MAX_ARRAY_BUFFER_LENGTH,
|
||||||
MAX_ARRAY_BUFFER_LENGTH,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
||||||
@@ -2806,32 +2805,20 @@ pub fn uint8array_set_from_base64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeR
|
|||||||
};
|
};
|
||||||
let (read, written) = match store {
|
let (read, written) = match store {
|
||||||
BufferStoreMut::Ab(bytes) => {
|
BufferStoreMut::Ab(bytes) => {
|
||||||
native_try!(ta_decode_base64(
|
native_try!(ta_decode_base64(vm, string, options, Some(ta_live_length(view)), &mut |idx, b| {
|
||||||
vm,
|
// 缓冲可被 resize 收缩:目标字节越界时静默不写(live 视图越界语义)。
|
||||||
string,
|
if start + idx < bytes.len() {
|
||||||
options,
|
bytes[start + idx] = b;
|
||||||
Some(ta_live_length(view)),
|
}
|
||||||
&mut |idx, b| {
|
},))
|
||||||
// 缓冲可被 resize 收缩:目标字节越界时静默不写(live 视图越界语义)。
|
|
||||||
if start + idx < bytes.len() {
|
|
||||||
bytes[start + idx] = b;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
BufferStoreMut::Sab(buffer) => {
|
BufferStoreMut::Sab(buffer) => {
|
||||||
native_try!(ta_decode_base64(
|
native_try!(ta_decode_base64(vm, string, options, Some(ta_live_length(view)), &mut |idx, b| {
|
||||||
vm,
|
// 活长可被并发推进:目标字节越界时静默不写(live 视图越界语义)。
|
||||||
string,
|
if start + idx < buffer.len() {
|
||||||
options,
|
let _ = buffer.write_range(start + idx, &[b]);
|
||||||
Some(ta_live_length(view)),
|
}
|
||||||
&mut |idx, b| {
|
},))
|
||||||
// 活长可被并发推进:目标字节越界时静默不写(live 视图越界语义)。
|
|
||||||
if start + idx < buffer.len() {
|
|
||||||
let _ = buffer.write_range(start + idx, &[b]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
NativeResult::Ok(ta_read_written_result(vm, read, written))
|
NativeResult::Ok(ta_read_written_result(vm, read, written))
|
||||||
@@ -2943,8 +2930,8 @@ pub fn uint8array_from_hex<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::sync::Arc;
|
|
||||||
use crate::array_buffer::{ArrayBufferPayload, SharedArrayBufferPayload};
|
use crate::array_buffer::{ArrayBufferPayload, SharedArrayBufferPayload};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn gate(text: &str, length: usize) -> TaIndexGate {
|
fn gate(text: &str, length: usize) -> TaIndexGate {
|
||||||
ta_index_gate_from_text(text, length)
|
ta_index_gate_from_text(text, length)
|
||||||
@@ -2974,10 +2961,7 @@ mod tests {
|
|||||||
obj.type_tag = JsObject::OBJ_TYPE_SHARED_ARRAY_BUFFER;
|
obj.type_tag = JsObject::OBJ_TYPE_SHARED_ARRAY_BUFFER;
|
||||||
let core = oxide_kernel::KernelCore::new(oxide_kernel::KernelConfig::minimal());
|
let core = oxide_kernel::KernelCore::new(oxide_kernel::KernelConfig::minimal());
|
||||||
let buffer = Arc::new(SharedBuffer::new(core, data.unwrap_or_default()));
|
let buffer = Arc::new(SharedBuffer::new(core, data.unwrap_or_default()));
|
||||||
let payload = SharedArrayBufferPayload {
|
let payload = SharedArrayBufferPayload { buffer, growable: false };
|
||||||
buffer,
|
|
||||||
growable: false,
|
|
||||||
};
|
|
||||||
let payload_ptr = Arc::into_raw(Arc::new(payload));
|
let payload_ptr = Arc::into_raw(Arc::new(payload));
|
||||||
// SAFETY: 载荷盒形态与 new_shared_array_buffer 的 native_fn 槽存储一致,测试结束前恰好释放一次。
|
// SAFETY: 载荷盒形态与 new_shared_array_buffer 的 native_fn 槽存储一致,测试结束前恰好释放一次。
|
||||||
obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(payload_ptr as *const ()) }));
|
obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(payload_ptr as *const ()) }));
|
||||||
|
|||||||
@@ -415,10 +415,7 @@ impl BuiltinWorld {
|
|||||||
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
|
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(current.broadcast_channel_proto.clone(), current.broadcast_channel_constructor.clone())
|
||||||
current.broadcast_channel_proto.clone(),
|
|
||||||
current.broadcast_channel_constructor.clone(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 迭代器原型与资源栈原型依赖 Object.prototype(链到其上):object 家族重建时
|
// 迭代器原型与资源栈原型依赖 Object.prototype(链到其上):object 家族重建时
|
||||||
|
|||||||
@@ -198,8 +198,7 @@ impl KernelSession {
|
|||||||
console: gen(BuiltinId::Console) != snap(BuiltinId::Console),
|
console: gen(BuiltinId::Console) != snap(BuiltinId::Console),
|
||||||
message_channel: gen(BuiltinId::MessagePortProto) != snap(BuiltinId::MessagePortProto)
|
message_channel: gen(BuiltinId::MessagePortProto) != snap(BuiltinId::MessagePortProto)
|
||||||
|| gen(BuiltinId::MessageChannelCtor) != snap(BuiltinId::MessageChannelCtor),
|
|| gen(BuiltinId::MessageChannelCtor) != snap(BuiltinId::MessageChannelCtor),
|
||||||
broadcast_channel: gen(BuiltinId::BroadcastChannelProto)
|
broadcast_channel: gen(BuiltinId::BroadcastChannelProto) != snap(BuiltinId::BroadcastChannelProto)
|
||||||
!= snap(BuiltinId::BroadcastChannelProto)
|
|
||||||
|| gen(BuiltinId::BroadcastChannelCtor) != snap(BuiltinId::BroadcastChannelCtor),
|
|| gen(BuiltinId::BroadcastChannelCtor) != snap(BuiltinId::BroadcastChannelCtor),
|
||||||
};
|
};
|
||||||
// wrapper 本体被写不落在任何家族位上(写的是 wrapper 自身而非所属 P
|
// wrapper 本体被写不落在任何家族位上(写的是 wrapper 自身而非所属 P
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ pub fn bind_message_channel(core: &Arc<KernelCore>, session: &KernelSession, glo
|
|||||||
if sh.lookup_position(ctor.shape_id(), si_name).is_none() {
|
if sh.lookup_position(ctor.shape_id(), si_name).is_none() {
|
||||||
let shape = sh.make_shape(ctor.shape_id(), si_name);
|
let shape = sh.make_shape(ctor.shape_id(), si_name);
|
||||||
ctor.set_shape_id(shape);
|
ctor.set_shape_id(shape);
|
||||||
ctor.ensure_hash_props().push(JsValue::perm_string(sf.string_ptr(sf.intern("MessageChannel").0)));
|
ctor.ensure_hash_props()
|
||||||
|
.push(JsValue::perm_string(sf.string_ptr(sf.intern("MessageChannel").0)));
|
||||||
let pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
|
let pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
|
||||||
ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
|
ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
|
||||||
ctor.bump_generation();
|
ctor.bump_generation();
|
||||||
@@ -101,8 +102,16 @@ pub fn bind_message_channel(core: &Arc<KernelCore>, session: &KernelSession, glo
|
|||||||
oxide_builtins::message_channel::message_port_post_message::<crate::vm::Vm> as *const (),
|
oxide_builtins::message_channel::message_port_post_message::<crate::vm::Vm> as *const (),
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
("close", oxide_builtins::message_channel::message_port_close::<crate::vm::Vm> as *const (), 0),
|
(
|
||||||
("start", oxide_builtins::message_channel::message_port_start::<crate::vm::Vm> as *const (), 0),
|
"close",
|
||||||
|
oxide_builtins::message_channel::message_port_close::<crate::vm::Vm> as *const (),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"start",
|
||||||
|
oxide_builtins::message_channel::message_port_start::<crate::vm::Vm> as *const (),
|
||||||
|
0,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,12 +372,6 @@ impl oxide_runtime_api::VmHost for Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn bc_lookup(&self, name: &str) -> Vec<*mut JsObject> {
|
fn bc_lookup(&self, name: &str) -> Vec<*mut JsObject> {
|
||||||
self.realm
|
self.realm.gc.borrow().broadcast_channels.get(name).cloned().unwrap_or_default()
|
||||||
.gc
|
|
||||||
.borrow()
|
|
||||||
.broadcast_channels
|
|
||||||
.get(name)
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -657,10 +657,7 @@ impl Vm {
|
|||||||
///
|
///
|
||||||
/// # 副作用
|
/// # 副作用
|
||||||
/// - 任务体对 `self` 的全部改写(寄存器 / 帧栈 / 对象表 / 异常侧通道)原样保留。
|
/// - 任务体对 `self` 的全部改写(寄存器 / 帧栈 / 对象表 / 异常侧通道)原样保留。
|
||||||
pub fn execute_task(
|
pub fn execute_task(&mut self, task: impl FnOnce(&mut Self) -> Result<JsValue, String>) -> Result<JsValue, String> {
|
||||||
&mut self,
|
|
||||||
task: impl FnOnce(&mut Self) -> Result<JsValue, String>,
|
|
||||||
) -> Result<JsValue, String> {
|
|
||||||
task(self)
|
task(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1081,11 +1078,7 @@ mod tests {
|
|||||||
assert!(!vm.job_queue.is_empty(), "反应应已入队");
|
assert!(!vm.job_queue.is_empty(), "反应应已入队");
|
||||||
vm.drain_microtasks();
|
vm.drain_microtasks();
|
||||||
assert!(vm.job_queue.is_empty(), "drain 后队列应清空");
|
assert!(vm.job_queue.is_empty(), "drain 后队列应清空");
|
||||||
assert_eq!(
|
assert_eq!(global_value(&mut vm, "done"), JsValue::bool(true), "promise 反应应已置 done = true");
|
||||||
global_value(&mut vm, "done"),
|
|
||||||
JsValue::bool(true),
|
|
||||||
"promise 反应应已置 done = true"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -72,10 +72,7 @@ pub struct WorkerHandle {
|
|||||||
/// - 每条 `Message` 经 rehydrate → execute_task → drain_microtasks 处理后,把处理
|
/// - 每条 `Message` 经 rehydrate → execute_task → drain_microtasks 处理后,把处理
|
||||||
/// 值 detach 回 worker → 主线程通道(935.3 的回显语义,935.4 的 onmessage 替换之)。
|
/// 值 detach 回 worker → 主线程通道(935.3 的回显语义,935.4 的 onmessage 替换之)。
|
||||||
fn worker_event_loop(
|
fn worker_event_loop(
|
||||||
core: Arc<KernelCore>,
|
core: Arc<KernelCore>, compiler: Arc<dyn CompilerService>, script: String, rx: Receiver<WorkerMail>,
|
||||||
compiler: Arc<dyn CompilerService>,
|
|
||||||
script: String,
|
|
||||||
rx: Receiver<WorkerMail>,
|
|
||||||
out_tx: Sender<MessageValue>,
|
out_tx: Sender<MessageValue>,
|
||||||
) {
|
) {
|
||||||
let mut vm = Vm::with_kernel_core(core);
|
let mut vm = Vm::with_kernel_core(core);
|
||||||
@@ -164,12 +161,7 @@ impl Vm {
|
|||||||
worker_event_loop(core, compiler, script_owned, rx, out_tx);
|
worker_event_loop(core, compiler, script_owned, rx, out_tx);
|
||||||
});
|
});
|
||||||
|
|
||||||
let worker = WorkerHandle {
|
let worker = WorkerHandle { id, tx, rx_out: out_rx, handle };
|
||||||
id,
|
|
||||||
tx,
|
|
||||||
rx_out: out_rx,
|
|
||||||
handle,
|
|
||||||
};
|
|
||||||
self.worker_registry.insert(id, worker);
|
self.worker_registry.insert(id, worker);
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
@@ -183,10 +175,7 @@ impl Vm {
|
|||||||
/// # 返回值
|
/// # 返回值
|
||||||
/// 投递成功 `Ok(())`,失败 `Err`(含错误描述)。
|
/// 投递成功 `Ok(())`,失败 `Err`(含错误描述)。
|
||||||
pub fn worker_post_message(&mut self, id: u64, msg: MessageValue) -> Result<(), String> {
|
pub fn worker_post_message(&mut self, id: u64, msg: MessageValue) -> Result<(), String> {
|
||||||
let worker = self
|
let worker = self.worker_registry.get_mut(&id).ok_or_else(|| format!("worker {id} 不存在"))?;
|
||||||
.worker_registry
|
|
||||||
.get_mut(&id)
|
|
||||||
.ok_or_else(|| format!("worker {id} 不存在"))?;
|
|
||||||
worker
|
worker
|
||||||
.tx
|
.tx
|
||||||
.send(WorkerMail::Message(msg))
|
.send(WorkerMail::Message(msg))
|
||||||
@@ -212,14 +201,8 @@ impl Vm {
|
|||||||
let _ = worker.tx.send(WorkerMail::Terminate);
|
let _ = worker.tx.send(WorkerMail::Terminate);
|
||||||
}
|
}
|
||||||
// 从注册表移除并 join 线程(句柄 drop 前必须 join)。
|
// 从注册表移除并 join 线程(句柄 drop 前必须 join)。
|
||||||
let worker = self
|
let worker = self.worker_registry.remove(&id).ok_or_else(|| format!("worker {id} 不存在"))?;
|
||||||
.worker_registry
|
worker.handle.join().map_err(|_| format!("worker {id} 线程异常退出"))?;
|
||||||
.remove(&id)
|
|
||||||
.ok_or_else(|| format!("worker {id} 不存在"))?;
|
|
||||||
worker
|
|
||||||
.handle
|
|
||||||
.join()
|
|
||||||
.map_err(|_| format!("worker {id} 线程异常退出"))?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,8 +296,7 @@ mod tests {
|
|||||||
let id = vm.spawn_worker("1 + 1").expect("worker 应派生成功");
|
let id = vm.spawn_worker("1 + 1").expect("worker 应派生成功");
|
||||||
assert_eq!(vm.active_workers(), vec![id], "应有唯一活跃 worker");
|
assert_eq!(vm.active_workers(), vec![id], "应有唯一活跃 worker");
|
||||||
|
|
||||||
vm.worker_post_message(id, MessageValue::Number(42.0))
|
vm.worker_post_message(id, MessageValue::Number(42.0)).expect("投递应成功");
|
||||||
.expect("投递应成功");
|
|
||||||
let messages = poll_until_message(&mut vm, id);
|
let messages = poll_until_message(&mut vm, id);
|
||||||
assert_eq!(messages.len(), 1, "应回显一条消息");
|
assert_eq!(messages.len(), 1, "应回显一条消息");
|
||||||
// 整数值经 number_to_js 归为 Int 表示。
|
// 整数值经 number_to_js 归为 Int 表示。
|
||||||
@@ -329,9 +311,7 @@ mod tests {
|
|||||||
fn worker_script_compile_failure_reports_error() {
|
fn worker_script_compile_failure_reports_error() {
|
||||||
let mut vm = vm_with_compiler();
|
let mut vm = vm_with_compiler();
|
||||||
|
|
||||||
let id = vm
|
let id = vm.spawn_worker("function { 语法错误").expect("worker 应派生成功");
|
||||||
.spawn_worker("function { 语法错误")
|
|
||||||
.expect("worker 应派生成功");
|
|
||||||
let messages = poll_until_message(&mut vm, id);
|
let messages = poll_until_message(&mut vm, id);
|
||||||
assert!(!messages.is_empty(), "编译失败应上报错误串");
|
assert!(!messages.is_empty(), "编译失败应上报错误串");
|
||||||
assert!(messages[0].is_string(), "错误串应为字符串值");
|
assert!(messages[0].is_string(), "错误串应为字符串值");
|
||||||
@@ -348,10 +328,8 @@ mod tests {
|
|||||||
let id_b = vm.spawn_worker("2").expect("worker B 应派生成功");
|
let id_b = vm.spawn_worker("2").expect("worker B 应派生成功");
|
||||||
assert_eq!(vm.active_workers(), vec![id_a, id_b], "应有两个活跃 worker");
|
assert_eq!(vm.active_workers(), vec![id_a, id_b], "应有两个活跃 worker");
|
||||||
|
|
||||||
vm.worker_post_message(id_a, MessageValue::Number(1.0))
|
vm.worker_post_message(id_a, MessageValue::Number(1.0)).expect("投递 A 应成功");
|
||||||
.expect("投递 A 应成功");
|
vm.worker_post_message(id_b, MessageValue::Number(2.0)).expect("投递 B 应成功");
|
||||||
vm.worker_post_message(id_b, MessageValue::Number(2.0))
|
|
||||||
.expect("投递 B 应成功");
|
|
||||||
|
|
||||||
let messages_a = poll_until_message(&mut vm, id_a);
|
let messages_a = poll_until_message(&mut vm, id_a);
|
||||||
assert_eq!(messages_a[0], JsValue::int(1), "A 应回显 1");
|
assert_eq!(messages_a[0], JsValue::int(1), "A 应回显 1");
|
||||||
|
|||||||
Reference in New Issue
Block a user