Skip to content

Commit cae6cd0

Browse files
authored
Primitive this values of accessors should not be coerced in strict mode (#3854)
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai [email protected]
1 parent 10e78a4 commit cae6cd0

File tree

2 files changed

+89
-56
lines changed

2 files changed

+89
-56
lines changed

jerry-core/vm/vm.c

Lines changed: 73 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -154,84 +154,101 @@ vm_op_get_value (ecma_value_t object, /**< base object */
154154
* if the property setting is unsuccessful
155155
*/
156156
static ecma_value_t
157-
vm_op_set_value (ecma_value_t object, /**< base object */
157+
vm_op_set_value (ecma_value_t base, /**< base object */
158158
ecma_value_t property, /**< property name */
159159
ecma_value_t value, /**< ecma value */
160160
bool is_strict) /**< strict mode */
161161
{
162-
ecma_object_t * object_p;
162+
ecma_value_t result = ECMA_VALUE_EMPTY;
163+
ecma_object_t *object_p;
164+
ecma_string_t *property_p;
163165

164-
if (JERRY_UNLIKELY (!ecma_is_value_object (object)))
166+
if (JERRY_UNLIKELY (!ecma_is_value_object (base)))
165167
{
166-
ecma_value_t to_object = ecma_op_to_object (object);
167-
ecma_free_value (object);
168-
169-
if (ECMA_IS_VALUE_ERROR (to_object))
168+
if (JERRY_UNLIKELY (ecma_is_value_null (base) || ecma_is_value_undefined (base)))
170169
{
171170
#if ENABLED (JERRY_ERROR_MESSAGES)
172-
ecma_free_value (to_object);
173-
jcontext_release_exception ();
174-
175-
ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE,
176-
"Cannot set property '%' of %",
177-
property,
178-
object);
179-
ecma_free_value (property);
180-
181-
return error_value;
171+
result = ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE,
172+
"Cannot set property '%' of %",
173+
property,
174+
base);
182175
#else /* !ENABLED (JERRY_ERROR_MESSAGES) */
183-
ecma_free_value (property);
184-
return to_object;
176+
result = ecma_raise_type_error (NULL);
185177
#endif /* ENABLED (JERRY_ERROR_MESSAGES) */
178+
ecma_free_value (property);
179+
return result;
186180
}
187181

188-
object_p = ecma_get_object_from_value (to_object);
182+
if (JERRY_UNLIKELY (!ecma_is_value_prop_name (property)))
183+
{
184+
property_p = ecma_op_to_string (property);
185+
ecma_fast_free_value (property);
186+
187+
if (JERRY_UNLIKELY (property_p == NULL))
188+
{
189+
ecma_free_value (base);
190+
return ECMA_VALUE_ERROR;
191+
}
192+
}
193+
else
194+
{
195+
property_p = ecma_get_prop_name_from_value (property);
196+
}
197+
198+
ecma_value_t object = ecma_op_to_object (base);
199+
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (object));
200+
201+
object_p = ecma_get_object_from_value (object);
189202
ecma_op_ordinary_object_prevent_extensions (object_p);
203+
204+
result = ecma_op_object_put_with_receiver (object_p,
205+
property_p,
206+
value,
207+
base,
208+
is_strict);
209+
210+
ecma_free_value (base);
190211
}
191212
else
192213
{
193-
object_p = ecma_get_object_from_value (object);
194-
}
214+
object_p = ecma_get_object_from_value (base);
195215

196-
ecma_string_t *property_p;
197-
198-
if (!ecma_is_value_prop_name (property))
199-
{
200-
property_p = ecma_op_to_prop_name (property);
201-
ecma_fast_free_value (property);
216+
if (JERRY_UNLIKELY (!ecma_is_value_prop_name (property)))
217+
{
218+
property_p = ecma_op_to_string (property);
219+
ecma_fast_free_value (property);
202220

203-
if (JERRY_UNLIKELY (property_p == NULL))
221+
if (JERRY_UNLIKELY (property_p == NULL))
222+
{
223+
ecma_deref_object (object_p);
224+
return ECMA_VALUE_ERROR;
225+
}
226+
}
227+
else
204228
{
205-
ecma_deref_object (object_p);
206-
return ECMA_VALUE_ERROR;
229+
property_p = ecma_get_prop_name_from_value (property);
207230
}
208-
}
209-
else
210-
{
211-
property_p = ecma_get_prop_name_from_value (property);
212-
}
213231

214-
ecma_value_t completion_value = ECMA_VALUE_EMPTY;
215-
216-
if (!ecma_is_lexical_environment (object_p))
217-
{
218-
completion_value = ecma_op_object_put (object_p,
219-
property_p,
220-
value,
221-
is_strict);
222-
}
223-
else
224-
{
225-
completion_value = ecma_op_set_mutable_binding (object_p,
226-
property_p,
227-
value,
228-
is_strict);
232+
if (!ecma_is_lexical_environment (object_p))
233+
{
234+
result = ecma_op_object_put_with_receiver (object_p,
235+
property_p,
236+
value,
237+
base,
238+
is_strict);
239+
}
240+
else
241+
{
242+
result = ecma_op_set_mutable_binding (object_p,
243+
property_p,
244+
value,
245+
is_strict);
246+
}
229247
}
230248

231249
ecma_deref_object (object_p);
232250
ecma_deref_ecma_string (property_p);
233-
234-
return completion_value;
251+
return result;
235252
} /* vm_op_set_value */
236253

237254
/** Compact bytecode define */
@@ -3882,9 +3899,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
38823899
else if (opcode_data & VM_OC_PUT_REFERENCE)
38833900
{
38843901
ecma_value_t property = *(--stack_top_p);
3885-
ecma_value_t object = *(--stack_top_p);
3902+
ecma_value_t base = *(--stack_top_p);
38863903

3887-
if (object == ECMA_VALUE_REGISTER_REF)
3904+
if (base == ECMA_VALUE_REGISTER_REF)
38883905
{
38893906
property = (ecma_value_t) ecma_get_integer_from_value (property);
38903907
ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, property));
@@ -3898,7 +3915,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
38983915
}
38993916
else
39003917
{
3901-
ecma_value_t set_value_result = vm_op_set_value (object,
3918+
ecma_value_t set_value_result = vm_op_set_value (base,
39023919
property,
39033920
result,
39043921
is_strict);

tests/jerry/getter-setter-this-value.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,19 @@ Object.defineProperty(Box.prototype, 'data', {
3232
assert(box.data === '=');
3333
box.data = '+';
3434
assert(box.data === '+');
35+
36+
function test_access(value, proto) {
37+
"use strict"
38+
39+
Object.defineProperty(proto, 'test', {
40+
get: function () { assert (this === value) },
41+
set: function () { assert (this === value) }
42+
});
43+
44+
value.test;
45+
value.test = undefined;
46+
}
47+
48+
test_access ("str", String.prototype);
49+
test_access (1, Number.prototype);
50+
test_access (true, Boolean.prototype);

0 commit comments

Comments
 (0)