Skip to content
File

Blob: src/rust/jsg-test/tests/symbol.rs

rust145 lines
1// Copyright (c) 2026 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5//! Tests for `Local<Symbol>` โ€” `v8::Symbol` bindings.
6 
7use jsg::v8;
8use jsg::v8::Local;
9 
10// =============================================================================
11// is_symbol on Local<Value>
12// =============================================================================
13 
14#[test]
15fn value_is_symbol_for_symbol() {
16 let harness = crate::Harness::new();
17 harness.run_in_context(|_lock, ctx| {
18 let val = ctx.eval_raw("Symbol('test')").unwrap();
19 assert!(val.is_symbol());
20 Ok(())
21 });
22}
23 
24#[test]
25fn value_is_symbol_false_for_string() {
26 let harness = crate::Harness::new();
27 harness.run_in_context(|_lock, ctx| {
28 let val = ctx.eval_raw("'not a symbol'").unwrap();
29 assert!(!val.is_symbol());
30 Ok(())
31 });
32}
33 
34#[test]
35fn value_is_symbol_false_for_number() {
36 let harness = crate::Harness::new();
37 harness.run_in_context(|_lock, ctx| {
38 let val = ctx.eval_raw("42").unwrap();
39 assert!(!val.is_symbol());
40 Ok(())
41 });
42}
43 
44// =============================================================================
45// Symbol::new โ€” uniqueness and description
46// =============================================================================
47 
48#[test]
49fn symbol_new_without_description() {
50 let harness = crate::Harness::new();
51 harness.run_in_context(|lock, _ctx| {
52 let sym = v8::Symbol::new(lock, None);
53 assert!(sym.is_symbol());
54 assert!(sym.description(lock).is_none());
55 Ok(())
56 });
57}
58 
59#[test]
60fn symbol_new_with_description() {
61 let harness = crate::Harness::new();
62 harness.run_in_context(|lock, _ctx| {
63 let desc = v8::String::new_from_str(lock, "my-symbol").unwrap(lock);
64 let sym = v8::Symbol::new(lock, Some(desc));
65 assert!(sym.is_symbol());
66 let got = sym.description(lock).expect("expected a description");
67 assert_eq!(got.to_string(lock), "my-symbol");
68 Ok(())
69 });
70}
71 
72#[test]
73fn symbol_new_is_unique() {
74 let harness = crate::Harness::new();
75 harness.run_in_context(|lock, _ctx| {
76 let a = v8::Symbol::new(lock, None);
77 let b = v8::Symbol::new(lock, None);
78 // Two different symbols are not the same V8 object.
79 let a_val: Local<v8::Value> = a.into();
80 let b_val: Local<v8::Value> = b.into();
81 assert_ne!(a_val, b_val);
82 Ok(())
83 });
84}
85 
86#[test]
87fn symbol_with_same_description_is_still_unique() {
88 let harness = crate::Harness::new();
89 harness.run_in_context(|lock, _ctx| {
90 let make_sym = |lock: &mut jsg::Lock| {
91 let desc = v8::String::new_from_str(lock, "same").unwrap(lock);
92 v8::Symbol::new(lock, Some(desc))
93 };
94 let a = make_sym(lock);
95 let b = make_sym(lock);
96 let a_val: Local<v8::Value> = a.into();
97 let b_val: Local<v8::Value> = b.into();
98 // Symbol('same') !== Symbol('same')
99 assert_ne!(a_val, b_val);
100 Ok(())
101 });
102}
103 
104// =============================================================================
105// try_as cast from Local<Value>
106// =============================================================================
107 
108#[test]
109fn value_try_as_symbol_succeeds() {
110 let harness = crate::Harness::new();
111 harness.run_in_context(|_lock, ctx| {
112 let val = ctx.eval_raw("Symbol('cast-test')").unwrap();
113 assert!(val.is_symbol());
114 let sym = val.try_as::<v8::Symbol>().expect("should cast to Symbol");
115 assert!(sym.is_symbol());
116 Ok(())
117 });
118}
119 
120#[test]
121fn value_try_as_symbol_fails_for_string() {
122 let harness = crate::Harness::new();
123 harness.run_in_context(|_lock, ctx| {
124 let val = ctx.eval_raw("'hello'").unwrap();
125 assert!(val.try_as::<v8::Symbol>().is_none());
126 Ok(())
127 });
128}
129 
130// =============================================================================
131// Symbol โ†’ Value upcast
132// =============================================================================
133 
134#[test]
135fn symbol_into_value_preserves_is_symbol() {
136 let harness = crate::Harness::new();
137 harness.run_in_context(|lock, _ctx| {
138 let sym = v8::Symbol::new(lock, None);
139 let val: Local<v8::Value> = sym.into();
140 assert!(val.is_symbol());
141 assert!(!val.is_string());
142 Ok(())
143 });
144}