├── .clang_complete
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── core.cpp
├── core.h
├── exception.h
├── extension.cpp
├── fromiterator.cpp
├── fromiterator.h
├── fromphp.cpp
├── fromphp.h
├── isolate.cpp
├── isolate.h
├── link.h
├── linker.cpp
├── linker.h
├── names.h
├── php-js.ini
├── php_array.h
├── php_base.cpp
├── php_base.h
├── php_context.cpp
├── php_context.h
├── php_exception.h
├── php_function.cpp
├── php_function.h
├── php_iterator.cpp
├── php_iterator.h
├── php_object.cpp
├── php_object.h
├── php_script.h
├── php_variable.cpp
├── php_variable.h
├── platform.cpp
├── platform.h
├── scope.h
├── script.cpp
├── script.h
├── template.cpp
├── template.h
├── tests
├── input1.js
├── object.js
├── object.php
├── test1.php
├── test2.php
├── test3.php
├── test4.php
└── test5.php
├── timeout.h
└── version.sh
/.clang_complete:
--------------------------------------------------------------------------------
1 | -std=c++11
2 | -Wno-pragma-once-outside-header
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.so
3 | *.d
4 | *_blob.bin
5 | *_blob.h
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Makefile template
3 | #
4 | # This is an example Makefile that can be used by anyone who is building
5 | # his or her own PHP extensions using the PHP-CPP library.
6 | #
7 | # In the top part of this file we have included variables that can be
8 | # altered to fit your configuration, near the bottom the instructions and
9 | # dependencies for the compiler are defined. The deeper you get into this
10 | # file, the less likely it is that you will have to change anything in it.
11 | #
12 |
13 | #
14 | # Name of your extension
15 | #
16 | # This is the name of your extension. Based on this extension name, the
17 | # name of the library file (name.so) and the name of the config file (name.ini)
18 | # are automatically generated
19 | #
20 |
21 | NAME = php-js
22 |
23 |
24 | #
25 | # Php.ini directories
26 | #
27 | # In the past, PHP used a single php.ini configuration file. Today, most
28 | # PHP installations use a conf.d directory that holds a set of config files,
29 | # one for each extension. Use this variable to specify this directory.
30 | #
31 | #
32 |
33 | INI_DIR = $(shell php-config --ini-path)/../mods-available
34 |
35 | #
36 | # The extension dirs
37 | #
38 | # This is normally a directory like /usr/lib/php/20121221 (based on the
39 | # PHP version that you use. We make use of the command line 'php-config'
40 | # instruction to find out what the extension directory is, you can override
41 | # this with a different fixed directory
42 | #
43 |
44 | EXTENSION_DIR = $(shell php-config --extension-dir)
45 |
46 |
47 | #
48 | # The name of the extension and the name of the .ini file
49 | #
50 | # These two variables are based on the name of the extension. We simply add
51 | # a certain extension to them (.so or .ini)
52 | #
53 |
54 | EXTENSION = ${NAME}.so
55 | INI = ${NAME}.ini
56 |
57 |
58 | #
59 | # Compiler
60 | #
61 | # By default, the GNU C++ compiler is used. If you want to use a different
62 | # compiler, you can change that here. You can change this for both the
63 | # compiler (the program that turns the c++ files into object files) and for
64 | # the linker (the program that links all object files into the single .so
65 | # library file. By default, g++ (the GNU C++ compiler) is used for both.
66 | #
67 |
68 | COMPILER = c++
69 | LINKER = c++
70 |
71 |
72 | #
73 | # Compiler and linker flags
74 | #
75 | # - V8_COMPRESS_POINTERS is needed because the V8 library is compiled with a special optimization for pointers
76 | # - V8_ENABLE_SANDBOX is needed because the V8 library is compiled with sandbox support
77 | #
78 |
79 | COMPILER_FLAGS = -Wall -c -O2 -MD -std=c++20 -fpic -DVERSION="`./version.sh`" -DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX -I. -g
80 | LINKER_FLAGS = -shared
81 | LINKER_DEPENDENCIES = -Wl,--no-as-needed -lphpcpp -lv8_libplatform -lv8
82 |
83 |
84 | #
85 | # Command to remove files, copy files and create directories.
86 | #
87 | # I've never encountered a *nix environment in which these commands do not work.
88 | # So you can probably leave this as it is
89 | #
90 |
91 | RM = rm -f
92 | CP = cp -f
93 | MKDIR = mkdir -p
94 | XXD = xxd -i
95 |
96 |
97 | #
98 | # All source files are simply all *.cpp files found in the current directory
99 | #
100 | # A builtin Makefile macro is used to scan the current directory and find
101 | # all source files. The object files are all compiled versions of the source
102 | # file, with the .cpp extension being replaced by .o.
103 | #
104 |
105 | SOURCES = $(wildcard *.cpp)
106 | OBJECTS = $(SOURCES:%.cpp=%.o)
107 | DEPENDENCIES = $(SOURCES:%.cpp=%.d)
108 |
109 |
110 | #
111 | # From here the build instructions start
112 | #
113 |
114 | all: ${OBJECTS} ${EXTENSION}
115 |
116 | #
117 | # Use dependency tracking
118 | #
119 | -include ${DEPENDENCIES}
120 |
121 |
122 | ${EXTENSION}: ${OBJECTS}
123 | ${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} ${LINKER_DEPENDENCIES}
124 |
125 | ${OBJECTS}:
126 | ${COMPILER} ${COMPILER_FLAGS} -o $@ ${@:%.o=%.cpp}
127 |
128 | install:
129 | ${CP} ${EXTENSION} ${EXTENSION_DIR}
130 | ${CP} ${INI} ${INI_DIR}
131 |
132 | clean:
133 | ${RM} ${EXTENSION} ${OBJECTS} ${DEPENDENCIES}
134 |
135 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PHP-JS
2 |
3 | A library to integrate the Google V8 Javascript Engine in PHP
4 |
5 | ## ABOUT
6 |
7 | The PHP-JS library is created and maintained by [Copernica](https://www.copernica.com). This extension
8 | gives you the power to execute javascript right from your PHP script.
9 | This javascript code is executed using the Google V8 engine - the same engine
10 | that powers the Google Chrome browser and Node.js.
11 |
12 | A typical use case is server-side execution of user-defined JavaScript, for example in
13 | applications that allow end users to write custom scripts or automation logic.
14 |
15 | ## HOW DOES IT WORK?
16 |
17 | PHP-JS allows you to execute JavaScript from PHP code, and expose PHP variables
18 | and functions to a Javascript environment.
19 |
20 | ```
21 | // create a javascript context
22 | $context = new JS\Context();
23 |
24 | // assign a javascript function to show a variable
25 | $context->assign('show', function($data) {
26 | var_dump($data);
27 | });
28 |
29 | // assign a function to summarize
30 | $context->assign('add', function($x, $y) {
31 | return $x + $y;
32 | });
33 |
34 | // assign some additional variables
35 | $context->assign('x', 10);
36 | $context->assign('y', 'abc');
37 | $context->assign('z', new DateTime());
38 |
39 | // evaluate a javscript
40 | try
41 | {
42 | $context->evaluate("show(x); show(y); show(z);");
43 | }
44 | catch (Exception $exception)
45 | {
46 | echo("Error: ".$exception->getMessage()."\n");
47 | }
48 | ```
49 |
50 | PHP-JS can map PHP variables to JS variables and vica versa. Scalars, arrays, objects,
51 | and traversable structures (like iterators) are converted between both environments. Note,
52 | however, that due to fundamental differences between Javascript and PHP, not all
53 | constructs can be 1-to-1 mapped. It is recommended to stick to straightforward
54 | data types and structures.
55 |
56 |
57 | ## DEPENDENCIES
58 |
59 | PHP-JS relies on [PHP-CPP](http://www.php-cpp.com) and the [Google V8 engine](https://v8.dev/).
60 | It is known to work with V8 version 13.6. We recommend compiling V8 using GCC and your system
61 | libraries, rather than the ones bundled with V8. This avoids conflicts whtn installing PHP-JS
62 | as a PHP extension, as PHP itself also uses system libraries.
63 |
64 | Use the following flags when building V8:
65 |
66 | ```
67 | is_debug=false
68 | is_component_build=true
69 | v8_enable_i18n_support=false
70 | is_clang=false
71 | use_sysroot=false
72 | use_custom_libcxx=false
73 | ```
74 |
75 | These flags ensure:
76 |
77 | - GCC is used instead of Clang (`is_clang=false`)
78 | - System libraries are used instead of bundled versions (`use_custom_libcxx=false`)
79 | - Unnecessary features like ICU (internationalization) are disabled for a leaner build
80 |
81 | For more details on building V8, visit [https://v8.dev/docs/build-gn](https://v8.dev/docs/build-gn).
82 |
83 |
84 | ## EXTRA INFO
85 |
86 | If you appreciate our work and are you looking for other high quality solutions, take
87 | a look at:
88 |
89 | * PHP-CPP (www.php-cpp.com)
90 | * Copernica Marketing Suite (www.copernica.com)
91 | * MailerQ MTA (www.mailerq.com)
92 |
--------------------------------------------------------------------------------
/core.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Core.cpp
3 | *
4 | * Implementation file for the context class
5 | *
6 | * @author Emiel Bruijntjes
7 | * @copyright 2025 Copernica BV
8 | */
9 |
10 | /**
11 | * Dependencies
12 | */
13 | #include "core.h"
14 | #include "fromphp.h"
15 | #include "php_variable.h"
16 | #include "scope.h"
17 | #include "php_object.h"
18 | #include "php_exception.h"
19 | #include "script.h"
20 | #include "names.h"
21 |
22 | /**
23 | * Begin of namespace
24 | */
25 | namespace JS {
26 |
27 | /**
28 | * Constructor
29 | */
30 | Core::Core() : _platform(Platform::instance()), _isolate(this)
31 | {
32 | // when we access the isolate, we need a scope
33 | v8::HandleScope scope(_isolate);
34 |
35 | // create a context
36 | v8::Local context(v8::Context::New(_isolate));
37 |
38 | // we want to persist the context
39 | _context.Reset(_isolate, context);
40 |
41 | // symbol for linking js and php objects together
42 | v8::Local key = v8::Private::ForApi(_isolate, v8::String::NewFromUtf8Literal(_isolate, "js2php"));
43 |
44 | // persist the key
45 | _symbol.Reset(_isolate, key);
46 | }
47 |
48 | /**
49 | * Wrap a certain PHP object into a javascript object
50 | * @param object MUST be an array or object!
51 | * @return v8::Local
52 | */
53 | v8::Local Core::wrap(const Php::Value &object)
54 | {
55 | // if the object is already known to be a JS\Object
56 | auto *instance = PhpBase::unwrap(this, object);
57 |
58 | // was this possible? then we reuse the original handle
59 | if (instance != nullptr) return instance->handle();
60 |
61 | // check the prototypes that we have
62 | for (auto &prototype : _templates)
63 | {
64 | // is this one compatible with the object
65 | if (!prototype->matches(object)) continue;
66 |
67 | // we can apply this prototype
68 | return prototype->apply(object);
69 | }
70 |
71 | // we need a new template
72 | _templates.emplace_back(new Template(_isolate, object));
73 |
74 | // use it
75 | return _templates.back()->apply(object);
76 | }
77 |
78 | /**
79 | * Assign a variable to the javascript context
80 | * @param name name of property to assign required
81 | * @param value value to be assigned
82 | * @param attribytes property attributes
83 | * @return Php::Value
84 | */
85 | Php::Value Core::assign(const Php::Value &name, const Php::Value &value, const Php::Value &attributes)
86 | {
87 | // avoid that other contexts are assigned
88 | if (value.instanceOf(Names::Context) || value.instanceOf(Names::Script)) return false;
89 |
90 | // scope for the context
91 | Scope scope(shared_from_this());
92 |
93 | // retrieve the global object from the context
94 | v8::Local global(scope.global());
95 |
96 | // the attribute for the newly assigned property
97 | auto attribute = attributes.isNull() ? v8::None : static_cast(attributes.numericValue());
98 |
99 | // convert the property to a javascript name
100 | v8::Local property = FromPhp(_isolate, name.clone(Php::Type::String));
101 |
102 | // store the value
103 | v8::Maybe result = global->DefineOwnProperty(scope, property.As(), FromPhp(_isolate, value), attribute);
104 |
105 | // check for success
106 | return result.IsJust() && result.FromJust();
107 | }
108 |
109 | /**
110 | * Parse a piece of javascript code
111 | * @param source the code to execute
112 | * @param timeout possible timeout in seconds
113 | * @return Php::Value
114 | * @throws Php::Exception
115 | */
116 | Php::Value Core::evaluate(const Php::Value &source, const Php::Value &timeout)
117 | {
118 | // create a script
119 | Script script(shared_from_this(), source.clone(Php::Type::String).rawValue());
120 |
121 | // evaluate the script
122 | return script.execute(timeout);
123 | }
124 |
125 | /**
126 | * End of namespace
127 | */
128 | }
129 |
130 |
--------------------------------------------------------------------------------
/core.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Core.h
3 | *
4 | * The main javascript class, used for assigning variables
5 | * and executing javascript
6 | *
7 | * @copyright 2015 - 2025 Copernica B.V.
8 | */
9 |
10 | /**
11 | * Include guard
12 | */
13 | #pragma once
14 |
15 | /**
16 | * Dependencies
17 | */
18 | #include
19 | #include "platform.h"
20 | #include "isolate.h"
21 | #include "template.h"
22 |
23 | /**
24 | * Start namespace
25 | */
26 | namespace JS {
27 |
28 | /**
29 | * Class definition
30 | */
31 | class Core : public std::enable_shared_from_this
32 | {
33 | private:
34 | /**
35 | * Pointer to the full javascript v8 platform
36 | * @var Platform
37 | */
38 | Platform *_platform;
39 |
40 | /**
41 | * The Isolate that manages the v8 environment (this is a bit like the "window"
42 | * platform in a browser, a fully separated environment)
43 | * @var Isolate
44 | */
45 | Isolate _isolate;
46 |
47 | /**
48 | * The context in which variables are stored
49 | * @var v8::Global
50 | */
51 | v8::Global _context;
52 |
53 | /**
54 | * The private symbol that we use for associating php objects to js objects
55 | * @var v8::Global
56 | */
57 | v8::Global _symbol;
58 |
59 | /**
60 | * Templates for wrapping objects
61 | * @var std::vector
62 | */
63 | std::vector> _templates;
64 |
65 | public:
66 | /**
67 | * Constructor
68 | */
69 | Core();
70 |
71 | /**
72 | * No copying allowed
73 | * @param that the object we cannot copy
74 | */
75 | Core(const Core &that) = delete;
76 |
77 | /**
78 | * Destructor
79 | */
80 | virtual ~Core() = default;
81 |
82 | /**
83 | * Given an isolate, it is possible to upgrade to the full context
84 | * @return std::shared_ptr
85 | */
86 | static std::shared_ptr upgrade(v8::Isolate *isolate)
87 | {
88 | return Isolate::core(isolate)->shared_from_this();
89 | }
90 |
91 | /**
92 | * The isolate of this context
93 | * @return Isolate
94 | */
95 | v8::Isolate *isolate() { return _isolate; }
96 |
97 | /**
98 | * The symbol used for linkin php and js objects to each other
99 | * @return v8::Global
100 | */
101 | const v8::Global &symbol() const { return _symbol; }
102 |
103 | /**
104 | * Wrap a certain PHP object into a javascript object
105 | * @param object MUST be an object!
106 | * @return v8::Local
107 | */
108 | v8::Local wrap(const Php::Value &object);
109 |
110 | /**
111 | * Expose the context
112 | * Watch out: a handling-scope must be passed to prove that is exists
113 | * @param scope
114 | * @return v8::Local
115 | */
116 | v8::Local context(const v8::HandleScope &scope) { return _context.Get(_isolate); }
117 |
118 | /**
119 | * Assign a variable to the javascript context
120 | * @param name name of property to assign required
121 | * @param value value to be assigned
122 | * @param attribytes property attributes
123 | * @return Php::Value
124 | */
125 | Php::Value assign(const Php::Value &name, const Php::Value &value, const Php::Value &attributes);
126 |
127 | /**
128 | * Parse a piece of javascript code
129 | * @param code the code to execute
130 | * @param timeout possible timeout in seconds
131 | * @return Php::Value
132 | * @throws Php::Exception
133 | */
134 | Php::Value evaluate(const Php::Value &code, const Php::Value &timeout);
135 | };
136 |
137 | /**
138 | * End namespace
139 | */
140 | }
141 |
--------------------------------------------------------------------------------
/exception.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Exception.h
3 | *
4 | * Utility class to turn a PHP space exception into a JS exception
5 | *
6 | * @author Emiel Bruijntjes
7 | * @copyright 2025 Copernica BV
8 | */
9 |
10 | /**
11 | * Include guard
12 | */
13 | #pragma once
14 |
15 | /**
16 | * Begin of namespace
17 | */
18 | namespace JS {
19 |
20 | /**
21 | * Class definition
22 | */
23 | class Exception : public v8::Local
24 | {
25 | public:
26 | /**
27 | * Constructor
28 | * @param isolate
29 | * @param exception
30 | */
31 | Exception(v8::Isolate *isolate, const Php::Exception &exception) :
32 | v8::Local(v8::Exception::Error(v8::String::NewFromUtf8(isolate, exception.what()).ToLocalChecked())) {}
33 | };
34 |
35 | /**
36 | * End of namespace
37 | */
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/extension.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * extension.cpp
3 | *
4 | * Startup file for the PHP extension
5 | *
6 | * @copyright 2015 - 2025 Copernica BV
7 | */
8 |
9 | /**
10 | * Dependencies
11 | */
12 | #include
13 | #include "php_context.h"
14 | #include "php_object.h"
15 | #include "php_function.h"
16 | #include "php_script.h"
17 | #include "platform.h"
18 | #include "names.h"
19 |
20 | /**
21 | * The VERSION macro is going to be used as string with surrounded quotes
22 | */
23 | #define STR_VALUE(arg) #arg
24 | #define VERSION_NAME(name) STR_VALUE(name)
25 | #define THE_VERSION VERSION_NAME(VERSION)
26 |
27 | /**
28 | * tell the compiler that the get_module is a pure C function
29 | */
30 | extern "C" {
31 |
32 | /**
33 | * Function that is called by PHP right after the PHP process
34 | * has started, and that returns an address of an internal PHP
35 | * strucure with all the details and features of your extension
36 | *
37 | * @return void* a pointer to an address that is understood by PHP
38 | */
39 | PHPCPP_EXPORT void *get_module()
40 | {
41 | // static(!) Php::Extension object that should stay in memory
42 | // for the entire duration of the process (that's why it's static)
43 | static Php::Extension extension("PHP-JS2", THE_VERSION);
44 |
45 | // declare the accessor attributes
46 | // @todo use constants
47 | extension.add(Php::Constant(JS::Names::None, v8::None));
48 | extension.add(Php::Constant(JS::Names::ReadOnly, v8::ReadOnly));
49 | extension.add(Php::Constant(JS::Names::DontDelete, v8::DontDelete));
50 | extension.add(Php::Constant(JS::Names::DontEnumerate, v8::DontEnum));
51 |
52 | // create the classes
53 | Php::Class context(JS::Names::Context);
54 | Php::Class script(JS::Names::Script);
55 | Php::Class object(JS::Names::Object);
56 | Php::Class function(JS::Names::Function);
57 |
58 | // properties can be assigned to the context
59 | context.method<&JS::PhpContext::assign>("assign", {
60 | Php::ByVal("name", Php::Type::String, true),
61 | Php::ByVal("value", Php::Type::Null, true),
62 | Php::ByVal("attribute", Php::Type::Numeric, false)
63 | });
64 |
65 | // add a method to parse + execute some script
66 | context.method<&JS::PhpContext::evaluate>("evaluate", {
67 | Php::ByVal("script", Php::Type::String, true),
68 | Php::ByVal("timeout", Php::Type::Numeric, false)
69 | });
70 |
71 | // add a script-method to construct the script
72 | script.method<&JS::PhpScript::__construct>("__construct", {
73 | Php::ByVal("script", Php::Type::String, true),
74 | });
75 |
76 | // add a script-method to assign
77 | script.method<&JS::PhpScript::assign>("assign", {
78 | Php::ByVal("name", Php::Type::String, true),
79 | Php::ByVal("value", Php::Type::Null, true),
80 | Php::ByVal("attribute", Php::Type::Numeric, false)
81 | });
82 |
83 | // add a script-method to execute
84 | script.method<&JS::PhpScript::execute>("execute", {
85 | Php::ByVal("timeout", Php::Type::Numeric, false)
86 | });
87 |
88 | // add the classes to the extension
89 | extension.add(std::move(context));
90 | extension.add(std::move(object));
91 | extension.add(std::move(function));
92 |
93 | // the platform needs to be cleaned up on engine shutdown
94 | extension.onShutdown([]{
95 |
96 | // clean up the platform
97 | JS::Platform::shutdown();
98 | });
99 |
100 | // return the extension
101 | return extension;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/fromiterator.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * FromIterator.cpp
3 | *
4 | * Implementation file of the FromIterator class
5 | *
6 | * @author Emiel Bruijntjes
7 | * @copyright 2025 Copernica BV
8 | */
9 |
10 | /**
11 | * Dependencies
12 | */
13 | #include "fromiterator.h"
14 | #include "scope.h"
15 |
16 | /**
17 | * Begin of namespace
18 | */
19 | namespace JS {
20 |
21 | /**
22 | * Constructor
23 | * @param isolate the isolate
24 | * @param object the object that will be returned
25 | * @param value iterable php object
26 | */
27 | FromIterator::FromIterator(v8::Isolate *isolate, const Php::Value &value)
28 | {
29 | // we need a scope
30 | Scope scope(isolate);
31 |
32 | // we need the context for looking up the symbol
33 | auto core = Core::upgrade(isolate);
34 |
35 | // create a new object
36 | _iterator = v8::Object::New(isolate);
37 |
38 | // store pointer to state data
39 | _iterator->SetPrivate(scope, core->symbol().Get(isolate), v8::External::New(isolate, new Data(isolate, value)));
40 |
41 | // we need to set a "next" method and a "return" method on the iterator
42 | auto nxtlabel = v8::String::NewFromUtf8Literal(isolate, "next");
43 | auto retlabel = v8::String::NewFromUtf8Literal(isolate, "return");
44 |
45 | // we need the next and return methods
46 | auto nxtmethod = v8::Function::New(scope, &FromIterator::nxtmethod).ToLocalChecked();
47 | auto retmethod = v8::Function::New(scope, &FromIterator::retmethod).ToLocalChecked();
48 |
49 | // install them on the object
50 | _iterator->Set(scope, nxtlabel, nxtmethod).Check();
51 | _iterator->Set(scope, retlabel, retmethod).Check();
52 |
53 | // we also make the iterator of itself iterable (when the iterator is explicitly iterated)
54 | _iterator->Set(scope, v8::Symbol::GetIterator(isolate), _iterator).Check();
55 | }
56 |
57 | /**
58 | * Helper method to get access to underlying data
59 | * @param isolate
60 | * @param obj
61 | * @return Data*
62 | */
63 | FromIterator::Data *FromIterator::restore(v8::Isolate *isolate, const v8::Local &obj)
64 | {
65 | // we need the symbol for linking pointers to objects
66 | auto symbol = Core::upgrade(isolate)->symbol().Get(isolate);
67 |
68 | // we need a local value
69 | v8::Local val;
70 |
71 | // get the symbol value
72 | if (!obj->GetPrivate(isolate->GetCurrentContext(), symbol).ToLocal(&val)) return nullptr;
73 |
74 | // should be external
75 | if (!val->IsExternal()) return nullptr;
76 |
77 | // get the value back
78 | return static_cast(val.As()->Value());
79 | }
80 |
81 | /**
82 | * Helper method to destruct the underlying data
83 | * @param isolate
84 | * @param obj
85 | * @return Data*
86 | */
87 | void FromIterator::destruct(v8::Isolate *isolate, const v8::Local &obj)
88 | {
89 | // get the underlying data
90 | auto *data = restore(isolate, obj);
91 |
92 | // do nothing if not needed
93 | if (data == nullptr) return;
94 |
95 | // destruct the object
96 | delete data;
97 |
98 | // we need the symbol for linking pointers to objects
99 | auto symbol = Core::upgrade(isolate)->symbol().Get(isolate);
100 |
101 | // unset the symbol value
102 | obj->DeletePrivate(isolate->GetCurrentContext(), symbol);
103 | }
104 |
105 | /**
106 | * Method that is called by v8 when the next item is requested
107 | * @param args
108 | */
109 | void FromIterator::nxtmethod(const v8::FunctionCallbackInfo &args)
110 | {
111 | // the current isolate
112 | auto isolate = args.GetIsolate();
113 |
114 | // get a handle scope
115 | Scope scope(isolate);
116 |
117 | // the object that is being called
118 | auto obj = args.This();
119 |
120 | // pointer to data
121 | auto *data = restore(isolate, obj);
122 |
123 | // if iterator was already destructed
124 | if (data == nullptr || data->done()) return retmethod(args);
125 |
126 | // create a new return object
127 | auto result = v8::Object::New(isolate);
128 |
129 | // set the value
130 | result->Set(scope, v8::String::NewFromUtf8Literal(isolate, "value"), data->current()).Check();
131 | result->Set(scope, v8::String::NewFromUtf8Literal(isolate, "done"), v8::Boolean::New(isolate, !data->next())).Check();
132 |
133 | // install the return-value
134 | args.GetReturnValue().Set(result);
135 |
136 | // if the iterator is done by now we can forget it
137 | if (data->done()) destruct(isolate, obj);
138 | }
139 |
140 | /**
141 | * Method that is called when the iterator leaps out prematurely
142 | * @param args
143 | */
144 | void FromIterator::retmethod(const v8::FunctionCallbackInfo &args)
145 | {
146 | // the current isolate
147 | auto isolate = args.GetIsolate();
148 |
149 | // get a handle scope
150 | Scope scope(isolate);
151 |
152 | // the object that is being called
153 | auto obj = args.This();
154 |
155 | // destruct internally stored data
156 | destruct(isolate, obj);
157 |
158 | // create a new return object
159 | auto result = v8::Object::New(isolate);
160 |
161 | // set the "done" state
162 | result->Set(scope, v8::String::NewFromUtf8Literal(isolate, "done"), v8::True(isolate)).Check();
163 |
164 | // install the return-value
165 | args.GetReturnValue().Set(result);
166 | }
167 |
168 | /**
169 | * End of namespace
170 | */
171 | }
172 |
173 |
--------------------------------------------------------------------------------
/fromiterator.h:
--------------------------------------------------------------------------------
1 | /**
2 | * FromIterator.h
3 | *
4 | * Class that turns a PHP traversable object into something that
5 | * is iterable in a javascript environment too.
6 | *
7 | * @author Emiel Bruijntjes
8 | * @copyright 2025 Copernica BV
9 | */
10 |
11 | /**
12 | * Include guard
13 | */
14 | #pragma once
15 |
16 | /**
17 | * Dependencies
18 | */
19 | #include "fromphp.h"
20 |
21 | /**
22 | * Begin of namespace
23 | */
24 | namespace JS {
25 |
26 | /**
27 | * Class definition
28 | */
29 | class FromIterator
30 | {
31 | private:
32 | /**
33 | * The variable that represents the iterator
34 | * @var v8::Local
35 | */
36 | v8::Local _iterator;
37 |
38 | /**
39 | * Structure that holds the data associated with the iterator,
40 | * and that is added via a symbol in the javascript-object
41 | */
42 | class Data
43 | {
44 | private:
45 | /**
46 | * Reference to the isolate
47 | * @var v8::Isolate
48 | */
49 | v8::Isolate *_isolate;
50 |
51 | /**
52 | * The PHP space Iterator object
53 | * @var Php::Value
54 | */
55 | Php::Value _value;
56 |
57 | public:
58 | /**
59 | * Constructor
60 | * @param isolate
61 | * @param iterator
62 | */
63 | Data(v8::Isolate *isolate, const Php::Value &value) :
64 | _isolate(isolate), _value(value) {}
65 |
66 | /**
67 | * Destructor
68 | */
69 | virtual ~Data() = default;
70 |
71 | /**
72 | * Is the iterator still valid?
73 | * @return bool
74 | */
75 | bool valid() { return _value.call("valid"); }
76 |
77 | /**
78 | * Is the iterator done?
79 | * @return bool
80 | */
81 | bool done() { return !valid(); }
82 |
83 | /**
84 | * Get the current value
85 | * @return Php::Value
86 | */
87 | Php::Value value() { return _value.call("current"); }
88 |
89 | /**
90 | * Get the current value
91 | * @return v8::Local
92 | */
93 | v8::Local current() { return FromPhp(_isolate, _value.call("current")); }
94 |
95 | /**
96 | * Proceed to the next record
97 | * @return bool
98 | */
99 | bool next() { _value.call("next"); return valid(); }
100 | };
101 |
102 |
103 | /**
104 | * Helper method to get access to the underlying data
105 | * @param isolate
106 | * @param obj
107 | * @return Data*
108 | */
109 | static Data *restore(v8::Isolate *isolate, const v8::Local &obj);
110 |
111 | /**
112 | * Destruct internally stored data
113 | * @param isolate
114 | * @param obj
115 | * @return Data*
116 | */
117 | static void destruct(v8::Isolate *isolate, const v8::Local &obj);
118 |
119 | /**
120 | * Method that is called by v8 when the next item is requested
121 | * @param args
122 | */
123 | static void nxtmethod(const v8::FunctionCallbackInfo &args);
124 |
125 | /**
126 | * Method that is called when the iterator leaps out prematurely
127 | * @param args
128 | */
129 | static void retmethod(const v8::FunctionCallbackInfo &args);
130 |
131 |
132 | public:
133 | /**
134 | * Constructor
135 | * @param isolate the isolate
136 | * @param value iterable php object
137 | */
138 | FromIterator(v8::Isolate *isolate, const Php::Value &value);
139 |
140 | /**
141 | * Private destructor (object is self-destructing)
142 | */
143 | virtual ~FromIterator() = default;
144 |
145 | /**
146 | * Cast to the local object
147 | * @return v8::Local
148 | */
149 | v8::Local &value() { return _iterator; }
150 | };
151 |
152 | /**
153 | * End of namespace
154 | */
155 | }
156 |
157 |
--------------------------------------------------------------------------------
/fromphp.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * FromPhp.cpp
3 | *
4 | * Implementation file for the FromPhp class
5 | *
6 | * @author Emiel Bruijntjes
7 | * @copyright 2025 Copernica BV
8 | */
9 |
10 | /**
11 | * Dependencies
12 | */
13 | #include "fromphp.h"
14 | #include "core.h"
15 |
16 | /**
17 | * Begin of namespace
18 | */
19 | namespace JS {
20 |
21 | /**
22 | * Constructor
23 | * @param isolate
24 | * @param value
25 | */
26 | FromPhp::FromPhp(v8::Isolate *isolate, const Php::Value &value)
27 | {
28 | // check the type
29 | switch (value.type()) {
30 | case Php::Type::Null: operator=(v8::Null(isolate)); return;
31 | case Php::Type::Numeric: operator=(v8::Integer::New(isolate, value)); return;
32 | case Php::Type::Float: operator=(v8::Number::New(isolate, value)); return;
33 | case Php::Type::Bool: operator=(v8::Boolean::New(isolate, value)); return;
34 | case Php::Type::True: operator=(v8::Boolean::New(isolate, true)); return;
35 | case Php::Type::False: operator=(v8::Boolean::New(isolate, false)); return;
36 | case Php::Type::String: operator=(v8::String::NewFromUtf8(isolate, value).ToLocalChecked()); return;
37 | case Php::Type::Object: operator=(Core::upgrade(isolate)->wrap(value)); return;
38 | case Php::Type::Array: operator=(Core::upgrade(isolate)->wrap(value)); return;
39 | default: operator=(v8::Undefined(isolate)); return;
40 | }
41 |
42 | // @todo do we also need Callable? the old code did support this!
43 | }
44 |
45 | /**
46 | * End of namespace
47 | */
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/fromphp.h:
--------------------------------------------------------------------------------
1 | /**
2 | * FromPhp.h
3 | *
4 | * Class to convert a variable from php space into javascript context
5 | *
6 | * @author Emiel Bruijntjes
7 | * @copyright 2025 Copernica BV
8 | */
9 |
10 | /**
11 | * Include guard
12 | */
13 | #pragma once
14 |
15 | /**
16 | * Dependencies
17 | */
18 | #include
19 | #include
20 |
21 | /**
22 | * Begin of namespace
23 | */
24 | namespace JS {
25 |
26 | /**
27 | * Class definition
28 | */
29 | class FromPhp : public v8::Local
30 | {
31 | public:
32 | /**
33 | * Constructor
34 | * @param isolate
35 | * @param value
36 | */
37 | FromPhp(v8::Isolate *isolate, const Php::Value &value);
38 |
39 | /**
40 | * Destructor
41 | */
42 | virtual ~FromPhp() = default;
43 |
44 | /**
45 | * Expose base class assignment
46 | */
47 | using v8::Local::operator=;
48 | };
49 |
50 | /**
51 | * End of namespace
52 | */
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/isolate.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * isolate.cpp
3 | *
4 | * Simple getter for the (unique) v8 isolate. This
5 | * method makes sure that a single isolate gets
6 | * constructed and that the v8 engine is properly
7 | * initialized once.
8 | *
9 | * Note that this is explicitly not thread-safe,
10 | * but it is fast. Since none of our other extensions
11 | * are properly thread-safe, this is an acceptable
12 | * limitation
13 | *
14 | * @copyright 2015 Copernica B.V.
15 | */
16 |
17 | #if false
18 |
19 | /**
20 | * Dependencies
21 | */
22 | #include "platform.h"
23 | #include "isolate.h"
24 | #include
25 | #include
26 |
27 | /**
28 | * Start namespace
29 | */
30 | namespace JS {
31 |
32 | /**
33 | * The isolate instance for this thread
34 | * @var std::unique_ptr
35 | */
36 | static thread_local std::unique_ptr isolate;
37 |
38 | class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
39 | public:
40 | virtual void* Allocate(size_t length) {
41 | void* data = AllocateUninitialized(length);
42 | return data == NULL ? data : memset(data, 0, length);
43 | }
44 | virtual void* AllocateUninitialized(size_t length)
45 | {
46 | return malloc(length);
47 | }
48 | virtual void Free(void* data, size_t)
49 | {
50 | free(data);
51 | }
52 | };
53 |
54 | static ArrayBufferAllocator allocator;
55 |
56 | /**
57 | * Constructor
58 | */
59 | Isolate::Isolate()
60 | {
61 | // create a platform
62 | Platform::create();
63 |
64 | // create our parameters
65 | v8::Isolate::CreateParams params;
66 |
67 | // set our custom allocator
68 | params.array_buffer_allocator = &allocator;
69 |
70 | // create the actual isolate
71 | _isolate = v8::Isolate::New(params);
72 |
73 | // associate ourselves with this isolate
74 | // so that we can find it back from the pointer
75 | _isolate->SetData(0, this);
76 |
77 | // and enter it
78 | _isolate->Enter();
79 | }
80 |
81 | /**
82 | * Destructor
83 | */
84 | Isolate::~Isolate()
85 | {
86 | // run all tasks still awaiting executing
87 | runTasks();
88 |
89 | /**
90 | * the tasks that are still there are scheduled
91 | * somewhere in the future, we just delete these
92 | * - this seems like a strange thing to do, but
93 | * executing them now seems to throw v8 off guard
94 | * and results in either a deadlock or some weird
95 | * error message about garbage collection running
96 | * in some old "space" or something equally weird
97 | * and confusing.
98 | */
99 | _tasks.clear();
100 |
101 | // leave the isolate scope
102 | _isolate->Exit();
103 |
104 | // clean it up
105 | _isolate->Dispose();
106 | }
107 |
108 | /**
109 | * Perform all waiting tasks for this isolate
110 | */
111 | void Isolate::runTasks()
112 | {
113 | // no tasks? then we're done fast!
114 | if (_tasks.empty()) return;
115 |
116 | // determine the current time
117 | auto now = std::chrono::system_clock::now();
118 |
119 | // loop over all the tasks
120 | for (auto iter = _tasks.begin(); iter != _tasks.end(); ++iter)
121 | {
122 | // is the execution time still in the future?
123 | if (now < iter->first)
124 | {
125 | // first task? then don't remove anything
126 | if (iter == _tasks.begin()) return;
127 |
128 | // remove from the beginning up until the task
129 | // since we already moved past the last task we
130 | // need to go back one so we don't remove a task
131 | // we have not actually executed yet
132 | _tasks.erase(_tasks.begin(), --iter);
133 |
134 | // tasks executed and removed
135 | return;
136 | }
137 |
138 | // execute the task
139 | iter->second->Run();
140 | }
141 |
142 | // we ran through all the tasks and executed all of them
143 | _tasks.clear();
144 | }
145 |
146 | /**
147 | * Schedule a task to be executed
148 | *
149 | * @param isolate The isolate to execute the task under
150 | * @param task The task to execute
151 | * @param delay Number of seconds to wait before executing
152 | */
153 | void Isolate::scheduleTask(v8::Isolate *isolate, v8::Task *task, double delay)
154 | {
155 | // first retrieve the isolate to schedule it under
156 | auto *real = static_cast(isolate->GetData(0));
157 |
158 | // determine the time at which the task should be executed
159 | auto expire = std::chrono::system_clock::now() + std::chrono::microseconds{ static_cast(delay * 1000000) };
160 |
161 | // schedule the task to be executed
162 | real->_tasks.emplace(std::make_pair(expire, std::unique_ptr{ task }));
163 | }
164 |
165 | /**
166 | * Get the isolate for this thread
167 | *
168 | * @return The thread-local isolate instance
169 | */
170 | v8::Isolate *Isolate::get()
171 | {
172 | // do we still have to create the isolate?
173 | if (!isolate) isolate.reset(new Isolate);
174 |
175 | // execute tasks for this isolate
176 | isolate->runTasks();
177 |
178 | // return the isolate
179 | return *isolate;
180 | }
181 |
182 | /**
183 | * Clean up the isolate - if any - for this thread
184 | */
185 | void Isolate::destroy()
186 | {
187 | // remove the isolate
188 | isolate.reset();
189 | }
190 |
191 | /**
192 | * Cast to the underlying isolate
193 | *
194 | * @return v8::Isolate*
195 | */
196 | Isolate::operator v8::Isolate* () const
197 | {
198 | // return member
199 | return _isolate;
200 | }
201 |
202 | /**
203 | * End namespace
204 | */
205 | }
206 |
207 | #endif
208 |
--------------------------------------------------------------------------------
/isolate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * isolate.h
3 | *
4 | * Simple getter for the (unique) v8 isolate. This
5 | * method makes sure that a single isolate gets
6 | * constructed and that the v8 engine is properly
7 | * initialized once.
8 | *
9 | * Note that this is explicitly not thread-safe,
10 | * but it is fast. Since none of our other extensions
11 | * are properly thread-safe, this is an acceptable
12 | * limitation
13 | *
14 | * @copyright 2015 Copernica B.V.
15 | */
16 |
17 | /**
18 | * Include guard
19 | */
20 | #pragma once
21 |
22 | /**
23 | * Dependencies
24 | */
25 | //#include
26 | //#include
27 | #include
28 | //#include