Skip to content

Ensure MacOS support by tests #539

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: php8
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 126 additions & 32 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
@@ -12,38 +12,29 @@ permissions:
contents: read

jobs:
build:
self-built-v8-cache-warmup:
strategy:
# set in accordance with number of v8-versions, so caching can kick in properly
max-parallel: 2

matrix:
operating-system:
operating-system: # &self-built-v8-operating-systems
- ubuntu-latest
# - windows-latest
# - macos-latest
php-versions:
# - '8.1'
# - '8.2'
- '8.3'
- '8.4'
v8-versions:
- macos-latest
v8-versions: # &self-built-v8-v8-versions
- 10.9.194
# - 11.9.172
- 12.9.203
# - 13.1.104
- 13.5.212

runs-on: ${{ matrix.operating-system }}

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none
- name: Prepare cache folder v8 ${{ matrix.v8-versions }}
run: |
sudo mkdir -p /opt/v8/self-built/{lib,include}
sudo chown -R $(id -u):$(id -g) /opt/v8/self-built

- name: Restore cache v8 ${{ matrix.v8-versions }} build
id: v8-build-cache
@@ -61,25 +52,45 @@ jobs:
if: steps.v8-build-cache.outputs.cache-hit != 'true'
run: |
# Store extra tools somewhere undisturbing
set -x
cd "$(mktemp -d)"

fetch v8
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" ]]; then
V8CONFIG="x64.release"
ARCH_SHORT="x64"
elif [[ "$ARCH" == "arm64" ]]; then
V8CONFIG="arm64.release"
ARCH_SHORT="arm64"
else
echo "Unknown architecture: $ARCH" >&2
exit 1
fi
fetch --nohooks --no-history v8
cd v8

git checkout ${{ matrix.v8-versions }}
gclient sync -D
git fetch --tag origin refs/tags/${{ matrix.v8-versions }} > /dev/null 2>&1
git checkout ${{ matrix.v8-versions }} > /dev/null 2>&1
gclient sync -D > /dev/null 2>&1

# Setup GN
# Warnings are no errors - @see https://issues.chromium.org/issues/42203398#comment9
tools/dev/v8gen.py -vv x64.release -- is_component_build=true use_custom_libcxx=false treat_warnings_as_errors=false
if [[ "${{ runner.os }}" == "macOS" ]]; then
# Run gn gen with args as v8gen does not override target_cpu properly
gn gen out.gn/$V8CONFIG --args='target_cpu="'$ARCH_SHORT'" v8_target_cpu="'$ARCH_SHORT'" is_component_build=true use_custom_libcxx=true treat_warnings_as_errors=false'
else
tools/dev/v8gen.py -vv $V8CONFIG -- is_component_build=true use_custom_libcxx=true treat_warnings_as_errors=false
fi

# Build
ninja -C out.gn/x64.release/
ninja -C out.gn/$V8CONFIG/

# Install to /opt/v8/self-built
sudo mkdir -p /opt/v8/self-built/{lib,include}
sudo cp out.gn/x64.release/lib*.so out.gn/x64.release/*_blob.bin out.gn/x64.release/icudtl.dat /opt/v8/self-built/lib/
sudo cp -R include/* /opt/v8/self-built/include/
if [[ "${{ runner.os }}" == "macOS" ]]; then
LIB_EXT=dylib
else
LIB_EXT=so
fi
cp out.gn/$V8CONFIG/lib*.${LIB_EXT} out.gn/$V8CONFIG/*_blob.bin out.gn/$V8CONFIG/icudtl.dat /opt/v8/self-built/lib/
cp -R include/* /opt/v8/self-built/include/

# Go back to origin
cd "${GITHUB_WORKSPACE}"
@@ -91,6 +102,44 @@ jobs:
path: /opt/v8/self-built
key: ${{ steps.v8-build-cache.outputs.cache-primary-key }}

self-built-v8:
needs: self-built-v8-cache-warmup

strategy:
matrix:
operating-system: # *self-built-v8-operating-systems
- ubuntu-latest
# - windows-latest
- macos-latest
v8-versions: # *self-built-v8-v8-versions
- 10.9.194
# - 11.9.172
- 12.9.203
- 13.5.212
php-versions:
# - '8.1'
- '8.2'
- '8.3'
- '8.4'

runs-on: ${{ matrix.operating-system }}

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none

- name: Download cache v8 ${{ matrix.v8-versions }} build
uses: actions/cache/restore@v4
with:
path: /opt/v8/self-built
key: ${{ runner.os }}-${{ matrix.v8-versions }}-v8-build

- name: Build extension
run: |
phpize
@@ -102,12 +151,12 @@ jobs:
if: failure()
uses: actions/upload-artifact@v4
with:
name: phpt-test-results
name: phpt-test-results-on-${{ runner.os }}-${{ matrix.v8-versions }}-${{ matrix.php-versions }}
path: |
php_test_results*.txt
tests/*.out

alpine:
alpine-package-manager-apk:
runs-on: ubuntu-latest

steps:
@@ -120,7 +169,7 @@ jobs:
- name: Install dependencies
run: |
cat /etc/alpine-release
apk add php83-dev nodejs-dev g++ make
apk add php83-dev nodejs-dev nodejs g++ make file
shell: alpine.sh --root {0}

- name: Build extension
@@ -135,7 +184,52 @@ jobs:
if: failure()
uses: actions/upload-artifact@v4
with:
name: phpt-test-results
name: phpt-test-results-on-alpine
path: |
php_test_results*.txt
tests/*.out

macos-package-manager-brew:
strategy:
matrix:
php-versions:
- '8.2'
- '8.3'
- '8.4'

runs-on: macos-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none

- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master

- name: Install dependencies
run: |
brew install v8
# Symlink icudtl.dat to the default location
ln -sf /opt/homebrew/Cellar/v8/$(brew list --versions v8 | awk '{print $2}')/libexec/icudtl.dat /opt/homebrew/lib/icudtl.dat

- name: Build extension
run: |
phpize
./configure --with-v8js=/opt/homebrew CPPFLAGS="-DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX"
make
make test

- name: Archive test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: phpt-test-results-on-macos-brew-${{ matrix.php-versions }}
path: |
php_test_results*.txt
tests/*.out
14 changes: 9 additions & 5 deletions README.Linux.md
Original file line number Diff line number Diff line change
@@ -89,23 +89,27 @@ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"

# Download v8
fetch v8
fetch --nohooks --no-history v8
gclient sync -D --no-history
cd v8

# (optional) If you'd like to build a certain version:
git fetch --tag origin refs/tags/12.0.267.36
git checkout 12.0.267.36
gclient sync -D

ARCH=$(uname -m)

# Setup GN
tools/dev/v8gen.py -vv x64.release -- is_component_build=true use_custom_libcxx=false
tools/dev/v8gen.py -vv ${ARCH}.release -- is_component_build=true use_custom_libcxx=false

# Build
ninja -C out.gn/x64.release/
ninja -C out.gn/${ARCH}.release/

# Install to /opt/v8/
sudo mkdir -p /opt/v8/{lib,include}
sudo cp out.gn/x64.release/lib*.so out.gn/x64.release/*_blob.bin \
out.gn/x64.release/icudtl.dat /opt/v8/lib/
sudo cp out.gn/${ARCH}.release/lib*.so out.gn/${ARCH}.release/*_blob.bin \
out.gn/${ARCH}.release/icudtl.dat /opt/v8/lib/
sudo cp -R include/* /opt/v8/include/
```

18 changes: 17 additions & 1 deletion README.MacOS.md
Original file line number Diff line number Diff line change
@@ -16,8 +16,24 @@ cd /tmp
git clone https://github.com/phpv8/v8js.git
cd v8js
phpize
./configure --with-v8js=/opt/homebrew CPPFLAGS="-DV8_COMPRESS_POINTERS"
./configure --with-v8js=/opt/homebrew CPPFLAGS="-DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX"
make -j4
make test
make install
```

V8Js' build system assumes that the `icudtl.dat` file is located next to the `libv8.so`
library file and compiles the path into the library itself. If for whatever reason the
`icudtl.dat` file is stored at a different place during runtime, you need to set the
php.ini variable `v8js.icudtl_dat_path` to point to the file. Otherwise locale-aware
features of V8 will not work as expected.

To avoid having to configure `v8js.icudtl_dat_path` manually, you can symlink or copy the ICU data file into the default library location. For Homebrew users, run:

In case of a brew installed v8, run:

```
ln -sf /opt/homebrew/Cellar/v8/$(brew list --versions v8 | awk '{print $2}')/libexec/icudtl.dat /opt/homebrew/lib/icudtl.dat
```

This ensures V8Js will find `icudtl.dat` automatically and timezone/i18n support will work out of the box.
1 change: 1 addition & 0 deletions config.m4
Original file line number Diff line number Diff line change
@@ -118,6 +118,7 @@ if test "$PHP_V8JS" != "no"; then

CPPFLAGS="$CPPFLAGS -I$V8_INCLUDE_DIR -std=$ac_cv_v8_cstd"
LDFLAGS="$LDFLAGS -L$V8_LIBRARY_DIR"
LIBS="-L$V8_LIBRARY_DIR $LIBS"

if test "$libname" = "v8"; then
AC_MSG_CHECKING([for libv8_libplatform])
15 changes: 9 additions & 6 deletions tests/set_memory_limit_001.phpt
Original file line number Diff line number Diff line change
@@ -13,20 +13,23 @@ if (getenv("SKIP_SLOW_TESTS")) {

$JS = <<< EOT
var jsfunc = function() {
var text = "abcdefghijklmnopqrstuvwyxz0123456789";
var text = "abcdefghijklmnopqrstuvwyxz0123456789"; // 36 bytes
var memory = "";
for (var i = 0; i < 100; ++i) {
for (var j = 0; j < 10000; ++j) {
// should generate 360 MB
for (var i = 0; i < 10_000; ++i) {
for (var j = 0; j < 1000; ++j) {
memory += text;
}
sleep(0);
}
sleep(0);
}

return memory;
};
jsfunc;
EOT;

$v8 = new V8Js();
$v8->setMemoryLimit(10000000);
$v8->setMemoryLimit(10_000_000);

$func = $v8->executeString($JS);
var_dump($func);
48 changes: 48 additions & 0 deletions tests/set_memory_limit_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
--TEST--
Test V8::setMemoryLimit() : Memory limit can be set but does not trigger when not exceeded
--SKIPIF--
<?php
require_once(dirname(__FILE__) . '/skipif.inc');

if (getenv("SKIP_SLOW_TESTS")) {
die("skip slow test");
}
?>
--FILE--
<?php

$JS = <<< EOT
var jsfunc = function() {
var text = "abcdefghijklmnopqrstuvwyxz0123456789"; // 36 bytes
var memory = "";
// should generate ~ 800 kB
for (var i = 0; i < 22; ++i) {
for (var j = 0; j < 1000; ++j) {
memory += text;
}
sleep(0);
}

return memory;
};
jsfunc;
EOT;

$v8 = new V8Js();
$v8->setMemoryLimit(10_000_000);

$func = $v8->executeString($JS);
var_dump($func);

try {
$func();
} catch (V8JsMemoryLimitException $e) {
print get_class($e); print PHP_EOL;
print $e->getMessage(); print PHP_EOL;
}
?>
===EOF===
--EXPECTF--
object(V8Function)#%d (0) {
}
===EOF===
15 changes: 9 additions & 6 deletions tests/set_memory_limit_003.phpt
Original file line number Diff line number Diff line change
@@ -14,22 +14,25 @@ if (getenv("SKIP_SLOW_TESTS")) {
$JS = <<< EOT
var jsfunc = function() {
PHP.imposeMemoryLimit();
var text = "abcdefghijklmnopqrstuvwyxz0123456789";
var text = "abcdefghijklmnopqrstuvwyxz0123456789"; // 36 bytes
var memory = "";
for (var i = 0; i < 100; ++i) {
for (var j = 0; j < 10000; ++j) {
// should generate 360 MB
for (var i = 0; i < 10_000; ++i) {
for (var j = 0; j < 1000; ++j) {
memory += text;
}
sleep(0);
}
sleep(0);
}
return memory;
};
jsfunc;
EOT;

$v8 = new V8Js();

$v8->imposeMemoryLimit = function() use ($v8) {
$v8->setMemoryLimit(10000000);
$v8->setMemoryLimit(10_000_000);
};

$func = $v8->executeString($JS);
6 changes: 5 additions & 1 deletion tests/time_limit.phpt
Original file line number Diff line number Diff line change
@@ -12,8 +12,12 @@ if (getenv("SKIP_SLOW_TESTS")) {
<?php

$JS = <<< EOT
var start = Date.now();
var text = "abcdefghijklmnopqrstuvwyxz0123456789";
for (var i = 0; i < 20000000; ++i) {
while (true) {
if (Date.now() - start > 2000) { // 2 seconds safety valve
break;
}
var encoded = encodeURI(text);
}
EOT;
52 changes: 45 additions & 7 deletions v8js_array_access.cc
Original file line number Diff line number Diff line change
@@ -59,7 +59,12 @@ static zval v8js_array_access_dispatch(zend_object *object, const char *method_n
V8JS_INTERCEPTED v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif

zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));

@@ -83,7 +88,12 @@ V8JS_INTERCEPTED v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> v
const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif

zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));

@@ -157,7 +167,12 @@ static bool v8js_array_access_isset_p(zend_object *object, int index) /* {{{ */
static void v8js_array_access_length(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif

zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));

@@ -169,7 +184,12 @@ static void v8js_array_access_length(v8::Local<v8::String> property, const v8::P
V8JS_INTERCEPTED v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif

zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));

@@ -187,7 +207,12 @@ V8JS_INTERCEPTED v8js_array_access_deleter(uint32_t index, const v8::PropertyCal
V8JS_INTERCEPTED v8js_array_access_query(uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif

zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));

@@ -206,7 +231,13 @@ V8JS_INTERCEPTED v8js_array_access_query(uint32_t index, const v8::PropertyCallb
void v8js_array_access_enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;

#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif

zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));

@@ -240,7 +271,14 @@ V8JS_INTERCEPTED v8js_array_access_named_getter(v8::Local<v8::Name> property_nam
return V8JS_INTERCEPTED_YES;
}

v8::Local<v8::Value> ret_value = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_GETTER);
v8::Local<v8::Object> holder;
#if PHP_V8_API_VERSION >= 13000000
holder = info.This();
#else
holder = info.Holder();
#endif

v8::Local<v8::Value> ret_value = v8js_named_property_callback(info.GetIsolate(), holder, property, V8JS_PROP_GETTER);

if(ret_value.IsEmpty()) {
v8::Local<v8::Array> arr = v8::Array::New(isolate);
64 changes: 56 additions & 8 deletions v8js_object_export.cc
Original file line number Diff line number Diff line change
@@ -212,7 +212,11 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, c
return_value = v8js_propagate_exception(ctx);
} else if (Z_TYPE(retval) == IS_OBJECT && Z_OBJ(retval) == object) {
// special case: "return $this"
#if PHP_V8_API_VERSION >= 13000000
return_value = info.This();
#else
return_value = info.Holder();
#endif
} else {
return_value = zval_to_v8js(&retval, isolate);
}
@@ -227,7 +231,12 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, c
/* Callback for PHP methods and functions */
void v8js_php_callback(const v8::FunctionCallbackInfo<v8::Value>& info) /* {{{ */
{
v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif

zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));
zend_function *method_ptr;
@@ -364,7 +373,12 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo<v8::Ar
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Context> v8_context = isolate->GetEnteredOrMicrotaskContext();

v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif
v8::Local<v8::Array> result = v8::Array::New(isolate, 0);
uint32_t result_len = 0;

@@ -466,7 +480,12 @@ static void v8js_invoke_callback(const v8::FunctionCallbackInfo<v8::Value>& info
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Context> v8_context = isolate->GetEnteredOrMicrotaskContext();

v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif
v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(info.Data());
int argc = info.Length(), i;
v8::Local<v8::Value> *argv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>) * argc));
@@ -511,7 +530,12 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& info)
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Context> v8_context = isolate->GetEnteredOrMicrotaskContext();

v8::Local<v8::Object> self = info.Holder();
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif
v8::Local<v8::Value> return_value = V8JS_NULL;

char *error;
@@ -859,7 +883,13 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Isolate *isolate, v8::Loca

static V8JS_INTERCEPTED v8js_named_property_getter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value> &info) /* {{{ */
{
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_GETTER);
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), self, property, V8JS_PROP_GETTER);

if (r.IsEmpty()) {
return V8JS_INTERCEPTED_NO;
@@ -872,7 +902,13 @@ static V8JS_INTERCEPTED v8js_named_property_getter(v8::Local<v8::Name> property,

static V8JS_INTERCEPTED v8js_named_property_setter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info) /* {{{ */
{
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_SETTER, value);
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), self, property, V8JS_PROP_SETTER, value);
#if PHP_V8_HAS_INTERCEPTED
return r.IsEmpty() ? v8::Intercepted::kNo : v8::Intercepted::kYes;
#else
@@ -883,7 +919,13 @@ static V8JS_INTERCEPTED v8js_named_property_setter(v8::Local<v8::Name> property,

static V8JS_INTERCEPTED v8js_named_property_query(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Integer> &info) /* {{{ */
{
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_QUERY);
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), self, property, V8JS_PROP_QUERY);
if (r.IsEmpty()) {
return V8JS_INTERCEPTED_NO;
}
@@ -901,7 +943,13 @@ static V8JS_INTERCEPTED v8js_named_property_query(v8::Local<v8::Name> property,

static V8JS_INTERCEPTED v8js_named_property_deleter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Boolean> &info) /* {{{ */
{
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), info.Holder(), property, V8JS_PROP_DELETER);
v8::Local<v8::Object> self;
#if PHP_V8_API_VERSION >= 13000000
self = info.This();
#else
self = info.Holder();
#endif
v8::Local<v8::Value> r = v8js_named_property_callback(info.GetIsolate(), self, property, V8JS_PROP_DELETER);
if (r.IsEmpty()) {
return V8JS_INTERCEPTED_NO;
}