reflection for namespaced constants
In repo mode this does the right thing and returns the right constant, but for non-repo it thinks it is an undefined non-namespace constant. I'll have to do something more hardcore if that starts to matter While I was in there, I made the correct name for `ReflectionParameter` that was added in 5.4 instead of the draft we copied.
Esse commit está contido em:
@@ -277,5 +277,5 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
// code generation functions
|
||||
|
||||
void ConstantExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
cg_printf("%s", m_name.c_str());
|
||||
cg_printf("%s", getNonNSOriginalName().c_str());
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ public:
|
||||
bool m_dbgNoBreak;
|
||||
bool doFCall(HPHP::ActRec* ar, PC& pc);
|
||||
bool doFCallArray(PC& pc);
|
||||
CVarRef getEvaledArg(const StringData* val);
|
||||
CVarRef getEvaledArg(const StringData* val, CStrRef namespacedName);
|
||||
private:
|
||||
void enterVMWork(ActRec* enterFnAr);
|
||||
void enterVMPrologue(ActRec* enterFnAr);
|
||||
|
||||
@@ -449,7 +449,10 @@ static void set_function_info(Array &ret, const Func* func) {
|
||||
// undefined class constants can cause the eval() to
|
||||
// fatal. Zend lets such fatals propagate, so don't bother catching
|
||||
// exceptions here.
|
||||
CVarRef v = g_vmContext->getEvaledArg(fpi.phpCode());
|
||||
CVarRef v = g_vmContext->getEvaledArg(
|
||||
fpi.phpCode(),
|
||||
func->cls() ? func->cls()->nameRef() : func->nameRef()
|
||||
);
|
||||
param.set(s_default, v);
|
||||
}
|
||||
param.set(s_defaultText, VarNR(fpi.phpCode()));
|
||||
|
||||
@@ -2479,14 +2479,29 @@ bool VMExecutionContext::evalUnit(Unit* unit, PC& pc, int funcType) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
CVarRef VMExecutionContext::getEvaledArg(const StringData* val) {
|
||||
StaticString
|
||||
s_php_namespace("<?php namespace "),
|
||||
s_curly_return(" { return "),
|
||||
s_semicolon_curly("; }"),
|
||||
s_php_return("<?php return "),
|
||||
s_semicolon(";");
|
||||
CVarRef VMExecutionContext::getEvaledArg(const StringData* val,
|
||||
CStrRef namespacedName) {
|
||||
CStrRef key = *(String*)&val;
|
||||
|
||||
if (m_evaledArgs.get()) {
|
||||
CVarRef arg = m_evaledArgs.get()->get(key);
|
||||
if (&arg != &null_variant) return arg;
|
||||
}
|
||||
String code = HPHP::concat3("<?php return ", key, ";");
|
||||
|
||||
String code;
|
||||
int pos = namespacedName.rfind('\\');
|
||||
if (pos != -1) {
|
||||
auto ns = namespacedName.substr(0, pos);
|
||||
code = s_php_namespace + ns + s_curly_return + key + s_semicolon_curly;
|
||||
} else {
|
||||
code = s_php_return + key + s_semicolon;
|
||||
}
|
||||
Unit* unit = compileEvalString(code.get());
|
||||
assert(unit != nullptr);
|
||||
Variant v;
|
||||
|
||||
@@ -587,7 +587,10 @@ void Func::getFuncInfo(ClassInfo::MethodInfo* mi) const {
|
||||
// that access of undefined class constants can cause the eval() to
|
||||
// fatal. Zend lets such fatals propagate, so don't bother catching
|
||||
// exceptions here.
|
||||
CVarRef v = g_vmContext->getEvaledArg(fpi.phpCode());
|
||||
CVarRef v = g_vmContext->getEvaledArg(
|
||||
fpi.phpCode(),
|
||||
cls() ? cls()->nameRef() : nameRef()
|
||||
);
|
||||
pi->value = strdup(f_serialize(v).get()->data());
|
||||
}
|
||||
// This is a raw char*, but its lifetime should be at least as long
|
||||
|
||||
@@ -306,7 +306,25 @@ class ReflectionParameter implements Reflector {
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function getDefaultValueText() {
|
||||
return $this->getDefaultValueConstantName();
|
||||
}
|
||||
|
||||
// This doc comment block generated by idl/sysdoc.php
|
||||
/**
|
||||
* ( excerpt from
|
||||
* http://php.net/manual/en/reflectionparameter.getdefaultvalueconstantname.php
|
||||
* )
|
||||
*
|
||||
* WarningThis function is currently not documented; only its argument
|
||||
* list is available.
|
||||
*
|
||||
* @return mixed Returns string on success or NULL on failure.
|
||||
*/
|
||||
public function getDefaultValueConstantName() {
|
||||
if (isset($this->info['defaultText'])) {
|
||||
return $this->info['defaultText'];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace A {
|
||||
const B = 'c';
|
||||
class D {
|
||||
public function e($f = PHP_VERSION, $g = B,
|
||||
$h = array(PHP_VERSION), $i = array(B)) {
|
||||
}
|
||||
}
|
||||
function j($k = PHP_VERSION, $l = B, $m = array(PHP_VERSION), $n = array(B)) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
$tests = array(
|
||||
new ReflectionMethod('A\D', 'e'),
|
||||
new ReflectionFunction('A\j'),
|
||||
);
|
||||
foreach ($tests as $method) {
|
||||
$params = $method->getParameters();
|
||||
foreach ($params as $param) {
|
||||
var_dump(
|
||||
$param->getDefaultValue(),
|
||||
$param->getDefaultValueConstantName()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
string(14) "5.4.999-hiphop"
|
||||
string(11) "PHP_VERSION"
|
||||
string(1) "c"
|
||||
string(1) "B"
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(14) "5.4.999-hiphop"
|
||||
}
|
||||
string(18) "array(PHP_VERSION)"
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
}
|
||||
string(%d) "array%w(%a)"
|
||||
string(14) "5.4.999-hiphop"
|
||||
string(11) "PHP_VERSION"
|
||||
string(1) "c"
|
||||
string(1) "B"
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(14) "5.4.999-hiphop"
|
||||
}
|
||||
string(18) "array(PHP_VERSION)"
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
}
|
||||
string(%d) "array%w(%a)"
|
||||
Referência em uma Nova Issue
Bloquear um usuário