Skip to content

Commit

Permalink
Return varray / darray from ext_soap
Browse files Browse the repository at this point in the history
Summary: `ext_soap` is a nest of PHP arrays and zend values: let's try to return `varray` and `darray` where we can.

Reviewed By: jjgriego

Differential Revision: D10446808

fbshipit-source-id: 09f5af8e7bc06b1d7b5273cdd1b5d7b9d6f28bc5
  • Loading branch information
hgoldstein authored and hhvm-bot committed Nov 17, 2018
1 parent 1b01e01 commit 253b620
Show file tree
Hide file tree
Showing 22 changed files with 827 additions and 29 deletions.
38 changes: 18 additions & 20 deletions hphp/runtime/ext/soap/ext_soap.cpp
Expand Up @@ -27,6 +27,7 @@
#include "hphp/runtime/base/comparisons.h" #include "hphp/runtime/base/comparisons.h"
#include "hphp/runtime/base/http-client.h" #include "hphp/runtime/base/http-client.h"
#include "hphp/runtime/base/php-globals.h" #include "hphp/runtime/base/php-globals.h"
#include "hphp/runtime/base/type-variant.h"
#include "hphp/runtime/server/http-protocol.h" #include "hphp/runtime/server/http-protocol.h"
#include "hphp/runtime/ext/soap/soap.h" #include "hphp/runtime/ext/soap/soap.h"
#include "hphp/runtime/ext/soap/packet.h" #include "hphp/runtime/ext/soap/packet.h"
Expand Down Expand Up @@ -2098,15 +2099,19 @@ Variant HHVM_METHOD(SoapServer, getfunctions) {
} else if (data->m_type == SOAP_CLASS) { } else if (data->m_type == SOAP_CLASS) {
class_name = data->m_soap_class.name; class_name = data->m_soap_class.name;
} else if (data->m_soap_functions.functions_all) { } else if (data->m_soap_functions.functions_all) {
return Unit::getSystemFunctions() + Unit::getUserFunctions(); return (Unit::getSystemFunctions() + Unit::getUserFunctions()).toVArray();
} else if (!data->m_soap_functions.ft.empty()) { } else if (!data->m_soap_functions.ft.empty()) {
return array_keys_helper(data->m_soap_functions.ftOriginal); auto ret = array_keys_helper(data->m_soap_functions.ftOriginal);
if (ret.isArray()) {
return ret.toVArray();
}
return ret;
} }


Class* cls = Unit::lookupClass(class_name.get()); Class* cls = Unit::lookupClass(class_name.get());
auto ret = Array::attach(PackedArray::MakeReserve(cls->numMethods())); auto ret = Array::attach(PackedArray::MakeReserve(cls->numMethods()));
Class::getMethodNames(cls, nullptr, ret); Class::getMethodNames(cls, nullptr, ret);
return Variant::attach(HHVM_FN(array_values)(ret)); return ret.toVArray();
} }


static bool valid_function(SoapServer *server, Object &soap_obj, static bool valid_function(SoapServer *server, Object &soap_obj,
Expand Down Expand Up @@ -2543,12 +2548,13 @@ void HHVM_METHOD(SoapClient, __construct,
} }
} }


Variant HHVM_METHOD(SoapClient, __soapcall, Variant HHVM_METHOD(SoapClient, soapcallImpl,
const String& name, const String& name,
const Array& args, const Array& args,
const Array& options = null_array, const Array& options = null_array,
const Variant& input_headers = uninit_variant, const Variant& input_headers = uninit_variant,
VRefParam output_headers_ref = init_null()) { VRefParam output_headers_ref = init_null()) {
SuppressHACRefBindNotices shacn;
auto* data = Native::data<SoapClient>(this_); auto* data = Native::data<SoapClient>(this_);
SoapClientScope ss(this_); SoapClientScope ss(this_);


Expand Down Expand Up @@ -2706,13 +2712,6 @@ Variant HHVM_METHOD(SoapClient, __soapcall,
return return_value; return return_value;
} }


Variant HHVM_METHOD(SoapClient, __call,
const Variant& name,
const Variant& args) {
return HHVM_MN(SoapClient, __soapcall)(this_, name.toString(),
args.toArray());
}

Variant HHVM_METHOD(SoapClient, __getlastrequest) { Variant HHVM_METHOD(SoapClient, __getlastrequest) {
auto* data = Native::data<SoapClient>(this_); auto* data = Native::data<SoapClient>(this_);
return data->m_last_request; return data->m_last_request;
Expand All @@ -2738,13 +2737,13 @@ Variant HHVM_METHOD(SoapClient, __getfunctions) {
SoapClientScope ss(this_); SoapClientScope ss(this_);


if (data->m_sdl) { if (data->m_sdl) {
Array ret = Array::Create(); VArrayInit ret(data->m_sdl->functionsOrder.size());
for (auto& func: data->m_sdl->functionsOrder) { for (const auto& func: data->m_sdl->functionsOrder) {
StringBuffer sb; StringBuffer sb;
function_to_string(data->m_sdl->functions[func], sb); function_to_string(data->m_sdl->functions[func], sb);
ret.append(sb.detach()); ret.append(sb.detach());
} }
return ret; return ret.toArray();
} }
return init_null(); return init_null();
} }
Expand All @@ -2754,13 +2753,13 @@ Variant HHVM_METHOD(SoapClient, __gettypes) {
SoapClientScope ss(this_); SoapClientScope ss(this_);


if (data->m_sdl) { if (data->m_sdl) {
Array ret = Array::Create(); VArrayInit ret(data->m_sdl->types.size());
for (unsigned int i = 0; i < data->m_sdl->types.size(); i++) { for (const auto& type: data->m_sdl->types) {
StringBuffer sb; StringBuffer sb;
type_to_string(data->m_sdl->types[i].get(), sb, 0); type_to_string(type.get(), sb, 0);
ret.append(sb.detach()); ret.append(sb.detach());
} }
return ret; return ret.toArray();
} }
return init_null(); return init_null();
} }
Expand Down Expand Up @@ -3108,8 +3107,7 @@ static struct SoapExtension final : Extension {
Native::NDIFlags::NO_SWEEP); Native::NDIFlags::NO_SWEEP);


HHVM_ME(SoapClient, __construct); HHVM_ME(SoapClient, __construct);
HHVM_ME(SoapClient, __call); HHVM_ME(SoapClient, soapcallImpl);
HHVM_ME(SoapClient, __soapcall);
HHVM_ME(SoapClient, __getlastrequest); HHVM_ME(SoapClient, __getlastrequest);
HHVM_ME(SoapClient, __getlastresponse); HHVM_ME(SoapClient, __getlastresponse);
HHVM_ME(SoapClient, __getlastrequestheaders); HHVM_ME(SoapClient, __getlastrequestheaders);
Expand Down
78 changes: 69 additions & 9 deletions hphp/runtime/ext/soap/ext_soap.php
Expand Up @@ -4,7 +4,10 @@
class SoapServer { class SoapServer {


<<__Native>> <<__Native>>
function __construct(mixed $wsdl, array $options = []): void; function __construct(
mixed $wsdl,
darray<string, mixed> $options = darray[],
): void;


/** /**
* Exports all methods from specified class. The object can be made * Exports all methods from specified class. The object can be made
Expand Down Expand Up @@ -115,18 +118,75 @@ function addsoapheader(mixed $fault): void;
<<__NativeData("SoapClient")>> <<__NativeData("SoapClient")>>
class SoapClient { class SoapClient {


<<__Native>> // Clean out different kinds of arrays, recursively, from an input. For
function __construct(mixed $wsdl, array $options = []): void; // __soapcall, we want to pass in PHP arrays but receive Hack arrays, so we
// invoke cleanArrays twice: once with a PHP array as the base, once with
// a Hack array as the base.
private static function cleanArrays(
mixed $input,
mixed $base,
mixed $seen = null,
): mixed {
if ($seen === null) {
$seen = new stdClass();
$seen->set = keyset[];
}
if (HH\is_any_array($input)) {
$ret = $base;
foreach ($input as $k => $v) {
$ret[$k] = self::cleanArrays($v, $base, $seen);
}
return $ret;
} else if (is_object($input)) {
$hash = spl_object_hash($input);
if (array_key_exists($hash, $seen->set)) {
return $input;
}
$seen->set[] = $hash;
foreach ($input as $k => $v) {
$input->$k = self::cleanArrays($v, $base, $seen);
}
return $input;
}
return $input;
}


<<__Native>> <<__Native>>
function __call(mixed $name, mixed $args): mixed; function __construct(
mixed $wsdl,
darray<string, mixed> $options = darray[],
): void;


<<__Native>> <<__Native>>
function __soapcall(string $name, private function soapcallImpl(
array $args, string $name,
array $options = [], varray<mixed> $args,
mixed $input_headers = null, darray $options = darray[],
mixed &$output_headers = null): mixed; mixed $input_headers = null,
mixed &$output_headers = null
): mixed;

function __call(mixed $name, mixed $args): mixed {
return $this->__soapcall($name, $args);
}

function __soapcall(
string $name,
varray<mixed> $args,
darray $options = darray[],
mixed $input_headers = null,
mixed &$output_headers = null,
): mixed {
$args = self::cleanArrays($args, array());
$ret = $this->soapcallImpl(
$name,
varray($args),
$options,
$input_headers,
&$output_headers,
);
return self::cleanArrays($ret, darray[]);
}


<<__Native>> <<__Native>>
function __getlastrequest(): mixed; function __getlastrequest(): mixed;
Expand Down
55 changes: 55 additions & 0 deletions hphp/test/slow/dv_array/ext_soap/1809.wsdl
@@ -0,0 +1,55 @@
<?xml version="1.0" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="http://linuxsrv.home/~dmitry/soap/test.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">

<types>
<xsd:schema targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>

<message name="AddRequest">
<part name="x" type="xsd:double" />
<part name="y" type="xsd:double" />
</message>
<message name="AddResponse">
<part name="result" type="xsd:double" />
</message>

<portType name="TestServicePortType">
<operation name="Add">
<input message="tns:AddRequest" />
<output message="tns:AddResponse" />
</operation>
</portType>

<binding name="TestServiceBinding" type="tns:TestServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="Add">
<soap:operation soapAction="Add" style="rpc" />
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>

<service name="TestService">
<port name="TestServicePort" binding="tns:TestServiceBinding">
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
</port>
</service>

</definitions>
33 changes: 33 additions & 0 deletions hphp/test/slow/dv_array/ext_soap/bug38055.php
@@ -0,0 +1,33 @@
<?hh

function Test($param) {
global $g1, $g2;
$g1 = $param->boolA;
$g2 = $param->boolB;
return 1;
}

class TestSoapClient extends SoapClient {
function __construct($wsdl) {
parent::__construct($wsdl);
$this->server = new SoapServer($wsdl);
$this->server->addFunction('Test');
}

function __doRequest($request, $location, $action, $version, $one_way = 0) {
ob_start();
$this->server->handle($request);
$response = ob_get_contents();
ob_end_clean();
return $response;
}
}

$client = new TestSoapClient(dirname(__FILE__).'/bug38055.wsdl');
var_dump($client->__getfunctions());
var_dump($client->__gettypes());
$boolA = 1;
$boolB = '1';
$res = $client->Test(darray['boolA'=>$boolA, 'boolB'=>$boolB]);
var_dump($g1);
var_dump($g2);
13 changes: 13 additions & 0 deletions hphp/test/slow/dv_array/ext_soap/bug38055.php.expectf
@@ -0,0 +1,13 @@
array(1) {
[0]=>
string(26) "int Test(Test $parameters)"
}
array(1) {
[0]=>
string(47) "struct Test {
boolean boolA;
boolean boolB;
}"
}
bool(true)
bool(true)
49 changes: 49 additions & 0 deletions hphp/test/slow/dv_array/ext_soap/bug38055.wsdl
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:s0="http://test.pl"
targetNamespace="http://test.pl"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema elementFormDefault="qualified" targetNamespace="http://test.pl">
<s:complexType name="Test">
<s:attribute use="required" name="boolA" type="s:boolean"/>
<s:attribute use="required" name="boolB" type="s:boolean"/>
</s:complexType>
<s:element type="s0:Test" name="Test"/>
<s:element type="s:int" name="Ret"/>
</s:schema>
</types>

<message name="TestSoapIn">
<part name="parameters" element="s0:Test"/>
</message>
<message name="TestSoapOut">
<part name="parameters" element="s0:Ret"/>
</message>
<portType name="TestSoap">
<operation name="Test">
<input message="s0:TestSoapIn"/>
<output message="s0:TestSoapOut"/>
</operation>
</portType>
<binding name="TestSoap" type="s0:TestSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="Test">
<soap:operation soapAction="http:/Test/Test" style="document"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="Test">
<port name="TestSoapPort" binding="s0:TestSoap">
<soap:address location="http://localhost/server.php"/>
</port>
</service>
</definitions>
28 changes: 28 additions & 0 deletions hphp/test/slow/dv_array/ext_soap/config.ini
@@ -0,0 +1,28 @@
hhvm.env_variables[HPHP_INTERPRETER] = 1
hhvm.error_handling.notice_frequency = 1
hhvm.error_handling.warning_frequency = 1
hhvm.allow_hhas = true
hhvm.jit_a_size = 10485760
hhvm.jit_a_cold_size = 4194304
hhvm.jit_a_frozen_size = 6291456
hhvm.jit_a_prof_size = 6291456
hhvm.jit_global_data_size = 2097152
hhvm.thread_tc_main_buffer_size = 1048576
hhvm.thread_tc_cold_buffer_size = 1048576
hhvm.thread_tc_frozen_buffer_size = 1048576
hhvm.hack.lang.auto_typecheck = false
hhvm.hack.lang.ints_overflow_to_ints = true
hhvm.hack.lang.look_for_typechecker = false
hhvm.http.slow_query_threshold = 0
hhvm.mysql.read_timeout = 5000
hhvm.mysql.slow_query_threshold = 0
hhvm.resource_limit.serialization_size_limit = 134217728
hhvm.server_variables[ALPHA_CONSOLE] = 1
hhvm.server_variables[TFBENV] = 16777216
hhvm.hack.lang.autoprime_generators = true
hhvm.raise_missing_this = false
hhvm.php7.all = false

hhvm.force_hh = true
hhvm.hack_arr_compat_type_hint_notices = 1
hhvm.hack_arr_compat_check_ref_bind = 1

0 comments on commit 253b620

Please sign in to comment.