From d6a594757f545bbca124534e2d0a1a19865afac4 Mon Sep 17 00:00:00 2001 From: tofpie <75836434+tofpie@users.noreply.github.com> Date: Fri, 1 Jan 2021 17:07:42 +0100 Subject: [PATCH] Implement support of Symbol.toPrimitive (#1020) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: João Borges Co-authored-by: tofpie --- boa/src/value/mod.rs | 20 +++++++++++++++++--- boa/src/value/tests.rs | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/boa/src/value/mod.rs b/boa/src/value/mod.rs index 2e79a1e65b..ae5cce3ebf 100644 --- a/boa/src/value/mod.rs +++ b/boa/src/value/mod.rs @@ -527,11 +527,25 @@ impl Value { // 1. Assert: input is an ECMAScript language value. (always a value not need to check) // 2. If Type(input) is Object, then if let Value::Object(obj) = self { + if let Some(exotic_to_prim) = + obj.get_method(context, context.well_known_symbols().to_primitive_symbol())? + { + let hint = match preferred_type { + PreferredType::String => "string", + PreferredType::Number => "number", + PreferredType::Default => "default", + } + .into(); + let result = exotic_to_prim.call(&self, &[hint], context)?; + return if result.is_object() { + Err(context.construct_type_error("Symbol.toPrimitive cannot return an object")) + } else { + Ok(result) + }; + } + let mut hint = preferred_type; - // Skip d, e we don't support Symbols yet - // TODO: add when symbols are supported - // TODO: Add other steps. if hint == PreferredType::Default { hint = PreferredType::Number; }; diff --git a/boa/src/value/tests.rs b/boa/src/value/tests.rs index 0fef0eb1f4..f64ad32caa 100644 --- a/boa/src/value/tests.rs +++ b/boa/src/value/tests.rs @@ -619,6 +619,20 @@ fn test_accessors() { assert_eq!(forward(&mut context, "arr"), r#"[ "a" ]"#); } +#[test] +fn to_primitive() { + let mut context = Context::new(); + let src = r#" + let a = {}; + a[Symbol.toPrimitive] = function() { + return 42; + }; + let primitive = a + 0; + "#; + context.eval(src).unwrap(); + assert_eq!(forward(&mut context, "primitive"), "42"); +} + /// Test cyclic conversions that previously caused stack overflows /// Relevant mitigations for these are in `GcObject::ordinary_to_primitive` and /// `GcObject::to_json`