mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 848062 - Make arrow functions inherit the value of 'this' from the enclosing scope. r=bhackett.
This commit is contained in:
parent
7471460fe5
commit
17cbc269fd
@ -6929,6 +6929,9 @@ bool
|
||||
IonBuilder::jsop_lambda(JSFunction *fun)
|
||||
{
|
||||
JS_ASSERT(script()->analysis()->usesScopeChain());
|
||||
if (fun->isArrow())
|
||||
return abort("bound arrow function");
|
||||
|
||||
MLambda *ins = MLambda::New(current->scopeChain(), fun);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
17
js/src/jit-test/tests/arrow-functions/this-1.js
Normal file
17
js/src/jit-test/tests/arrow-functions/this-1.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 'this' is lexically scoped in arrow functions
|
||||
|
||||
var obj = {
|
||||
f: function (expected) {
|
||||
assertEq(this, expected);
|
||||
return a => this;
|
||||
}
|
||||
};
|
||||
|
||||
var g = obj.f(obj);
|
||||
assertEq(g(), obj);
|
||||
|
||||
var obj2 = {f: obj.f};
|
||||
var g2 = obj2.f(obj2);
|
||||
assertEq(g2(), obj2);
|
||||
assertEq(g(), obj);
|
||||
|
14
js/src/jit-test/tests/arrow-functions/this-2.js
Normal file
14
js/src/jit-test/tests/arrow-functions/this-2.js
Normal file
@ -0,0 +1,14 @@
|
||||
// 'this' is lexically scoped in direct eval code in arrow functions
|
||||
|
||||
var obj = {
|
||||
f: function (s) {
|
||||
dis();
|
||||
return a => eval(s);
|
||||
}
|
||||
};
|
||||
|
||||
var g = obj.f("this");
|
||||
assertEq(g(), obj);
|
||||
|
||||
var obj2 = {g: g, fail: true};
|
||||
assertEq(obj2.g(), obj);
|
13
js/src/jit-test/tests/arrow-functions/this-3.js
Normal file
13
js/src/jit-test/tests/arrow-functions/this-3.js
Normal file
@ -0,0 +1,13 @@
|
||||
// 'this' is lexically scoped in arrow functions in direct eval code
|
||||
|
||||
var obj = {
|
||||
f: function (s) {
|
||||
return eval(s);
|
||||
}
|
||||
};
|
||||
|
||||
var g = obj.f("a => this");
|
||||
assertEq(g(), obj);
|
||||
|
||||
var obj2 = {g: g, fail: true};
|
||||
assertEq(obj2.g(), obj);
|
5
js/src/jit-test/tests/arrow-functions/this-4.js
Normal file
5
js/src/jit-test/tests/arrow-functions/this-4.js
Normal file
@ -0,0 +1,5 @@
|
||||
// 'this' in a toplevel arrow is the global object.
|
||||
|
||||
var f = () => this;
|
||||
assertEq(f(), this);
|
||||
assertEq({f: f}.f(), this);
|
@ -623,6 +623,16 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
|
||||
StringBuffer out(cx);
|
||||
RootedScript script(cx);
|
||||
|
||||
// If the object is an automatically-bound arrow function, get the source
|
||||
// of the pre-binding target.
|
||||
if (fun->isBoundFunction()) {
|
||||
JSObject *target = fun->getBoundFunctionTarget();
|
||||
if (target->isFunction() && target->toFunction()->isArrow()) {
|
||||
RootedFunction targetfun(cx, target->toFunction());
|
||||
return FunctionToString(cx, targetfun, bodyOnly, lambdaParen);
|
||||
}
|
||||
}
|
||||
|
||||
if (fun->hasScript()) {
|
||||
script = fun->nonLazyScript();
|
||||
if (script->isGeneratorExp) {
|
||||
|
@ -724,6 +724,9 @@ UseNewTypeForClone(JSFunction *fun)
|
||||
if (fun->nonLazyScript()->shouldCloneAtCallsite)
|
||||
return true;
|
||||
|
||||
if (fun->isArrow())
|
||||
return true;
|
||||
|
||||
if (fun->hasSingletonType())
|
||||
return false;
|
||||
|
||||
|
@ -2775,10 +2775,9 @@ BEGIN_CASE(JSOP_LAMBDA)
|
||||
RootedFunction &fun = rootFunction0;
|
||||
fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
|
||||
|
||||
JSFunction *obj = CloneFunctionObjectIfNotSingleton(cx, fun, regs.fp()->scopeChain());
|
||||
JSObject *obj = Lambda(cx, fun, regs.fp()->scopeChain());
|
||||
if (!obj)
|
||||
goto error;
|
||||
|
||||
JS_ASSERT(obj->getProto());
|
||||
PUSH_OBJECT(*obj);
|
||||
}
|
||||
@ -3461,6 +3460,20 @@ js::Lambda(JSContext *cx, HandleFunction fun, HandleObject parent)
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
if (fun->isArrow()) {
|
||||
StackFrame *fp = cx->fp();
|
||||
|
||||
// Note that this will assert if called from Ion code. Ion can't yet
|
||||
// emit code for a bound arrow function (bug 851913).
|
||||
if (!ComputeThis(cx, fp))
|
||||
return NULL;
|
||||
|
||||
RootedValue thisval(cx, fp->thisValue());
|
||||
clone = js_fun_bind(cx, clone, thisval, NULL, 0);
|
||||
if (!clone)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_ASSERT(clone->global() == clone->global());
|
||||
return clone;
|
||||
}
|
||||
|
@ -1016,11 +1016,11 @@ JSObject * JS_FASTCALL
|
||||
stubs::Lambda(VMFrame &f, JSFunction *fun_)
|
||||
{
|
||||
RootedFunction fun(f.cx, fun_);
|
||||
fun = CloneFunctionObjectIfNotSingleton(f.cx, fun, f.fp()->scopeChain());
|
||||
if (!fun)
|
||||
JSObject *clone = Lambda(f.cx, fun, f.fp()->scopeChain());
|
||||
if (!clone)
|
||||
THROWV(NULL);
|
||||
|
||||
return fun;
|
||||
return clone;
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
|
Loading…
Reference in New Issue
Block a user