@@ -2839,8 +2839,10 @@ pub fn evaluate_statements_with_labels<'gc>(
28392839 env_set_strictness(mc, &eval_lex_env, true)?;
28402840 }
28412841
2842- // Hoist var/function declarations to caller's env (skip lexicals)
2843- hoist_declarations(mc, env, statements, true, false)?;
2842+ // Hoist var/function declarations to caller's env (skip lexicals).
2843+ // Pass is_eval=true so global var bindings are created as
2844+ // configurable per EvalDeclarationInstantiation §19.2.1.3.
2845+ hoist_declarations(mc, env, statements, true, true)?;
28442846
28452847 // Hoist let/const/class into the fresh eval lex env
28462848 for stmt in statements {
@@ -13150,63 +13152,79 @@ pub fn evaluate_call_dispatch<'gc>(
1315013152 },
1315113153 };
1315213154
13153- for src_expr in eval_args.iter().skip(1) {
13154- if matches!(src_expr, Value::Undefined | Value::Null) {
13155- continue;
13156- }
13157-
13158- let source_obj = match src_expr {
13159- Value::Object(o) => *o,
13160- other => match crate::js_class::handle_object_constructor(mc, std::slice::from_ref(other), env)? {
13161- Value::Object(o) => o,
13162- _ => return Err(raise_type_error!("Cannot convert value to object").into()),
13163- },
13164- };
13165-
13166- let ordered = if let Some(proxy_cell) = crate::core::slot_get(&source_obj, &InternalSlot::Proxy)
13167- && let Value::Proxy(proxy) = &*proxy_cell.borrow()
13168- {
13169- crate::js_proxy::proxy_own_keys(mc, proxy)?
13170- } else {
13171- crate::core::ordinary_own_property_keys_mc(mc, &source_obj)?
13172- };
13155+ // Object.assign uses [[Set]] with Throw=true (§22.1.2.1 step 5.e.iv.2),
13156+ // so property-set failures must always throw TypeError.
13157+ let was_strict = crate::core::env_get_strictness(env);
13158+ if !was_strict {
13159+ crate::core::env_set_strictness(mc, env, true)?;
13160+ }
1317313161
13174- for key in ordered {
13175- if key == "__proto__".into() {
13162+ let assign_result: Result<Value<'gc>, EvalError<'gc>> = (|| {
13163+ for src_expr in eval_args.iter().skip(1) {
13164+ if matches!(src_expr, Value::Undefined | Value::Null) {
1317613165 continue;
1317713166 }
1317813167
13179- let is_enumerable = if let Some(proxy_cell) = crate::core::slot_get(&source_obj, &InternalSlot::Proxy)
13168+ let source_obj = match src_expr {
13169+ Value::Object(o) => *o,
13170+ other => match crate::js_class::handle_object_constructor(mc, std::slice::from_ref(other), env)? {
13171+ Value::Object(o) => o,
13172+ _ => return Err(raise_type_error!("Cannot convert value to object").into()),
13173+ },
13174+ };
13175+
13176+ let ordered = if let Some(proxy_cell) = crate::core::slot_get(&source_obj, &InternalSlot::Proxy)
1318013177 && let Value::Proxy(proxy) = &*proxy_cell.borrow()
1318113178 {
13182- match crate::js_proxy::proxy_get_own_property_is_enumerable(mc, proxy, &key)? {
13183- Some(en) => en,
13184- None => continue,
13185- }
13179+ crate::js_proxy::proxy_own_keys(mc, proxy)?
1318613180 } else {
13187- if crate::core::get_own_property(&source_obj, &key).is_none() {
13181+ crate::core::ordinary_own_property_keys_mc(mc, &source_obj)?
13182+ };
13183+
13184+ for key in ordered {
13185+ if key == "__proto__".into() {
1318813186 continue;
1318913187 }
13190- source_obj.borrow().is_enumerable(&key)
13191- };
1319213188
13193- if !is_enumerable {
13194- continue;
13195- }
13189+ let is_enumerable = if let Some(proxy_cell) = crate::core::slot_get(&source_obj, &InternalSlot::Proxy)
13190+ && let Value::Proxy(proxy) = &*proxy_cell.borrow()
13191+ {
13192+ match crate::js_proxy::proxy_get_own_property_is_enumerable(mc, proxy, &key)? {
13193+ Some(en) => en,
13194+ None => continue,
13195+ }
13196+ } else {
13197+ if crate::core::get_own_property(&source_obj, &key).is_none() {
13198+ continue;
13199+ }
13200+ source_obj.borrow().is_enumerable(&key)
13201+ };
1319613202
13197- let prop_value = crate::core::get_property_with_accessors(mc, env, &source_obj, &key)?;
13198- crate::core::set_property_with_accessors(
13199- mc,
13200- env,
13201- &target_obj,
13202- key,
13203- &prop_value,
13204- Some(&Value::Object(target_obj)),
13205- )?;
13203+ if !is_enumerable {
13204+ continue;
13205+ }
13206+
13207+ let prop_value = crate::core::get_property_with_accessors(mc, env, &source_obj, &key)?;
13208+ crate::core::set_property_with_accessors(
13209+ mc,
13210+ env,
13211+ &target_obj,
13212+ key,
13213+ &prop_value,
13214+ Some(&Value::Object(target_obj)),
13215+ )?;
13216+ }
1320613217 }
13218+
13219+ Ok(Value::Object(target_obj))
13220+ })();
13221+
13222+ // Restore env strictness
13223+ if !was_strict {
13224+ crate::core::env_set_strictness(mc, env, was_strict)?;
1320713225 }
1320813226
13209- Ok(Value::Object(target_obj))
13227+ assign_result
1321013228 } else {
1321113229 Ok(crate::js_object::handle_object_method(mc, suffix, eval_args, env)?)
1321213230 }
@@ -21122,6 +21140,13 @@ pub(crate) fn call_accessor<'gc>(
2112221140 call_env.borrow_mut(mc).prototype = Some(*captured_env);
2112321141 call_env.borrow_mut(mc).is_function_scope = true;
2112421142 object_set_key_value(mc, &call_env, "this", &Value::Object(*receiver))?;
21143+ // Getters are ordinary functions — provide an `arguments` object
21144+ // (empty, since getters receive no arguments) for sloppy-mode code.
21145+ {
21146+ let args_obj = crate::core::new_js_object_data(mc);
21147+ object_set_key_value(mc, &args_obj, "length", &Value::Number(0.0))?;
21148+ object_set_key_value(mc, &call_env, "arguments", &Value::Object(args_obj))?;
21149+ }
2112521150 // If the getter carried a home object, propagate it into call env so `super` resolves
2112621151 call_env.borrow_mut(mc).set_home_object(home_opt.clone());
2112721152 let body_clone = body.clone();
0 commit comments