8.7.2 PutValue

2010-04-19

void PutValue(R:Reference, W: mixed)

Put the value W at whatever reference R is pointing to.

Code: (Abstract Ecma)
function PutValue(R,W){
if (Type(R) != 'Reference') throw ReferenceError;
var base = GetBase(R);
if (IsUnresolvedReference(R)) {
if (IsStrictReference(R)) throw ReferenceError;
global.[[Put]](GetReferencedName(R), W, false);
} else if (IsPropertyReference(R)) {
if (HasPrimitive(R)) {
var put = function(P,W,Throw){
var O = ToObject(base);
if (!O.[[CanPut]]) {
if (Throw) throw TypeError;
return;
}
var ownDesc = O.[[GetOwnProperty]](P);
if (IsDataDescriptor(ownDesc)) {
if (Throw) throw TypeError;
return;
}
var desc = O.[[GetProperty]](P); // own/inherited accessor property or inherited data property
if (IsAccessorDescriptor(desc)) {
var setter = desc.[[Set]]; // cannot be undefined
setter.[[Call]](base, W);
} else {
if (Throw) throw TypeError;
}
};
} else {
var put = base.[[Put]];
}
put.[[Call]](base, GetReferencedName(V), W, IsStrictReference(R));
} else { // base must be environment record
base.[[SetMutableBinding]](GetRefrencedName(R), W, IsStrictReference(R));
}
}

The spec also says that the object created in the inner function can be skipped if an implementor wants to. The object can only be gotten through accessors or one of the throws. If any properties are created on that object while Trow is true, an error will be thrown. You don't have to worry about this unless you're actually trying :)