From a6d70040fa340985ed5d77765c698d3582c20111 Mon Sep 17 00:00:00 2001 From: ptarjan Date: Wed, 20 Mar 2013 19:39:55 -0700 Subject: [PATCH] fix static closures I added the check for this in the interpreter but ##f_array_map## re-enteres the VM via a different path than FCall. Here is the equivilent check for the VM. --- hphp/runtime/base/builtin_functions.cpp | 3 ++- hphp/runtime/vm/bytecode.cpp | 3 ++- hphp/test/vm/closure_static.php | 8 ++++++++ hphp/test/vm/closure_static.php.exp | 24 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/hphp/runtime/base/builtin_functions.cpp b/hphp/runtime/base/builtin_functions.cpp index c1d26a1d6..a5f4fee83 100644 --- a/hphp/runtime/base/builtin_functions.cpp +++ b/hphp/runtime/base/builtin_functions.cpp @@ -344,7 +344,8 @@ vm_decode_function(CVarRef function, this_ = function.asCObjRef().get(); cls = nullptr; const HPHP::VM::Func *f = this_->getVMClass()->lookupMethod(invokeStr); - if (f != nullptr && (f->attrs() & HPHP::VM::AttrStatic)) { + if (f != nullptr && + ((f->attrs() & HPHP::VM::AttrStatic) && !f->isClosureBody())) { // If __invoke is static, invoke it as such cls = this_->getVMClass(); this_ = nullptr; diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 6d4d9a9f9..b56df2e11 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -2071,7 +2071,8 @@ void VMExecutionContext::invokeFunc(TypedValue* retval, // If this is a method, either this_ or cls must be non-NULL assert(!f->preClass() || (this_ || cls)); // If this is a static method, this_ must be NULL - assert(!(f->attrs() & HPHP::VM::AttrStatic) || (!this_)); + assert(!(f->attrs() & HPHP::VM::AttrStatic && !f->isClosureBody()) || + (!this_)); // invName should only be non-NULL if we are calling __call or // __callStatic assert(!invName || f->name()->isame(s___call.get()) || diff --git a/hphp/test/vm/closure_static.php b/hphp/test/vm/closure_static.php index cbedab0ff..bc01ee4a7 100644 --- a/hphp/test/vm/closure_static.php +++ b/hphp/test/vm/closure_static.php @@ -26,7 +26,15 @@ class A { }; $a(); } + + static function d() { + var_dump(array_map(function($a) { return $a; }, array(1,2,3))); + } } (new A)->b(); +A::b(); (new A)->c(); +A::c(); +(new A)->d(); +A::d(); diff --git a/hphp/test/vm/closure_static.php.exp b/hphp/test/vm/closure_static.php.exp index 26c81027c..677f9c7ae 100644 --- a/hphp/test/vm/closure_static.php.exp +++ b/hphp/test/vm/closure_static.php.exp @@ -4,7 +4,31 @@ object(A)#1 (1) { } HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 13 NULL +HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 8 +NULL +HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 13 +NULL HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 20 NULL HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 25 NULL +HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 20 +NULL +HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 25 +NULL +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +}