From 25c9f06b38d6323b3a5231a0e92a7cddb979312e Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Thu, 18 Aug 2016 00:17:59 +0300 Subject: [PATCH 01/10] Add script to replace EXPECT block with generated, [skip ci] --- scripts/replace_expect.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 scripts/replace_expect.php diff --git a/scripts/replace_expect.php b/scripts/replace_expect.php new file mode 100644 index 0000000..1af96bd --- /dev/null +++ b/scripts/replace_expect.php @@ -0,0 +1,29 @@ +key(); + $base_name = preg_replace('/\.out$/i', '', $iterator->key()); + $test_file = $base_name .'.phpt'; + + $test_content = file_get_contents($tests_dir . '/' . $test_file); + + if (false !== ($pos = strpos($test_content, '--EXPECT--'))) { + printf("--EXPECT-- [%s]".PHP_EOL, $iterator->key()); + + $test_content = substr($test_content, 0, $pos); + $test_content .= '--EXPECT--'.PHP_EOL; + $test_content .= file_get_contents($tests_dir . '/' . $out_file); + $test_content .= PHP_EOL; + file_put_contents($tests_dir . '/' . $test_file, $test_content); + + foreach (['.diff', '.exp', '.log', '.mem', '.out', '.php'] as $ext) { + @unlink($tests_dir. '/'.$base_name . $ext); + } + } else { + printf("please, edit manually [%s]".PHP_EOL, $iterator->key()); + } +} From c2fe6e2c96ca52b9a1637d08f6932b4f1cbc8a6b Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Thu, 18 Aug 2016 00:18:46 +0300 Subject: [PATCH 02/10] Add Value::TypeOf() --- src/php_v8_value.cc | 26 +++++++++++++++ stubs/src/Value.php | 11 +++++++ tests/.testsuite.php | 18 +++++++++-- tests/.v8-helpers.php | 5 +++ tests/004-ICU-Intl_DateTimeFormat.phpt | 2 +- tests/004-ICU-Intl_NumberFormat.phpt | 2 +- tests/V8ArrayObject.phpt | 14 ++++---- tests/V8Boolean.phpt | 2 ++ tests/V8BooleanObject.phpt | 4 +++ tests/V8DateObject.phpt | 2 ++ tests/V8Exception_CreateMessage.phpt | 2 ++ tests/V8Exception_Error.phpt | 2 ++ tests/V8Exception_RangeError.phpt | 2 ++ tests/V8Exception_ReferenceError.phpt | 2 ++ tests/V8Exception_SyntaxError.phpt | 2 ++ tests/V8Exception_TypeError.phpt | 2 ++ tests/V8FunctionObject.phpt | 4 +-- tests/V8Int32Value.phpt | 6 +++- tests/V8IntegerValue.phpt | 6 +++- tests/V8Isolate_ThrowException.phpt | 6 ++++ tests/V8NameValue.phpt | 10 ++++-- tests/V8NullValue.phpt | 4 ++- tests/V8NumberObject.phpt | 4 +++ tests/V8NumberValue.phpt | 4 ++- tests/V8ObjectValue.phpt | 20 ++++++------ tests/V8PrimitiveValue.phpt | 6 +++- tests/V8RegExpObject.phpt | 2 ++ tests/V8Script.phpt | 2 ++ tests/V8Script_Run.phpt | 2 ++ tests/V8StringObject.phpt | 6 +++- tests/V8StringValue.phpt | 8 +++-- tests/V8SymbolObject.phpt | 4 ++- tests/V8SymbolValue.phpt | 44 ++++++++++++++++---------- tests/V8Uint32Value.phpt | 4 ++- tests/V8Value.phpt | 8 ++++- 35 files changed, 194 insertions(+), 54 deletions(-) diff --git a/src/php_v8_value.cc b/src/php_v8_value.cc index 644b310..a656acb 100644 --- a/src/php_v8_value.cc +++ b/src/php_v8_value.cc @@ -1050,6 +1050,26 @@ static PHP_METHOD(V8Value, SameValue) { RETVAL_BOOL(val); } +static PHP_METHOD(V8Value, TypeOf) { + zval *php_v8_isolate_zv; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &php_v8_isolate_zv) == FAILURE) { + return; + } + + PHP_V8_ISOLATE_FETCH_WITH_CHECK(php_v8_isolate_zv, php_v8_isolate); + PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value); + + PHP_V8_DATA_ISOLATES_CHECK_USING(php_v8_value, php_v8_isolate); + + PHP_V8_ENTER_STORED_ISOLATE(php_v8_value); + + v8::Local local_string = php_v8_value_get_value_local(isolate, php_v8_value)->TypeOf(isolate); + + PHP_V8_THROW_EXCEPTION_WHEN_EMPTY(local_string, "Failed to get type of value"); + + php_v8_get_or_create_value(return_value, local_string, isolate); +} ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_value___construct, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) @@ -1175,6 +1195,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_value_SameValue, ZEND_SEND_BY_VAL, ZEND_RETURN ZEND_ARG_OBJ_INFO(0, that, V8\\Value, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_value_TypeOf, ZEND_RETURN_VALUE, 0, IS_OBJECT, PHP_V8_NS "\\StringValue", 0) + ZEND_ARG_OBJ_INFO(0, isolate, V8\\Isolate, 0) +ZEND_END_ARG_INFO() + static const zend_function_entry php_v8_value_methods[] = { PHP_ME(V8Value, __construct, arginfo_v8_value___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) @@ -1222,6 +1246,8 @@ static const zend_function_entry php_v8_value_methods[] = { PHP_ME(V8Value, Equals, arginfo_v8_value_Equals, ZEND_ACC_PUBLIC) PHP_ME(V8Value, StrictEquals, arginfo_v8_value_StrictEquals, ZEND_ACC_PUBLIC) PHP_ME(V8Value, SameValue, arginfo_v8_value_SameValue, ZEND_ACC_PUBLIC) + PHP_ME(V8Value, TypeOf, arginfo_v8_value_TypeOf, ZEND_ACC_PUBLIC) + PHP_FE_END }; diff --git a/stubs/src/Value.php b/stubs/src/Value.php index 1e49732..ce94d79 100644 --- a/stubs/src/Value.php +++ b/stubs/src/Value.php @@ -406,10 +406,21 @@ public function SameValue(Value $that) { } + // /** // * @param Value $value // * @return Value // */ ////template V8_INLINE static Value* Cast(T* value); // public static function Cast(Value $value) {} +// Local TypeOf(v8::Isolate*); + + /** + * @param Isolate $isolate + * + * @return StringValue + */ + public function TypeOf(Isolate $isolate) : StringValue + { + } } diff --git a/tests/.testsuite.php b/tests/.testsuite.php index e25466e..71ff5f1 100644 --- a/tests/.testsuite.php +++ b/tests/.testsuite.php @@ -34,6 +34,11 @@ public function header($title) echo str_repeat('-', strlen($title) + 1), PHP_EOL; } + public function inline($message, $value) + { + echo $message, ': ', $value, PHP_EOL; + } + public function space($new_lines_number = 2) { echo str_repeat(PHP_EOL, max(1, $new_lines_number)); @@ -448,11 +453,16 @@ class CallChainFinalizer extends DefaultFinalizer { * @var array */ private $args; + /** + * @var bool + */ + private $expanded; - public function __construct(array $map = [], array $args = []) + public function __construct(array $map = [], array $args = [], $expanded = true) { $this->map = $map; $this->args = $args; + $this->expanded = $expanded; } public function finalize($res, Throwable $exception = null) : string @@ -484,7 +494,11 @@ public function finalize($res, Throwable $exception = null) : string // TODO: at this place exception possible $res = $res->$method(...$args); - return PHP_EOL . ' ' . '@@' .$cls . '->'. $method .'(): ' . parent::finalize($res, $exception); + if ($this->expanded) { + return PHP_EOL . ' ' . '@@' .$cls . '->'. $method .'(): ' . parent::finalize($res, $exception); + } + + return $cls.'->'. $method .'(): ' . parent::finalize($res, $exception); } } diff --git a/tests/.v8-helpers.php b/tests/.v8-helpers.php index 5bf9939..a36049e 100644 --- a/tests/.v8-helpers.php +++ b/tests/.v8-helpers.php @@ -115,6 +115,11 @@ public function run_checks(\V8\Value $value, $title=null) { $title = $title ?: 'Checks on ' . get_class($value); $this->testsuite->header($title); + $filter = new ArrayListFilter(['TypeOf'], false); + $finalizer = new CallChainFinalizer([\V8\StringValue::class => 'Value'], [], false); + $this->testsuite->dump_object_methods($value, ['@@default' => [$value->GetIsolate()]], $filter, $finalizer); + $this->testsuite->line(); + $filter = new RegexpFilter('/^Is/'); $this->testsuite->dump_object_methods($value, [], $filter); $this->testsuite->space(); diff --git a/tests/004-ICU-Intl_DateTimeFormat.phpt b/tests/004-ICU-Intl_DateTimeFormat.phpt index cad53bf..44fc4a0 100644 --- a/tests/004-ICU-Intl_DateTimeFormat.phpt +++ b/tests/004-ICU-Intl_DateTimeFormat.phpt @@ -1,7 +1,7 @@ --TEST-- ICU - Intl.DateTimeFormat() --SKIPIF-- - + --ENV-- TZ=UTC --INI-- diff --git a/tests/004-ICU-Intl_NumberFormat.phpt b/tests/004-ICU-Intl_NumberFormat.phpt index d9f11b9..1959c5d 100644 --- a/tests/004-ICU-Intl_NumberFormat.phpt +++ b/tests/004-ICU-Intl_NumberFormat.phpt @@ -1,7 +1,7 @@ --TEST-- ICU - Intl.NumberFormat() --SKIPIF-- - + --FILE-- ToBoolean(): - object(V8\BooleanValue)#93 (1) { + object(V8\BooleanValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -145,7 +145,7 @@ V8\ArrayObject(V8\Value)->ToBoolean(): } } V8\ArrayObject(V8\Value)->ToNumber(): - object(V8\NumberValue)#93 (1) { + object(V8\NumberValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -161,7 +161,7 @@ V8\ArrayObject(V8\Value)->ToNumber(): } } V8\ArrayObject(V8\Value)->ToString(): - object(V8\StringValue)#93 (1) { + object(V8\StringValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -177,7 +177,7 @@ V8\ArrayObject(V8\Value)->ToString(): } } V8\ArrayObject(V8\Value)->ToDetailString(): - object(V8\StringValue)#93 (1) { + object(V8\StringValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -246,7 +246,7 @@ V8\ArrayObject(V8\Value)->ToObject(): } } V8\ArrayObject(V8\Value)->ToInteger(): - object(V8\NumberValue)#93 (1) { + object(V8\NumberValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -262,7 +262,7 @@ V8\ArrayObject(V8\Value)->ToInteger(): } } V8\ArrayObject(V8\Value)->ToUint32(): - object(V8\NumberValue)#93 (1) { + object(V8\NumberValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -278,7 +278,7 @@ V8\ArrayObject(V8\Value)->ToUint32(): } } V8\ArrayObject(V8\Value)->ToInt32(): - object(V8\NumberValue)#93 (1) { + object(V8\NumberValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8Boolean.phpt b/tests/V8Boolean.phpt index 19b5a35..4a0f081 100644 --- a/tests/V8Boolean.phpt +++ b/tests/V8Boolean.phpt @@ -81,6 +81,8 @@ V8\BooleanValue->Value(): bool(true) Checkers: --------- +V8\BooleanValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(7) "boolean" + V8\BooleanValue(V8\Value)->IsUndefined(): bool(false) V8\BooleanValue(V8\Value)->IsNull(): bool(false) V8\BooleanValue(V8\Value)->IsTrue(): bool(true) diff --git a/tests/V8BooleanObject.phpt b/tests/V8BooleanObject.phpt index 6e2f460..001f5aa 100644 --- a/tests/V8BooleanObject.phpt +++ b/tests/V8BooleanObject.phpt @@ -121,6 +121,8 @@ V8\BooleanObject->ValueOf(): bool(true) Checkers: --------- +V8\BooleanObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\BooleanObject(V8\ObjectValue)->IsCallable(): bool(false) V8\BooleanObject(V8\Value)->IsUndefined(): bool(false) V8\BooleanObject(V8\Value)->IsNull(): bool(false) @@ -152,6 +154,8 @@ typeof val: object Checkers on boxed from script: ------------------------------ +V8\BooleanObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\BooleanObject(V8\ObjectValue)->IsCallable(): bool(false) V8\BooleanObject(V8\Value)->IsUndefined(): bool(false) V8\BooleanObject(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8DateObject.phpt b/tests/V8DateObject.phpt index 27d2b49..6f46d9e 100644 --- a/tests/V8DateObject.phpt +++ b/tests/V8DateObject.phpt @@ -179,6 +179,8 @@ V8\DateObject->ValueOf(): float(1445444940000) Checkers: --------- +V8\DateObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\DateObject(V8\ObjectValue)->IsCallable(): bool(false) V8\DateObject(V8\Value)->IsUndefined(): bool(false) V8\DateObject(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Exception_CreateMessage.phpt b/tests/V8Exception_CreateMessage.phpt index 5b9616c..96bc8ed 100644 --- a/tests/V8Exception_CreateMessage.phpt +++ b/tests/V8Exception_CreateMessage.phpt @@ -154,6 +154,8 @@ V8\Message->IsOpaque(): bool(false) Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Exception_Error.phpt b/tests/V8Exception_Error.phpt index 92b7415..174eb24 100644 --- a/tests/V8Exception_Error.phpt +++ b/tests/V8Exception_Error.phpt @@ -102,6 +102,8 @@ exception.stack: Error: foo Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Exception_RangeError.phpt b/tests/V8Exception_RangeError.phpt index 67080a4..460b8c4 100644 --- a/tests/V8Exception_RangeError.phpt +++ b/tests/V8Exception_RangeError.phpt @@ -103,6 +103,8 @@ exception.stack: RangeError: foo Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Exception_ReferenceError.phpt b/tests/V8Exception_ReferenceError.phpt index 2416574..384d009 100644 --- a/tests/V8Exception_ReferenceError.phpt +++ b/tests/V8Exception_ReferenceError.phpt @@ -103,6 +103,8 @@ exception.stack: ReferenceError: foo Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Exception_SyntaxError.phpt b/tests/V8Exception_SyntaxError.phpt index 53c7344..57c48bb 100644 --- a/tests/V8Exception_SyntaxError.phpt +++ b/tests/V8Exception_SyntaxError.phpt @@ -103,6 +103,8 @@ exception.stack: SyntaxError: foo Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Exception_TypeError.phpt b/tests/V8Exception_TypeError.phpt index 779192b..b9fbeed 100644 --- a/tests/V8Exception_TypeError.phpt +++ b/tests/V8Exception_TypeError.phpt @@ -103,6 +103,8 @@ exception.stack: TypeError: foo Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8FunctionObject.phpt b/tests/V8FunctionObject.phpt index ffd1d2c..778f2bb 100644 --- a/tests/V8FunctionObject.phpt +++ b/tests/V8FunctionObject.phpt @@ -114,7 +114,7 @@ Should output Hello World string string(11) "Script done" v8Tests\TrackingDtors\FunctionObject(V8\FunctionObject)->GetScriptOrigin(): - object(V8\ScriptOrigin)#107 (6) { + object(V8\ScriptOrigin)#108 (6) { ["resource_name":"V8\ScriptOrigin":private]=> string(0) "" ["resource_line_offset":"V8\ScriptOrigin":private]=> @@ -122,7 +122,7 @@ v8Tests\TrackingDtors\FunctionObject(V8\FunctionObject)->GetScriptOrigin(): ["resource_column_offset":"V8\ScriptOrigin":private]=> int(0) ["options":"V8\ScriptOrigin":private]=> - object(V8\ScriptOriginOptions)#108 (3) { + object(V8\ScriptOriginOptions)#109 (3) { ["is_embedder_debug_script":"V8\ScriptOriginOptions":private]=> bool(false) ["is_shared_cross_origin":"V8\ScriptOriginOptions":private]=> diff --git a/tests/V8Int32Value.phpt b/tests/V8Int32Value.phpt index caae54a..abeb074 100644 --- a/tests/V8Int32Value.phpt +++ b/tests/V8Int32Value.phpt @@ -108,6 +108,8 @@ V8\Int32Value->Value(): int(2147483646) Checkers: --------- +V8\Int32Value(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "number" + V8\Int32Value(V8\Value)->IsUndefined(): bool(false) V8\Int32Value(V8\Value)->IsNull(): bool(false) V8\Int32Value(V8\Value)->IsTrue(): bool(false) @@ -134,7 +136,7 @@ V8\Int32Value(V8\Value)->IsRegExp(): bool(false) V8\Int32Value::ToString() converting: ------------------------------------- -object(V8\StringValue)#7 (1) { +object(V8\StringValue)#52 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#1 (5) { ["snapshot":"V8\Isolate":private]=> @@ -167,6 +169,8 @@ V8\Int32Value(V8\Value)->NumberValue(): float(-123) Checkers for negative: ---------------------- +V8\Int32Value(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "number" + V8\Int32Value(V8\Value)->IsUndefined(): bool(false) V8\Int32Value(V8\Value)->IsNull(): bool(false) V8\Int32Value(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8IntegerValue.phpt b/tests/V8IntegerValue.phpt index fe9e5fe..48dfe5b 100644 --- a/tests/V8IntegerValue.phpt +++ b/tests/V8IntegerValue.phpt @@ -108,6 +108,8 @@ V8\IntegerValue->Value(): int(123) Checkers: --------- +V8\IntegerValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "number" + V8\IntegerValue(V8\Value)->IsUndefined(): bool(false) V8\IntegerValue(V8\Value)->IsNull(): bool(false) V8\IntegerValue(V8\Value)->IsTrue(): bool(false) @@ -134,7 +136,7 @@ V8\IntegerValue(V8\Value)->IsRegExp(): bool(false) V8\IntegerValue::ToString() converting: --------------------------------------- -object(V8\StringValue)#7 (1) { +object(V8\StringValue)#52 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#1 (5) { ["snapshot":"V8\Isolate":private]=> @@ -167,6 +169,8 @@ V8\IntegerValue(V8\Value)->NumberValue(): float(-123) Checkers for negative: ---------------------- +V8\IntegerValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "number" + V8\IntegerValue(V8\Value)->IsUndefined(): bool(false) V8\IntegerValue(V8\Value)->IsNull(): bool(false) V8\IntegerValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Isolate_ThrowException.phpt b/tests/V8Isolate_ThrowException.phpt index e392c25..e41477c 100644 --- a/tests/V8Isolate_ThrowException.phpt +++ b/tests/V8Isolate_ThrowException.phpt @@ -117,6 +117,8 @@ CHECK $res->StrictEquals(new \V8\StringValue($isolate, 'foo')): OK Checks on V8\StringValue: ------------------------- +V8\StringValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "string" + V8\StringValue->IsOneByte(): bool(true) V8\StringValue(V8\Value)->IsUndefined(): bool(false) V8\StringValue(V8\Value)->IsNull(): bool(false) @@ -147,6 +149,8 @@ exception.stack: Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) @@ -178,6 +182,8 @@ exception.stack: Error Checks on V8\ObjectValue: ------------------------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\ObjectValue->IsCallable(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8NameValue.phpt b/tests/V8NameValue.phpt index 4438064..0acf8c2 100644 --- a/tests/V8NameValue.phpt +++ b/tests/V8NameValue.phpt @@ -30,7 +30,7 @@ $helper->method_matches($value, 'GetIsolate', $isolate); $helper->space(); $helper->header('Getters'); -$helper->method_export($value, 'GetIdentityHash'); +$helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->space(); @@ -95,11 +95,13 @@ V8\NameValue::GetIsolate() matches expected value Getters: -------- -V8\NameValue->GetIdentityHash(): int(0) +GetIdentityHash is integer: ok Checks on V8\NameValue: ----------------------- +V8\NameValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(9) "undefined" + V8\NameValue(V8\Value)->IsUndefined(): bool(true) V8\NameValue(V8\Value)->IsNull(): bool(false) V8\NameValue(V8\Value)->IsTrue(): bool(false) @@ -132,7 +134,7 @@ V8\NameValue(V8\Value)->NumberValue(): float(NAN) V8\NameValue::ToString() converting: ------------------------------------ -object(V8\StringValue)#7 (1) { +object(V8\StringValue)#52 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -152,6 +154,8 @@ string(9) "undefined" Checkers after ToString() converting: ------------------------------------- +V8\NameValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(9) "undefined" + V8\NameValue(V8\Value)->IsUndefined(): bool(true) V8\NameValue(V8\Value)->IsNull(): bool(false) V8\NameValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8NullValue.phpt b/tests/V8NullValue.phpt index 02bd0ce..ec277df 100644 --- a/tests/V8NullValue.phpt +++ b/tests/V8NullValue.phpt @@ -80,6 +80,8 @@ V8\NullValue->Value(): NULL Checkers: --------- +V8\NullValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\NullValue(V8\Value)->IsUndefined(): bool(false) V8\NullValue(V8\Value)->IsNull(): bool(true) V8\NullValue(V8\Value)->IsTrue(): bool(false) @@ -112,7 +114,7 @@ V8\NullValue(V8\Value)->NumberValue(): float(0) V8\NullValue::ToString() converting: ------------------------------------ -object(V8\StringValue)#7 (1) { +object(V8\StringValue)#52 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#1 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8NumberObject.phpt b/tests/V8NumberObject.phpt index 8b65d39..166562a 100644 --- a/tests/V8NumberObject.phpt +++ b/tests/V8NumberObject.phpt @@ -132,6 +132,8 @@ V8\NumberObject->ValueOf(): float(42.12) Checkers: --------- +V8\NumberObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\NumberObject(V8\ObjectValue)->IsCallable(): bool(false) V8\NumberObject(V8\Value)->IsUndefined(): bool(false) V8\NumberObject(V8\Value)->IsNull(): bool(false) @@ -168,6 +170,8 @@ Expected value is identical to actual value Checkers on boxed from script: ------------------------------ +V8\NumberObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\NumberObject(V8\ObjectValue)->IsCallable(): bool(false) V8\NumberObject(V8\Value)->IsUndefined(): bool(false) V8\NumberObject(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8NumberValue.phpt b/tests/V8NumberValue.phpt index d1cafec..4209482 100644 --- a/tests/V8NumberValue.phpt +++ b/tests/V8NumberValue.phpt @@ -105,6 +105,8 @@ V8\NumberValue->Value(): float(123.456) Checkers: --------- +V8\NumberValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "number" + V8\NumberValue(V8\Value)->IsUndefined(): bool(false) V8\NumberValue(V8\Value)->IsNull(): bool(false) V8\NumberValue(V8\Value)->IsTrue(): bool(false) @@ -131,7 +133,7 @@ V8\NumberValue(V8\Value)->IsRegExp(): bool(false) V8\NumberValue::ToString() converting: -------------------------------------- -object(V8\StringValue)#7 (1) { +object(V8\StringValue)#52 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8ObjectValue.phpt b/tests/V8ObjectValue.phpt index a38706d..cf1e39e 100644 --- a/tests/V8ObjectValue.phpt +++ b/tests/V8ObjectValue.phpt @@ -32,14 +32,14 @@ $helper->method_matches($value, 'CreationContext', $context); $helper->space(); $helper->header('Getters'); -$helper->method_export($value, 'GetIdentityHash'); +$helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->space(); $helper->header('Converters'); $helper->dump_object_methods($value, ['@@default' => [$context]], new RegexpFilter('/^To/')); ?> ---EXPECTF-- +--EXPECT-- Object representation: ---------------------- object(V8\ObjectValue)#5 (2) { @@ -108,13 +108,13 @@ V8\ObjectValue::CreationContext() matches expected value Getters: -------- -V8\ObjectValue->GetIdentityHash(): int(%d) +GetIdentityHash is integer: ok Converters: ----------- V8\ObjectValue(V8\Value)->ToBoolean(): - object(V8\BooleanValue)#90 (1) { + object(V8\BooleanValue)#91 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#2 (5) { ["snapshot":"V8\Isolate":private]=> @@ -130,7 +130,7 @@ V8\ObjectValue(V8\Value)->ToBoolean(): } } V8\ObjectValue(V8\Value)->ToNumber(): - object(V8\NumberValue)#90 (1) { + object(V8\NumberValue)#91 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#2 (5) { ["snapshot":"V8\Isolate":private]=> @@ -146,7 +146,7 @@ V8\ObjectValue(V8\Value)->ToNumber(): } } V8\ObjectValue(V8\Value)->ToString(): - object(V8\StringValue)#90 (1) { + object(V8\StringValue)#91 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#2 (5) { ["snapshot":"V8\Isolate":private]=> @@ -162,7 +162,7 @@ V8\ObjectValue(V8\Value)->ToString(): } } V8\ObjectValue(V8\Value)->ToDetailString(): - object(V8\StringValue)#90 (1) { + object(V8\StringValue)#91 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#2 (5) { ["snapshot":"V8\Isolate":private]=> @@ -231,7 +231,7 @@ V8\ObjectValue(V8\Value)->ToObject(): } } V8\ObjectValue(V8\Value)->ToInteger(): - object(V8\NumberValue)#90 (1) { + object(V8\NumberValue)#91 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#2 (5) { ["snapshot":"V8\Isolate":private]=> @@ -247,7 +247,7 @@ V8\ObjectValue(V8\Value)->ToInteger(): } } V8\ObjectValue(V8\Value)->ToUint32(): - object(V8\NumberValue)#90 (1) { + object(V8\NumberValue)#91 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#2 (5) { ["snapshot":"V8\Isolate":private]=> @@ -263,7 +263,7 @@ V8\ObjectValue(V8\Value)->ToUint32(): } } V8\ObjectValue(V8\Value)->ToInt32(): - object(V8\NumberValue)#90 (1) { + object(V8\NumberValue)#91 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#2 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8PrimitiveValue.phpt b/tests/V8PrimitiveValue.phpt index 010ba8a..04c1963 100644 --- a/tests/V8PrimitiveValue.phpt +++ b/tests/V8PrimitiveValue.phpt @@ -90,6 +90,8 @@ V8\PrimitiveValue::GetIsolate() matches expected value Checks on V8\PrimitiveValue: ---------------------------- +V8\PrimitiveValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(9) "undefined" + V8\PrimitiveValue(V8\Value)->IsUndefined(): bool(true) V8\PrimitiveValue(V8\Value)->IsNull(): bool(false) V8\PrimitiveValue(V8\Value)->IsTrue(): bool(false) @@ -122,7 +124,7 @@ V8\PrimitiveValue(V8\Value)->NumberValue(): float(NAN) V8\PrimitiveValue::ToString() converting: ----------------------------------------- -object(V8\StringValue)#48 (1) { +object(V8\StringValue)#51 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -142,6 +144,8 @@ string(9) "undefined" Checkers after ToString() converting: ------------------------------------- +V8\PrimitiveValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(9) "undefined" + V8\PrimitiveValue(V8\Value)->IsUndefined(): bool(true) V8\PrimitiveValue(V8\Value)->IsNull(): bool(false) V8\PrimitiveValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8RegExpObject.phpt b/tests/V8RegExpObject.phpt index e4c720c..175dfb6 100644 --- a/tests/V8RegExpObject.phpt +++ b/tests/V8RegExpObject.phpt @@ -129,6 +129,8 @@ V8\RegExpObject->GetFlags(): int(2) Checkers: --------- +V8\RegExpObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\RegExpObject(V8\ObjectValue)->IsCallable(): bool(false) V8\RegExpObject(V8\Value)->IsUndefined(): bool(false) V8\RegExpObject(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Script.phpt b/tests/V8Script.phpt index e552773..c54c3b8 100644 --- a/tests/V8Script.phpt +++ b/tests/V8Script.phpt @@ -149,6 +149,8 @@ V8\StringValue::GetIsolate() matches expected value Checkers: --------- +V8\StringValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "string" + V8\StringValue->IsOneByte(): bool(true) V8\StringValue(V8\Value)->IsUndefined(): bool(false) V8\StringValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8Script_Run.phpt b/tests/V8Script_Run.phpt index 1b0251d..faab303 100644 --- a/tests/V8Script_Run.phpt +++ b/tests/V8Script_Run.phpt @@ -56,6 +56,8 @@ $helper->value_matches_with_no_output($res, $obj); --EXPECT-- Checks on V8\StringValue: ------------------------- +V8\StringValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "string" + V8\StringValue->IsOneByte(): bool(true) V8\StringValue(V8\Value)->IsUndefined(): bool(false) V8\StringValue(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8StringObject.phpt b/tests/V8StringObject.phpt index 7576606..ceab265 100644 --- a/tests/V8StringObject.phpt +++ b/tests/V8StringObject.phpt @@ -127,7 +127,7 @@ StringObject extends ObjectValue: ok Getters: -------- V8\StringObject->ValueOf(): - object(V8\StringValue)#93 (1) { + object(V8\StringValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -147,6 +147,8 @@ V8\StringValue->Value(): string(11) "test string" Checkers: --------- +V8\StringObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\StringObject(V8\ObjectValue)->IsCallable(): bool(false) V8\StringObject(V8\Value)->IsUndefined(): bool(false) V8\StringObject(V8\Value)->IsNull(): bool(false) @@ -183,6 +185,8 @@ Expected value is identical to actual value Checkers on boxed from script: ------------------------------ +V8\StringObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\StringObject(V8\ObjectValue)->IsCallable(): bool(false) V8\StringObject(V8\Value)->IsUndefined(): bool(false) V8\StringObject(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8StringValue.phpt b/tests/V8StringValue.phpt index 1013ee4..93db112 100644 --- a/tests/V8StringValue.phpt +++ b/tests/V8StringValue.phpt @@ -40,7 +40,7 @@ $helper->space(); $v8_helper->run_checks($value, 'Checkers'); $helper->header('Getters'); -$helper->method_export($value, 'GetIdentityHash'); +$helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->method_export($value, 'Length'); $helper->method_export($value, 'Utf8Length'); $helper->method_export($value, 'IsOneByte'); @@ -93,7 +93,7 @@ foreach (['Hello, world!', 'Привет, мир!', 'こんにちは世界'] as ?> ---EXPECTF-- +--EXPECT-- Default constructor: -------------------- object(V8\StringValue)#4 (1) { @@ -143,6 +143,8 @@ V8\StringValue->Value(): string(11) "test string" Checkers: --------- +V8\StringValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "string" + V8\StringValue->IsOneByte(): bool(true) V8\StringValue(V8\Value)->IsUndefined(): bool(false) V8\StringValue(V8\Value)->IsNull(): bool(false) @@ -170,7 +172,7 @@ V8\StringValue(V8\Value)->IsRegExp(): bool(false) Getters: -------- -V8\StringValue(V8\NameValue)->GetIdentityHash(): int(%d) +GetIdentityHash is integer: ok V8\StringValue->Length(): int(11) V8\StringValue->Utf8Length(): int(11) V8\StringValue->IsOneByte(): bool(true) diff --git a/tests/V8SymbolObject.phpt b/tests/V8SymbolObject.phpt index 2033a61..099d1d4 100644 --- a/tests/V8SymbolObject.phpt +++ b/tests/V8SymbolObject.phpt @@ -130,7 +130,7 @@ SymbolObject extends ObjectValue: ok Getters: -------- V8\SymbolObject->ValueOf(): - object(V8\SymbolValue)#93 (1) { + object(V8\SymbolValue)#94 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -150,6 +150,8 @@ Symbol name:: string(4) "test" Checkers: --------- +V8\SymbolObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + V8\SymbolObject(V8\ObjectValue)->IsCallable(): bool(false) V8\SymbolObject(V8\Value)->IsUndefined(): bool(false) V8\SymbolObject(V8\Value)->IsNull(): bool(false) diff --git a/tests/V8SymbolValue.phpt b/tests/V8SymbolValue.phpt index a8e6b12..fd7467c 100644 --- a/tests/V8SymbolValue.phpt +++ b/tests/V8SymbolValue.phpt @@ -30,7 +30,7 @@ $helper->line(); $helper->header('Accessors'); $helper->method_matches($value, 'GetIsolate', $isolate); $helper->method_export($value, 'Name'); -$helper->method_export($value, 'GetIdentityHash'); +$helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->space(); $v8_helper->run_checks($value, 'Checkers'); @@ -50,7 +50,7 @@ $helper->line(); $helper->header('Accessors'); $helper->method_matches($value, 'GetIsolate', $isolate); $helper->method_export($value, 'Name'); -$helper->method_export($value, 'GetIdentityHash'); +$helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->space(); $v8_helper->run_checks($value, 'Checkers'); @@ -69,7 +69,7 @@ $helper->line(); $helper->header('Accessors'); $helper->method_matches($value, 'GetIsolate', $isolate); $helper->method_export($value, 'Name'); -$helper->method_export($value, 'GetIdentityHash'); +$helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->space(); $v8_helper->run_checks($value, 'Checkers'); @@ -93,7 +93,7 @@ $helper->line(); $helper->header('Accessors'); $helper->method_matches($value, 'GetIsolate', $isolate); $helper->method_export($value, 'Name'); -$helper->method_export($value, 'GetIdentityHash'); +$helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->space(); $v8_helper->run_checks($value, 'Checkers'); @@ -170,7 +170,7 @@ $helper->pretty_dump('Symbol GetIsConcatSpreadable() name', $value->Name()->Valu $helper->line(); ?> ---EXPECTF-- +--EXPECT-- Default constructor: -------------------- @@ -199,7 +199,7 @@ Accessors: ---------- V8\SymbolValue::GetIsolate() matches expected value V8\SymbolValue->Name(): - object(V8\Value)#58 (1) { + object(V8\Value)#59 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -214,11 +214,13 @@ V8\SymbolValue->Name(): bool(false) } } -V8\SymbolValue(V8\NameValue)->GetIdentityHash(): int(%d) +GetIdentityHash is integer: ok Checkers: --------- +V8\SymbolValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "symbol" + V8\SymbolValue(V8\Value)->IsUndefined(): bool(false) V8\SymbolValue(V8\Value)->IsNull(): bool(false) V8\SymbolValue(V8\Value)->IsTrue(): bool(false) @@ -248,7 +250,7 @@ Null constructor: Object representation: ---------------------- -object(V8\SymbolValue)#5 (1) { +object(V8\SymbolValue)#59 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -271,7 +273,7 @@ Accessors: ---------- V8\SymbolValue::GetIsolate() matches expected value V8\SymbolValue->Name(): - object(V8\Value)#8 (1) { + object(V8\Value)#7 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -286,11 +288,13 @@ V8\SymbolValue->Name(): bool(false) } } -V8\SymbolValue(V8\NameValue)->GetIdentityHash(): int(%d) +GetIdentityHash is integer: ok Checkers: --------- +V8\SymbolValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "symbol" + V8\SymbolValue(V8\Value)->IsUndefined(): bool(false) V8\SymbolValue(V8\Value)->IsNull(): bool(false) V8\SymbolValue(V8\Value)->IsTrue(): bool(false) @@ -320,7 +324,7 @@ Empty StringValue constructor: Object representation: ---------------------- -object(V8\SymbolValue)#4 (1) { +object(V8\SymbolValue)#7 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -343,7 +347,7 @@ Accessors: ---------- V8\SymbolValue::GetIsolate() matches expected value V8\SymbolValue->Name(): - object(V8\StringValue)#58 (1) { + object(V8\StringValue)#8 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -358,11 +362,13 @@ V8\SymbolValue->Name(): bool(false) } } -V8\SymbolValue(V8\NameValue)->GetIdentityHash(): int(%d) +GetIdentityHash is integer: ok Checkers: --------- +V8\SymbolValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "symbol" + V8\SymbolValue(V8\Value)->IsUndefined(): bool(false) V8\SymbolValue(V8\Value)->IsNull(): bool(false) V8\SymbolValue(V8\Value)->IsTrue(): bool(false) @@ -396,7 +402,7 @@ Non-empty StringValue constructor: Object representation: ---------------------- -object(V8\SymbolValue)#5 (1) { +object(V8\SymbolValue)#8 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -419,7 +425,7 @@ Accessors: ---------- V8\SymbolValue::GetIsolate() matches expected value V8\SymbolValue->Name(): - object(V8\StringValue)#8 (1) { + object(V8\StringValue)#60 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -434,11 +440,13 @@ V8\SymbolValue->Name(): bool(false) } } -V8\SymbolValue(V8\NameValue)->GetIdentityHash(): int(%d) +GetIdentityHash is integer: ok Checkers: --------- +V8\SymbolValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "symbol" + V8\SymbolValue(V8\Value)->IsUndefined(): bool(false) V8\SymbolValue(V8\Value)->IsNull(): bool(false) V8\SymbolValue(V8\Value)->IsTrue(): bool(false) @@ -469,6 +477,8 @@ string(4) "test" Checkers on name: ----------------- +V8\StringValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "string" + V8\StringValue->IsOneByte(): bool(true) V8\StringValue(V8\Value)->IsUndefined(): bool(false) V8\StringValue(V8\Value)->IsNull(): bool(false) @@ -496,6 +506,8 @@ V8\StringValue(V8\Value)->IsRegExp(): bool(false) Checkers on Symbol value from script: ------------------------------------- +V8\SymbolValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "symbol" + V8\SymbolValue(V8\Value)->IsUndefined(): bool(false) V8\SymbolValue(V8\Value)->IsNull(): bool(false) V8\SymbolValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Uint32Value.phpt b/tests/V8Uint32Value.phpt index 82f439f..c076385 100644 --- a/tests/V8Uint32Value.phpt +++ b/tests/V8Uint32Value.phpt @@ -98,6 +98,8 @@ V8\Uint32Value->Value(): int(2147483648) Checkers for negative: ---------------------- +V8\Uint32Value(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "number" + V8\Uint32Value(V8\Value)->IsUndefined(): bool(false) V8\Uint32Value(V8\Value)->IsNull(): bool(false) V8\Uint32Value(V8\Value)->IsTrue(): bool(false) @@ -124,7 +126,7 @@ V8\Uint32Value(V8\Value)->IsRegExp(): bool(false) V8\Uint32Value::ToString() converting: -------------------------------------- -object(V8\StringValue)#7 (1) { +object(V8\StringValue)#52 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8Value.phpt b/tests/V8Value.phpt index d689e11..4f3f916 100644 --- a/tests/V8Value.phpt +++ b/tests/V8Value.phpt @@ -23,6 +23,7 @@ $helper->dump($value); $helper->space(); $helper->assert('Value extends Data', $value instanceof \V8\Data); +$helper->assert('TypeOf returns StringValue', $value->TypeOf($isolate) instanceof \V8\StringValue); $helper->line(); $helper->header('Accessors'); @@ -82,6 +83,7 @@ object(V8\Value)#4 (1) { Value extends Data: ok +TypeOf returns StringValue: ok Accessors: ---------- @@ -90,6 +92,8 @@ V8\Value::GetIsolate() matches expected value Checks on V8\Value: ------------------- +V8\Value->TypeOf(): V8\StringValue->Value(): string(9) "undefined" + V8\Value->IsUndefined(): bool(true) V8\Value->IsNull(): bool(false) V8\Value->IsTrue(): bool(false) @@ -122,7 +126,7 @@ V8\Value->NumberValue(): float(NAN) V8\Value::ToString() converting: -------------------------------- -object(V8\StringValue)#48 (1) { +object(V8\StringValue)#51 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -142,6 +146,8 @@ string(9) "undefined" Checkers after ToString() converting: ------------------------------------- +V8\Value->TypeOf(): V8\StringValue->Value(): string(9) "undefined" + V8\Value->IsUndefined(): bool(true) V8\Value->IsNull(): bool(false) V8\Value->IsTrue(): bool(false) From fcc9eb1808831338dc6477eda03f828a57062898 Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Thu, 18 Aug 2016 00:35:37 +0300 Subject: [PATCH 03/10] Add ObjectValue::IsConstructor() method V8 commit: https://github.com/v8/v8/commit/acbbd59f29306a679e9e85b8ccfaa4eaaf969a6d --- scripts/replace_expect.php | 2 +- src/php_v8_object.cc | 19 ++++++ stubs/src/ObjectValue.php | 9 +++ tests/V8ArrayObject.phpt | 14 ++--- tests/V8BooleanObject.phpt | 2 + tests/V8DateObject.phpt | 1 + tests/V8Exception_CreateMessage.phpt | 1 + tests/V8Exception_Error.phpt | 1 + tests/V8Exception_RangeError.phpt | 1 + tests/V8Exception_ReferenceError.phpt | 1 + tests/V8Exception_SyntaxError.phpt | 1 + tests/V8Exception_TypeError.phpt | 1 + tests/V8FunctionObject.phpt | 51 +++++++++++++--- tests/V8Isolate_ThrowException.phpt | 2 + tests/V8NumberObject.phpt | 2 + tests/V8ObjectValue.phpt | 87 +++++++++++++++++++-------- tests/V8RegExpObject.phpt | 1 + tests/V8StringObject.phpt | 4 +- tests/V8SymbolObject.phpt | 3 +- 19 files changed, 159 insertions(+), 44 deletions(-) diff --git a/scripts/replace_expect.php b/scripts/replace_expect.php index 1af96bd..a6a8221 100644 --- a/scripts/replace_expect.php +++ b/scripts/replace_expect.php @@ -20,7 +20,7 @@ $test_content .= PHP_EOL; file_put_contents($tests_dir . '/' . $test_file, $test_content); - foreach (['.diff', '.exp', '.log', '.mem', '.out', '.php'] as $ext) { + foreach (['.diff', '.exp', '.log', '.mem', '.out', '.php', '.sh'] as $ext) { @unlink($tests_dir. '/'.$base_name . $ext); } } else { diff --git a/src/php_v8_object.cc b/src/php_v8_object.cc index e526a18..bd7254f 100644 --- a/src/php_v8_object.cc +++ b/src/php_v8_object.cc @@ -1293,6 +1293,21 @@ static PHP_METHOD(V8Object, IsCallable) { RETURN_BOOL(local_object->IsCallable()); } + +static PHP_METHOD(V8Object, IsConstructor) { + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value); + PHP_V8_ENTER_ISOLATE(php_v8_value->php_v8_isolate); + + v8::Local local_value = php_v8_value_get_value_local(isolate, php_v8_value); + v8::Local local_object = v8::Local::Cast(local_value); + + RETURN_BOOL(local_object->IsConstructor()); +} + static PHP_METHOD(V8Object, CallAsFunction) { zval *php_v8_context_zv; zval *php_v8_recv_zv; @@ -1568,6 +1583,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_object_IsCallable, ZEND_RETURN_VALUE, 0, _IS_BOOL, NULL, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_object_IsConstructor, ZEND_RETURN_VALUE, 0, _IS_BOOL, NULL, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_object_CallAsFunction, ZEND_RETURN_VALUE, 2, IS_OBJECT, PHP_V8_NS "\\Value", 0) ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0) ZEND_ARG_OBJ_INFO(0, recv, V8\\Value, 0) @@ -1630,6 +1648,7 @@ static const zend_function_entry php_v8_object_methods[] = { PHP_ME(V8Object, CreationContext, arginfo_v8_object_CreationContext, ZEND_ACC_PUBLIC) PHP_ME(V8Object, IsCallable, arginfo_v8_object_IsCallable, ZEND_ACC_PUBLIC) + PHP_ME(V8Object, IsConstructor, arginfo_v8_object_IsConstructor, ZEND_ACC_PUBLIC) PHP_ME(V8Object, CallAsFunction, arginfo_v8_object_CallAsFunction, ZEND_ACC_PUBLIC) PHP_ME(V8Object, CallAsConstructor, arginfo_v8_object_CallAsConstructor, ZEND_ACC_PUBLIC) diff --git a/stubs/src/ObjectValue.php b/stubs/src/ObjectValue.php index c5c3b63..25abfca 100644 --- a/stubs/src/ObjectValue.php +++ b/stubs/src/ObjectValue.php @@ -477,6 +477,15 @@ public function IsCallable() : bool { } + /** + * True if this object is a constructor. + * + * @return bool + */ + public function IsConstructor() : bool + { + } + /** * Call an Object as a function if a callback is set by the * ObjectTemplate::SetCallAsFunctionHandler method. diff --git a/tests/V8ArrayObject.phpt b/tests/V8ArrayObject.phpt index c4b0f6c..44d48aa 100644 --- a/tests/V8ArrayObject.phpt +++ b/tests/V8ArrayObject.phpt @@ -129,7 +129,7 @@ V8\ArrayObject::CreationContext() matches expected value Converters: ----------- V8\ArrayObject(V8\Value)->ToBoolean(): - object(V8\BooleanValue)#94 (1) { + object(V8\BooleanValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -145,7 +145,7 @@ V8\ArrayObject(V8\Value)->ToBoolean(): } } V8\ArrayObject(V8\Value)->ToNumber(): - object(V8\NumberValue)#94 (1) { + object(V8\NumberValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -161,7 +161,7 @@ V8\ArrayObject(V8\Value)->ToNumber(): } } V8\ArrayObject(V8\Value)->ToString(): - object(V8\StringValue)#94 (1) { + object(V8\StringValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -177,7 +177,7 @@ V8\ArrayObject(V8\Value)->ToString(): } } V8\ArrayObject(V8\Value)->ToDetailString(): - object(V8\StringValue)#94 (1) { + object(V8\StringValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -246,7 +246,7 @@ V8\ArrayObject(V8\Value)->ToObject(): } } V8\ArrayObject(V8\Value)->ToInteger(): - object(V8\NumberValue)#94 (1) { + object(V8\NumberValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -262,7 +262,7 @@ V8\ArrayObject(V8\Value)->ToInteger(): } } V8\ArrayObject(V8\Value)->ToUint32(): - object(V8\NumberValue)#94 (1) { + object(V8\NumberValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -278,7 +278,7 @@ V8\ArrayObject(V8\Value)->ToUint32(): } } V8\ArrayObject(V8\Value)->ToInt32(): - object(V8\NumberValue)#94 (1) { + object(V8\NumberValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8BooleanObject.phpt b/tests/V8BooleanObject.phpt index 001f5aa..1ddc662 100644 --- a/tests/V8BooleanObject.phpt +++ b/tests/V8BooleanObject.phpt @@ -124,6 +124,7 @@ Checkers: V8\BooleanObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\BooleanObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\BooleanObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\BooleanObject(V8\Value)->IsUndefined(): bool(false) V8\BooleanObject(V8\Value)->IsNull(): bool(false) V8\BooleanObject(V8\Value)->IsTrue(): bool(false) @@ -157,6 +158,7 @@ Checkers on boxed from script: V8\BooleanObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\BooleanObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\BooleanObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\BooleanObject(V8\Value)->IsUndefined(): bool(false) V8\BooleanObject(V8\Value)->IsNull(): bool(false) V8\BooleanObject(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8DateObject.phpt b/tests/V8DateObject.phpt index 6f46d9e..9eaf74e 100644 --- a/tests/V8DateObject.phpt +++ b/tests/V8DateObject.phpt @@ -182,6 +182,7 @@ Checkers: V8\DateObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\DateObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\DateObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\DateObject(V8\Value)->IsUndefined(): bool(false) V8\DateObject(V8\Value)->IsNull(): bool(false) V8\DateObject(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Exception_CreateMessage.phpt b/tests/V8Exception_CreateMessage.phpt index 96bc8ed..950a1ec 100644 --- a/tests/V8Exception_CreateMessage.phpt +++ b/tests/V8Exception_CreateMessage.phpt @@ -157,6 +157,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Exception_Error.phpt b/tests/V8Exception_Error.phpt index 174eb24..268ef53 100644 --- a/tests/V8Exception_Error.phpt +++ b/tests/V8Exception_Error.phpt @@ -105,6 +105,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Exception_RangeError.phpt b/tests/V8Exception_RangeError.phpt index 460b8c4..d1c68ea 100644 --- a/tests/V8Exception_RangeError.phpt +++ b/tests/V8Exception_RangeError.phpt @@ -106,6 +106,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Exception_ReferenceError.phpt b/tests/V8Exception_ReferenceError.phpt index 384d009..e64b096 100644 --- a/tests/V8Exception_ReferenceError.phpt +++ b/tests/V8Exception_ReferenceError.phpt @@ -106,6 +106,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Exception_SyntaxError.phpt b/tests/V8Exception_SyntaxError.phpt index 57c48bb..cd57c36 100644 --- a/tests/V8Exception_SyntaxError.phpt +++ b/tests/V8Exception_SyntaxError.phpt @@ -106,6 +106,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8Exception_TypeError.phpt b/tests/V8Exception_TypeError.phpt index b9fbeed..8aebbc2 100644 --- a/tests/V8Exception_TypeError.phpt +++ b/tests/V8Exception_TypeError.phpt @@ -106,6 +106,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8FunctionObject.phpt b/tests/V8FunctionObject.phpt index 778f2bb..c2642b1 100644 --- a/tests/V8FunctionObject.phpt +++ b/tests/V8FunctionObject.phpt @@ -10,6 +10,9 @@ V8\FunctionObject /** @var \Phpv8Testsuite $helper */ $helper = require '.testsuite.php'; +require '.v8-helpers.php'; +$v8_helper = new PhpV8Helpers($helper); + require '.tracking_dtors.php'; $isolate1 = new v8Tests\TrackingDtors\Isolate(); @@ -33,6 +36,7 @@ $helper->space(); $helper->assert('FunctionObject extends ObjectValue', $func instanceof \V8\ObjectValue); $helper->line(); +$v8_helper->run_checks($func, 'Checkers'); $context1->GlobalObject()->Set($context1, new \V8\StringValue($isolate1, 'print'), $func); @@ -54,9 +58,9 @@ echo 'We are done for now', PHP_EOL; --EXPECT-- Object representation: ---------------------- -object(v8Tests\TrackingDtors\FunctionObject)#5 (2) { +object(v8Tests\TrackingDtors\FunctionObject)#6 (2) { ["isolate":"V8\Value":private]=> - object(v8Tests\TrackingDtors\Isolate)#2 (5) { + object(v8Tests\TrackingDtors\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -69,9 +73,9 @@ object(v8Tests\TrackingDtors\FunctionObject)#5 (2) { bool(false) } ["context":"V8\ObjectValue":private]=> - object(V8\Context)#4 (4) { + object(V8\Context)#5 (4) { ["isolate":"V8\Context":private]=> - object(v8Tests\TrackingDtors\Isolate)#2 (5) { + object(v8Tests\TrackingDtors\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -87,9 +91,9 @@ object(v8Tests\TrackingDtors\FunctionObject)#5 (2) { array(0) { } ["global_template":"V8\Context":private]=> - object(V8\ObjectTemplate)#3 (1) { + object(V8\ObjectTemplate)#4 (1) { ["isolate":"V8\Template":private]=> - object(v8Tests\TrackingDtors\Isolate)#2 (5) { + object(v8Tests\TrackingDtors\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -110,11 +114,42 @@ object(v8Tests\TrackingDtors\FunctionObject)#5 (2) { FunctionObject extends ObjectValue: ok +Checkers: +--------- +v8Tests\TrackingDtors\FunctionObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(8) "function" + +v8Tests\TrackingDtors\FunctionObject(V8\FunctionObject)->IsBuiltin(): bool(true) +v8Tests\TrackingDtors\FunctionObject(V8\ObjectValue)->IsCallable(): bool(true) +v8Tests\TrackingDtors\FunctionObject(V8\ObjectValue)->IsConstructor(): bool(true) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsUndefined(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsNull(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsTrue(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsFalse(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsName(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsString(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsSymbol(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsFunction(): bool(true) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsArray(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsObject(): bool(true) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsBoolean(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsNumber(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsInt32(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsUint32(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsDate(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsArgumentsObject(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsBooleanObject(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsNumberObject(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsStringObject(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsSymbolObject(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsNativeError(): bool(false) +v8Tests\TrackingDtors\FunctionObject(V8\Value)->IsRegExp(): bool(false) + + Should output Hello World string string(11) "Script done" v8Tests\TrackingDtors\FunctionObject(V8\FunctionObject)->GetScriptOrigin(): - object(V8\ScriptOrigin)#108 (6) { + object(V8\ScriptOrigin)#110 (6) { ["resource_name":"V8\ScriptOrigin":private]=> string(0) "" ["resource_line_offset":"V8\ScriptOrigin":private]=> @@ -122,7 +157,7 @@ v8Tests\TrackingDtors\FunctionObject(V8\FunctionObject)->GetScriptOrigin(): ["resource_column_offset":"V8\ScriptOrigin":private]=> int(0) ["options":"V8\ScriptOrigin":private]=> - object(V8\ScriptOriginOptions)#109 (3) { + object(V8\ScriptOriginOptions)#111 (3) { ["is_embedder_debug_script":"V8\ScriptOriginOptions":private]=> bool(false) ["is_shared_cross_origin":"V8\ScriptOriginOptions":private]=> diff --git a/tests/V8Isolate_ThrowException.phpt b/tests/V8Isolate_ThrowException.phpt index e41477c..b3e66cb 100644 --- a/tests/V8Isolate_ThrowException.phpt +++ b/tests/V8Isolate_ThrowException.phpt @@ -152,6 +152,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) @@ -185,6 +186,7 @@ Checks on V8\ObjectValue: V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) V8\ObjectValue(V8\Value)->IsNull(): bool(false) V8\ObjectValue(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8NumberObject.phpt b/tests/V8NumberObject.phpt index 166562a..74185e6 100644 --- a/tests/V8NumberObject.phpt +++ b/tests/V8NumberObject.phpt @@ -135,6 +135,7 @@ Checkers: V8\NumberObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\NumberObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\NumberObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\NumberObject(V8\Value)->IsUndefined(): bool(false) V8\NumberObject(V8\Value)->IsNull(): bool(false) V8\NumberObject(V8\Value)->IsTrue(): bool(false) @@ -173,6 +174,7 @@ Checkers on boxed from script: V8\NumberObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\NumberObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\NumberObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\NumberObject(V8\Value)->IsUndefined(): bool(false) V8\NumberObject(V8\Value)->IsNull(): bool(false) V8\NumberObject(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8ObjectValue.phpt b/tests/V8ObjectValue.phpt index cf1e39e..d1560f5 100644 --- a/tests/V8ObjectValue.phpt +++ b/tests/V8ObjectValue.phpt @@ -8,6 +8,9 @@ V8\ObjectValue /** @var \Phpv8Testsuite $helper */ $helper = require '.testsuite.php'; +require '.v8-helpers.php'; +$v8_helper = new PhpV8Helpers($helper); + $isolate = new \V8\Isolate(); $extensions = []; $global_template = new V8\ObjectTemplate($isolate); @@ -35,6 +38,8 @@ $helper->header('Getters'); $helper->assert('GetIdentityHash is integer', gettype($value->GetIdentityHash()), 'integer'); $helper->space(); +$v8_helper->run_checks($value, 'Checkers'); + $helper->header('Converters'); $helper->dump_object_methods($value, ['@@default' => [$context]], new RegexpFilter('/^To/')); @@ -42,9 +47,9 @@ $helper->dump_object_methods($value, ['@@default' => [$context]], new RegexpFilt --EXPECT-- Object representation: ---------------------- -object(V8\ObjectValue)#5 (2) { +object(V8\ObjectValue)#6 (2) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -57,9 +62,9 @@ object(V8\ObjectValue)#5 (2) { bool(false) } ["context":"V8\ObjectValue":private]=> - object(V8\Context)#4 (4) { + object(V8\Context)#5 (4) { ["isolate":"V8\Context":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -75,9 +80,9 @@ object(V8\ObjectValue)#5 (2) { array(0) { } ["global_template":"V8\Context":private]=> - object(V8\ObjectTemplate)#3 (1) { + object(V8\ObjectTemplate)#4 (1) { ["isolate":"V8\Template":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -111,12 +116,42 @@ Getters: GetIdentityHash is integer: ok +Checkers: +--------- +V8\ObjectValue(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" + +V8\ObjectValue->IsCallable(): bool(false) +V8\ObjectValue->IsConstructor(): bool(false) +V8\ObjectValue(V8\Value)->IsUndefined(): bool(false) +V8\ObjectValue(V8\Value)->IsNull(): bool(false) +V8\ObjectValue(V8\Value)->IsTrue(): bool(false) +V8\ObjectValue(V8\Value)->IsFalse(): bool(false) +V8\ObjectValue(V8\Value)->IsName(): bool(false) +V8\ObjectValue(V8\Value)->IsString(): bool(false) +V8\ObjectValue(V8\Value)->IsSymbol(): bool(false) +V8\ObjectValue(V8\Value)->IsFunction(): bool(false) +V8\ObjectValue(V8\Value)->IsArray(): bool(false) +V8\ObjectValue(V8\Value)->IsObject(): bool(true) +V8\ObjectValue(V8\Value)->IsBoolean(): bool(false) +V8\ObjectValue(V8\Value)->IsNumber(): bool(false) +V8\ObjectValue(V8\Value)->IsInt32(): bool(false) +V8\ObjectValue(V8\Value)->IsUint32(): bool(false) +V8\ObjectValue(V8\Value)->IsDate(): bool(false) +V8\ObjectValue(V8\Value)->IsArgumentsObject(): bool(false) +V8\ObjectValue(V8\Value)->IsBooleanObject(): bool(false) +V8\ObjectValue(V8\Value)->IsNumberObject(): bool(false) +V8\ObjectValue(V8\Value)->IsStringObject(): bool(false) +V8\ObjectValue(V8\Value)->IsSymbolObject(): bool(false) +V8\ObjectValue(V8\Value)->IsNativeError(): bool(false) +V8\ObjectValue(V8\Value)->IsRegExp(): bool(false) + + Converters: ----------- V8\ObjectValue(V8\Value)->ToBoolean(): - object(V8\BooleanValue)#91 (1) { + object(V8\BooleanValue)#92 (1) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -130,9 +165,9 @@ V8\ObjectValue(V8\Value)->ToBoolean(): } } V8\ObjectValue(V8\Value)->ToNumber(): - object(V8\NumberValue)#91 (1) { + object(V8\NumberValue)#92 (1) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -146,9 +181,9 @@ V8\ObjectValue(V8\Value)->ToNumber(): } } V8\ObjectValue(V8\Value)->ToString(): - object(V8\StringValue)#91 (1) { + object(V8\StringValue)#92 (1) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -162,9 +197,9 @@ V8\ObjectValue(V8\Value)->ToString(): } } V8\ObjectValue(V8\Value)->ToDetailString(): - object(V8\StringValue)#91 (1) { + object(V8\StringValue)#92 (1) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -178,9 +213,9 @@ V8\ObjectValue(V8\Value)->ToDetailString(): } } V8\ObjectValue(V8\Value)->ToObject(): - object(V8\ObjectValue)#5 (2) { + object(V8\ObjectValue)#6 (2) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -193,9 +228,9 @@ V8\ObjectValue(V8\Value)->ToObject(): bool(false) } ["context":"V8\ObjectValue":private]=> - object(V8\Context)#4 (4) { + object(V8\Context)#5 (4) { ["isolate":"V8\Context":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -211,9 +246,9 @@ V8\ObjectValue(V8\Value)->ToObject(): array(0) { } ["global_template":"V8\Context":private]=> - object(V8\ObjectTemplate)#3 (1) { + object(V8\ObjectTemplate)#4 (1) { ["isolate":"V8\Template":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -231,9 +266,9 @@ V8\ObjectValue(V8\Value)->ToObject(): } } V8\ObjectValue(V8\Value)->ToInteger(): - object(V8\NumberValue)#91 (1) { + object(V8\NumberValue)#92 (1) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -247,9 +282,9 @@ V8\ObjectValue(V8\Value)->ToInteger(): } } V8\ObjectValue(V8\Value)->ToUint32(): - object(V8\NumberValue)#91 (1) { + object(V8\NumberValue)#92 (1) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> @@ -263,9 +298,9 @@ V8\ObjectValue(V8\Value)->ToUint32(): } } V8\ObjectValue(V8\Value)->ToInt32(): - object(V8\NumberValue)#91 (1) { + object(V8\NumberValue)#92 (1) { ["isolate":"V8\Value":private]=> - object(V8\Isolate)#2 (5) { + object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> NULL ["time_limit":"V8\Isolate":private]=> diff --git a/tests/V8RegExpObject.phpt b/tests/V8RegExpObject.phpt index 175dfb6..5f55149 100644 --- a/tests/V8RegExpObject.phpt +++ b/tests/V8RegExpObject.phpt @@ -132,6 +132,7 @@ Checkers: V8\RegExpObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\RegExpObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\RegExpObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\RegExpObject(V8\Value)->IsUndefined(): bool(false) V8\RegExpObject(V8\Value)->IsNull(): bool(false) V8\RegExpObject(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8StringObject.phpt b/tests/V8StringObject.phpt index ceab265..38e9c98 100644 --- a/tests/V8StringObject.phpt +++ b/tests/V8StringObject.phpt @@ -127,7 +127,7 @@ StringObject extends ObjectValue: ok Getters: -------- V8\StringObject->ValueOf(): - object(V8\StringValue)#94 (1) { + object(V8\StringValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -150,6 +150,7 @@ Checkers: V8\StringObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\StringObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\StringObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\StringObject(V8\Value)->IsUndefined(): bool(false) V8\StringObject(V8\Value)->IsNull(): bool(false) V8\StringObject(V8\Value)->IsTrue(): bool(false) @@ -188,6 +189,7 @@ Checkers on boxed from script: V8\StringObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\StringObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\StringObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\StringObject(V8\Value)->IsUndefined(): bool(false) V8\StringObject(V8\Value)->IsNull(): bool(false) V8\StringObject(V8\Value)->IsTrue(): bool(false) diff --git a/tests/V8SymbolObject.phpt b/tests/V8SymbolObject.phpt index 099d1d4..2f3f988 100644 --- a/tests/V8SymbolObject.phpt +++ b/tests/V8SymbolObject.phpt @@ -130,7 +130,7 @@ SymbolObject extends ObjectValue: ok Getters: -------- V8\SymbolObject->ValueOf(): - object(V8\SymbolValue)#94 (1) { + object(V8\SymbolValue)#95 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -153,6 +153,7 @@ Checkers: V8\SymbolObject(V8\Value)->TypeOf(): V8\StringValue->Value(): string(6) "object" V8\SymbolObject(V8\ObjectValue)->IsCallable(): bool(false) +V8\SymbolObject(V8\ObjectValue)->IsConstructor(): bool(false) V8\SymbolObject(V8\Value)->IsUndefined(): bool(false) V8\SymbolObject(V8\Value)->IsNull(): bool(false) V8\SymbolObject(V8\Value)->IsTrue(): bool(false) From 260773eafcc7baf09ba6770efab9b0c9c9e4e375 Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Thu, 18 Aug 2016 23:16:33 +0300 Subject: [PATCH 04/10] Add V8\ObjectValue::SetIntegrityLevel() V8 commit: https://github.com/v8/v8/commit/93c60dca132a30d58a8a6c7ee2b0e1937b5bb331 --- config.m4 | 1 + scripts/replace_expect.php | 1 + src/php_v8_integrity_level.cc | 50 +++++++++++ src/php_v8_integrity_level.h | 51 +++++++++++ src/php_v8_object.cc | 41 +++++++++ stubs/src/IntegrityLevel.php | 27 ++++++ stubs/src/ObjectValue.php | 19 ++++- tests/V8ArrayObject.phpt | 14 ++-- tests/V8FunctionObject.phpt | 4 +- tests/V8IntegrityLevel.phpt | 36 ++++++++ tests/V8ObjectValue.phpt | 14 ++-- tests/V8ObjectValue_SetIntegrityLevel.phpt | 98 ++++++++++++++++++++++ tests/V8StringObject.phpt | 2 +- tests/V8SymbolObject.phpt | 2 +- v8.cc | 2 + 15 files changed, 343 insertions(+), 19 deletions(-) mode change 100644 => 100755 scripts/replace_expect.php create mode 100644 src/php_v8_integrity_level.cc create mode 100644 src/php_v8_integrity_level.h create mode 100644 stubs/src/IntegrityLevel.php create mode 100644 tests/V8IntegrityLevel.phpt create mode 100644 tests/V8ObjectValue_SetIntegrityLevel.phpt diff --git a/config.m4 b/config.m4 index 16d46c9..c87742d 100644 --- a/config.m4 +++ b/config.m4 @@ -209,6 +209,7 @@ if test "$PHP_V8" != "no"; then src/php_v8_integer.cc \ src/php_v8_int32.cc \ src/php_v8_uint32.cc \ + src/php_v8_integrity_level.cc \ src/php_v8_object.cc \ src/php_v8_function.cc \ src/php_v8_array.cc \ diff --git a/scripts/replace_expect.php b/scripts/replace_expect.php old mode 100644 new mode 100755 index a6a8221..f073e23 --- a/scripts/replace_expect.php +++ b/scripts/replace_expect.php @@ -1,3 +1,4 @@ +#!/usr/bin/env php | + | | + | Licensed under the MIT license: http://opensource.org/licenses/MIT | + | | + | For the full copyright and license information, please view the | + | LICENSE file that was distributed with this source or visit | + | http://opensource.org/licenses/MIT | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_v8_integrity_level.h" +#include "php_v8.h" + +zend_class_entry* php_v8_integrity_level_class_entry; +#define this_ce php_v8_integrity_level_class_entry + + +static const zend_function_entry php_v8_integrity_level_methods[] = { + PHP_FE_END +}; + + +PHP_MINIT_FUNCTION(php_v8_integrity_level) { + zend_class_entry ce; + INIT_NS_CLASS_ENTRY(ce, PHP_V8_NS, "IntegrityLevel", php_v8_integrity_level_methods); + this_ce = zend_register_internal_class(&ce); + + zend_declare_class_constant_long(this_ce, ZEND_STRL("kFrozen"), static_cast(v8::IntegrityLevel::kFrozen)); + zend_declare_class_constant_long(this_ce, ZEND_STRL("kSealed"), static_cast(v8::IntegrityLevel::kSealed)); + + return SUCCESS; +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/src/php_v8_integrity_level.h b/src/php_v8_integrity_level.h new file mode 100644 index 0000000..a07769b --- /dev/null +++ b/src/php_v8_integrity_level.h @@ -0,0 +1,51 @@ +/* + +----------------------------------------------------------------------+ + | This file is part of the pinepain/php-v8 PHP extension. | + | | + | Copyright (c) 2015-2016 Bogdan Padalko | + | | + | Licensed under the MIT license: http://opensource.org/licenses/MIT | + | | + | For the full copyright and license information, please view the | + | LICENSE file that was distributed with this source or visit | + | http://opensource.org/licenses/MIT | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_V8_INTEGRITY_LEVEL_H +#define PHP_V8_INTEGRITY_LEVEL_H + +#include + +extern "C" { +#include "php.h" + +#ifdef ZTS +#include "TSRM.h" +#endif +} + +extern zend_class_entry* php_v8_integrity_level_class_entry; + +PHP_MINIT_FUNCTION (php_v8_integrity_level); + +#define PHP_V8_INTEGRITY_LEVEL_FLAGS ( 0 \ + | static_cast(v8::IntegrityLevel::kFrozen) \ + | static_cast(v8::IntegrityLevel::kSealed) \ +) + + +#endif //PHP_V8_INTEGRITY_LEVEL_H +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + + + + + diff --git a/src/php_v8_object.cc b/src/php_v8_object.cc index bd7254f..5f4aefa 100644 --- a/src/php_v8_object.cc +++ b/src/php_v8_object.cc @@ -17,6 +17,7 @@ #endif #include "php_v8_object.h" +#include "php_v8_integrity_level.h" #include "php_v8_exceptions.h" #include "php_v8_function_template.h" #include "php_v8_function.h" @@ -933,6 +934,40 @@ static PHP_METHOD(V8Object, GetConstructorName) { php_v8_get_or_create_value(return_value, local_object->GetConstructorName(), isolate); } +static PHP_METHOD(V8Object, SetIntegrityLevel) { + zval *php_v8_context_zv; + zend_long level; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ol", &php_v8_context_zv, &level) == FAILURE) { + return; + } + + PHP_V8_VALUE_FETCH_WITH_CHECK(getThis(), php_v8_value); + PHP_V8_CONTEXT_FETCH_WITH_CHECK(php_v8_context_zv, php_v8_context); + + PHP_V8_DATA_ISOLATES_CHECK(php_v8_value, php_v8_context) + + PHP_V8_ENTER_STORED_ISOLATE(php_v8_value); + PHP_V8_ENTER_CONTEXT(php_v8_context); + + v8::Local local_context = php_v8_context_get_local(isolate, php_v8_context); + v8::Local local_obj = php_v8_value_get_object_local(isolate, php_v8_value); + + level = level ? level & PHP_V8_INTEGRITY_LEVEL_FLAGS : level; + + PHP_V8_TRY_CATCH(isolate); + PHP_V8_INIT_ISOLATE_LIMITS_ON_OBJECT_VALUE(php_v8_value); + + v8::Maybe maybe_res = local_obj->SetIntegrityLevel(local_context, static_cast(level)); + + PHP_V8_MAYBE_CATCH(php_v8_context, try_catch); + PHP_V8_THROW_EXCEPTION_WHEN_NOTHING(maybe_res, "Failed to set integrity level"); + + RETURN_BOOL(maybe_res.FromJust()); +} + + + static PHP_METHOD(V8Object, HasOwnProperty) { zval *php_v8_context_zv; zval *php_v8_name_zv; @@ -1525,6 +1560,11 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_object_GetConstructorName, ZEND_RETURN_VALUE, 0, IS_OBJECT, PHP_V8_NS "\\StringValue", 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_object_SetIntegrityLevel, ZEND_RETURN_VALUE, 2, _IS_BOOL, NULL, 0) + ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0) + ZEND_ARG_TYPE_INFO(0, level, IS_LONG, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_object_HasOwnProperty, ZEND_RETURN_VALUE, 2, _IS_BOOL, NULL, 0) ZEND_ARG_OBJ_INFO(0, context, V8\\Context, 0) ZEND_ARG_INFO(0, key) @@ -1630,6 +1670,7 @@ static const zend_function_entry php_v8_object_methods[] = { PHP_ME(V8Object, FindInstanceInPrototypeChain, arginfo_php_v8_object_FindInstanceInPrototypeChain, ZEND_ACC_PUBLIC) PHP_ME(V8Object, ObjectProtoToString, arginfo_php_v8_object_ObjectProtoToString, ZEND_ACC_PUBLIC) PHP_ME(V8Object, GetConstructorName, arginfo_v8_object_GetConstructorName, ZEND_ACC_PUBLIC) + PHP_ME(V8Object, SetIntegrityLevel, arginfo_v8_object_SetIntegrityLevel, ZEND_ACC_PUBLIC) PHP_ME(V8Object, HasOwnProperty, arginfo_v8_object_HasOwnProperty, ZEND_ACC_PUBLIC) PHP_ME(V8Object, HasRealNamedProperty, arginfo_v8_object_HasRealNamedProperty, ZEND_ACC_PUBLIC) diff --git a/stubs/src/IntegrityLevel.php b/stubs/src/IntegrityLevel.php new file mode 100644 index 0000000..02b23c1 --- /dev/null +++ b/stubs/src/IntegrityLevel.php @@ -0,0 +1,27 @@ + | + | | + | Licensed under the MIT license: http://opensource.org/licenses/MIT | + | | + | For the full copyright and license information, please view the | + | LICENSE file that was distributed with this source or visit | + | http://opensource.org/licenses/MIT | + +----------------------------------------------------------------------+ +*/ + + +namespace V8; + +/** + * Integrity level for objects. + */ +class IntegrityLevel +{ + const kFrozen = 0; + const kSealed = 1; +} diff --git a/stubs/src/ObjectValue.php b/stubs/src/ObjectValue.php index 25abfca..52e4a39 100644 --- a/stubs/src/ObjectValue.php +++ b/stubs/src/ObjectValue.php @@ -103,7 +103,12 @@ public function CreateDataPropertyIndex(Context $context, int $index, Value $val * * @return bool */ - public function DefineOwnProperty(Context $context, NameValue $key, Value $value, int $attributes = PropertyAttribute::None) : bool + public function DefineOwnProperty( + Context $context, + NameValue $key, + Value $value, + int $attributes = PropertyAttribute::None + ) : bool { } @@ -319,6 +324,18 @@ public function GetConstructorName() : StringValue { } + /** + * Sets the integrity level of the object. + * + * @param Context $context + * @param int $level One of \V8\IntegrityLevel::{kFrozen, kSealed} + * + * @return bool + */ + public function SetIntegrityLevel(Context $context, int $level) : bool + { + } + /** * @param Context $context * @param string $key diff --git a/tests/V8ArrayObject.phpt b/tests/V8ArrayObject.phpt index 44d48aa..89b8387 100644 --- a/tests/V8ArrayObject.phpt +++ b/tests/V8ArrayObject.phpt @@ -129,7 +129,7 @@ V8\ArrayObject::CreationContext() matches expected value Converters: ----------- V8\ArrayObject(V8\Value)->ToBoolean(): - object(V8\BooleanValue)#95 (1) { + object(V8\BooleanValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -145,7 +145,7 @@ V8\ArrayObject(V8\Value)->ToBoolean(): } } V8\ArrayObject(V8\Value)->ToNumber(): - object(V8\NumberValue)#95 (1) { + object(V8\NumberValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -161,7 +161,7 @@ V8\ArrayObject(V8\Value)->ToNumber(): } } V8\ArrayObject(V8\Value)->ToString(): - object(V8\StringValue)#95 (1) { + object(V8\StringValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -177,7 +177,7 @@ V8\ArrayObject(V8\Value)->ToString(): } } V8\ArrayObject(V8\Value)->ToDetailString(): - object(V8\StringValue)#95 (1) { + object(V8\StringValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -246,7 +246,7 @@ V8\ArrayObject(V8\Value)->ToObject(): } } V8\ArrayObject(V8\Value)->ToInteger(): - object(V8\NumberValue)#95 (1) { + object(V8\NumberValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -262,7 +262,7 @@ V8\ArrayObject(V8\Value)->ToInteger(): } } V8\ArrayObject(V8\Value)->ToUint32(): - object(V8\NumberValue)#95 (1) { + object(V8\NumberValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -278,7 +278,7 @@ V8\ArrayObject(V8\Value)->ToUint32(): } } V8\ArrayObject(V8\Value)->ToInt32(): - object(V8\NumberValue)#95 (1) { + object(V8\NumberValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8FunctionObject.phpt b/tests/V8FunctionObject.phpt index c2642b1..4e476cb 100644 --- a/tests/V8FunctionObject.phpt +++ b/tests/V8FunctionObject.phpt @@ -149,7 +149,7 @@ Should output Hello World string string(11) "Script done" v8Tests\TrackingDtors\FunctionObject(V8\FunctionObject)->GetScriptOrigin(): - object(V8\ScriptOrigin)#110 (6) { + object(V8\ScriptOrigin)#111 (6) { ["resource_name":"V8\ScriptOrigin":private]=> string(0) "" ["resource_line_offset":"V8\ScriptOrigin":private]=> @@ -157,7 +157,7 @@ v8Tests\TrackingDtors\FunctionObject(V8\FunctionObject)->GetScriptOrigin(): ["resource_column_offset":"V8\ScriptOrigin":private]=> int(0) ["options":"V8\ScriptOrigin":private]=> - object(V8\ScriptOriginOptions)#111 (3) { + object(V8\ScriptOriginOptions)#112 (3) { ["is_embedder_debug_script":"V8\ScriptOriginOptions":private]=> bool(false) ["is_shared_cross_origin":"V8\ScriptOriginOptions":private]=> diff --git a/tests/V8IntegrityLevel.phpt b/tests/V8IntegrityLevel.phpt new file mode 100644 index 0000000..4b8ae6e --- /dev/null +++ b/tests/V8IntegrityLevel.phpt @@ -0,0 +1,36 @@ +--TEST-- +V8\PropertyAttribute +--SKIPIF-- + +--FILE-- +header('Object representation'); +$helper->dump($obj); +$helper->space(); + + +$helper->header('Class constants'); +$helper->dump_object_constants($obj); +$helper->space(); + +?> +--EXPECT-- +Object representation: +---------------------- +object(V8\IntegrityLevel)#1 (0) { +} + + +Class constants: +---------------- +V8\IntegrityLevel::kFrozen = 0 +V8\IntegrityLevel::kSealed = 1 diff --git a/tests/V8ObjectValue.phpt b/tests/V8ObjectValue.phpt index d1560f5..2b35c8b 100644 --- a/tests/V8ObjectValue.phpt +++ b/tests/V8ObjectValue.phpt @@ -149,7 +149,7 @@ V8\ObjectValue(V8\Value)->IsRegExp(): bool(false) Converters: ----------- V8\ObjectValue(V8\Value)->ToBoolean(): - object(V8\BooleanValue)#92 (1) { + object(V8\BooleanValue)#93 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -165,7 +165,7 @@ V8\ObjectValue(V8\Value)->ToBoolean(): } } V8\ObjectValue(V8\Value)->ToNumber(): - object(V8\NumberValue)#92 (1) { + object(V8\NumberValue)#93 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -181,7 +181,7 @@ V8\ObjectValue(V8\Value)->ToNumber(): } } V8\ObjectValue(V8\Value)->ToString(): - object(V8\StringValue)#92 (1) { + object(V8\StringValue)#93 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -197,7 +197,7 @@ V8\ObjectValue(V8\Value)->ToString(): } } V8\ObjectValue(V8\Value)->ToDetailString(): - object(V8\StringValue)#92 (1) { + object(V8\StringValue)#93 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -266,7 +266,7 @@ V8\ObjectValue(V8\Value)->ToObject(): } } V8\ObjectValue(V8\Value)->ToInteger(): - object(V8\NumberValue)#92 (1) { + object(V8\NumberValue)#93 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -282,7 +282,7 @@ V8\ObjectValue(V8\Value)->ToInteger(): } } V8\ObjectValue(V8\Value)->ToUint32(): - object(V8\NumberValue)#92 (1) { + object(V8\NumberValue)#93 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> @@ -298,7 +298,7 @@ V8\ObjectValue(V8\Value)->ToUint32(): } } V8\ObjectValue(V8\Value)->ToInt32(): - object(V8\NumberValue)#92 (1) { + object(V8\NumberValue)#93 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8ObjectValue_SetIntegrityLevel.phpt b/tests/V8ObjectValue_SetIntegrityLevel.phpt new file mode 100644 index 0000000..8a37a0f --- /dev/null +++ b/tests/V8ObjectValue_SetIntegrityLevel.phpt @@ -0,0 +1,98 @@ +--TEST-- +V8\ObjectValue::SetIntegrityLevel() +--SKIPIF-- + +--FILE-- +injectConsoleLog($context1); + + +$obj0 = new \V8\ObjectValue($context1); +$obj0->Set($context1, new \V8\StringValue($isolate1, 'test'), new \V8\IntegerValue($isolate1, 42)); +$context1->GlobalObject()->Set($context1, new \V8\StringValue($isolate1, 'obj0'), $obj0); + +$obj1 = new \V8\ObjectValue($context1); +$obj1->Set($context1, new \V8\StringValue($isolate1, 'test'), new \V8\IntegerValue($isolate1, 42)); +$obj1->SetIntegrityLevel($context1, \V8\IntegrityLevel::kFrozen); +$context1->GlobalObject()->Set($context1, new \V8\StringValue($isolate1, 'obj1'), $obj1); + +$obj2 = new \V8\ObjectValue($context1); +$obj2->Set($context1, new \V8\StringValue($isolate1, 'test'), new \V8\IntegerValue($isolate1, 42)); +$obj2->SetIntegrityLevel($context1, \V8\IntegrityLevel::kSealed); +$context1->GlobalObject()->Set($context1, new \V8\StringValue($isolate1, 'obj2'), $obj2); + +$source1 = ' +console.log(Object.isFrozen(obj0)); +console.log(Object.isSealed(obj0)); +console.log(obj0.test); +console.log(obj0.test1); +obj0.test = "foo"; +obj0.test1 = "bar"; +console.log(obj0.test); +console.log(obj0.test1); +console.log(); + + +console.log(Object.isFrozen(obj1)); +console.log(Object.isSealed(obj1)); +console.log(obj1.test); +console.log(obj1.test1); +obj1.test = "foo"; +obj1.test1 = "bar"; +console.log(obj1.test); +console.log(obj1.test1); +console.log(); + + +console.log(Object.isFrozen(obj2)); +console.log(Object.isSealed(obj2)); +console.log(obj2.test); +console.log(obj2.test1); +obj2.test = "foo"; +obj2.test1 = "bar"; +console.log(obj2.test); +console.log(obj2.test1); +console.log(); + + +'; +$file_name1 = 'test.js'; + +$script1 = new V8\Script($context1, new \V8\StringValue($isolate1, $source1), new \V8\ScriptOrigin($file_name1)); + +$script1->Run($context1); + +?> +--EXPECT-- +false +false +42 + +foo +bar + +true +true +42 + +42 + + +false +true +42 + +foo + diff --git a/tests/V8StringObject.phpt b/tests/V8StringObject.phpt index 38e9c98..bb47786 100644 --- a/tests/V8StringObject.phpt +++ b/tests/V8StringObject.phpt @@ -127,7 +127,7 @@ StringObject extends ObjectValue: ok Getters: -------- V8\StringObject->ValueOf(): - object(V8\StringValue)#95 (1) { + object(V8\StringValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/tests/V8SymbolObject.phpt b/tests/V8SymbolObject.phpt index 2f3f988..55fd416 100644 --- a/tests/V8SymbolObject.phpt +++ b/tests/V8SymbolObject.phpt @@ -130,7 +130,7 @@ SymbolObject extends ObjectValue: ok Getters: -------- V8\SymbolObject->ValueOf(): - object(V8\SymbolValue)#95 (1) { + object(V8\SymbolValue)#96 (1) { ["isolate":"V8\Value":private]=> object(V8\Isolate)#3 (5) { ["snapshot":"V8\Isolate":private]=> diff --git a/v8.cc b/v8.cc index e375f70..714236d 100644 --- a/v8.cc +++ b/v8.cc @@ -44,6 +44,7 @@ #include "php_v8_uint32.h" #include "php_v8_primitive.h" #include "php_v8_object.h" +#include "php_v8_integrity_level.h" #include "php_v8_function.h" #include "php_v8_array.h" #include "php_v8_date.h" @@ -124,6 +125,7 @@ PHP_MINIT_FUNCTION(v8) PHP_MINIT(php_v8_integer)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(php_v8_int32)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(php_v8_uint32)(INIT_FUNC_ARGS_PASSTHRU); + PHP_MINIT(php_v8_integrity_level)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(php_v8_object)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(php_v8_function)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(php_v8_array)(INIT_FUNC_ARGS_PASSTHRU); From d7b6b86548cde1fdcce29a183dd8f175baeb44e8 Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Fri, 19 Aug 2016 00:34:12 +0300 Subject: [PATCH 05/10] Add malloced_memory to V8\HeapStatistics V8 commit: https://github.com/v8/v8/commit/cb7aa79b1265b09e21a82d31d4c60470a4444fa5 --- src/php_v8_heap_statistics.cc | 25 +++++++++++- stubs/src/HeapStatistics.php | 64 ++++++++++++++++++------------- tests/V8HeapStatistics.phpt | 8 +++- tests/V8Isolate.phpt | 4 +- tests/V8Isolate_limit_memory.phpt | 4 +- 5 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/php_v8_heap_statistics.cc b/src/php_v8_heap_statistics.cc index 1b22a4c..cafbb51 100644 --- a/src/php_v8_heap_statistics.cc +++ b/src/php_v8_heap_statistics.cc @@ -35,6 +35,7 @@ void php_v8_heap_statistics_create_from_heap_statistics(zval *return_value, v8:: zend_update_property_double(this_ce, return_value, ZEND_STRL("total_available_size"), hs->total_available_size()); zend_update_property_double(this_ce, return_value, ZEND_STRL("used_heap_size"), hs->used_heap_size()); zend_update_property_double(this_ce, return_value, ZEND_STRL("heap_size_limit"), hs->heap_size_limit()); + zend_update_property_double(this_ce, return_value, ZEND_STRL("malloced_memory"), hs->malloced_memory()); zend_update_property_bool(this_ce, return_value, ZEND_STRL("does_zap_garbage"), static_cast(hs->does_zap_garbage())); @@ -47,12 +48,13 @@ static PHP_METHOD(V8HeapStatistics, __construct) { double total_available_size = 0; double used_heap_size = 0; double heap_size_limit = 0; + double malloced_memory = 0; zend_bool does_zap_garbage = '\0'; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ddddddb", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|dddddddb", &total_heap_size, &total_heap_size_executable, &total_physical_size, &total_available_size, - &used_heap_size, &heap_size_limit, &does_zap_garbage) == FAILURE) { + &used_heap_size, &heap_size_limit, &malloced_memory, &does_zap_garbage) == FAILURE) { return; } @@ -62,6 +64,7 @@ static PHP_METHOD(V8HeapStatistics, __construct) { zend_update_property_double(this_ce, getThis(), ZEND_STRL("total_available_size"), total_available_size); zend_update_property_double(this_ce, getThis(), ZEND_STRL("used_heap_size"), used_heap_size); zend_update_property_double(this_ce, getThis(), ZEND_STRL("heap_size_limit"), heap_size_limit); + zend_update_property_double(this_ce, getThis(), ZEND_STRL("malloced_memory"), malloced_memory); zend_update_property_bool(this_ce, getThis(), ZEND_STRL("does_zap_garbage"), does_zap_garbage); } @@ -126,6 +129,16 @@ static PHP_METHOD(V8HeapStatistics, heap_size_limit) { RETVAL_ZVAL(zend_read_property(this_ce, getThis(), ZEND_STRL("heap_size_limit"), 0, &rv), 1, 0); } +static PHP_METHOD(V8HeapStatistics, malloced_memory) { + zval rv; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETVAL_ZVAL(zend_read_property(this_ce, getThis(), ZEND_STRL("malloced_memory"), 0, &rv), 1, 0); +} + static PHP_METHOD(V8HeapStatistics, does_zap_garbage) { zval rv; @@ -144,6 +157,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_heap_statistics___construct, ZEND_SEND_BY_VAL, ZEND_ARG_TYPE_INFO(0, total_available_size, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, used_heap_size, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, heap_size_limit, IS_DOUBLE, 0) + ZEND_ARG_TYPE_INFO(0, malloced_memory, IS_DOUBLE, 0) + ZEND_ARG_TYPE_INFO(0, peak_malloced_memory, IS_DOUBLE, 0) + ZEND_ARG_TYPE_INFO(0, does_zap_garbage, _IS_BOOL, 0) ZEND_END_ARG_INFO() @@ -165,6 +181,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_heap_statistics__heap_size_limit, ZEND_RETURN_VALUE, 0, IS_DOUBLE, NULL, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_heap_statistics__malloced_memory, ZEND_RETURN_VALUE, 0, IS_DOUBLE, NULL, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_heap_statistics__does_zap_garbage, ZEND_RETURN_VALUE, 0, _IS_BOOL, NULL, 0) ZEND_END_ARG_INFO() @@ -178,6 +197,7 @@ static const zend_function_entry php_v8_heap_statistics_methods[] = { PHP_ME(V8HeapStatistics, total_available_size, arginfo_v8_heap_statistics__total_available_size, ZEND_ACC_PUBLIC) PHP_ME(V8HeapStatistics, used_heap_size, arginfo_v8_heap_statistics__used_heap_size, ZEND_ACC_PUBLIC) PHP_ME(V8HeapStatistics, heap_size_limit, arginfo_v8_heap_statistics__heap_size_limit, ZEND_ACC_PUBLIC) + PHP_ME(V8HeapStatistics, malloced_memory, arginfo_v8_heap_statistics__malloced_memory, ZEND_ACC_PUBLIC) PHP_ME(V8HeapStatistics, does_zap_garbage, arginfo_v8_heap_statistics__does_zap_garbage, ZEND_ACC_PUBLIC) PHP_FE_END @@ -195,6 +215,7 @@ PHP_MINIT_FUNCTION (php_v8_heap_statistics) { zend_declare_property_double(this_ce, ZEND_STRL("total_available_size"), 0, ZEND_ACC_PRIVATE); zend_declare_property_double(this_ce, ZEND_STRL("used_heap_size"), 0, ZEND_ACC_PRIVATE); zend_declare_property_double(this_ce, ZEND_STRL("heap_size_limit"), 0, ZEND_ACC_PRIVATE); + zend_declare_property_double(this_ce, ZEND_STRL("malloced_memory"), 0, ZEND_ACC_PRIVATE); zend_declare_property_bool(this_ce, ZEND_STRL("does_zap_garbage"), false, ZEND_ACC_PRIVATE); diff --git a/stubs/src/HeapStatistics.php b/stubs/src/HeapStatistics.php index 49ea5f4..ef90f9b 100644 --- a/stubs/src/HeapStatistics.php +++ b/stubs/src/HeapStatistics.php @@ -27,50 +27,56 @@ class HeapStatistics { /** - * @var int + * @var float */ private $total_heap_size; /** - * @var int + * @var float */ private $total_heap_size_executable; /** - * @var int + * @var float */ private $total_physical_size; /** - * @var int + * @var float */ private $total_available_size; /** - * @var int + * @var float */ private $used_heap_size; /** - * @var int + * @var float */ private $heap_size_limit; + /** + * @var float + */ + private $malloced_memory; /** * @var bool */ private $does_zap_garbage; /** - * @param int $total_heap_size - * @param int $total_heap_size_executable - * @param int $total_physical_size - * @param int $total_available_size - * @param int $used_heap_size - * @param int $heap_size_limit - * @param bool $does_zap_garbage + * @param float $total_heap_size + * @param float $total_heap_size_executable + * @param float $total_physical_size + * @param float $total_available_size + * @param float $used_heap_size + * @param float $heap_size_limit + * @param float $malloced_memory + * @param bool $does_zap_garbage */ public function __construct( - int $total_heap_size, - int $total_heap_size_executable, - int $total_physical_size, - int $total_available_size, - int $used_heap_size, - int $heap_size_limit, + float $total_heap_size, + float $total_heap_size_executable, + float $total_physical_size, + float $total_available_size, + float $used_heap_size, + float $heap_size_limit, + float $malloced_memory, bool $does_zap_garbage ) { $this->total_heap_size = $total_heap_size; @@ -79,40 +85,46 @@ public function __construct( $this->total_available_size = $total_available_size; $this->used_heap_size = $used_heap_size; $this->heap_size_limit = $heap_size_limit; + $this->malloced_memory = $malloced_memory; $this->does_zap_garbage = $does_zap_garbage; } - public function total_heap_size() + public function total_heap_size() : float { return $this->total_heap_size; } - public function total_heap_size_executable() + public function total_heap_size_executable() : float { return $this->total_heap_size_executable; } - public function total_physical_size() + public function total_physical_size() : float { return $this->total_physical_size; } - public function total_available_size() + public function total_available_size() : float { return $this->total_available_size; } - public function used_heap_size() + public function used_heap_size() : float { return $this->used_heap_size; } - public function heap_size_limit() + public function heap_size_limit() : float { return $this->heap_size_limit; } - public function does_zap_garbage() + public function malloced_memory() : float + { + return $this->malloced_memory; + } + + public function does_zap_garbage() : bool { return $this->does_zap_garbage; } diff --git a/tests/V8HeapStatistics.phpt b/tests/V8HeapStatistics.phpt index 1db6eb9..ae6e04b 100644 --- a/tests/V8HeapStatistics.phpt +++ b/tests/V8HeapStatistics.phpt @@ -8,7 +8,7 @@ V8\HeapStatistics /** @var \Phpv8Testsuite $helper */ $helper = require '.testsuite.php'; -$hs = new \V8\HeapStatistics(1, 2, 3, 4, 5, 6, true); +$hs = new \V8\HeapStatistics(1, 2, 3, 4, 5, 6, 7, true); $helper->header('Object representation'); $helper->dump($hs); @@ -20,7 +20,7 @@ $helper->dump_object_methods($hs); --EXPECT-- Object representation: ---------------------- -object(V8\HeapStatistics)#2 (7) { +object(V8\HeapStatistics)#2 (8) { ["total_heap_size":"V8\HeapStatistics":private]=> float(1) ["total_heap_size_executable":"V8\HeapStatistics":private]=> @@ -33,6 +33,8 @@ object(V8\HeapStatistics)#2 (7) { float(5) ["heap_size_limit":"V8\HeapStatistics":private]=> float(6) + ["malloced_memory":"V8\HeapStatistics":private]=> + float(7) ["does_zap_garbage":"V8\HeapStatistics":private]=> bool(true) } @@ -43,4 +45,6 @@ V8\HeapStatistics->total_physical_size(): float(3) V8\HeapStatistics->total_available_size(): float(4) V8\HeapStatistics->used_heap_size(): float(5) V8\HeapStatistics->heap_size_limit(): float(6) +V8\HeapStatistics->malloced_memory(): float(7) +V8\HeapStatistics->peak_malloced_memory(): float(8) V8\HeapStatistics->does_zap_garbage(): bool(true) diff --git a/tests/V8Isolate.phpt b/tests/V8Isolate.phpt index a6a3384..10b52cc 100644 --- a/tests/V8Isolate.phpt +++ b/tests/V8Isolate.phpt @@ -46,7 +46,7 @@ object(V8\Isolate)#2 (5) { V8\Exceptions\GenericException: Not in context! V8\Isolate->GetHeapStatistics(): - object(V8\HeapStatistics)#28 (7) { + object(V8\HeapStatistics)#28 (8) { ["total_heap_size":"V8\HeapStatistics":private]=> float(%d) ["total_heap_size_executable":"V8\HeapStatistics":private]=> @@ -59,6 +59,8 @@ V8\Isolate->GetHeapStatistics(): float(%d) ["heap_size_limit":"V8\HeapStatistics":private]=> float(%d) + ["malloced_memory":"V8\HeapStatistics":private]=> + float(%d) ["does_zap_garbage":"V8\HeapStatistics":private]=> bool(false) } diff --git a/tests/V8Isolate_limit_memory.phpt b/tests/V8Isolate_limit_memory.phpt index f3fd52e..acdf847 100644 --- a/tests/V8Isolate_limit_memory.phpt +++ b/tests/V8Isolate_limit_memory.phpt @@ -91,7 +91,7 @@ object(V8\Isolate)#3 (5) { ["memory_limit_hit":"V8\Isolate":private]=> bool(true) } -object(V8\HeapStatistics)#14 (7) { +object(V8\HeapStatistics)#14 (8) { ["total_heap_size":"V8\HeapStatistics":private]=> float(%d) ["total_heap_size_executable":"V8\HeapStatistics":private]=> @@ -104,6 +104,8 @@ object(V8\HeapStatistics)#14 (7) { float(%d) ["heap_size_limit":"V8\HeapStatistics":private]=> float(%d) + ["malloced_memory":"V8\HeapStatistics":private]=> + float(%d) ["does_zap_garbage":"V8\HeapStatistics":private]=> bool(false) } From 9ece87f6bd41b5c6cfd7f2b90afc25dc39c290b4 Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Sat, 20 Aug 2016 02:04:38 +0300 Subject: [PATCH 06/10] Cleanup callback info creation and invalidation --- src/php_v8_callback_info.cc | 23 ++++++++-------- src/php_v8_callback_info.h | 7 +++-- src/php_v8_callbacks.cc | 13 ++++++--- src/php_v8_function_callback_info.cc | 19 +++++++------ src/php_v8_function_callback_info.h | 3 +- src/php_v8_property_callback_info.cc | 41 +++++++++++++++------------- src/php_v8_property_callback_info.h | 11 ++++---- src/php_v8_return_value.cc | 14 +++++++--- src/php_v8_return_value.h | 7 +++-- 9 files changed, 80 insertions(+), 58 deletions(-) diff --git a/src/php_v8_callback_info.cc b/src/php_v8_callback_info.cc index ffa66f0..ed64103 100644 --- a/src/php_v8_callback_info.cc +++ b/src/php_v8_callback_info.cc @@ -31,12 +31,9 @@ php_v8_callback_info_t * php_v8_callback_info_fetch_object(zend_object *obj) { return (php_v8_callback_info_t *)((char *)obj - XtOffsetOf(php_v8_callback_info_t, std)); } -void php_v8_callback_info_invalidate(zval *val) { - PHP_V8_CALLBACK_INFO_FETCH_INTO(val, php_v8_callback_info); - php_v8_callback_info->php_v8_isolate = NULL; - - if (!Z_ISUNDEF(php_v8_callback_info->retval)) { - php_v8_return_value_mark_expired(&php_v8_callback_info->retval); +void php_v8_callback_info_invalidate(php_v8_callback_info_t *php_v8_callback_info) { + if (php_v8_callback_info->php_v8_return_value) { + php_v8_return_value_mark_expired(php_v8_callback_info->php_v8_return_value); } } @@ -44,7 +41,7 @@ void php_v8_callback_info_invalidate(zval *val) { static HashTable * php_v8_callback_info_gc(zval *object, zval **table, int *n) { PHP_V8_CALLBACK_INFO_FETCH_INTO(object, php_v8_callback_info); - int size = 2; // args + retval + int size = 2; // args + php_v8_return_value->this_ptr if (php_v8_callback_info->gc_data_count < size) { php_v8_callback_info->gc_data = (zval *)safe_erealloc(php_v8_callback_info->gc_data, size, sizeof(zval), 0); @@ -53,7 +50,7 @@ static HashTable * php_v8_callback_info_gc(zval *object, zval **table, int *n) { php_v8_callback_info->gc_data_count = size; ZVAL_COPY_VALUE(&php_v8_callback_info->gc_data[0], &php_v8_callback_info->args); - ZVAL_COPY_VALUE(&php_v8_callback_info->gc_data[1], &php_v8_callback_info->retval); + ZVAL_COPY_VALUE(&php_v8_callback_info->gc_data[1], &php_v8_callback_info->php_v8_return_value->this_ptr); *table = php_v8_callback_info->gc_data; *n = php_v8_callback_info->gc_data_count; @@ -93,8 +90,12 @@ void php_v8_callback_info_free(zend_object *object) { delete php_v8_callback_info->holder_obj; } - if (!Z_ISUNDEF(php_v8_callback_info->retval)) { - zval_ptr_dtor(&php_v8_callback_info->retval); + if (php_v8_callback_info->php_v8_return_value) { + if (!Z_ISUNDEF(php_v8_callback_info->php_v8_return_value->this_ptr)) { + zval_ptr_dtor(&php_v8_callback_info->php_v8_return_value->this_ptr); + } + + php_v8_callback_info->php_v8_return_value = NULL; } if (!Z_ISUNDEF(php_v8_callback_info->args)) { @@ -186,7 +187,7 @@ static PHP_METHOD(V8CallbackInfo, GetReturnValue) { PHP_V8_CALLBACK_INFO_FETCH_WITH_CHECK(getThis(), php_v8_callback_info); PHP_V8_V8_CALLBACK_INFO_CHECK_IN_CONTEXT(php_v8_callback_info); - RETVAL_ZVAL(&php_v8_callback_info->retval, 1, 0); + RETVAL_ZVAL(&php_v8_callback_info->php_v8_return_value->this_ptr, 1, 0); } diff --git a/src/php_v8_callback_info.h b/src/php_v8_callback_info.h index ab82e69..97c12b3 100644 --- a/src/php_v8_callback_info.h +++ b/src/php_v8_callback_info.h @@ -17,6 +17,7 @@ typedef struct _php_v8_callback_info_t php_v8_callback_info_t; +#include "php_v8_return_value.h" #include "php_v8_exceptions.h" #include "php_v8_context.h" #include "php_v8_isolate.h" @@ -34,7 +35,7 @@ extern zend_class_entry* php_v8_callback_info_class_entry; extern php_v8_callback_info_t * php_v8_callback_info_fetch_object(zend_object *obj); -extern void php_v8_callback_info_invalidate(zval *val); +extern void php_v8_callback_info_invalidate(php_v8_callback_info_t *php_v8_callback_info); #define PHP_V8_CALLBACK_INFO_FETCH(zv) php_v8_callback_info_fetch_object(Z_OBJ_P(zv)) #define PHP_V8_CALLBACK_INFO_FETCH_INTO(pzval, into) php_v8_callback_info_t *(into) = PHP_V8_CALLBACK_INFO_FETCH((pzval)); @@ -51,7 +52,7 @@ extern void php_v8_callback_info_invalidate(zval *val); // TODO: suggest better naming #define PHP_V8_V8_CALLBACK_INFO_CHECK_IN_CONTEXT(value) \ - if ((value)->php_v8_isolate == NULL) { \ + if ((value)->php_v8_return_value == NULL || PHP_V8_RETVAL_ACCEPTS_INVALID == (value)->php_v8_return_value->accepts) { \ PHP_V8_THROW_EXCEPTION("Attempt to use callback info object out of callback context"); \ return; \ } @@ -69,7 +70,7 @@ struct _php_v8_callback_info_t { v8::Persistent *holder_obj; bool is_construct_call; - zval retval; + php_v8_return_value_t *php_v8_return_value; zval args; zval *gc_data; diff --git a/src/php_v8_callbacks.cc b/src/php_v8_callbacks.cc index e3da6b6..2e4d721 100644 --- a/src/php_v8_callbacks.cc +++ b/src/php_v8_callbacks.cc @@ -419,16 +419,21 @@ void php_v8_callback_call_from_bucket_with_zargs(size_t index, v8::Local void php_v8_callback_call_from_bucket_with_zargs(size_t index, const T &info, zval *args) { zval callback_info; - + php_v8_callback_info_t *php_v8_callback_info; // Wrap callback info - php_v8_callback_info_create_from_info(&callback_info, info); + php_v8_callback_info = php_v8_callback_info_create_from_info(&callback_info, info); + + if (!php_v8_callback_info) { + return; + } + add_next_index_zval(args, &callback_info); php_v8_callback_call_from_bucket_with_zargs(index, info.Data(), args, NULL); - php_v8_callback_set_retval_from_callback_info(info.GetReturnValue(), PHP_V8_RETURN_VALUE_FETCH(&PHP_V8_CALLBACK_INFO_FETCH(&callback_info)->retval)); + php_v8_callback_set_retval_from_callback_info(info.GetReturnValue(), php_v8_callback_info->php_v8_return_value); - php_v8_callback_info_invalidate(&callback_info); + php_v8_callback_info_invalidate(php_v8_callback_info); } diff --git a/src/php_v8_function_callback_info.cc b/src/php_v8_function_callback_info.cc index b70489d..5d18563 100644 --- a/src/php_v8_function_callback_info.cc +++ b/src/php_v8_function_callback_info.cc @@ -27,13 +27,14 @@ zend_class_entry* php_v8_function_callback_info_class_entry; #define this_ce php_v8_function_callback_info_class_entry -void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::FunctionCallbackInfo &args) { +php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::FunctionCallbackInfo &args) { + zval retval; v8::Isolate *isolate = args.GetIsolate(); v8::Local context = isolate->GetCurrentContext(); if (context.IsEmpty()) { PHP_V8_THROW_EXCEPTION("Internal exception: no calling context found"); - return; + return NULL; } object_init_ex(this_ptr, this_ce); @@ -42,15 +43,15 @@ void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::FunctionCal php_v8_callback_info->php_v8_isolate = PHP_V8_ISOLATE_FETCH_REFERENCE(isolate); php_v8_callback_info->php_v8_context = php_v8_context_get_reference(context); - PHP_V8_COPY_ISOLATE_OBJECT_HANDLE(php_v8_callback_info->php_v8_isolate, php_v8_callback_info); - php_v8_callback_info->this_obj->Reset(isolate, args.This()); php_v8_callback_info->holder_obj->Reset(isolate, args.Holder()); - php_v8_return_value_create_from_return_value(&php_v8_callback_info->retval, - php_v8_callback_info->php_v8_isolate, - php_v8_callback_info->php_v8_context, - PHP_V8_RETVAL_ACCEPTS_ANY); + php_v8_callback_info->php_v8_return_value = php_v8_return_value_create_from_return_value( + &retval, + php_v8_callback_info->php_v8_isolate, + php_v8_callback_info->php_v8_context, + PHP_V8_RETVAL_ACCEPTS_ANY + ); /* function callback specific part */ php_v8_callback_info->length = args.Length(); @@ -62,6 +63,8 @@ void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::FunctionCal } php_v8_callback_info->is_construct_call = args.IsConstructCall(); + + return php_v8_callback_info; } diff --git a/src/php_v8_function_callback_info.h b/src/php_v8_function_callback_info.h index 2ffb1bc..1d26b21 100644 --- a/src/php_v8_function_callback_info.h +++ b/src/php_v8_function_callback_info.h @@ -15,6 +15,7 @@ #ifndef PHP_V8_FUNCTION_CALLBACK_INFO_H #define PHP_V8_FUNCTION_CALLBACK_INFO_H +#include "php_v8_callback_info.h" #include extern "C" { @@ -27,7 +28,7 @@ extern "C" { extern zend_class_entry* php_v8_function_callback_info_class_entry; -extern void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::FunctionCallbackInfo&args); +extern php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::FunctionCallbackInfo&args); PHP_MINIT_FUNCTION (php_v8_function_callback_info); diff --git a/src/php_v8_property_callback_info.cc b/src/php_v8_property_callback_info.cc index dae6b29..0afbb6f 100644 --- a/src/php_v8_property_callback_info.cc +++ b/src/php_v8_property_callback_info.cc @@ -26,37 +26,38 @@ zend_class_entry *php_v8_property_callback_info_class_entry; template -void php_v8_callback_info_create_from_info_meta(zval *this_ptr, const v8::PropertyCallbackInfo &info, int accepts); +php_v8_callback_info_t *php_v8_callback_info_create_from_info_meta(zval *this_ptr, const v8::PropertyCallbackInfo &info, int accepts); -void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { - php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_ANY); +php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { + return php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_ANY); } -void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { - php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_ARRAY); +php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { + return php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_ARRAY); } -void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { - php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_INTEGER); +php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { + return php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_INTEGER); } -void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { - php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_BOOLEAN); +php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { + return php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_BOOLEAN); } -void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { - php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_VOID); +php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info) { + return php_v8_callback_info_create_from_info_meta(this_ptr, info, PHP_V8_RETVAL_ACCEPTS_VOID); } template -void php_v8_callback_info_create_from_info_meta(zval *this_ptr, const v8::PropertyCallbackInfo &info, int accepts) { +php_v8_callback_info_t *php_v8_callback_info_create_from_info_meta(zval *this_ptr, const v8::PropertyCallbackInfo &info, int accepts) { + zval retval; v8::Isolate *isolate = info.GetIsolate(); v8::Local context = isolate->GetCurrentContext(); if (context.IsEmpty()) { PHP_V8_THROW_EXCEPTION("Internal exception: no calling context found"); - return; + return NULL; } object_init_ex(this_ptr, this_ce); @@ -65,15 +66,17 @@ void php_v8_callback_info_create_from_info_meta(zval *this_ptr, const v8::Proper php_v8_callback_info->php_v8_isolate = PHP_V8_ISOLATE_FETCH_REFERENCE(isolate); php_v8_callback_info->php_v8_context = php_v8_context_get_reference(context); - PHP_V8_COPY_ISOLATE_OBJECT_HANDLE(php_v8_callback_info->php_v8_isolate, php_v8_callback_info); - php_v8_callback_info->this_obj->Reset(isolate, info.This()); php_v8_callback_info->holder_obj->Reset(isolate, info.Holder()); - php_v8_return_value_create_from_return_value(&php_v8_callback_info->retval, - php_v8_callback_info->php_v8_isolate, - php_v8_callback_info->php_v8_context, - accepts); + php_v8_callback_info->php_v8_return_value = php_v8_return_value_create_from_return_value( + &retval, + php_v8_callback_info->php_v8_isolate, + php_v8_callback_info->php_v8_context, + accepts + ); + + return php_v8_callback_info; } static const zend_function_entry php_v8_property_callback_info_methods[] = { diff --git a/src/php_v8_property_callback_info.h b/src/php_v8_property_callback_info.h index 274ad0b..1184bf8 100644 --- a/src/php_v8_property_callback_info.h +++ b/src/php_v8_property_callback_info.h @@ -15,6 +15,7 @@ #ifndef PHP_V8_PROPERTY_CALLBACK_INFO_H #define PHP_V8_PROPERTY_CALLBACK_INFO_H +#include "php_v8_callback_info.h" #include extern "C" { @@ -27,11 +28,11 @@ extern "C" { extern zend_class_entry* php_v8_property_callback_info_class_entry; -extern void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); -extern void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); -extern void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); -extern void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); -extern void php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); +extern php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); +extern php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); +extern php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); +extern php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); +extern php_v8_callback_info_t *php_v8_callback_info_create_from_info(zval *this_ptr, const v8::PropertyCallbackInfo &info); PHP_MINIT_FUNCTION (php_v8_property_callback_info); diff --git a/src/php_v8_return_value.cc b/src/php_v8_return_value.cc index 614dac2..1e0c794 100644 --- a/src/php_v8_return_value.cc +++ b/src/php_v8_return_value.cc @@ -65,6 +65,10 @@ static void php_v8_return_value_free(zend_object *object) { zval_ptr_dtor(&php_v8_return_value->value.php_v8_value_zv); } + if (!Z_ISUNDEF(php_v8_return_value->this_ptr)) { + zval_ptr_dtor(&php_v8_return_value->this_ptr); + } + if (php_v8_return_value->gc_data) { efree(php_v8_return_value->gc_data); } @@ -87,7 +91,7 @@ static zend_object * php_v8_return_value_ctor(zend_class_entry *ce) { } -void php_v8_return_value_create_from_return_value(zval *this_ptr, php_v8_isolate_t *php_v8_isolate, php_v8_context_t *php_v8_context, int accepts) { +php_v8_return_value_t *php_v8_return_value_create_from_return_value(zval *this_ptr, php_v8_isolate_t *php_v8_isolate, php_v8_context_t *php_v8_context, int accepts) { object_init_ex(this_ptr, this_ce); PHP_V8_RETURN_VALUE_FETCH_INTO(this_ptr, php_v8_return_value); @@ -95,11 +99,13 @@ void php_v8_return_value_create_from_return_value(zval *this_ptr, php_v8_isolate php_v8_return_value->php_v8_isolate = php_v8_isolate; php_v8_return_value->php_v8_context = php_v8_context; php_v8_return_value->accepts = accepts; -} -void php_v8_return_value_mark_expired(zval *this_ptr) { - PHP_V8_RETURN_VALUE_FETCH_INTO(this_ptr, php_v8_return_value); + ZVAL_COPY_VALUE(&php_v8_return_value->this_ptr, this_ptr); + + return php_v8_return_value; +} +void php_v8_return_value_mark_expired(php_v8_return_value_t *php_v8_return_value) { php_v8_return_value->accepts = PHP_V8_RETVAL_ACCEPTS_INVALID; } diff --git a/src/php_v8_return_value.h b/src/php_v8_return_value.h index f6235ee..21d934e 100644 --- a/src/php_v8_return_value.h +++ b/src/php_v8_return_value.h @@ -32,9 +32,9 @@ extern "C" { extern zend_class_entry *php_v8_return_value_class_entry; -extern void php_v8_return_value_create_from_return_value(zval *this_ptr, php_v8_isolate_t *php_v8_isolate, php_v8_context_t *php_v8_context, int accepts); -extern void php_v8_return_value_mark_expired(zval *this_ptr); -extern php_v8_return_value_t * php_v8_return_value_fetch_object(zend_object *obj); +extern php_v8_return_value_t *php_v8_return_value_create_from_return_value(zval *this_ptr, php_v8_isolate_t *php_v8_isolate, php_v8_context_t *php_v8_context, int accepts); +extern void php_v8_return_value_mark_expired(php_v8_return_value_t *php_v8_return_value); +extern php_v8_return_value_t *php_v8_return_value_fetch_object(zend_object *obj); #define PHP_V8_RETURN_VALUE_FETCH(zv) php_v8_return_value_fetch_object(Z_OBJ_P(zv)) @@ -128,6 +128,7 @@ struct _php_v8_return_value_t { zval *gc_data; int gc_data_count; + zval this_ptr; zend_object std; }; From 2d4d7dad2b94f3e7f0cdcb24400c622ecd54182d Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Sat, 20 Aug 2016 17:17:01 +0300 Subject: [PATCH 07/10] Add ReturnValue::Get(), refactor retval internals, improve context checking --- src/php_v8_callback_info.cc | 14 ++ src/php_v8_callback_info.h | 4 +- src/php_v8_callbacks.cc | 163 ++++--------------- src/php_v8_return_value.cc | 261 +++++++++++++++++++++--------- src/php_v8_return_value.h | 68 +------- stubs/src/CallbackInfo.php | 9 ++ stubs/src/ReturnValue.php | 20 +++ tests/V8FunctionCallbackInfo.phpt | 42 ++++- tests/V8ReturnValue.phpt | 28 +++- tests/V8ReturnValue_context.phpt | 93 +++++++++++ 10 files changed, 430 insertions(+), 272 deletions(-) create mode 100644 tests/V8ReturnValue_context.phpt diff --git a/src/php_v8_callback_info.cc b/src/php_v8_callback_info.cc index ed64103..cfbd932 100644 --- a/src/php_v8_callback_info.cc +++ b/src/php_v8_callback_info.cc @@ -190,6 +190,16 @@ static PHP_METHOD(V8CallbackInfo, GetReturnValue) { RETVAL_ZVAL(&php_v8_callback_info->php_v8_return_value->this_ptr, 1, 0); } +static PHP_METHOD(V8CallbackInfo, InContext) { + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + PHP_V8_CALLBACK_INFO_FETCH_WITH_CHECK(getThis(), php_v8_callback_info); + + RETURN_BOOL(PHP_V8_V8_CALLBACK_INFO_IN_CONTEXT(php_v8_callback_info)); +} + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_callback_info_GetIsolate, ZEND_RETURN_VALUE, 0, IS_OBJECT, PHP_V8_NS "\\Isolate", 0) ZEND_END_ARG_INFO() @@ -206,6 +216,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_callback_info_GetReturnValue, ZEND_RETURN_VALUE, 0, IS_OBJECT, PHP_V8_NS "\\ReturnValue", 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_callback_info_InContext, ZEND_RETURN_VALUE, 0, _IS_BOOL, NULL, 0) +ZEND_END_ARG_INFO() + static const zend_function_entry php_v8_callback_info_methods[] = { PHP_ME(V8CallbackInfo, This, arginfo_v8_callback_info_This, ZEND_ACC_PUBLIC) @@ -213,6 +226,7 @@ static const zend_function_entry php_v8_callback_info_methods[] = { PHP_ME(V8CallbackInfo, GetIsolate, arginfo_v8_callback_info_GetIsolate, ZEND_ACC_PUBLIC) PHP_ME(V8CallbackInfo, GetContext, arginfo_v8_callback_info_GetContext, ZEND_ACC_PUBLIC) PHP_ME(V8CallbackInfo, GetReturnValue, arginfo_v8_callback_info_GetReturnValue, ZEND_ACC_PUBLIC) + PHP_ME(V8CallbackInfo, InContext, arginfo_v8_callback_info_InContext, ZEND_ACC_PUBLIC) PHP_FE_END }; diff --git a/src/php_v8_callback_info.h b/src/php_v8_callback_info.h index 97c12b3..e67d0d5 100644 --- a/src/php_v8_callback_info.h +++ b/src/php_v8_callback_info.h @@ -49,10 +49,10 @@ extern void php_v8_callback_info_invalidate(php_v8_callback_info_t *php_v8_callb PHP_V8_CALLBACK_INFO_FETCH_INTO(pzval, into); \ PHP_V8_CHECK_EMPTY_CALLBACK_INFO_HANDLER(into); +#define PHP_V8_V8_CALLBACK_INFO_IN_CONTEXT(value) ((value)->php_v8_return_value != NULL && PHP_V8_RETURN_VALUE_IN_CONTEXT((value)->php_v8_return_value)) -// TODO: suggest better naming #define PHP_V8_V8_CALLBACK_INFO_CHECK_IN_CONTEXT(value) \ - if ((value)->php_v8_return_value == NULL || PHP_V8_RETVAL_ACCEPTS_INVALID == (value)->php_v8_return_value->accepts) { \ + if (!PHP_V8_V8_CALLBACK_INFO_IN_CONTEXT(value)) { \ PHP_V8_THROW_EXCEPTION("Attempt to use callback info object out of callback context"); \ return; \ } diff --git a/src/php_v8_callbacks.cc b/src/php_v8_callbacks.cc index 2e4d721..0b2c75f 100644 --- a/src/php_v8_callbacks.cc +++ b/src/php_v8_callbacks.cc @@ -258,130 +258,32 @@ void php_v8_bucket_gc(php_v8_callbacks_bucket_t *bucket, zval **gc_data, int * g *n = *gc_data_count; } -void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue retval, php_v8_return_value_t *return_value) { - if (!return_value->type) { - return; - } - - switch (return_value->type) { - default: - // should never get here, just in case new types will be added in future - PHP_V8_THROW_EXCEPTION("Failed to set returned value: unsupported type"); - return; - break; - } +static inline void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue *rv, php_v8_return_value_t *php_v8_return_value) { + php_v8_return_value->accepts = PHP_V8_RETVAL_ACCEPTS_VOID; + php_v8_return_value->rv_void = rv; } -void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue retval, php_v8_return_value_t *return_value) { - if (!return_value->type) { - return; - } - - switch (return_value->type) { - case PHP_V8_RETVAL_UNDEFINED: - retval.SetUndefined(); - break; - case PHP_V8_RETVAL_NULL: - retval.SetNull(); - break; - case PHP_V8_RETVAL_EMPTY_STRING: - retval.SetEmptyString(); - break; - case PHP_V8_RETVAL_BOOL: - retval.Set(return_value->value.set_bool); - break; - case PHP_V8_RETVAL_INT32: - retval.Set(return_value->value.set_int32); - break; - case PHP_V8_RETVAL_UINT32: - retval.Set(return_value->value.set_uint32); - break; - case PHP_V8_RETVAL_LONG: - retval.Set(static_cast(return_value->value.set_long)); - - break; - case PHP_V8_RETVAL_DOUBLE: - retval.Set(return_value->value.set_double); - break; - case PHP_V8_RETVAL_V8_VALUE: - retval.Set(php_v8_value_get_value_local(retval.GetIsolate(), - PHP_V8_VALUE_FETCH(&return_value->value.php_v8_value_zv))); - break; - default: - // should never get here, just in case new types will be added in future - - // TODO: maybe value exception? - PHP_V8_THROW_EXCEPTION("Failed to set returned value: unsupported type"); - return; - break; - } +static inline void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue *rv, php_v8_return_value_t *php_v8_return_value) { + php_v8_return_value->accepts = PHP_V8_RETVAL_ACCEPTS_ANY; + php_v8_return_value->rv_any = rv; } -void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue retval, php_v8_return_value_t *return_value) { - if (!return_value->type) { - return; - } - - switch (return_value->type) { - case PHP_V8_RETVAL_V8_VALUE: - retval.Set(php_v8_value_get_array_local(retval.GetIsolate(), - PHP_V8_VALUE_FETCH(&return_value->value.php_v8_value_zv))); - break; - default: - // should never get here, just in case new types will be added in future - PHP_V8_THROW_EXCEPTION("Failed to set returned value: unsupported type"); - return; - break; - } +static inline void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue *rv, php_v8_return_value_t *php_v8_return_value) { + php_v8_return_value->accepts = PHP_V8_RETVAL_ACCEPTS_INTEGER; + php_v8_return_value->rv_integer = rv; } -void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue retval, php_v8_return_value_t *return_value) { - if (!return_value->type) { - return; - } - - switch (return_value->type) { - case PHP_V8_RETVAL_INT32: - retval.Set(return_value->value.set_int32); - break; - case PHP_V8_RETVAL_UINT32: - retval.Set(return_value->value.set_uint32); - break; - case PHP_V8_RETVAL_V8_VALUE: - retval.Set(php_v8_value_get_integer_local(retval.GetIsolate(), - PHP_V8_VALUE_FETCH(&return_value->value.php_v8_value_zv))); - break; - default: - // should never get here, just in case new types will be added in future - PHP_V8_THROW_EXCEPTION("Failed to set returned value: unsupported type"); - return; - break; - } +static inline void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue *rv, php_v8_return_value_t *php_v8_return_value) { + php_v8_return_value->accepts = PHP_V8_RETVAL_ACCEPTS_BOOLEAN; + php_v8_return_value->rv_boolean = rv; } -void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue retval, php_v8_return_value_t *return_value) { - if (!return_value->type) { - return; - } - - switch (return_value->type) { - case PHP_V8_RETVAL_BOOL: - retval.Set(return_value->value.set_bool); - break; - case PHP_V8_RETVAL_V8_VALUE: - retval.Set(php_v8_value_get_boolean_local(retval.GetIsolate(), - PHP_V8_VALUE_FETCH(&return_value->value.php_v8_value_zv))); - break; - default: - // should never get here, just in case new types will be added in future - PHP_V8_THROW_EXCEPTION("Failed to set returned value: unsupported type"); - return; - break; - } +static inline void php_v8_callback_set_retval_from_callback_info(v8::ReturnValue *rv, php_v8_return_value_t *php_v8_return_value) { + php_v8_return_value->accepts = PHP_V8_RETVAL_ACCEPTS_ARRAY; + php_v8_return_value->rv_array = rv; } - void php_v8_callback_call_from_bucket_with_zargs(size_t index, v8::Local data, zval *args, zval *retval) { php_v8_callbacks_bucket_t *bucket; @@ -416,8 +318,8 @@ void php_v8_callback_call_from_bucket_with_zargs(size_t index, v8::Local -void php_v8_callback_call_from_bucket_with_zargs(size_t index, const T &info, zval *args) { +template +void php_v8_callback_call_from_bucket_with_zargs(size_t index, const T &info, M rv, zval *args) { zval callback_info; php_v8_callback_info_t *php_v8_callback_info; // Wrap callback info @@ -429,15 +331,14 @@ void php_v8_callback_call_from_bucket_with_zargs(size_t index, const T &info, zv add_next_index_zval(args, &callback_info); - php_v8_callback_call_from_bucket_with_zargs(index, info.Data(), args, NULL); + php_v8_callback_set_retval_from_callback_info(&rv, php_v8_callback_info->php_v8_return_value); - php_v8_callback_set_retval_from_callback_info(info.GetReturnValue(), php_v8_callback_info->php_v8_return_value); + php_v8_callback_call_from_bucket_with_zargs(index, info.Data(), args, NULL); php_v8_callback_info_invalidate(php_v8_callback_info); } - void php_v8_callback_function(const v8::FunctionCallbackInfo &info) { PHP_V8_DECLARE_ISOLATE_LOCAL_ALIAS(info.GetIsolate()); @@ -446,7 +347,7 @@ void php_v8_callback_function(const v8::FunctionCallbackInfo &info) { /* Build the parameter array */ array_init_size(&args, 1); - php_v8_callback_call_from_bucket_with_zargs(0, info, &args); + php_v8_callback_call_from_bucket_with_zargs(0, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -463,7 +364,7 @@ void php_v8_callback_accessor_name_getter(v8::Local property, const v8 php_v8_get_or_create_value(&property_name, property, isolate); add_index_zval(&args, 0, &property_name); - php_v8_callback_call_from_bucket_with_zargs(0, info, &args); + php_v8_callback_call_from_bucket_with_zargs(0, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -484,7 +385,7 @@ void php_v8_callback_accessor_name_setter(v8::Local property, v8::Loca add_index_zval(&args, 0, &property_name); add_index_zval(&args, 1, &property_value); - php_v8_callback_call_from_bucket_with_zargs(1, info, &args); + php_v8_callback_call_from_bucket_with_zargs(1, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -502,7 +403,7 @@ void php_v8_callback_generic_named_property_getter(v8::Local property, php_v8_get_or_create_value(&property_name, property, isolate); add_index_zval(&args, 0, &property_name); - php_v8_callback_call_from_bucket_with_zargs(0, info, &args); + php_v8_callback_call_from_bucket_with_zargs(0, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -523,7 +424,7 @@ void php_v8_callback_generic_named_property_setter(v8::Local property, add_index_zval(&args, 0, &property_name); add_index_zval(&args, 1, &property_value); - php_v8_callback_call_from_bucket_with_zargs(1, info, &args); + php_v8_callback_call_from_bucket_with_zargs(1, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -540,7 +441,7 @@ void php_v8_callback_generic_named_property_query(v8::Local property, php_v8_get_or_create_value(&property_name, property, isolate); add_index_zval(&args, 0, &property_name); - php_v8_callback_call_from_bucket_with_zargs(2, info, &args); + php_v8_callback_call_from_bucket_with_zargs(2, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -557,7 +458,7 @@ void php_v8_callback_generic_named_property_deleter(v8::Local property php_v8_get_or_create_value(&property_name, property, isolate); add_index_zval(&args, 0, &property_name); - php_v8_callback_call_from_bucket_with_zargs(3, info, &args); + php_v8_callback_call_from_bucket_with_zargs(3, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -570,7 +471,7 @@ void php_v8_callback_generic_named_property_enumerator(const v8::PropertyCallbac /* Build the parameter array */ array_init_size(&args, 1); - php_v8_callback_call_from_bucket_with_zargs(4, info, &args); + php_v8_callback_call_from_bucket_with_zargs(4, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -589,7 +490,7 @@ void php_v8_callback_indexed_property_getter(uint32_t index, const v8::PropertyC ZVAL_LONG(&property_name, index); add_index_zval(&args, 0, &property_name); - php_v8_callback_call_from_bucket_with_zargs(0, info, &args); + php_v8_callback_call_from_bucket_with_zargs(0, info, info.GetReturnValue(), &args); zval_ptr_dtor(&args); } @@ -610,7 +511,7 @@ void php_v8_callback_indexed_property_setter(uint32_t index, v8::Localtype & PHP_V8_RETVAL_ZVAL && !Z_ISUNDEF(php_v8_return_value->value.php_v8_value_zv)) { - size ++; - } - - if (php_v8_return_value->gc_data_count < size) { - php_v8_return_value->gc_data = (zval *)safe_erealloc(php_v8_return_value->gc_data, size, sizeof(zval), 0); - } - - php_v8_return_value->gc_data_count = size; - - if (size) { - ZVAL_COPY_VALUE(&php_v8_return_value->gc_data[0], &php_v8_return_value->value.php_v8_value_zv); - } - - *table = php_v8_return_value->gc_data; - *n = php_v8_return_value->gc_data_count; - - return zend_std_get_properties(object); -} - static void php_v8_return_value_free(zend_object *object) { php_v8_return_value_t *php_v8_return_value = php_v8_return_value_fetch_object(object); zend_object_std_dtor(&php_v8_return_value->std); - if (php_v8_return_value->type & PHP_V8_RETVAL_ZVAL && !Z_ISUNDEF(php_v8_return_value->value.php_v8_value_zv)) { - zval_ptr_dtor(&php_v8_return_value->value.php_v8_value_zv); - } - if (!Z_ISUNDEF(php_v8_return_value->this_ptr)) { zval_ptr_dtor(&php_v8_return_value->this_ptr); } - - if (php_v8_return_value->gc_data) { - efree(php_v8_return_value->gc_data); - } } static zend_object * php_v8_return_value_ctor(zend_class_entry *ce) { @@ -109,6 +77,67 @@ void php_v8_return_value_mark_expired(php_v8_return_value_t *php_v8_return_value php_v8_return_value->accepts = PHP_V8_RETVAL_ACCEPTS_INVALID; } +//static inline void php_v8_return_value(php_v8_return_value_t *php_v8_return_value) { +// assert(PHP_V8_RETVAL_ACCEPTS_INVALID != php_v8_return_value->accepts); +// +// switch (php_v8_return_value->accepts) { +// case PHP_V8_RETVAL_ACCEPTS_VOID: +// php_v8_return_value->rv_void; +// break; +// case PHP_V8_RETVAL_ACCEPTS_ANY: +// php_v8_return_value->rv_any; +// break; +// case PHP_V8_RETVAL_ACCEPTS_INTEGER: +// php_v8_return_value->rv_integer; +// break; +// case PHP_V8_RETVAL_ACCEPTS_BOOLEAN: +// php_v8_return_value->rv_boolean; +// break; +// case PHP_V8_RETVAL_ACCEPTS_ARRAY: +// php_v8_return_value->rv_array; +// break; +// default: +// assert(false); +// break; +// } +//} + +static inline v8::Local php_v8_return_value_get(php_v8_return_value_t *php_v8_return_value) { + assert(PHP_V8_RETVAL_ACCEPTS_INVALID != php_v8_return_value->accepts); + + switch (php_v8_return_value->accepts) { + case PHP_V8_RETVAL_ACCEPTS_VOID: + return php_v8_return_value->rv_void->Get(); + case PHP_V8_RETVAL_ACCEPTS_ANY: + return php_v8_return_value->rv_any->Get(); + case PHP_V8_RETVAL_ACCEPTS_INTEGER: + return php_v8_return_value->rv_integer->Get(); + case PHP_V8_RETVAL_ACCEPTS_BOOLEAN: + return php_v8_return_value->rv_boolean->Get(); + case PHP_V8_RETVAL_ACCEPTS_ARRAY: + return php_v8_return_value->rv_array->Get(); + default: + assert(false); + } + + assert(false); + return v8::Undefined(php_v8_return_value->php_v8_isolate->isolate); +} + + +static PHP_METHOD(V8ReturnValue, Get) { + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); + PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(php_v8_return_value); + + v8::Local local_value = php_v8_return_value_get(php_v8_return_value); + + php_v8_get_or_create_value(return_value, local_value, php_v8_return_value->php_v8_isolate->isolate); +} + static PHP_METHOD(V8ReturnValue, Set) { zval *php_v8_value_zv; @@ -125,48 +154,43 @@ static PHP_METHOD(V8ReturnValue, Set) { v8::Local local_value = php_v8_value_get_value_local(php_v8_return_value->php_v8_isolate->isolate, php_v8_value); - if (local_value->IsUndefined()) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_UNDEFINED); + if (PHP_V8_RETVAL_ACCEPTS_VOID == php_v8_return_value->accepts) { + PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any value"); return; } - if (local_value->IsNull()) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_NULL); + if (PHP_V8_RETVAL_ACCEPTS_ANY == php_v8_return_value->accepts) { + php_v8_return_value->rv_any->Set(local_value); return; } - if (local_value->IsBoolean()) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_BOOL); - php_v8_return_value->value.set_bool = static_cast(local_value->IsTrue()); - return; + if (PHP_V8_RETVAL_ACCEPTS_INTEGER == php_v8_return_value->accepts) { + if (local_value->IsInt32() || local_value->IsUint32()) { + php_v8_return_value->rv_integer->Set(local_value.As()); + return; + } + PHP_V8_THROW_EXCEPTION("ReturnValue accepts only integers"); } - if (local_value->IsInt32()) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_INT32); - php_v8_return_value->value.set_int32 = local_value.As()->Value(); - return; + if (PHP_V8_RETVAL_ACCEPTS_BOOLEAN == php_v8_return_value->accepts && !local_value->IsBoolean()) { + if (local_value->IsBoolean()) { + php_v8_return_value->rv_boolean->Set(local_value.As()); + return; + } + PHP_V8_THROW_EXCEPTION("ReturnValue accepts only boolean"); } - if (local_value->IsUint32()) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_UINT32); - php_v8_return_value->value.set_uint32 = local_value.As()->Value(); - return; + if (PHP_V8_RETVAL_ACCEPTS_ARRAY == php_v8_return_value->accepts && local_value->IsArray()) { + if (local_value->IsArray()) { + php_v8_return_value->rv_array->Set(local_value.As()); + return; + } + PHP_V8_THROW_EXCEPTION("ReturnValue accepts only instances of \\V8\\ArrayObject class"); } - if (local_value->IsNumber()) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_DOUBLE); - php_v8_return_value->value.set_double = local_value.As()->Value(); - return; - } - - if (local_value->IsArray()) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_ACCEPTS_ARRAY); - } else { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_V8_VALUE); - } - php_v8_return_value->type = PHP_V8_RETVAL_V8_VALUE; - ZVAL_COPY(&php_v8_return_value->value.php_v8_value_zv, php_v8_value_zv); + // should never go here + PHP_V8_THROW_EXCEPTION("Invalid ReturnValue to set"); } // Fast JS primitive setters @@ -178,7 +202,17 @@ static PHP_METHOD(V8ReturnValue, SetNull) { PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(php_v8_return_value); - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_NULL); + if (PHP_V8_RETVAL_ACCEPTS_VOID == php_v8_return_value->accepts) { + PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any value"); + return; + } + + if (PHP_V8_RETVAL_ACCEPTS_ANY == php_v8_return_value->accepts) { + php_v8_return_value->rv_any->SetNull(); + return; + } + + PHP_V8_THROW_EXCEPTION("Invalid ReturnValue to set"); } static PHP_METHOD(V8ReturnValue, SetUndefined) { @@ -189,7 +223,17 @@ static PHP_METHOD(V8ReturnValue, SetUndefined) { PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(php_v8_return_value); - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_UNDEFINED); + if (PHP_V8_RETVAL_ACCEPTS_VOID == php_v8_return_value->accepts) { + PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any value"); + return; + } + + if (PHP_V8_RETVAL_ACCEPTS_ANY == php_v8_return_value->accepts) { + php_v8_return_value->rv_any->SetUndefined(); + return; + } + + PHP_V8_THROW_EXCEPTION("Invalid ReturnValue to set"); } static PHP_METHOD(V8ReturnValue, SetEmptyString) { @@ -200,7 +244,18 @@ static PHP_METHOD(V8ReturnValue, SetEmptyString) { PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(php_v8_return_value); - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_EMPTY_STRING); + if (PHP_V8_RETVAL_ACCEPTS_VOID == php_v8_return_value->accepts) { + PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any value"); + return; + } + + if (PHP_V8_RETVAL_ACCEPTS_ANY == php_v8_return_value->accepts) { + php_v8_return_value->rv_any->SetEmptyString(); + return; + } + + PHP_V8_THROW_EXCEPTION("Invalid ReturnValue to set"); + } // Non-standard primitive setters @@ -214,8 +269,22 @@ static PHP_METHOD(V8ReturnValue, SetBool) { PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(php_v8_return_value); - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_BOOL); - php_v8_return_value->value.set_bool = static_cast(value); + if (PHP_V8_RETVAL_ACCEPTS_VOID == php_v8_return_value->accepts) { + PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any value"); + return; + } + + if (PHP_V8_RETVAL_ACCEPTS_ANY == php_v8_return_value->accepts) { + php_v8_return_value->rv_any->Set(static_cast(value)); + return; + } + + if (PHP_V8_RETVAL_ACCEPTS_BOOLEAN == php_v8_return_value->accepts) { + php_v8_return_value->rv_boolean->Set(static_cast(value)); + return; + } + + PHP_V8_THROW_EXCEPTION("Invalid ReturnValue to set"); } static PHP_METHOD(V8ReturnValue, SetInteger) { @@ -230,15 +299,33 @@ static PHP_METHOD(V8ReturnValue, SetInteger) { PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(php_v8_return_value); - if (value > INT32_MAX) { - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_UINT32); - php_v8_return_value->value.set_uint32 = static_cast(value); + if (PHP_V8_RETVAL_ACCEPTS_VOID == php_v8_return_value->accepts) { + PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any value"); + return; } - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_INT32); - php_v8_return_value->value.set_int32 = static_cast(value); + if (PHP_V8_RETVAL_ACCEPTS_ANY == php_v8_return_value->accepts) { + if (value > INT32_MAX) { + php_v8_return_value->rv_any->Set(static_cast(value)); + } else { + php_v8_return_value->rv_any->Set(static_cast(value)); + } + return; + } + + if (PHP_V8_RETVAL_ACCEPTS_INTEGER == php_v8_return_value->accepts) { + if (value > INT32_MAX) { + php_v8_return_value->rv_integer->Set(static_cast(value)); + } else { + php_v8_return_value->rv_integer->Set(static_cast(value)); + } + return; + } + + PHP_V8_THROW_EXCEPTION("Invalid ReturnValue to set"); } + static PHP_METHOD(V8ReturnValue, SetFloat) { double value; @@ -249,8 +336,17 @@ static PHP_METHOD(V8ReturnValue, SetFloat) { PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(php_v8_return_value); - PHP_V8_CHECK_ACCEPTS(php_v8_return_value, PHP_V8_RETVAL_DOUBLE); - php_v8_return_value->value.set_double = value; + if (PHP_V8_RETVAL_ACCEPTS_VOID == php_v8_return_value->accepts) { + PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any value"); + return; + } + + if (PHP_V8_RETVAL_ACCEPTS_ANY == php_v8_return_value->accepts) { + php_v8_return_value->rv_any->Set(value); + return; + } + + PHP_V8_THROW_EXCEPTION("Invalid ReturnValue to set"); } @@ -278,6 +374,17 @@ static PHP_METHOD(V8ReturnValue, GetContext) { RETVAL_ZVAL(&php_v8_return_value->php_v8_context->this_ptr, 1, 0); } +static PHP_METHOD(V8ReturnValue, InContext) { + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + PHP_V8_FETCH_RETURN_VALUE_WITH_CHECK(getThis(), php_v8_return_value); + + RETURN_BOOL(PHP_V8_RETURN_VALUE_IN_CONTEXT(php_v8_return_value)); +} + + ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_return_value_Set, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1) ZEND_ARG_OBJ_INFO(0, value, V8\\Value, 0) ZEND_END_ARG_INFO() @@ -310,7 +417,11 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_return_value_GetContext, ZEND_RETURN_VALUE, 0, IS_OBJECT, PHP_V8_NS "\\Context", 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_return_value_InContext, ZEND_RETURN_VALUE, 0, _IS_BOOL, NULL, 0) +ZEND_END_ARG_INFO() + static const zend_function_entry php_v8_return_value_methods[] = { + PHP_ME(V8ReturnValue, Get, arginfo_v8_return_value_Set, ZEND_ACC_PUBLIC) PHP_ME(V8ReturnValue, Set, arginfo_v8_return_value_Set, ZEND_ACC_PUBLIC) PHP_ME(V8ReturnValue, SetNull, arginfo_v8_return_value_SetNull, ZEND_ACC_PUBLIC) PHP_ME(V8ReturnValue, SetUndefined, arginfo_v8_return_value_SetUndefined, ZEND_ACC_PUBLIC) @@ -321,6 +432,7 @@ static const zend_function_entry php_v8_return_value_methods[] = { PHP_ME(V8ReturnValue, GetIsolate, arginfo_v8_return_value_GetIsolate, ZEND_ACC_PUBLIC) PHP_ME(V8ReturnValue, GetContext, arginfo_v8_return_value_GetContext, ZEND_ACC_PUBLIC) + PHP_ME(V8ReturnValue, InContext, arginfo_v8_return_value_InContext, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -336,7 +448,6 @@ PHP_MINIT_FUNCTION (php_v8_return_value) { php_v8_return_value_object_handlers.offset = XtOffsetOf(php_v8_return_value_t, std); php_v8_return_value_object_handlers.free_obj = php_v8_return_value_free; - php_v8_return_value_object_handlers.get_gc = php_v8_return_value_gc; return SUCCESS; } diff --git a/src/php_v8_return_value.h b/src/php_v8_return_value.h index 21d934e..cad7b68 100644 --- a/src/php_v8_return_value.h +++ b/src/php_v8_return_value.h @@ -40,8 +40,6 @@ extern php_v8_return_value_t *php_v8_return_value_fetch_object(zend_object *obj) #define PHP_V8_RETURN_VALUE_FETCH(zv) php_v8_return_value_fetch_object(Z_OBJ_P(zv)) #define PHP_V8_RETURN_VALUE_FETCH_INTO(pzval, into) php_v8_return_value_t *(into) = PHP_V8_RETURN_VALUE_FETCH((pzval)); - - #define PHP_V8_EMPTY_RETURN_VALUE_MSG "ReturnValue" PHP_V8_EMPTY_HANDLER_MSG_PART #define PHP_V8_CHECK_EMPTY_RETURN_VALUE_HANDLER(val, message) if (NULL == (val)->php_v8_isolate) { PHP_V8_THROW_EXCEPTION(message); return; } #define PHP_V8_CHECK_EMPTY_RETURN_VALUE(val) PHP_V8_CHECK_EMPTY_RETURN_VALUE_HANDLER((val), PHP_V8_EMPTY_RETURN_VALUE_MSG) @@ -51,9 +49,10 @@ extern php_v8_return_value_t *php_v8_return_value_fetch_object(zend_object *obj) PHP_V8_CHECK_EMPTY_RETURN_VALUE(into); +#define PHP_V8_RETURN_VALUE_IN_CONTEXT(value) (PHP_V8_RETVAL_ACCEPTS_INVALID != (value)->accepts) #define PHP_V8_RETURN_VALUE_CHECK_IN_CONTEXT(value) \ - if ((value)->accepts < 0) { \ - PHP_V8_THROW_EXCEPTION("Attempt to use ReturnValue out of calling function context"); \ + if (!PHP_V8_RETURN_VALUE_IN_CONTEXT(value)) { \ + PHP_V8_THROW_EXCEPTION("Attempt to use return value out of calling function context"); \ return; \ } @@ -64,49 +63,6 @@ extern php_v8_return_value_t *php_v8_return_value_fetch_object(zend_object *obj) #define PHP_V8_RETVAL_ACCEPTS_BOOLEAN (1 << 2) #define PHP_V8_RETVAL_ACCEPTS_ARRAY (1 << 3) -#define PHP_V8_RETVAL_ZVAL (1 << 4 | PHP_V8_RETVAL_ACCEPTS_ANY) -#define PHP_V8_RETVAL_UNDEFINED (1 << 5 | PHP_V8_RETVAL_ACCEPTS_ANY) -#define PHP_V8_RETVAL_NULL (1 << 6 | PHP_V8_RETVAL_ACCEPTS_ANY) -#define PHP_V8_RETVAL_EMPTY_STRING (1 << 7 | PHP_V8_RETVAL_ACCEPTS_ANY) -#define PHP_V8_RETVAL_BOOL (1 << 8 | PHP_V8_RETVAL_ACCEPTS_BOOLEAN) -#define PHP_V8_RETVAL_INT32 (1 << 9 | PHP_V8_RETVAL_ACCEPTS_INTEGER) -#define PHP_V8_RETVAL_UINT32 (1 << 10 | PHP_V8_RETVAL_ACCEPTS_INTEGER) -// DEPRECATED -//#define PHP_V8_RETVAL_STRING (1 << 11 | PHP_V8_RETVAL_ACCEPTS_ANY | PHP_V8_RETVAL_ZVAL) -#define PHP_V8_RETVAL_LONG (1 << 12 | PHP_V8_RETVAL_ACCEPTS_ANY) -#define PHP_V8_RETVAL_DOUBLE (1 << 13 | PHP_V8_RETVAL_ACCEPTS_ANY) -#define PHP_V8_RETVAL_V8_VALUE (1 << 14 | PHP_V8_RETVAL_ACCEPTS_ANY | PHP_V8_RETVAL_ZVAL) - -#define PHP_V8_CHECK_ACCEPTS(retval, val_type) { \ - if (!(val_type)) { \ - return; \ - } \ - \ - if((retval)->accepts == PHP_V8_RETVAL_ACCEPTS_VOID) { \ - PHP_V8_THROW_EXCEPTION("ReturnValue doesn't accept any return value"); \ - return; \ - } \ - \ - if((retval)->accepts == PHP_V8_RETVAL_ACCEPTS_INTEGER && !((val_type) & PHP_V8_RETVAL_ACCEPTS_INTEGER)) { \ - PHP_V8_THROW_EXCEPTION("ReturnValue accepts only integers"); \ - return; \ - } \ - \ - if((retval)->accepts == PHP_V8_RETVAL_ACCEPTS_BOOLEAN && !((val_type) & PHP_V8_RETVAL_ACCEPTS_BOOLEAN)) { \ - PHP_V8_THROW_EXCEPTION("ReturnValue accepts only boolean"); \ - return; \ - } \ - \ - if((retval)->accepts == PHP_V8_RETVAL_ACCEPTS_ARRAY && !((val_type) & PHP_V8_RETVAL_ACCEPTS_ARRAY)) { \ - PHP_V8_THROW_EXCEPTION("ReturnValue accepts only instances of \\V8\\ArrayObject class"); \ - return; \ - } \ - \ - if ((retval)->type & PHP_V8_RETVAL_ZVAL && !Z_ISUNDEF((retval)->value.php_v8_value_zv)) { \ - zval_ptr_dtor(&(retval)->value.php_v8_value_zv); \ - }\ - (retval)->type = (val_type); \ -} struct _php_v8_return_value_t { php_v8_isolate_t *php_v8_isolate; @@ -114,19 +70,11 @@ struct _php_v8_return_value_t { int accepts; - int type; - - union { - bool set_bool; - int32_t set_int32; - uint32_t set_uint32; - zend_long set_long; - double set_double; - zval php_v8_value_zv; - } value; - - zval *gc_data; - int gc_data_count; + v8::ReturnValue *rv_void; + v8::ReturnValue *rv_any; + v8::ReturnValue *rv_integer; + v8::ReturnValue *rv_boolean; + v8::ReturnValue *rv_array; zval this_ptr; zend_object std; diff --git a/stubs/src/CallbackInfo.php b/stubs/src/CallbackInfo.php index c075ecd..4f527bc 100644 --- a/stubs/src/CallbackInfo.php +++ b/stubs/src/CallbackInfo.php @@ -53,4 +53,13 @@ public function Holder() : ObjectValue public function GetReturnValue() : ReturnValue { } + + /** + * Check whether object is in current calling context and thus is usable + * + * @return bool + */ + public function InContext() : bool + { + } } diff --git a/stubs/src/ReturnValue.php b/stubs/src/ReturnValue.php index 03f09b6..83899fe 100644 --- a/stubs/src/ReturnValue.php +++ b/stubs/src/ReturnValue.php @@ -27,6 +27,17 @@ public function Set(Value $value) { } + /** + * Getter + * + * If the ReturnValue was not yet set, this will return the undefined value. + * + * @return Value + */ + public function Get() : Value + { + } + public function SetNull() { } @@ -73,4 +84,13 @@ public function GetIsolate() : Isolate public function GetContext() : Context { } + + /** + * Check whether object is in current calling context and thus is usable + * + * @return bool + */ + public function InContext() : bool + { + } } diff --git a/tests/V8FunctionCallbackInfo.phpt b/tests/V8FunctionCallbackInfo.phpt index 0284a41..09fade5 100644 --- a/tests/V8FunctionCallbackInfo.phpt +++ b/tests/V8FunctionCallbackInfo.phpt @@ -24,14 +24,22 @@ $context1 = new V8\Context($isolate1, $extensions1, $global_template1); $scalar = new \V8\StringValue($isolate1, "test"); $object = new \V8\ObjectValue($context1); +/** @var V8\FunctionCallbackInfo $callback_info */ +$callback_info = null; -$func = new v8Tests\TrackingDtors\FunctionObject($context1, function (\V8\FunctionCallbackInfo $info) use ($helper, $scalar, $object, $isolate1, $context1) { +$func = new v8Tests\TrackingDtors\FunctionObject($context1, function (V8\FunctionCallbackInfo $info) use ($helper, &$callback_info, $scalar, $object, $isolate1, $context1) { echo 'Function called', PHP_EOL; + $helper->header('Object representation'); + $helper->dump($info); + $helper->space(); + + $callback_info = $info; $helper->assert('Original arguments number passed', $info->Length() == 2); $helper->assert('Callback info holds original isolate object', $info->GetIsolate(), $isolate1); $helper->assert('Callback info holds original isolate object', $info->GetContext(), $context1); + $helper->assert('Callback info object is in context', $info->InContext()); // scalars hold no info about their zval, so they their zvals are recreated on each access $helper->value_matches_with_no_output($scalar, $info->Arguments()[0]); // shouldn't match @@ -51,18 +59,50 @@ $script1 = new V8\Script($context1, new \V8\StringValue($isolate1, $source1), ne $helper->dump($script1->Run($context1)->ToString($context1)->Value()); +$helper->space(); + +$helper->assert('Callback info object is out of context', false === $callback_info->InContext()); +try { + $callback_info->GetReturnValue(); +} catch (Exception $e) { + $helper->exception_export($e); +} +$helper->line(); + +$helper->header('Object representation (outside of context)'); +$helper->dump($callback_info); +$helper->space(); + echo 'We are done for now', PHP_EOL; ?> --EXPECT-- Function called +Object representation: +---------------------- +object(V8\FunctionCallbackInfo)#13 (0) { +} + + Original arguments number passed: ok Callback info holds original isolate object: ok Callback info holds original isolate object: ok +Callback info object is in context: ok Expected value is not identical to actual value Expected value is identical to actual value string(11) "Script done" + + +Callback info object is out of context: ok +V8\Exceptions\GenericException: Attempt to use callback info object out of callback context + +Object representation (outside of context): +------------------------------------------- +object(V8\FunctionCallbackInfo)#13 (0) { +} + + We are done for now FunctionObject dies now! Isolate dies now! diff --git a/tests/V8ReturnValue.phpt b/tests/V8ReturnValue.phpt index 71efc81..68a64af 100644 --- a/tests/V8ReturnValue.phpt +++ b/tests/V8ReturnValue.phpt @@ -29,9 +29,10 @@ $object = new \V8\ObjectValue($context1); $method = null; +$checker = null; $args = []; -$func = new v8Tests\TrackingDtors\FunctionObject($context1, function (\V8\FunctionCallbackInfo $info) use ($helper, $scalar, $object, $isolate1, $context1, &$method, &$args) { +$func = new v8Tests\TrackingDtors\FunctionObject($context1, function (\V8\FunctionCallbackInfo $info) use ($helper, $scalar, $object, $isolate1, $context1, &$method, &$checker, &$args) { $retval = $info->GetReturnValue(); @@ -39,11 +40,15 @@ $func = new v8Tests\TrackingDtors\FunctionObject($context1, function (\V8\Functi echo 'Function called', PHP_EOL; $helper->assert('Return value holds original isolate object', $retval->GetIsolate(), $isolate1); - $helper->assert('Return value holds original isolate object', $retval->GetContext(), $context1); + $helper->assert('Return value holds original context object', $retval->GetContext(), $context1); } + $helper->assert('Return value holds no value', $retval->Get()->IsUndefined()); if ($method) { $retval->{$method}(...$args); + if ($checker) { + $helper->assert('Return value was set and holds proper value', $retval->Get()->{$checker}()); + } } }); @@ -60,26 +65,31 @@ $helper->dump($script1->Run($context1)->ToString($context1)->Value()); $helper->space(); $method = 'SetUndefined'; +$checker = 'IsUndefined'; $args = []; $res = $v8_helper->CompileRun($context1, "test()"); $helper->assert('Returns undefined', $res->IsUndefined()); $method = 'SetNull'; +$checker = 'IsNull'; $args = []; $res = $v8_helper->CompileRun($context1, "test()"); $helper->assert('Returns null', $res->IsNull()); $method = 'SetBool'; +$checker = 'IsBoolean'; $args = [true]; $res = $v8_helper->CompileRun($context1, "test()"); $helper->assert('Returns boolean', $res->IsBoolean() && $res->IsTrue()); $method = 'SetInteger'; +$checker = 'IsInt32'; $args = [42]; $res = $v8_helper->CompileRun($context1, "test()"); $helper->assert('Returns integer', $res->IsNumber() && $res->IsInt32()); $method = 'SetFloat'; +$checker = 'IsNumber'; $args = [PHP_INT_MAX + 0.22]; $res = $v8_helper->CompileRun($context1, "test()"); $helper->assert('Returns float', $res->IsNumber() && !$res->IsInt32() && !$res->IsUint32()); @@ -88,20 +98,32 @@ $helper->pretty_dump('Returns float', $res->Value()); $helper->line(); + echo 'We are done for now', PHP_EOL; ?> --EXPECT-- Function called Return value holds original isolate object: ok -Return value holds original isolate object: ok +Return value holds original context object: ok +Return value holds no value: ok string(11) "Script done" +Return value holds no value: ok +Return value was set and holds proper value: ok Returns undefined: ok +Return value holds no value: ok +Return value was set and holds proper value: ok Returns null: ok +Return value holds no value: ok +Return value was set and holds proper value: ok Returns boolean: ok +Return value holds no value: ok +Return value was set and holds proper value: ok Returns integer: ok +Return value holds no value: ok +Return value was set and holds proper value: ok Returns float: ok Returns float: float(9.2233720368548E+18) diff --git a/tests/V8ReturnValue_context.phpt b/tests/V8ReturnValue_context.phpt new file mode 100644 index 0000000..9d746f3 --- /dev/null +++ b/tests/V8ReturnValue_context.phpt @@ -0,0 +1,93 @@ +--TEST-- +V8\ReturnValue - using in and outside context +--SKIPIF-- + +--FILE-- +GetReturnValue(); + + $helper->header('Object representation'); + $helper->dump($retval); + $helper->space(); + + $helper->assert('Return value object is in context', $retval->InContext()); + + $helper->assert('Return value holds original isolate object', $retval->GetIsolate(), $isolate); + $helper->assert('Return value holds original isolate object', $retval->GetContext(), $context); + $helper->assert('Return value holds no value', $retval->Get()->IsUndefined()); + + $retval->SetInteger(42); + + $helper->inline('Return value holds value', $retval->Get()->Value()); +}); + +$context->GlobalObject()->Set($context, new \V8\StringValue($isolate, 'test'), $func); + +$source1 = 'test(); "Script done";'; +$file_name1 = 'test.js'; + + +$script1 = new V8\Script($context, new \V8\StringValue($isolate, $source1), new \V8\ScriptOrigin($file_name1)); + +$script1->Run($context); +$helper->space(); + +$helper->assert('Return value object is out of context', false === $retval->InContext()); + +try { + $retval->Get(); +} catch (Exception $e) { + $helper->exception_export($e); +} + +$helper->line(); + +$helper->header('Object representation (outside of context)'); +$helper->dump($retval); +$helper->space(); + + + +?> +--EXPECT-- +Object representation: +---------------------- +object(V8\ReturnValue)#14 (0) { +} + + +Return value object is in context: ok +Return value holds original isolate object: ok +Return value holds original isolate object: ok +Return value holds no value: ok +Return value holds value: 42 + + +Return value object is out of context: ok +V8\Exceptions\GenericException: Attempt to use return value out of calling function context + +Object representation (outside of context): +------------------------------------------- +object(V8\ReturnValue)#14 (0) { +} From e3342f29749cdc430681d0daf99c530413440060 Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Sat, 20 Aug 2016 19:06:19 +0300 Subject: [PATCH 08/10] Gracefully die on OOM unsing new API to report OOM to embedder V8 commit: https://github.com/v8/v8/commit/bc44b1c627e92000cd37d46092f8bed8986f52f5 --- src/php_v8_isolate.cc | 4 ++ tests/V8Script_Run_out_of_memory.phpt | 94 ++++++++++++++++----------- 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/php_v8_isolate.cc b/src/php_v8_isolate.cc index 1179801..69a442e 100644 --- a/src/php_v8_isolate.cc +++ b/src/php_v8_isolate.cc @@ -170,6 +170,9 @@ static void php_v8_isolate_free(zend_object *object) { } } +static void php_v8_isolate_oom_error_callback(const char *location, bool is_heap_oom) { + zend_error(E_ERROR, "V8 OOM hit: location=%s, is_heap_oom=%s\n", location, is_heap_oom ? "yes" : "no"); +} static zend_object *php_v8_isolate_ctor(zend_class_entry *ce) { php_v8_isolate_t *php_v8_isolate; @@ -242,6 +245,7 @@ static PHP_METHOD(V8Isolate, __construct) { php_v8_isolate->isolate_handle = Z_OBJ_HANDLE_P(getThis()); php_v8_isolate->isolate->SetFatalErrorHandler(php_v8_fatal_error_handler); + php_v8_isolate->isolate->SetOOMErrorHandler(php_v8_isolate_oom_error_callback); } static PHP_METHOD(V8Isolate, SetTimeLimit) { diff --git a/tests/V8Script_Run_out_of_memory.phpt b/tests/V8Script_Run_out_of_memory.phpt index 03fb2f3..ff7c0db 100644 --- a/tests/V8Script_Run_out_of_memory.phpt +++ b/tests/V8Script_Run_out_of_memory.phpt @@ -2,7 +2,7 @@ V8\Script::Run() - out of memory example --SKIPIF-- - + --FILE-- 0){ - x = ""+x+x; + x = x+x; print(x.length, "\n"); } @@ -78,39 +78,55 @@ $helper->header('Object'); $helper->value_matches_with_no_output($res, $obj); ?> ---EXPECT-- -Checks on V8\StringValue: --------------------- -V8\StringValue::IsUndefined(): false -V8\StringValue::IsNull(): false -V8\StringValue::IsTrue(): false -V8\StringValue::IsFalse(): false -V8\StringValue::IsString(): true -V8\StringValue::IsFunction(): false -V8\StringValue::IsArray(): false -V8\StringValue::IsObject(): false -V8\StringValue::IsBoolean(): false -V8\StringValue::IsNumber(): false -V8\StringValue::IsInt32(): false -V8\StringValue::IsUint32(): false -V8\StringValue::IsDate(): false -V8\StringValue::IsArgumentsObject(): false -V8\StringValue::IsBooleanObject(): false -V8\StringValue::IsNumberObject(): false -V8\StringValue::IsStringObject(): false -V8\StringValue::IsNativeError(): false -V8\StringValue::IsRegExp(): false - - -string(25) "TEST VALUE 111, confirmed" refcount(1) - - -Scalar: -------- -Expected 123 value is identical to actual value 123 -Expected value is not identical to actual value - - -Object: -------- -Expected value is identical to actual value +--EXPECTF-- +2 +4 +8 +16 +32 +64 +128 +256 +512 +1024 +2048 +4096 +8192 +16384 +32768 +65536 +131072 +262144 +524288 +1048576 +2097152 +4194304 +8388608 +16777216 +33554432 + + + +Fatal error: V8 OOM hit: location=invalid array length, is_heap_oom=yes + in %s/V8Script_Run_out_of_memory.php on line 44 + +<--- Last few GCs ---> + +%s %d ms: Mark-sweep %f (%f) -> %f (%f) MB, %f / %f ms %s +%s %d ms: Mark-sweep %f (%f) -> %f (%f) MB, %f / %f ms %s +%s %d ms: Mark-sweep %f (%f) -> %f (%f) MB, %f / %f ms %s + + +<--- JS stacktrace ---> + +==== JS stack trace ========================================= + +Security context: 0x%x + 2: /* anonymous */ [test.js:~1] [pc=0x%x](this=0x%x ) + +==== Details ================================================ + +[2]: /* anonymous */ [test.js:~1] [pc=0x%x](this=0x%x ) { +// optimized frame +--------- s o u r c e c o d e --------- +%s From f980e3ab25264a1100eed220801312e01f9bbd4c Mon Sep 17 00:00:00 2001 From: Bogdan Padalko Date: Sat, 20 Aug 2016 19:53:06 +0300 Subject: [PATCH 09/10] Add peak_malloced_memory to V8\HeapStatistics V8 commit: https://github.com/v8/v8/commit/ad93c01aa5dae273d1209faca200a8bd331647ed --- src/php_v8_heap_statistics.cc | 25 ++++++++++++++++++++++--- stubs/src/HeapStatistics.php | 11 +++++++++++ tests/V8HeapStatistics.phpt | 6 ++++-- tests/V8Isolate.phpt | 4 +++- tests/V8Isolate_limit_memory.phpt | 4 +++- tests/V8Script_Run_out_of_memory.phpt | 3 ++- 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/php_v8_heap_statistics.cc b/src/php_v8_heap_statistics.cc index cafbb51..c1944e4 100644 --- a/src/php_v8_heap_statistics.cc +++ b/src/php_v8_heap_statistics.cc @@ -36,9 +36,9 @@ void php_v8_heap_statistics_create_from_heap_statistics(zval *return_value, v8:: zend_update_property_double(this_ce, return_value, ZEND_STRL("used_heap_size"), hs->used_heap_size()); zend_update_property_double(this_ce, return_value, ZEND_STRL("heap_size_limit"), hs->heap_size_limit()); zend_update_property_double(this_ce, return_value, ZEND_STRL("malloced_memory"), hs->malloced_memory()); + zend_update_property_double(this_ce, return_value, ZEND_STRL("peak_malloced_memory"), hs->peak_malloced_memory()); zend_update_property_bool(this_ce, return_value, ZEND_STRL("does_zap_garbage"), static_cast(hs->does_zap_garbage())); - } static PHP_METHOD(V8HeapStatistics, __construct) { @@ -49,12 +49,14 @@ static PHP_METHOD(V8HeapStatistics, __construct) { double used_heap_size = 0; double heap_size_limit = 0; double malloced_memory = 0; + double peak_malloced_memory = 0; zend_bool does_zap_garbage = '\0'; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|dddddddb", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|" "dddd" "dddd" "b", &total_heap_size, &total_heap_size_executable, &total_physical_size, &total_available_size, - &used_heap_size, &heap_size_limit, &malloced_memory, &does_zap_garbage) == FAILURE) { + &used_heap_size, &heap_size_limit, &malloced_memory, &peak_malloced_memory, + &does_zap_garbage) == FAILURE) { return; } @@ -65,6 +67,7 @@ static PHP_METHOD(V8HeapStatistics, __construct) { zend_update_property_double(this_ce, getThis(), ZEND_STRL("used_heap_size"), used_heap_size); zend_update_property_double(this_ce, getThis(), ZEND_STRL("heap_size_limit"), heap_size_limit); zend_update_property_double(this_ce, getThis(), ZEND_STRL("malloced_memory"), malloced_memory); + zend_update_property_double(this_ce, getThis(), ZEND_STRL("peak_malloced_memory"), peak_malloced_memory); zend_update_property_bool(this_ce, getThis(), ZEND_STRL("does_zap_garbage"), does_zap_garbage); } @@ -139,6 +142,16 @@ static PHP_METHOD(V8HeapStatistics, malloced_memory) { RETVAL_ZVAL(zend_read_property(this_ce, getThis(), ZEND_STRL("malloced_memory"), 0, &rv), 1, 0); } +static PHP_METHOD(V8HeapStatistics, peak_malloced_memory) { + zval rv; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETVAL_ZVAL(zend_read_property(this_ce, getThis(), ZEND_STRL("peak_malloced_memory"), 0, &rv), 1, 0); +} + static PHP_METHOD(V8HeapStatistics, does_zap_garbage) { zval rv; @@ -155,6 +168,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_v8_heap_statistics___construct, ZEND_SEND_BY_VAL, ZEND_ARG_TYPE_INFO(0, total_heap_size_executable, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, total_physical_size, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, total_available_size, IS_DOUBLE, 0) + ZEND_ARG_TYPE_INFO(0, used_heap_size, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, heap_size_limit, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, malloced_memory, IS_DOUBLE, 0) @@ -184,6 +198,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_heap_statistics__malloced_memory, ZEND_RETURN_VALUE, 0, IS_DOUBLE, NULL, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_heap_statistics__peak_malloced_memory, ZEND_RETURN_VALUE, 0, IS_DOUBLE, NULL, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_v8_heap_statistics__does_zap_garbage, ZEND_RETURN_VALUE, 0, _IS_BOOL, NULL, 0) ZEND_END_ARG_INFO() @@ -198,6 +215,7 @@ static const zend_function_entry php_v8_heap_statistics_methods[] = { PHP_ME(V8HeapStatistics, used_heap_size, arginfo_v8_heap_statistics__used_heap_size, ZEND_ACC_PUBLIC) PHP_ME(V8HeapStatistics, heap_size_limit, arginfo_v8_heap_statistics__heap_size_limit, ZEND_ACC_PUBLIC) PHP_ME(V8HeapStatistics, malloced_memory, arginfo_v8_heap_statistics__malloced_memory, ZEND_ACC_PUBLIC) + PHP_ME(V8HeapStatistics, peak_malloced_memory, arginfo_v8_heap_statistics__peak_malloced_memory, ZEND_ACC_PUBLIC) PHP_ME(V8HeapStatistics, does_zap_garbage, arginfo_v8_heap_statistics__does_zap_garbage, ZEND_ACC_PUBLIC) PHP_FE_END @@ -216,6 +234,7 @@ PHP_MINIT_FUNCTION (php_v8_heap_statistics) { zend_declare_property_double(this_ce, ZEND_STRL("used_heap_size"), 0, ZEND_ACC_PRIVATE); zend_declare_property_double(this_ce, ZEND_STRL("heap_size_limit"), 0, ZEND_ACC_PRIVATE); zend_declare_property_double(this_ce, ZEND_STRL("malloced_memory"), 0, ZEND_ACC_PRIVATE); + zend_declare_property_double(this_ce, ZEND_STRL("peak_malloced_memory"), 0, ZEND_ACC_PRIVATE); zend_declare_property_bool(this_ce, ZEND_STRL("does_zap_garbage"), false, ZEND_ACC_PRIVATE); diff --git a/stubs/src/HeapStatistics.php b/stubs/src/HeapStatistics.php index ef90f9b..bab8ad3 100644 --- a/stubs/src/HeapStatistics.php +++ b/stubs/src/HeapStatistics.php @@ -54,6 +54,10 @@ class HeapStatistics * @var float */ private $malloced_memory; + /** + * @var float + */ + private $peak_malloced_memory; /** * @var bool */ @@ -77,6 +81,7 @@ public function __construct( float $used_heap_size, float $heap_size_limit, float $malloced_memory, + float $peak_malloced_memory, bool $does_zap_garbage ) { $this->total_heap_size = $total_heap_size; @@ -86,6 +91,7 @@ public function __construct( $this->used_heap_size = $used_heap_size; $this->heap_size_limit = $heap_size_limit; $this->malloced_memory = $malloced_memory; + $this->peak_malloced_memory = $peak_malloced_memory; $this->does_zap_garbage = $does_zap_garbage; } @@ -124,6 +130,11 @@ public function malloced_memory() : float return $this->malloced_memory; } + public function peak_malloced_memory() : float + { + return $this->peak_malloced_memory; + } + public function does_zap_garbage() : bool { return $this->does_zap_garbage; diff --git a/tests/V8HeapStatistics.phpt b/tests/V8HeapStatistics.phpt index ae6e04b..474ad07 100644 --- a/tests/V8HeapStatistics.phpt +++ b/tests/V8HeapStatistics.phpt @@ -8,7 +8,7 @@ V8\HeapStatistics /** @var \Phpv8Testsuite $helper */ $helper = require '.testsuite.php'; -$hs = new \V8\HeapStatistics(1, 2, 3, 4, 5, 6, 7, true); +$hs = new \V8\HeapStatistics(1, 2, 3, 4, 5, 6, 7, 8, true); $helper->header('Object representation'); $helper->dump($hs); @@ -20,7 +20,7 @@ $helper->dump_object_methods($hs); --EXPECT-- Object representation: ---------------------- -object(V8\HeapStatistics)#2 (8) { +object(V8\HeapStatistics)#2 (9) { ["total_heap_size":"V8\HeapStatistics":private]=> float(1) ["total_heap_size_executable":"V8\HeapStatistics":private]=> @@ -35,6 +35,8 @@ object(V8\HeapStatistics)#2 (8) { float(6) ["malloced_memory":"V8\HeapStatistics":private]=> float(7) + ["peak_malloced_memory":"V8\HeapStatistics":private]=> + float(8) ["does_zap_garbage":"V8\HeapStatistics":private]=> bool(true) } diff --git a/tests/V8Isolate.phpt b/tests/V8Isolate.phpt index 10b52cc..d114f5b 100644 --- a/tests/V8Isolate.phpt +++ b/tests/V8Isolate.phpt @@ -46,7 +46,7 @@ object(V8\Isolate)#2 (5) { V8\Exceptions\GenericException: Not in context! V8\Isolate->GetHeapStatistics(): - object(V8\HeapStatistics)#28 (8) { + object(V8\HeapStatistics)#28 (9) { ["total_heap_size":"V8\HeapStatistics":private]=> float(%d) ["total_heap_size_executable":"V8\HeapStatistics":private]=> @@ -61,6 +61,8 @@ V8\Isolate->GetHeapStatistics(): float(%d) ["malloced_memory":"V8\HeapStatistics":private]=> float(%d) + ["peak_malloced_memory":"V8\HeapStatistics":private]=> + float(%d) ["does_zap_garbage":"V8\HeapStatistics":private]=> bool(false) } diff --git a/tests/V8Isolate_limit_memory.phpt b/tests/V8Isolate_limit_memory.phpt index acdf847..3ccf1ba 100644 --- a/tests/V8Isolate_limit_memory.phpt +++ b/tests/V8Isolate_limit_memory.phpt @@ -91,7 +91,7 @@ object(V8\Isolate)#3 (5) { ["memory_limit_hit":"V8\Isolate":private]=> bool(true) } -object(V8\HeapStatistics)#14 (8) { +object(V8\HeapStatistics)#14 (9) { ["total_heap_size":"V8\HeapStatistics":private]=> float(%d) ["total_heap_size_executable":"V8\HeapStatistics":private]=> @@ -106,6 +106,8 @@ object(V8\HeapStatistics)#14 (8) { float(%d) ["malloced_memory":"V8\HeapStatistics":private]=> float(%d) + ["peak_malloced_memory":"V8\HeapStatistics":private]=> + float(%d) ["does_zap_garbage":"V8\HeapStatistics":private]=> bool(false) } diff --git a/tests/V8Script_Run_out_of_memory.phpt b/tests/V8Script_Run_out_of_memory.phpt index ff7c0db..06e7d8a 100644 --- a/tests/V8Script_Run_out_of_memory.phpt +++ b/tests/V8Script_Run_out_of_memory.phpt @@ -2,7 +2,8 @@ V8\Script::Run() - out of memory example --SKIPIF-- - + + --FILE-- Date: Sat, 20 Aug 2016 22:36:48 +0300 Subject: [PATCH 10/10] Require V8 >= 5.4.420 --- config.m4 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index c87742d..81d7318 100644 --- a/config.m4 +++ b/config.m4 @@ -101,7 +101,7 @@ if test "$PHP_V8" != "no"; then AC_LANG_SAVE AC_LANG_CPLUSPLUS - + # NOTE: it is possible to get version string from headers with simple regexp match AC_CACHE_CHECK(for V8 version, ac_cv_v8_version, [ AC_TRY_RUN([ #include @@ -123,14 +123,20 @@ if test "$PHP_V8" != "no"; then ], [ac_cv_v8_version=`cat ./conftestval|awk '{print $1}'`], [ac_cv_v8_version=NONE], [ac_cv_v8_version=NONE]) ]) + V8_MIN_API_VERSION_STR=5.4.420 + if test "$ac_cv_v8_version" != "NONE"; then ac_IFS=$IFS IFS=. set $ac_cv_v8_version IFS=$ac_IFS V8_API_VERSION=`expr [$]1 \* 1000000 + [$]2 \* 1000 + [$]3` - if test "$V8_API_VERSION" -lt 501000 ; then - AC_MSG_ERROR([libv8 must be version 5.1.0 or greater]) + IFS=. + set $V8_MIN_API_VERSION_STR + IFS=$ac_IFS + V8_MIN_API_VERSION=`expr [$]1 \* 1000000 + [$]2 \* 1000 + [$]3` + if test "$V8_API_VERSION" -lt $V8_MIN_API_VERSION ; then + AC_MSG_ERROR([libv8 must be version $V8_MIN_API_VERSION_STR or greater]) fi AC_DEFINE_UNQUOTED([PHP_V8_LIBV8_API_VERSION], $V8_API_VERSION, [ ]) AC_DEFINE_UNQUOTED([PHP_V8_LIBV8_VERSION], "$ac_cv_v8_version", [ ])