Просмотр исходного кода

Throw `TypeError` on `Object.assign` with readonly property (#6853)

Assigning values to read-only properties via Object.assign should throw a TypeError but it didn't.
https://tc39.es/ecma262/#sec-set-o-p-v-throw

I'm not sure if / in how far this problem could exist for similar apis.
Fix #6523
Lukas Kurz 3 лет назад
Родитель
Сommit
9bf5a93b67

+ 2 - 3
lib/Runtime/Language/JavascriptOperators.cpp

@@ -1,6 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
-// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
+// Copyright (c) ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeLanguagePch.h"
@@ -2712,8 +2712,7 @@ CommonNumber:
         {
             if ((flags & Accessor) == Accessor)
             {
-                if (JavascriptError::ThrowIfStrictModeUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext) ||
-                    JavascriptError::ThrowIfNotExtensibleUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext))
+                if (JavascriptError::ThrowIfUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext, propertyId))
                 {
                     *result = TRUE;
                     return true;

+ 29 - 1
lib/Runtime/Library/JavascriptError.cpp

@@ -1,6 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
-// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
+// Copyright (c) ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeLibraryPch.h"
@@ -758,6 +758,34 @@ namespace Js
         return false;
     }
 
+    bool JavascriptError::ThrowIfUndefinedSetter(
+        PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext, PropertyId propertyId)
+    {
+        if (!JavascriptOperators::IsUndefinedAccessor(setterValue, scriptContext))
+            return false;
+
+        bool shouldThrow = scriptContext->GetThreadContext()->RecordImplicitException();
+        if (flags & PropertyOperation_StrictMode)
+        {
+            if (shouldThrow)
+                JavascriptError::ThrowTypeError(scriptContext, JSERR_CantAssignToReadOnly);
+            return true;
+        }
+        else if (flags & PropertyOperation_ThrowIfNotExtensible)
+        {
+            if (shouldThrow)
+                JavascriptError::ThrowTypeError(scriptContext, JSERR_DefineProperty_NotExtensible);
+            return true;
+        }
+        else if (flags & PropertyOperation_ThrowIfNonWritable)
+        {
+            if (shouldThrow)
+                JavascriptError::ThrowTypeError(scriptContext, JSERR_DefineProperty_NotWritable, scriptContext->GetPropertyName(propertyId)->GetBuffer());
+            return true;
+        }
+        return false;
+    }
+
     bool JavascriptError::ThrowIfStrictModeUndefinedSetter(
         PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext)
     {

+ 2 - 1
lib/Runtime/Library/JavascriptError.h

@@ -1,6 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
-// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
+// Copyright (c) ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -118,6 +118,7 @@ namespace Js
         static bool ThrowCantExtendIfStrictMode(PropertyOperationFlags flags, ScriptContext* scriptContext);
         static bool ThrowCantDeleteIfStrictMode(PropertyOperationFlags flags, ScriptContext* scriptContext, PCWSTR varName);
         static bool ThrowCantDeleteIfStrictModeOrNonconfigurable(PropertyOperationFlags flags, ScriptContext* scriptContext, PCWSTR varName);
+        static bool ThrowIfUndefinedSetter(PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext, PropertyId propertyId);
         static bool ThrowIfStrictModeUndefinedSetter(PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext);
         static bool ThrowIfNotExtensibleUndefinedSetter(PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext);
 

+ 13 - 0
test/Object/assign.js

@@ -1,8 +1,12 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
+// @ts-check
+/// <reference path="..\UnitTestFramework\UnitTestFramework.js" />
+
 WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
 
 var tests = [
@@ -150,6 +154,15 @@ var tests = [
             assert.areEqual(newObj[0], orig[0]);
             assert.areEqual(newObj[1], undefined);
         }
+    },
+    {
+        name: "Throw on assign to read-only",
+        body() {
+            const obj = {
+                get prop() { return 1; }
+            };
+            assert.throws(() => Object.assign(obj, obj), TypeError, "Object.assign should throw (readonly property)");
+        }
     }
 ];