mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
fix(ext/kv): stricter structured clone serializer (#18914)
This commit is contained in:
parent
93b8c72d89
commit
d9dfffa4c8
3 changed files with 52 additions and 3 deletions
|
@ -123,6 +123,36 @@ dbTest("set and get recursive object", async (db) => {
|
||||||
assert(resultValue.a === resultValue);
|
assert(resultValue.a === resultValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// invalid values (as per structured clone algorithm with _for storage_, NOT JSON)
|
||||||
|
const INVALID_VALUE_CASES = [
|
||||||
|
{ name: "function", value: () => {} },
|
||||||
|
{ name: "symbol", value: Symbol() },
|
||||||
|
{ name: "WeakMap", value: new WeakMap() },
|
||||||
|
{ name: "WeakSet", value: new WeakSet() },
|
||||||
|
{
|
||||||
|
name: "WebAssembly.Module",
|
||||||
|
value: new WebAssembly.Module(
|
||||||
|
new Uint8Array([0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00]),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SharedArrayBuffer",
|
||||||
|
value: new SharedArrayBuffer(3),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const { name, value } of INVALID_VALUE_CASES) {
|
||||||
|
dbTest(`set and get ${name} value (invalid)`, async (db) => {
|
||||||
|
await assertRejects(
|
||||||
|
async () => await db.set(["a"], value),
|
||||||
|
Error,
|
||||||
|
);
|
||||||
|
const res = await db.get(["a"]);
|
||||||
|
assertEquals(res.key, ["a"]);
|
||||||
|
assertEquals(res.value, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const keys = [
|
const keys = [
|
||||||
["a"],
|
["a"],
|
||||||
["a", "b"],
|
["a", "b"],
|
||||||
|
|
|
@ -211,6 +211,7 @@ fn op_decode<'a>(
|
||||||
struct SerializeDeserialize<'a> {
|
struct SerializeDeserialize<'a> {
|
||||||
host_objects: Option<v8::Local<'a, v8::Array>>,
|
host_objects: Option<v8::Local<'a, v8::Array>>,
|
||||||
error_callback: Option<v8::Local<'a, v8::Function>>,
|
error_callback: Option<v8::Local<'a, v8::Function>>,
|
||||||
|
for_storage: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
|
impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
|
||||||
|
@ -238,6 +239,9 @@ impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
|
||||||
scope: &mut v8::HandleScope<'s>,
|
scope: &mut v8::HandleScope<'s>,
|
||||||
shared_array_buffer: v8::Local<'s, v8::SharedArrayBuffer>,
|
shared_array_buffer: v8::Local<'s, v8::SharedArrayBuffer>,
|
||||||
) -> Option<u32> {
|
) -> Option<u32> {
|
||||||
|
if self.for_storage {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let state_rc = JsRuntime::state(scope);
|
let state_rc = JsRuntime::state(scope);
|
||||||
let state = state_rc.borrow_mut();
|
let state = state_rc.borrow_mut();
|
||||||
if let Some(shared_array_buffer_store) = &state.shared_array_buffer_store {
|
if let Some(shared_array_buffer_store) = &state.shared_array_buffer_store {
|
||||||
|
@ -254,6 +258,11 @@ impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
|
||||||
scope: &mut v8::HandleScope<'_>,
|
scope: &mut v8::HandleScope<'_>,
|
||||||
module: v8::Local<v8::WasmModuleObject>,
|
module: v8::Local<v8::WasmModuleObject>,
|
||||||
) -> Option<u32> {
|
) -> Option<u32> {
|
||||||
|
if self.for_storage {
|
||||||
|
let message = v8::String::new(scope, "Wasm modules cannot be stored")?;
|
||||||
|
self.throw_data_clone_error(scope, message);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let state_rc = JsRuntime::state(scope);
|
let state_rc = JsRuntime::state(scope);
|
||||||
let state = state_rc.borrow_mut();
|
let state = state_rc.borrow_mut();
|
||||||
if let Some(compiled_wasm_module_store) = &state.compiled_wasm_module_store
|
if let Some(compiled_wasm_module_store) = &state.compiled_wasm_module_store
|
||||||
|
@ -293,6 +302,9 @@ impl<'a> v8::ValueDeserializerImpl for SerializeDeserialize<'a> {
|
||||||
scope: &mut v8::HandleScope<'s>,
|
scope: &mut v8::HandleScope<'s>,
|
||||||
transfer_id: u32,
|
transfer_id: u32,
|
||||||
) -> Option<v8::Local<'s, v8::SharedArrayBuffer>> {
|
) -> Option<v8::Local<'s, v8::SharedArrayBuffer>> {
|
||||||
|
if self.for_storage {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let state_rc = JsRuntime::state(scope);
|
let state_rc = JsRuntime::state(scope);
|
||||||
let state = state_rc.borrow_mut();
|
let state = state_rc.borrow_mut();
|
||||||
if let Some(shared_array_buffer_store) = &state.shared_array_buffer_store {
|
if let Some(shared_array_buffer_store) = &state.shared_array_buffer_store {
|
||||||
|
@ -310,6 +322,9 @@ impl<'a> v8::ValueDeserializerImpl for SerializeDeserialize<'a> {
|
||||||
scope: &mut v8::HandleScope<'s>,
|
scope: &mut v8::HandleScope<'s>,
|
||||||
clone_id: u32,
|
clone_id: u32,
|
||||||
) -> Option<v8::Local<'s, v8::WasmModuleObject>> {
|
) -> Option<v8::Local<'s, v8::WasmModuleObject>> {
|
||||||
|
if self.for_storage {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let state_rc = JsRuntime::state(scope);
|
let state_rc = JsRuntime::state(scope);
|
||||||
let state = state_rc.borrow_mut();
|
let state = state_rc.borrow_mut();
|
||||||
if let Some(compiled_wasm_module_store) = &state.compiled_wasm_module_store
|
if let Some(compiled_wasm_module_store) = &state.compiled_wasm_module_store
|
||||||
|
@ -337,7 +352,7 @@ impl<'a> v8::ValueDeserializerImpl for SerializeDeserialize<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let message =
|
let message: v8::Local<v8::String> =
|
||||||
v8::String::new(scope, "Failed to deserialize host object").unwrap();
|
v8::String::new(scope, "Failed to deserialize host object").unwrap();
|
||||||
let error = v8::Exception::error(scope, message);
|
let error = v8::Exception::error(scope, message);
|
||||||
scope.throw_exception(error);
|
scope.throw_exception(error);
|
||||||
|
@ -350,6 +365,8 @@ impl<'a> v8::ValueDeserializerImpl for SerializeDeserialize<'a> {
|
||||||
struct SerializeDeserializeOptions<'a> {
|
struct SerializeDeserializeOptions<'a> {
|
||||||
host_objects: Option<serde_v8::Value<'a>>,
|
host_objects: Option<serde_v8::Value<'a>>,
|
||||||
transferred_array_buffers: Option<serde_v8::Value<'a>>,
|
transferred_array_buffers: Option<serde_v8::Value<'a>>,
|
||||||
|
#[serde(default)]
|
||||||
|
for_storage: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op(v8)]
|
#[op(v8)]
|
||||||
|
@ -385,6 +402,7 @@ fn op_serialize(
|
||||||
let serialize_deserialize = Box::new(SerializeDeserialize {
|
let serialize_deserialize = Box::new(SerializeDeserialize {
|
||||||
host_objects,
|
host_objects,
|
||||||
error_callback,
|
error_callback,
|
||||||
|
for_storage: options.for_storage,
|
||||||
});
|
});
|
||||||
let mut value_serializer =
|
let mut value_serializer =
|
||||||
v8::ValueSerializer::new(scope, serialize_deserialize);
|
v8::ValueSerializer::new(scope, serialize_deserialize);
|
||||||
|
@ -464,6 +482,7 @@ fn op_deserialize<'a>(
|
||||||
let serialize_deserialize = Box::new(SerializeDeserialize {
|
let serialize_deserialize = Box::new(SerializeDeserialize {
|
||||||
host_objects,
|
host_objects,
|
||||||
error_callback: None,
|
error_callback: None,
|
||||||
|
for_storage: options.for_storage,
|
||||||
});
|
});
|
||||||
let mut value_deserializer =
|
let mut value_deserializer =
|
||||||
v8::ValueDeserializer::new(scope, serialize_deserialize, &zero_copy);
|
v8::ValueDeserializer::new(scope, serialize_deserialize, &zero_copy);
|
||||||
|
|
|
@ -312,7 +312,7 @@ function deserializeValue(entry: RawKvEntry): Deno.KvEntry<unknown> {
|
||||||
case "v8":
|
case "v8":
|
||||||
return {
|
return {
|
||||||
...entry,
|
...entry,
|
||||||
value: core.deserialize(value),
|
value: core.deserialize(value, { forStorage: true }),
|
||||||
};
|
};
|
||||||
case "bytes":
|
case "bytes":
|
||||||
return {
|
return {
|
||||||
|
@ -343,7 +343,7 @@ function serializeValue(value: unknown): RawValue {
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
kind: "v8",
|
kind: "v8",
|
||||||
value: core.serialize(value),
|
value: core.serialize(value, { forStorage: true }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue