0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-21 15:04:33 -05:00

Implement the 'Hash' trait for local and global handles (#415)

This commit is contained in:
Bert Belder 2020-07-05 17:28:13 +02:00
parent 2b11a57d47
commit 9684640b48
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
8 changed files with 293 additions and 12 deletions

View file

@ -12,6 +12,7 @@
#include "v8/src/execution/isolate-utils.h"
#include "v8/src/objects/objects-inl.h"
#include "v8/src/objects/objects.h"
#include "v8/src/objects/smi.h"
using namespace support;
@ -621,6 +622,10 @@ long std__shared_ptr__v8__ArrayBuffer__Allocator__use_count(
return ptr.use_count();
}
int v8__Name__GetIdentityHash(const v8::Name& self) {
return ptr_to_local(&self)->GetIdentityHash();
}
const v8::String* v8__String__Empty(v8::Isolate* isolate) {
return local_to_ptr(v8::String::Empty(isolate));
}
@ -1730,6 +1735,17 @@ v8::Isolate* v8__internal__GetIsolateFromHeapObject(const v8::Data& data) {
? reinterpret_cast<v8::Isolate*>(isolate)
: nullptr;
}
int v8__internal__Object__GetHash(const v8::Data& data) {
namespace i = v8::internal;
i::Object object(reinterpret_cast<const i::Address&>(data));
i::Isolate* isolate;
int hash = object.IsHeapObject() && i::GetIsolateFromHeapObject(
object.GetHeapObject(), &isolate)
? object.GetOrCreateHash(isolate).value()
: i::Smi::ToInt(object.GetHash());
assert(hash != 0);
return hash;
}
} // extern "C"

View file

@ -6,12 +6,34 @@ use std::error::Error;
use std::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hash;
use std::hash::Hasher;
use std::mem::transmute;
use std::ops::Deref;
use crate::support::int;
use crate::support::Opaque;
use crate::Local;
extern "C" {
fn v8__Data__EQ(this: *const Data, other: *const Data) -> bool;
fn v8__internal__Object__GetHash(this: *const Data) -> int;
fn v8__Value__SameValue(this: *const Value, other: *const Value) -> bool;
fn v8__Value__StrictEquals(this: *const Value, other: *const Value) -> bool;
}
impl Data {
/// Returns the V8 hash value for this value. The current implementation
/// uses a hidden property to store the identity hash on some object types.
///
/// The return value will never be 0. Also, it is not guaranteed to be
/// unique.
pub fn get_hash(&self) -> int {
unsafe { v8__internal__Object__GetHash(self) }
}
}
macro_rules! impl_deref {
{ $target:ident for $type:ident } => {
impl Deref for $type {
@ -49,14 +71,18 @@ macro_rules! impl_try_from {
macro_rules! impl_eq {
{ for $type:ident } => {
impl<'s> Eq for $type {}
impl Eq for $type {}
};
}
extern "C" {
fn v8__Data__EQ(this: *const Data, other: *const Data) -> bool;
fn v8__Value__SameValue(this: *const Value, other: *const Value) -> bool;
fn v8__Value__StrictEquals(this: *const Value, other: *const Value) -> bool;
macro_rules! impl_hash {
{ for $type:ident } => {
impl Hash for $type {
fn hash<H: Hasher>(&self, state: &mut H) {
self.get_hash().hash(state)
}
}
};
}
macro_rules! impl_partial_eq {
@ -236,6 +262,7 @@ pub struct AccessorSignature(Opaque);
impl_deref! { Data for AccessorSignature }
impl_eq! { for AccessorSignature }
impl_hash! { for AccessorSignature }
impl_partial_eq! { Data for AccessorSignature use identity }
impl_partial_eq! { AccessorSignature for AccessorSignature use identity }
@ -246,6 +273,7 @@ pub struct Context(Opaque);
impl_deref! { Data for Context }
impl_eq! { for Context }
impl_hash! { for Context }
impl_partial_eq! { Data for Context use identity }
impl_partial_eq! { Context for Context use identity }
@ -255,6 +283,7 @@ pub struct Message(Opaque);
impl_deref! { Data for Message }
impl_eq! { for Message }
impl_hash! { for Message }
impl_partial_eq! { Data for Message use identity }
impl_partial_eq! { Message for Message use identity }
@ -264,6 +293,7 @@ pub struct Module(Opaque);
impl_deref! { Data for Module }
impl_eq! { for Module }
impl_hash! { for Module }
impl_partial_eq! { Data for Module use identity }
impl_partial_eq! { Module for Module use identity }
@ -277,6 +307,7 @@ pub struct PrimitiveArray(Opaque);
impl_deref! { Data for PrimitiveArray }
impl_eq! { for PrimitiveArray }
impl_hash! { for PrimitiveArray }
impl_partial_eq! { Data for PrimitiveArray use identity }
impl_partial_eq! { PrimitiveArray for PrimitiveArray use identity }
@ -288,6 +319,7 @@ pub struct Private(Opaque);
impl_deref! { Data for Private }
impl_eq! { for Private }
impl_hash! { for Private }
impl_partial_eq! { Data for Private use identity }
impl_partial_eq! { Private for Private use identity }
@ -298,6 +330,7 @@ pub struct Script(Opaque);
impl_deref! { Data for Script }
impl_eq! { for Script }
impl_hash! { for Script }
impl_partial_eq! { Data for Script use identity }
impl_partial_eq! { Script for Script use identity }
@ -310,6 +343,7 @@ pub struct ScriptOrModule(Opaque);
impl_deref! { Data for ScriptOrModule }
impl_eq! { for ScriptOrModule }
impl_hash! { for ScriptOrModule }
impl_partial_eq! { Data for ScriptOrModule use identity }
impl_partial_eq! { ScriptOrModule for ScriptOrModule use identity }
@ -324,6 +358,7 @@ pub struct Signature(Opaque);
impl_deref! { Data for Signature }
impl_eq! { for Signature }
impl_hash! { for Signature }
impl_partial_eq! { Data for Signature use identity }
impl_partial_eq! { Signature for Signature use identity }
@ -333,6 +368,7 @@ pub struct StackFrame(Opaque);
impl_deref! { Data for StackFrame }
impl_eq! { for StackFrame }
impl_hash! { for StackFrame }
impl_partial_eq! { Data for StackFrame use identity }
impl_partial_eq! { StackFrame for StackFrame use identity }
@ -344,6 +380,7 @@ pub struct StackTrace(Opaque);
impl_deref! { Data for StackTrace }
impl_eq! { for StackTrace }
impl_hash! { for StackTrace }
impl_partial_eq! { Data for StackTrace use identity }
impl_partial_eq! { StackTrace for StackTrace use identity }
@ -355,6 +392,7 @@ impl_deref! { Data for Template }
impl_from! { FunctionTemplate for Template }
impl_from! { ObjectTemplate for Template }
impl_eq! { for Template }
impl_hash! { for Template }
impl_partial_eq! { Data for Template use identity }
impl_partial_eq! { Template for Template use identity }
impl_partial_eq! { FunctionTemplate for Template use identity }
@ -470,6 +508,7 @@ pub struct FunctionTemplate(Opaque);
impl_deref! { Template for FunctionTemplate }
impl_eq! { for FunctionTemplate }
impl_hash! { for FunctionTemplate }
impl_partial_eq! { Data for FunctionTemplate use identity }
impl_partial_eq! { Template for FunctionTemplate use identity }
impl_partial_eq! { FunctionTemplate for FunctionTemplate use identity }
@ -483,6 +522,7 @@ pub struct ObjectTemplate(Opaque);
impl_deref! { Template for ObjectTemplate }
impl_eq! { for ObjectTemplate }
impl_hash! { for ObjectTemplate }
impl_partial_eq! { Data for ObjectTemplate use identity }
impl_partial_eq! { Template for ObjectTemplate use identity }
impl_partial_eq! { ObjectTemplate for ObjectTemplate use identity }
@ -493,6 +533,7 @@ pub struct UnboundModuleScript(Opaque);
impl_deref! { Data for UnboundModuleScript }
impl_eq! { for UnboundModuleScript }
impl_hash! { for UnboundModuleScript }
impl_partial_eq! { Data for UnboundModuleScript use identity }
impl_partial_eq! { UnboundModuleScript for UnboundModuleScript use identity }
@ -502,6 +543,7 @@ pub struct UnboundScript(Opaque);
impl_deref! { Data for UnboundScript }
impl_eq! { for UnboundScript }
impl_hash! { for UnboundScript }
impl_partial_eq! { Data for UnboundScript use identity }
impl_partial_eq! { UnboundScript for UnboundScript use identity }
@ -554,6 +596,7 @@ impl_from! { Integer for Value }
impl_from! { Int32 for Value }
impl_from! { Uint32 for Value }
impl_eq! { for Value }
impl_hash! { for Value }
impl_partial_eq! { Value for Value use same_value_zero }
impl_partial_eq! { External for Value use identity }
impl_partial_eq! { Object for Value use identity }
@ -607,6 +650,7 @@ pub struct External(Opaque);
impl_deref! { Value for External }
impl_try_from! { Value for External if v => v.is_external() }
impl_eq! { for External }
impl_hash! { for External }
impl_partial_eq! { Data for External use identity }
impl_partial_eq! { Value for External use identity }
impl_partial_eq! { External for External use identity }
@ -649,6 +693,7 @@ impl_from! { StringObject for Object }
impl_from! { SymbolObject for Object }
impl_from! { WasmModuleObject for Object }
impl_eq! { for Object }
impl_hash! { for Object }
impl_partial_eq! { Data for Object use identity }
impl_partial_eq! { Value for Object use identity }
impl_partial_eq! { Object for Object use identity }
@ -692,6 +737,7 @@ impl_deref! { Object for Array }
impl_try_from! { Value for Array if v => v.is_array() }
impl_try_from! { Object for Array if v => v.is_array() }
impl_eq! { for Array }
impl_hash! { for Array }
impl_partial_eq! { Data for Array use identity }
impl_partial_eq! { Value for Array use identity }
impl_partial_eq! { Object for Array use identity }
@ -705,6 +751,7 @@ impl_deref! { Object for ArrayBuffer }
impl_try_from! { Value for ArrayBuffer if v => v.is_array_buffer() }
impl_try_from! { Object for ArrayBuffer if v => v.is_array_buffer() }
impl_eq! { for ArrayBuffer }
impl_hash! { for ArrayBuffer }
impl_partial_eq! { Data for ArrayBuffer use identity }
impl_partial_eq! { Value for ArrayBuffer use identity }
impl_partial_eq! { Object for ArrayBuffer use identity }
@ -732,6 +779,7 @@ impl_from! { Uint32Array for ArrayBufferView }
impl_from! { Uint8Array for ArrayBufferView }
impl_from! { Uint8ClampedArray for ArrayBufferView }
impl_eq! { for ArrayBufferView }
impl_hash! { for ArrayBufferView }
impl_partial_eq! { Data for ArrayBufferView use identity }
impl_partial_eq! { Value for ArrayBufferView use identity }
impl_partial_eq! { Object for ArrayBufferView use identity }
@ -759,6 +807,7 @@ impl_try_from! { Value for DataView if v => v.is_data_view() }
impl_try_from! { Object for DataView if v => v.is_data_view() }
impl_try_from! { ArrayBufferView for DataView if v => v.is_data_view() }
impl_eq! { for DataView }
impl_hash! { for DataView }
impl_partial_eq! { Data for DataView use identity }
impl_partial_eq! { Value for DataView use identity }
impl_partial_eq! { Object for DataView use identity }
@ -786,6 +835,7 @@ impl_from! { Uint32Array for TypedArray }
impl_from! { Uint8Array for TypedArray }
impl_from! { Uint8ClampedArray for TypedArray }
impl_eq! { for TypedArray }
impl_hash! { for TypedArray }
impl_partial_eq! { Data for TypedArray use identity }
impl_partial_eq! { Value for TypedArray use identity }
impl_partial_eq! { Object for TypedArray use identity }
@ -813,6 +863,7 @@ impl_try_from! { Object for BigInt64Array if v => v.is_big_int64_array() }
impl_try_from! { ArrayBufferView for BigInt64Array if v => v.is_big_int64_array() }
impl_try_from! { TypedArray for BigInt64Array if v => v.is_big_int64_array() }
impl_eq! { for BigInt64Array }
impl_hash! { for BigInt64Array }
impl_partial_eq! { Data for BigInt64Array use identity }
impl_partial_eq! { Value for BigInt64Array use identity }
impl_partial_eq! { Object for BigInt64Array use identity }
@ -830,6 +881,7 @@ impl_try_from! { Object for BigUint64Array if v => v.is_big_uint64_array() }
impl_try_from! { ArrayBufferView for BigUint64Array if v => v.is_big_uint64_array() }
impl_try_from! { TypedArray for BigUint64Array if v => v.is_big_uint64_array() }
impl_eq! { for BigUint64Array }
impl_hash! { for BigUint64Array }
impl_partial_eq! { Data for BigUint64Array use identity }
impl_partial_eq! { Value for BigUint64Array use identity }
impl_partial_eq! { Object for BigUint64Array use identity }
@ -847,6 +899,7 @@ impl_try_from! { Object for Float32Array if v => v.is_float32_array() }
impl_try_from! { ArrayBufferView for Float32Array if v => v.is_float32_array() }
impl_try_from! { TypedArray for Float32Array if v => v.is_float32_array() }
impl_eq! { for Float32Array }
impl_hash! { for Float32Array }
impl_partial_eq! { Data for Float32Array use identity }
impl_partial_eq! { Value for Float32Array use identity }
impl_partial_eq! { Object for Float32Array use identity }
@ -864,6 +917,7 @@ impl_try_from! { Object for Float64Array if v => v.is_float64_array() }
impl_try_from! { ArrayBufferView for Float64Array if v => v.is_float64_array() }
impl_try_from! { TypedArray for Float64Array if v => v.is_float64_array() }
impl_eq! { for Float64Array }
impl_hash! { for Float64Array }
impl_partial_eq! { Data for Float64Array use identity }
impl_partial_eq! { Value for Float64Array use identity }
impl_partial_eq! { Object for Float64Array use identity }
@ -881,6 +935,7 @@ impl_try_from! { Object for Int16Array if v => v.is_int16_array() }
impl_try_from! { ArrayBufferView for Int16Array if v => v.is_int16_array() }
impl_try_from! { TypedArray for Int16Array if v => v.is_int16_array() }
impl_eq! { for Int16Array }
impl_hash! { for Int16Array }
impl_partial_eq! { Data for Int16Array use identity }
impl_partial_eq! { Value for Int16Array use identity }
impl_partial_eq! { Object for Int16Array use identity }
@ -898,6 +953,7 @@ impl_try_from! { Object for Int32Array if v => v.is_int32_array() }
impl_try_from! { ArrayBufferView for Int32Array if v => v.is_int32_array() }
impl_try_from! { TypedArray for Int32Array if v => v.is_int32_array() }
impl_eq! { for Int32Array }
impl_hash! { for Int32Array }
impl_partial_eq! { Data for Int32Array use identity }
impl_partial_eq! { Value for Int32Array use identity }
impl_partial_eq! { Object for Int32Array use identity }
@ -915,6 +971,7 @@ impl_try_from! { Object for Int8Array if v => v.is_int8_array() }
impl_try_from! { ArrayBufferView for Int8Array if v => v.is_int8_array() }
impl_try_from! { TypedArray for Int8Array if v => v.is_int8_array() }
impl_eq! { for Int8Array }
impl_hash! { for Int8Array }
impl_partial_eq! { Data for Int8Array use identity }
impl_partial_eq! { Value for Int8Array use identity }
impl_partial_eq! { Object for Int8Array use identity }
@ -932,6 +989,7 @@ impl_try_from! { Object for Uint16Array if v => v.is_uint16_array() }
impl_try_from! { ArrayBufferView for Uint16Array if v => v.is_uint16_array() }
impl_try_from! { TypedArray for Uint16Array if v => v.is_uint16_array() }
impl_eq! { for Uint16Array }
impl_hash! { for Uint16Array }
impl_partial_eq! { Data for Uint16Array use identity }
impl_partial_eq! { Value for Uint16Array use identity }
impl_partial_eq! { Object for Uint16Array use identity }
@ -949,6 +1007,7 @@ impl_try_from! { Object for Uint32Array if v => v.is_uint32_array() }
impl_try_from! { ArrayBufferView for Uint32Array if v => v.is_uint32_array() }
impl_try_from! { TypedArray for Uint32Array if v => v.is_uint32_array() }
impl_eq! { for Uint32Array }
impl_hash! { for Uint32Array }
impl_partial_eq! { Data for Uint32Array use identity }
impl_partial_eq! { Value for Uint32Array use identity }
impl_partial_eq! { Object for Uint32Array use identity }
@ -966,6 +1025,7 @@ impl_try_from! { Object for Uint8Array if v => v.is_uint8_array() }
impl_try_from! { ArrayBufferView for Uint8Array if v => v.is_uint8_array() }
impl_try_from! { TypedArray for Uint8Array if v => v.is_uint8_array() }
impl_eq! { for Uint8Array }
impl_hash! { for Uint8Array }
impl_partial_eq! { Data for Uint8Array use identity }
impl_partial_eq! { Value for Uint8Array use identity }
impl_partial_eq! { Object for Uint8Array use identity }
@ -983,6 +1043,7 @@ impl_try_from! { Object for Uint8ClampedArray if v => v.is_uint8_clamped_array()
impl_try_from! { ArrayBufferView for Uint8ClampedArray if v => v.is_uint8_clamped_array() }
impl_try_from! { TypedArray for Uint8ClampedArray if v => v.is_uint8_clamped_array() }
impl_eq! { for Uint8ClampedArray }
impl_hash! { for Uint8ClampedArray }
impl_partial_eq! { Data for Uint8ClampedArray use identity }
impl_partial_eq! { Value for Uint8ClampedArray use identity }
impl_partial_eq! { Object for Uint8ClampedArray use identity }
@ -998,6 +1059,7 @@ impl_deref! { Object for BigIntObject }
impl_try_from! { Value for BigIntObject if v => v.is_big_int_object() }
impl_try_from! { Object for BigIntObject if v => v.is_big_int_object() }
impl_eq! { for BigIntObject }
impl_hash! { for BigIntObject }
impl_partial_eq! { Data for BigIntObject use identity }
impl_partial_eq! { Value for BigIntObject use identity }
impl_partial_eq! { Object for BigIntObject use identity }
@ -1011,6 +1073,7 @@ impl_deref! { Object for BooleanObject }
impl_try_from! { Value for BooleanObject if v => v.is_boolean_object() }
impl_try_from! { Object for BooleanObject if v => v.is_boolean_object() }
impl_eq! { for BooleanObject }
impl_hash! { for BooleanObject }
impl_partial_eq! { Data for BooleanObject use identity }
impl_partial_eq! { Value for BooleanObject use identity }
impl_partial_eq! { Object for BooleanObject use identity }
@ -1024,6 +1087,7 @@ impl_deref! { Object for Date }
impl_try_from! { Value for Date if v => v.is_date() }
impl_try_from! { Object for Date if v => v.is_date() }
impl_eq! { for Date }
impl_hash! { for Date }
impl_partial_eq! { Data for Date use identity }
impl_partial_eq! { Value for Date use identity }
impl_partial_eq! { Object for Date use identity }
@ -1037,6 +1101,7 @@ impl_deref! { Object for Function }
impl_try_from! { Value for Function if v => v.is_function() }
impl_try_from! { Object for Function if v => v.is_function() }
impl_eq! { for Function }
impl_hash! { for Function }
impl_partial_eq! { Data for Function use identity }
impl_partial_eq! { Value for Function use identity }
impl_partial_eq! { Object for Function use identity }
@ -1050,6 +1115,7 @@ impl_deref! { Object for Map }
impl_try_from! { Value for Map if v => v.is_map() }
impl_try_from! { Object for Map if v => v.is_map() }
impl_eq! { for Map }
impl_hash! { for Map }
impl_partial_eq! { Data for Map use identity }
impl_partial_eq! { Value for Map use identity }
impl_partial_eq! { Object for Map use identity }
@ -1063,6 +1129,7 @@ impl_deref! { Object for NumberObject }
impl_try_from! { Value for NumberObject if v => v.is_number_object() }
impl_try_from! { Object for NumberObject if v => v.is_number_object() }
impl_eq! { for NumberObject }
impl_hash! { for NumberObject }
impl_partial_eq! { Data for NumberObject use identity }
impl_partial_eq! { Value for NumberObject use identity }
impl_partial_eq! { Object for NumberObject use identity }
@ -1076,6 +1143,7 @@ impl_deref! { Object for Promise }
impl_try_from! { Value for Promise if v => v.is_promise() }
impl_try_from! { Object for Promise if v => v.is_promise() }
impl_eq! { for Promise }
impl_hash! { for Promise }
impl_partial_eq! { Data for Promise use identity }
impl_partial_eq! { Value for Promise use identity }
impl_partial_eq! { Object for Promise use identity }
@ -1086,6 +1154,7 @@ pub struct PromiseResolver(Opaque);
impl_deref! { Object for PromiseResolver }
impl_eq! { for PromiseResolver }
impl_hash! { for PromiseResolver }
impl_partial_eq! { Data for PromiseResolver use identity }
impl_partial_eq! { Value for PromiseResolver use identity }
impl_partial_eq! { Object for PromiseResolver use identity }
@ -1100,6 +1169,7 @@ impl_deref! { Object for Proxy }
impl_try_from! { Value for Proxy if v => v.is_proxy() }
impl_try_from! { Object for Proxy if v => v.is_proxy() }
impl_eq! { for Proxy }
impl_hash! { for Proxy }
impl_partial_eq! { Data for Proxy use identity }
impl_partial_eq! { Value for Proxy use identity }
impl_partial_eq! { Object for Proxy use identity }
@ -1113,6 +1183,7 @@ impl_deref! { Object for RegExp }
impl_try_from! { Value for RegExp if v => v.is_reg_exp() }
impl_try_from! { Object for RegExp if v => v.is_reg_exp() }
impl_eq! { for RegExp }
impl_hash! { for RegExp }
impl_partial_eq! { Data for RegExp use identity }
impl_partial_eq! { Value for RegExp use identity }
impl_partial_eq! { Object for RegExp use identity }
@ -1126,6 +1197,7 @@ impl_deref! { Object for Set }
impl_try_from! { Value for Set if v => v.is_set() }
impl_try_from! { Object for Set if v => v.is_set() }
impl_eq! { for Set }
impl_hash! { for Set }
impl_partial_eq! { Data for Set use identity }
impl_partial_eq! { Value for Set use identity }
impl_partial_eq! { Object for Set use identity }
@ -1139,6 +1211,7 @@ impl_deref! { Object for SharedArrayBuffer }
impl_try_from! { Value for SharedArrayBuffer if v => v.is_shared_array_buffer() }
impl_try_from! { Object for SharedArrayBuffer if v => v.is_shared_array_buffer() }
impl_eq! { for SharedArrayBuffer }
impl_hash! { for SharedArrayBuffer }
impl_partial_eq! { Data for SharedArrayBuffer use identity }
impl_partial_eq! { Value for SharedArrayBuffer use identity }
impl_partial_eq! { Object for SharedArrayBuffer use identity }
@ -1152,6 +1225,7 @@ impl_deref! { Object for StringObject }
impl_try_from! { Value for StringObject if v => v.is_string_object() }
impl_try_from! { Object for StringObject if v => v.is_string_object() }
impl_eq! { for StringObject }
impl_hash! { for StringObject }
impl_partial_eq! { Data for StringObject use identity }
impl_partial_eq! { Value for StringObject use identity }
impl_partial_eq! { Object for StringObject use identity }
@ -1165,6 +1239,7 @@ impl_deref! { Object for SymbolObject }
impl_try_from! { Value for SymbolObject if v => v.is_symbol_object() }
impl_try_from! { Object for SymbolObject if v => v.is_symbol_object() }
impl_eq! { for SymbolObject }
impl_hash! { for SymbolObject }
impl_partial_eq! { Data for SymbolObject use identity }
impl_partial_eq! { Value for SymbolObject use identity }
impl_partial_eq! { Object for SymbolObject use identity }
@ -1177,6 +1252,7 @@ impl_deref! { Object for WasmModuleObject }
impl_try_from! { Value for WasmModuleObject if v => v.is_wasm_module_object() }
impl_try_from! { Object for WasmModuleObject if v => v.is_wasm_module_object() }
impl_eq! { for WasmModuleObject }
impl_hash! { for WasmModuleObject }
impl_partial_eq! { Data for WasmModuleObject use identity }
impl_partial_eq! { Value for WasmModuleObject use identity }
impl_partial_eq! { Object for WasmModuleObject use identity }
@ -1198,6 +1274,7 @@ impl_from! { Integer for Primitive }
impl_from! { Int32 for Primitive }
impl_from! { Uint32 for Primitive }
impl_eq! { for Primitive }
impl_hash! { for Primitive }
impl_partial_eq! { Value for Primitive use same_value_zero }
impl_partial_eq! { Primitive for Primitive use same_value_zero }
impl_partial_eq! { BigInt for Primitive use same_value_zero }
@ -1218,6 +1295,7 @@ impl_deref! { Primitive for BigInt }
impl_try_from! { Value for BigInt if v => v.is_big_int() }
impl_try_from! { Primitive for BigInt if v => v.is_big_int() }
impl_eq! { for BigInt }
impl_hash! { for BigInt }
impl_partial_eq! { Value for BigInt use same_value_zero }
impl_partial_eq! { Primitive for BigInt use same_value_zero }
impl_partial_eq! { BigInt for BigInt use strict_equals }
@ -1231,6 +1309,7 @@ impl_deref! { Primitive for Boolean }
impl_try_from! { Value for Boolean if v => v.is_boolean() }
impl_try_from! { Primitive for Boolean if v => v.is_boolean() }
impl_eq! { for Boolean }
impl_hash! { for Boolean }
impl_partial_eq! { Data for Boolean use identity }
impl_partial_eq! { Value for Boolean use identity }
impl_partial_eq! { Primitive for Boolean use identity }
@ -1246,6 +1325,7 @@ impl_try_from! { Primitive for Name if v => v.is_name() }
impl_from! { String for Name }
impl_from! { Symbol for Name }
impl_eq! { for Name }
impl_hash! { for Name }
impl_partial_eq! { Value for Name use same_value_zero }
impl_partial_eq! { Primitive for Name use same_value_zero }
impl_partial_eq! { Name for Name use strict_equals }
@ -1261,6 +1341,7 @@ impl_try_from! { Value for String if v => v.is_string() }
impl_try_from! { Primitive for String if v => v.is_string() }
impl_try_from! { Name for String if v => v.is_string() }
impl_eq! { for String }
impl_hash! { for String }
impl_partial_eq! { Value for String use same_value_zero }
impl_partial_eq! { Primitive for String use same_value_zero }
impl_partial_eq! { Name for String use strict_equals }
@ -1275,6 +1356,7 @@ impl_try_from! { Value for Symbol if v => v.is_symbol() }
impl_try_from! { Primitive for Symbol if v => v.is_symbol() }
impl_try_from! { Name for Symbol if v => v.is_symbol() }
impl_eq! { for Symbol }
impl_hash! { for Symbol }
impl_partial_eq! { Data for Symbol use identity }
impl_partial_eq! { Value for Symbol use identity }
impl_partial_eq! { Primitive for Symbol use identity }
@ -1292,6 +1374,7 @@ impl_from! { Integer for Number }
impl_from! { Int32 for Number }
impl_from! { Uint32 for Number }
impl_eq! { for Number }
impl_hash! { for Number }
impl_partial_eq! { Value for Number use same_value_zero }
impl_partial_eq! { Primitive for Number use same_value_zero }
impl_partial_eq! { Number for Number use same_value_zero }
@ -1310,6 +1393,7 @@ impl_try_from! { Number for Integer if v => v.is_int32() || v.is_uint32() }
impl_from! { Int32 for Integer }
impl_from! { Uint32 for Integer }
impl_eq! { for Integer }
impl_hash! { for Integer }
impl_partial_eq! { Value for Integer use same_value_zero }
impl_partial_eq! { Primitive for Integer use same_value_zero }
impl_partial_eq! { Number for Integer use same_value_zero }
@ -1327,6 +1411,7 @@ impl_try_from! { Primitive for Int32 if v => v.is_int32() }
impl_try_from! { Number for Int32 if v => v.is_int32() }
impl_try_from! { Integer for Int32 if v => v.is_int32() }
impl_eq! { for Int32 }
impl_hash! { for Int32 }
impl_partial_eq! { Value for Int32 use same_value_zero }
impl_partial_eq! { Primitive for Int32 use same_value_zero }
impl_partial_eq! { Number for Int32 use same_value_zero }
@ -1343,6 +1428,7 @@ impl_try_from! { Primitive for Uint32 if v => v.is_uint32() }
impl_try_from! { Number for Uint32 if v => v.is_uint32() }
impl_try_from! { Integer for Uint32 if v => v.is_uint32() }
impl_eq! { for Uint32 }
impl_hash! { for Uint32 }
impl_partial_eq! { Value for Uint32 use same_value_zero }
impl_partial_eq! { Primitive for Uint32 use same_value_zero }
impl_partial_eq! { Number for Uint32 use same_value_zero }

View file

@ -1,3 +1,6 @@
use std::borrow::Borrow;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData;
use std::mem::transmute;
use std::ops::Deref;
@ -237,9 +240,42 @@ impl<'a, T> Handle for &'a Global<T> {
}
}
impl<'s, T> Borrow<T> for Local<'s, T> {
fn borrow(&self) -> &T {
&**self
}
}
impl<T> Borrow<T> for Global<T> {
fn borrow(&self) -> &T {
let HandleInfo { data, host } = self.get_handle_info();
if let HandleHost::DisposedIsolate = host {
panic!("attempt to access Handle hosted by disposed Isolate");
}
unsafe { &*data.as_ptr() }
}
}
impl<'s, T> Eq for Local<'s, T> where T: Eq {}
impl<T> Eq for Global<T> where T: Eq {}
impl<'s, T: Hash> Hash for Local<'s, T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(&**self).hash(state)
}
}
impl<T: Hash> Hash for Global<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
unsafe {
if self.isolate_handle.get_isolate_ptr().is_null() {
panic!("can't hash Global after its host Isolate has been disposed");
}
self.data.as_ref().hash(state);
}
}
}
impl<'s, T, Rhs: Handle> PartialEq<Rhs> for Local<'s, T>
where
T: PartialEq<Rhs::Data>,

View file

@ -45,6 +45,7 @@ mod handle;
mod isolate;
mod isolate_create_params;
mod module;
mod name;
mod number;
mod object;
mod platform;

View file

@ -183,7 +183,9 @@ impl Module {
}
}
/// Returns the identity hash for this object.
/// The `Module` specific equivalent of `Data::get_hash()`.
/// This function is kept around for testing purposes only.
#[doc(hidden)]
pub fn get_identity_hash(&self) -> int {
unsafe { v8__Module__GetIdentityHash(self) }
}

17
src/name.rs Normal file
View file

@ -0,0 +1,17 @@
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
use crate::support::int;
use crate::Name;
extern "C" {
fn v8__Name__GetIdentityHash(this: *const Name) -> int;
}
impl Name {
/// The `String` or `Symbol` specific equivalent of `Data::get_hash()`.
/// This function is kept around for testing purposes only.
#[doc(hidden)]
pub fn get_identity_hash(&self) -> int {
unsafe { v8__Name__GetIdentityHash(self) }
}
}

View file

@ -286,11 +286,9 @@ impl Object {
.into()
}
/// Returns the identity hash for this object. The current implementation
/// uses a hidden property on the object to store the identity hash.
///
/// The return value will never be 0. Also, it is not guaranteed to be
/// unique.
/// The `Object` specific equivalent of `Data::get_hash()`.
/// This function is kept around for testing purposes only.
#[doc(hidden)]
pub fn get_identity_hash(&self) -> int {
unsafe { v8__Object__GetIdentityHash(self) }
}

View file

@ -1799,26 +1799,31 @@ fn equality_edge_cases() {
assert!(pos_zero.same_value(pos_zero));
assert!(pos_zero.same_value_zero(pos_zero));
assert!(pos_zero.strict_equals(pos_zero));
assert_eq!(pos_zero.get_hash(), pos_zero.get_hash());
assert!(neg_zero == neg_zero);
assert!(neg_zero.same_value(neg_zero));
assert!(neg_zero.same_value_zero(neg_zero));
assert!(neg_zero.strict_equals(neg_zero));
assert_eq!(neg_zero.get_hash(), neg_zero.get_hash());
assert!(pos_zero == neg_zero);
assert!(!pos_zero.same_value(neg_zero));
assert!(pos_zero.same_value_zero(neg_zero));
assert!(pos_zero.strict_equals(neg_zero));
assert_eq!(pos_zero.get_hash(), neg_zero.get_hash());
assert!(neg_zero == pos_zero);
assert!(!neg_zero.same_value(pos_zero));
assert!(neg_zero.same_value_zero(pos_zero));
assert!(pos_zero.strict_equals(pos_zero));
assert!(neg_zero.strict_equals(pos_zero));
assert_eq!(neg_zero.get_hash(), pos_zero.get_hash());
assert!(nan == nan);
assert!(nan.same_value(nan));
assert!(nan.same_value_zero(nan));
assert!(!nan.strict_equals(nan));
assert_eq!(nan.get_hash(), nan.get_hash());
assert!(nan != pos_zero);
assert!(!nan.same_value(pos_zero));
@ -1831,6 +1836,126 @@ fn equality_edge_cases() {
assert!(!neg_zero.strict_equals(nan));
}
#[test]
fn get_hash() {
use std::collections::HashMap;
use std::collections::HashSet;
use std::iter::once;
let _setup_guard = setup();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
// Note: the set with hashes and the collition counter is used below in both
// the 'primitives' and the 'objects' section.
let mut hashes = HashSet::new();
let mut collision_count = 0;
let mut get_primitives = || -> v8::Local<v8::Array> {
eval(
scope,
r#"[
undefined,
null,
false,
true,
0,
123,
12345e67,
123456789012345678901234567890123456789012345678901234567890n,
NaN,
-Infinity,
"",
"hello metaverse!",
Symbol.isConcatSpreadable
]"#,
)
.unwrap()
.try_into()
.unwrap()
};
let primitives1 = get_primitives();
let primitives2 = get_primitives();
let len = primitives1.length();
assert!(len > 10);
assert_eq!(len, primitives2.length());
let mut name_count = 0;
for i in 0..len {
let pri1 = primitives1.get_index(scope, i).unwrap();
let pri2 = primitives2.get_index(scope, i).unwrap();
let hash = pri1.get_hash();
assert_ne!(hash, 0);
assert_eq!(hash, pri2.get_hash());
if let Ok(name) = v8::Local::<v8::Name>::try_from(pri1) {
assert_eq!(hash, name.get_identity_hash());
name_count += 1;
}
if !hashes.insert(hash) {
collision_count += 1;
}
let map =
once((v8::Global::new(scope, pri1), i)).collect::<HashMap<_, _>>();
assert_eq!(map[&*pri2], i);
}
assert_eq!(name_count, 3);
assert!(collision_count <= 2);
for _ in 0..1 {
let objects: v8::Local::<v8::Array> = eval(
scope,
r#"[
[1, 2, 3],
(function() { return arguments; })(1, 2, 3),
{ a: 1, b: 2, c: 3 },
Object.create(null),
new Map([[null, 1], ["2", 3n]]),
new Set(),
function f() {},
function* f() {},
async function f() {},
async function* f() {},
foo => foo,
async bar => bar,
class Custom extends Object { method(p) { return -p; } },
new class MyString extends String { constructor() { super("yeaeaeah"); } },
(() => { try { not_defined } catch(e) { return e; } })()
]"#)
.unwrap()
.try_into()
.unwrap();
let len = objects.length();
assert!(len > 10);
for i in 0..len {
let val = objects.get_index(scope, i).unwrap();
let hash = val.get_hash();
assert_ne!(hash, 0);
let obj = v8::Local::<v8::Object>::try_from(val).unwrap();
assert_eq!(hash, obj.get_identity_hash());
if !hashes.insert(hash) {
collision_count += 1;
}
let map =
once((v8::Global::new(scope, obj), i)).collect::<HashMap<_, _>>();
assert_eq!(map[&*obj], i);
}
assert!(collision_count <= 2);
}
// TODO: add tests for `External` and for types that are not derived from
// `v8::Value`, like `Module`, `Function/ObjectTemplate` etc.
}
#[test]
fn array_buffer_view() {
let _setup_guard = setup();