Skip to content

Commit 658ae92

Browse files
committed
Add Symbol primitive support, symbol-keyed properties and tests
- Add Symbol primitive type (with optional description) and SymbolData - Introduce PropertyKey enum to handle string and symbol keys for objects - Update object storage and API (obj_get_value, obj_set_value, obj_delete, env helpers) to accept PropertyKey - Add Object.getOwnPropertySymbols implementation - Make Object.keys/Object.values/Object.assign ignore symbol-keyed properties where appropriate - Add extensive Symbol tests under tests/symbol_additional_tests.rs (typeof, toString/description, valueOf, JSON.stringify, keys/values/assign behavior, prototype shadowing, getOwnPropertySymbols) - Adjusted core evaluation logic to compare Symbols by identity and support symbol-indexed property access
1 parent c7b7141 commit 658ae92

24 files changed

+782
-524
lines changed

examples/rust_js.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,6 @@ fn main() {
5757
Value::Setter(_, _, _) => println!("[Setter]"),
5858
Value::Property { .. } => println!("[Property]"),
5959
Value::Promise(_) => println!("[object Promise]"),
60+
Value::Symbol(_) => println!("[object Symbol]"),
6061
}
6162
}

src/js_array.rs

Lines changed: 83 additions & 81 deletions
Large diffs are not rendered by default.

src/js_class.rs

Lines changed: 76 additions & 75 deletions
Large diffs are not rendered by default.

src/js_console.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::rc::Rc;
66
/// Create the console object with logging functions
77
pub fn make_console_object() -> Result<JSObjectDataPtr, JSError> {
88
let console_obj = Rc::new(RefCell::new(JSObjectData::new()));
9-
obj_set_value(&console_obj, "log", Value::Function("console.log".to_string()))?;
9+
obj_set_value(&console_obj, &"log".into(), Value::Function("console.log".to_string()))?;
1010
Ok(console_obj)
1111
}
1212

@@ -33,7 +33,7 @@ pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
3333
if i > 0 {
3434
print!(",");
3535
}
36-
if let Some(val_rc) = crate::core::obj_get_value(&obj, i.to_string())? {
36+
if let Some(val_rc) = crate::core::obj_get_value(&obj, &i.to_string().into())? {
3737
match &*val_rc.borrow() {
3838
Value::Number(n) => print!("{}", n),
3939
Value::String(s) => print!("\"{}\"", String::from_utf16_lossy(s)),
@@ -100,6 +100,7 @@ pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
100100
print!("]");
101101
}
102102
Value::Promise(_) => print!("[object Promise]"),
103+
Value::Symbol(_) => print!("[object Symbol]"),
103104
}
104105
}
105106
println!();

src/js_date.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub(crate) fn handle_date_constructor(args: &[Expr], env: &JSObjectDataPtr) -> R
149149

150150
// Create a Date object with timestamp
151151
let date_obj = Rc::new(RefCell::new(JSObjectData::new()));
152-
obj_set_value(&date_obj, "__timestamp", Value::Number(timestamp))?;
152+
obj_set_value(&date_obj, &"__timestamp".into(), Value::Number(timestamp))?;
153153

154154
// Add toString method
155155
Ok(Value::Object(date_obj))
@@ -164,7 +164,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
164164
message: "Date.toString() takes no arguments".to_string(),
165165
});
166166
}
167-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
167+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
168168
if let Value::Number(timestamp) = *timestamp_val.borrow() {
169169
// Convert timestamp to DateTime
170170
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
@@ -193,7 +193,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
193193
message: "Date.getTime() takes no arguments".to_string(),
194194
});
195195
}
196-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
196+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
197197
if let Value::Number(timestamp) = *timestamp_val.borrow() {
198198
Ok(Value::Number(timestamp))
199199
} else {
@@ -213,7 +213,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
213213
message: "Date.valueOf() takes no arguments".to_string(),
214214
});
215215
}
216-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
216+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
217217
if let Value::Number(timestamp) = *timestamp_val.borrow() {
218218
Ok(Value::Number(timestamp))
219219
} else {
@@ -233,7 +233,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
233233
message: "Date.getFullYear() takes no arguments".to_string(),
234234
});
235235
}
236-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
236+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
237237
if let Value::Number(timestamp) = *timestamp_val.borrow() {
238238
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
239239
Ok(Value::Number(dt.year() as f64))
@@ -257,7 +257,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
257257
message: "Date.getMonth() takes no arguments".to_string(),
258258
});
259259
}
260-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
260+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
261261
if let Value::Number(timestamp) = *timestamp_val.borrow() {
262262
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
263263
// JavaScript months are 0-based
@@ -282,7 +282,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
282282
message: "Date.getDate() takes no arguments".to_string(),
283283
});
284284
}
285-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
285+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
286286
if let Value::Number(timestamp) = *timestamp_val.borrow() {
287287
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
288288
Ok(Value::Number(dt.day() as f64))
@@ -306,7 +306,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
306306
message: "Date.getHours() takes no arguments".to_string(),
307307
});
308308
}
309-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
309+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
310310
if let Value::Number(timestamp) = *timestamp_val.borrow() {
311311
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
312312
Ok(Value::Number(dt.hour() as f64))
@@ -330,7 +330,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
330330
message: "Date.getMinutes() takes no arguments".to_string(),
331331
});
332332
}
333-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
333+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
334334
if let Value::Number(timestamp) = *timestamp_val.borrow() {
335335
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
336336
Ok(Value::Number(dt.minute() as f64))
@@ -354,7 +354,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
354354
message: "Date.getSeconds() takes no arguments".to_string(),
355355
});
356356
}
357-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
357+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
358358
if let Value::Number(timestamp) = *timestamp_val.borrow() {
359359
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
360360
Ok(Value::Number(dt.second() as f64))
@@ -378,7 +378,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
378378
message: "Date.getMilliseconds() takes no arguments".to_string(),
379379
});
380380
}
381-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
381+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
382382
if let Value::Number(timestamp) = *timestamp_val.borrow() {
383383
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
384384
Ok(Value::Number(dt.timestamp_subsec_millis() as f64))
@@ -402,7 +402,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
402402
message: "Date.toDateString() takes no arguments".to_string(),
403403
});
404404
}
405-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
405+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
406406
if let Value::Number(timestamp) = *timestamp_val.borrow() {
407407
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
408408
let local_dt = Local.from_utc_datetime(&dt.naive_utc());
@@ -428,7 +428,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
428428
message: "Date.toTimeString() takes no arguments".to_string(),
429429
});
430430
}
431-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
431+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
432432
if let Value::Number(timestamp) = *timestamp_val.borrow() {
433433
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
434434
let local_dt = Local.from_utc_datetime(&dt.naive_utc());
@@ -454,7 +454,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
454454
message: "Date.toISOString() takes no arguments".to_string(),
455455
});
456456
}
457-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
457+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
458458
if let Value::Number(timestamp) = *timestamp_val.borrow() {
459459
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
460460
let formatted = dt.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string();
@@ -481,7 +481,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
481481
message: "Date.toUTCString() takes no arguments".to_string(),
482482
});
483483
}
484-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
484+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
485485
if let Value::Number(timestamp) = *timestamp_val.borrow() {
486486
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
487487
let formatted = dt.format("%a, %d %b %Y %H:%M:%S GMT").to_string();
@@ -506,7 +506,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
506506
message: "Date.toJSON() takes no arguments".to_string(),
507507
});
508508
}
509-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
509+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
510510
if let Value::Number(timestamp) = *timestamp_val.borrow() {
511511
if timestamp.is_nan() {
512512
Ok(Value::Undefined)
@@ -535,7 +535,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
535535
message: "Date.toLocaleString() takes no arguments".to_string(),
536536
});
537537
}
538-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
538+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
539539
if let Value::Number(timestamp) = *timestamp_val.borrow() {
540540
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
541541
let local_dt = Local.from_utc_datetime(&dt.naive_utc());
@@ -562,7 +562,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
562562
message: "Date.toLocaleDateString() takes no arguments".to_string(),
563563
});
564564
}
565-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
565+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
566566
if let Value::Number(timestamp) = *timestamp_val.borrow() {
567567
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
568568
let local_dt = Local.from_utc_datetime(&dt.naive_utc());
@@ -589,7 +589,7 @@ pub(crate) fn handle_date_method(obj_map: &JSObjectDataPtr, method: &str, args:
589589
message: "Date.toLocaleTimeString() takes no arguments".to_string(),
590590
});
591591
}
592-
if let Some(timestamp_val) = obj_map.borrow().get("__timestamp") {
592+
if let Some(timestamp_val) = obj_map.borrow().get(&"__timestamp".into()) {
593593
if let Value::Number(timestamp) = *timestamp_val.borrow() {
594594
if let Some(dt) = Utc.timestamp_millis_opt(timestamp as i64).single() {
595595
let local_dt = Local.from_utc_datetime(&dt.naive_utc());

0 commit comments

Comments
 (0)