The following code prints 1
in Safari 13.0.4 on OSX.
let set = new Set
for(let x = 0; x < 2; x++) {
function f() {}
set.add(f)
}
console.log(set.size) // 1 in Safari non-strict mode
Also:
let set = new Set
for(let x = 0; x < 2; x++) {
function f() {}
f.test = x
set.add(f)
}
console.log(set.size); // 1 in Safari
for(let x of set) console.log(x.test) // 1 in Safari non-strict mode
And:
let set = new Set;
for(let x = 0; x < 2; x++) {
var v = (function () {})
set.add(v);
}
console.log(set.size); // 2 in Safari non-strict mode
Is this behavior compatible with section 13.7.4.8 (see below) of the specification?
Note that: Node 13.9.0, Chrome 80.0.3987.122, and Brave 1.3.118 print 2
.
13.7.4.8 of the spec:
(4.b seems pertinent)
The abstract operation ForBodyEvaluation with arguments test,
increment, stmt, perIterationBindings, and labelSet is
performed as follows:
1. Let V = undefined.
2. Let status be CreatePerIterationEnvironment(perIterationBindings).
3. ReturnIfAbrupt(status).
4. Repeat
a. If test is not [empty], then
i. Let testRef be the result of evaluating test.
ii. Let testValue be GetValue(testRef).
iii. ReturnIfAbrupt(testValue).
iv. If ToBoolean(testValue) is false, return NormalCompletion(V).
b. Let result be the result of evaluating stmt.
c. If LoopContinues(result, labelSet) is false, return d.
Completion(UpdateEmpty(result, V)).
d. If result.[[value]] is not empty, let V = result.[[value]].
e. Let status be CreatePerIterationEnvironment(perIterationBindings).
f. ReturnIfAbrupt(status).
g. If increment is not [empty], then
i. Let incRef be the result of evaluating increment.
ii. Let incValue be GetValue(incRef).
iii. ReturnIfAbrupt(incValue).