Skip to content

Commit a74920b

Browse files
committed
Fix the result value of Map#keys() (as part of PHP array proxies into JS).
1 parent 347e009 commit a74920b

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

src/node_php_phpobject_class.cc

+17-1
Original file line numberDiff line numberDiff line change
@@ -640,10 +640,14 @@ class PhpObject::PhpInvokeMsg : public MessageToPhp {
640640
objid_t obj, v8::Local<v8::String> method,
641641
const Nan::FunctionCallbackInfo<v8::Value> &info)
642642
: MessageToPhp(m, callback, is_sync), method_(m, method),
643-
argc_(info.Length()), argv_(Value::NewArray(m, info)) {
643+
argc_(info.Length()), argv_(Value::NewArray(m, info)),
644+
should_convert_array_to_iterator_(false) {
644645
obj_.SetJsObject(obj);
645646
}
646647
~PhpInvokeMsg() override { delete[] argv_; }
648+
inline bool should_convert_array_to_iterator() {
649+
return should_convert_array_to_iterator_;
650+
}
647651

648652
protected:
649653
bool IsEmptyRetvalOk() override {
@@ -756,6 +760,8 @@ class PhpObject::PhpInvokeMsg : public MessageToPhp {
756760
return;
757761
}
758762
if (0 == strcmp(cname, "keys")) {
763+
// Map#keys() should actually return an Iterator, not an array.
764+
should_convert_array_to_iterator_ = true;
759765
return PhpObject::ArrayEnum(m, EnumOp::ALL, arr,
760766
&retval_, &exception_ TSRMLS_CC);
761767
}
@@ -784,6 +790,7 @@ class PhpObject::PhpInvokeMsg : public MessageToPhp {
784790
Value method_;
785791
int argc_;
786792
Value *argv_;
793+
bool should_convert_array_to_iterator_;
787794
};
788795

789796

@@ -808,6 +815,15 @@ void PhpObject::MethodThunk_(v8::Local<v8::String> method,
808815
THROW_IF_EXCEPTION("PHP exception thrown during method invocation", /* */);
809816
if (msg.retval().IsEmpty()) {
810817
info.GetReturnValue().Set(Nan::Undefined());
818+
} else if (msg.should_convert_array_to_iterator()) {
819+
// Map#keys() method should actually return an iterator, not an
820+
// array, so call Array#values() on the result.
821+
v8::Local<v8::Array> r = msg.retval().ToJs(channel_).As<v8::Array>();
822+
v8::Local<v8::Object> values = Nan::Get(r, NEW_STR("values"))
823+
.ToLocalChecked().As<v8::Object>();
824+
Nan::MaybeLocal<v8::Value> newr =
825+
Nan::CallAsFunction(values, r, 0, nullptr);
826+
if (!newr.IsEmpty()) { info.GetReturnValue().Set(newr.ToLocalChecked()); }
811827
} else {
812828
info.GetReturnValue().Set(msg.retval().ToJs(channel_));
813829
}

0 commit comments

Comments
 (0)