Почему "foo".bar = 42; throw 'TypeError' в строгом режиме в ES6?

Согласно спецификации ES5.1, программа "use strict;" "foo".bar = 42; "use strict;" "foo".bar = 42; вызывает создание объекта String, присваивает ему свойство и затем удаляет объект, что не приводит к наблюдаемым эффектам, включая любые исключения. (Отсутствие эффекта можно подтвердить, попробовав его в ES5-совместимой реализации JS, как в Opera 12.)

В современных реализациях JS он вместо этого TypeError - попробуйте:

"use strict"; "foo".bar = 42;

Ответы

Ответ 1

Я предполагаю это здесь:

http://www.ecma-international.org/ecma-262/7.0/#sec-ordinaryset

9.1.9.1. OrdinarySet (O, P, V, Receiver)

[...]

4.b. Если Type (Receiver) не Object, верните false.

(Ранее называемый [[Set]], в ES6 §9.1.9.)

Хотя PutValue продвигает base к объекту, она не делает то же самое с приемником - GetThisValue(V) все еще вызывается на исходном V (с примитивной базой). Таким образом, GetThisValue возвращает примитив, OrdinarySet.4b не может назначить только что созданный ownDesc и возвращает false, а это в свою очередь заставляет PutValue.6d бросать TypeError, если ссылка строгая.

Соответствующая часть V8, похоже, следует той же логике:

Maybe<bool> Object::AddDataProperty(....
  if (!it->GetReceiver()->IsJSReceiver()) {
    return CannotCreateProperty(...

https://github.com/v8/v8/blob/3b39fc4dcdb6593013c497fc9e28a1d73dbcba03/src/objects.cc#L5140

Ответ 2

Ответ @georgs кажется правильной интерпретацией ES6+, но похоже, что поведение тоже не новое. Из ES5.1 PutValue:

  1. Иначе, если IsPropertyReference (V), то

    а. Если HasPrimitiveBase (V) является ложным, то пусть put будет внутренним методом [[Put]] базы, иначе пусть будет специальный [[Put]] внутренний метод, определенный ниже.

    б. Вызвать внутренний метод put, используя base, как его значение, и передать GetReferencedName (V) для имени свойства, W для значения и IsStrictReference (V) для флага Throw.

и в ссылке [[Put]]:

  1. Else, это запрос на создание собственного свойства на переходном объекте O

    а. Если Throw истинно, тогда выведите исключение TypeError.

Похоже, что Im, вероятно, неправильно читал что-то... но что еще может означать, что это скорее указывает на "это запрос на создание собственного свойства на переходном объекте O"?