Skip to content

Commit 9bf5a93

Browse files
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
1 parent 0a9c082 commit 9bf5a93

File tree

4 files changed

+46
-5
lines changed

4 files changed

+46
-5
lines changed

lib/Runtime/Language/JavascriptOperators.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3-
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
44
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
55
//-------------------------------------------------------------------------------------------------------
66
#include "RuntimeLanguagePch.h"
@@ -2712,8 +2712,7 @@ using namespace Js;
27122712
{
27132713
if ((flags & Accessor) == Accessor)
27142714
{
2715-
if (JavascriptError::ThrowIfStrictModeUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext) ||
2716-
JavascriptError::ThrowIfNotExtensibleUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext))
2715+
if (JavascriptError::ThrowIfUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext, propertyId))
27172716
{
27182717
*result = TRUE;
27192718
return true;

lib/Runtime/Library/JavascriptError.cpp

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3-
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
44
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
55
//-------------------------------------------------------------------------------------------------------
66
#include "RuntimeLibraryPch.h"
@@ -758,6 +758,34 @@ namespace Js
758758
return false;
759759
}
760760

761+
bool JavascriptError::ThrowIfUndefinedSetter(
762+
PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext, PropertyId propertyId)
763+
{
764+
if (!JavascriptOperators::IsUndefinedAccessor(setterValue, scriptContext))
765+
return false;
766+
767+
bool shouldThrow = scriptContext->GetThreadContext()->RecordImplicitException();
768+
if (flags & PropertyOperation_StrictMode)
769+
{
770+
if (shouldThrow)
771+
JavascriptError::ThrowTypeError(scriptContext, JSERR_CantAssignToReadOnly);
772+
return true;
773+
}
774+
else if (flags & PropertyOperation_ThrowIfNotExtensible)
775+
{
776+
if (shouldThrow)
777+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DefineProperty_NotExtensible);
778+
return true;
779+
}
780+
else if (flags & PropertyOperation_ThrowIfNonWritable)
781+
{
782+
if (shouldThrow)
783+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DefineProperty_NotWritable, scriptContext->GetPropertyName(propertyId)->GetBuffer());
784+
return true;
785+
}
786+
return false;
787+
}
788+
761789
bool JavascriptError::ThrowIfStrictModeUndefinedSetter(
762790
PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext)
763791
{

lib/Runtime/Library/JavascriptError.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3-
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
44
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
55
//-------------------------------------------------------------------------------------------------------
66
#pragma once
@@ -118,6 +118,7 @@ namespace Js
118118
static bool ThrowCantExtendIfStrictMode(PropertyOperationFlags flags, ScriptContext* scriptContext);
119119
static bool ThrowCantDeleteIfStrictMode(PropertyOperationFlags flags, ScriptContext* scriptContext, PCWSTR varName);
120120
static bool ThrowCantDeleteIfStrictModeOrNonconfigurable(PropertyOperationFlags flags, ScriptContext* scriptContext, PCWSTR varName);
121+
static bool ThrowIfUndefinedSetter(PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext, PropertyId propertyId);
121122
static bool ThrowIfStrictModeUndefinedSetter(PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext);
122123
static bool ThrowIfNotExtensibleUndefinedSetter(PropertyOperationFlags flags, Var setterValue, ScriptContext* scriptContext);
123124

test/Object/assign.js

+13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56

7+
// @ts-check
8+
/// <reference path="..\UnitTestFramework\UnitTestFramework.js" />
9+
610
WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
711

812
var tests = [
@@ -150,6 +154,15 @@ var tests = [
150154
assert.areEqual(newObj[0], orig[0]);
151155
assert.areEqual(newObj[1], undefined);
152156
}
157+
},
158+
{
159+
name: "Throw on assign to read-only",
160+
body() {
161+
const obj = {
162+
get prop() { return 1; }
163+
};
164+
assert.throws(() => Object.assign(obj, obj), TypeError, "Object.assign should throw (readonly property)");
165+
}
153166
}
154167
];
155168

0 commit comments

Comments
 (0)