12016-04-06 Saam barati <sbarati@apple.com>
2
3 Initial implementation of annex b.3.3 behavior was incorrect
4 https://bugs.webkit.org/show_bug.cgi?id=156276
5
6 Reviewed by Keith Miller.
7
8 I almost got annex B.3.3 correct in my first implementation.
9 There is a subtlety here I got wrong. We always create a local binding for
10 a function at the very beginning of execution of a block scope. So we
11 hoist function declarations to their local binding within a given
12 block scope. When we actually evaluate the function declaration statement
13 itself, we must lookup the binding in the current scope, and bind the
14 value to the binding in the "var" scope. We perform the following
15 abstract operations when executing a function declaration statement.
16
17 f = lookupBindingInCurrentScope("func")
18 store(varScope, "func", f)
19
20 I got this wrong by performing the store to the var binding at the beginning
21 of the block scope instead of when we evaluate the function declaration statement.
22 This behavior is observable. For example, a program could change the value
23 of "func" before the actual function declaration statement executes.
24 Consider the following two functions:
25 ```
26 function foo1() {
27 // func === undefined
28 {
29 // typeof func === "function"
30 function func() { } // Executing this statement binds the local "func" binding to the implicit "func" var binding.
31 func = 20 // This sets the local "func" binding to 20.
32 }
33 // typeof func === "function"
34 }
35
36 function foo2() {
37 // func === undefined
38 {
39 // typeof func === "function"
40 func = 20 // This sets the local "func" binding to 20.
41 function func() { } // Executing this statement binds the local "func" binding to the implicit "func" var binding.
42 }
43 // func === 20
44 }
45 ```
46
47 * bytecompiler/BytecodeGenerator.cpp:
48 (JSC::BytecodeGenerator::initializeBlockScopedFunctions):
49 (JSC::BytecodeGenerator::hoistSloppyModeFunctionIfNecessary):
50 * bytecompiler/BytecodeGenerator.h:
51 (JSC::BytecodeGenerator::emitNodeForLeftHandSide):
52 * bytecompiler/NodesCodegen.cpp:
53 (JSC::FuncDeclNode::emitBytecode):
54 * tests/stress/sloppy-mode-function-hoisting.js:
55 (test.foo):
56 (test):
57 (test.):
58 (test.bar):
59 (test.switch.case.0):
60 (test.capFoo1):
61 (test.switch.capFoo2):
62 (test.outer):
63 (foo):
64