This repository was archived by the owner on Mar 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathFunctionTemplate_require_implementation.phpt
128 lines (86 loc) · 3.35 KB
/
FunctionTemplate_require_implementation.phpt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
--TEST--
V8\FunctionTemplate - require() implementation
--SKIPIF--
<?php if (!extension_loaded("v8")) print "skip"; ?>
--FILE--
<?php
/** @var \Phpv8Testsuite $helper */
$helper = require '.testsuite.php';
require '.v8-helpers.php';
$v8_helper = new PhpV8Helpers($helper);
$isolate = new \V8\Isolate();
$code = [];
$code['test.js'] = 'var out = {"foo" : "unchanged"}; out';
// *** This is how require implemented in node.js: ***
/** @var \V8\Value[] $loaded */
$loaded_cache = [];
$require_func_tpl_cache = new \V8\FunctionTemplate($isolate, function (\V8\FunctionCallbackInfo $info) use (&$loaded_cache, &$code) {
$isolate = $info->getIsolate();
$context = $info->getContext();
$module = $info->arguments()[0]->toString($context)->value();
if (!isset($loaded_cache[$module])) {
$new_context = new \V8\Context($isolate, new \V8\ObjectTemplate($isolate));
$script = new \V8\Script($new_context, new \V8\StringValue($isolate, $code[$module]), new \V8\ScriptOrigin($module));
$loaded_cache[$module] = $script->run($new_context);
}
$info->getReturnValue()->set($loaded_cache[$module]);
});
$global_template = new V8\ObjectTemplate($isolate);
$global_template->set(new \V8\StringValue($isolate, 'require'), $require_func_tpl_cache, \V8\PropertyAttribute::DONT_DELETE);
$context = new V8\Context($isolate, $global_template);
$v8_helper->injectConsoleLog($context);
$JS = '
var test = require("test.js");
console.log(test.foo);
test.foo = "changed";
console.log(test.foo);
var test2 = require("test.js");
console.log(test2.foo);
';
$file_name2 = 'experiment.js';
$helper->header('Test require() (with cache)');
$script2 = new V8\Script($context, new \V8\StringValue($isolate, $JS), new \V8\ScriptOrigin($file_name2));
$res2 = $script2->run($context);
$helper->space();
// *** This is how custom require() implementation demo (no caching): ***
/** @var \V8\Script[] $loaded */
$loaded_no_cache = [];
$require_func_tpl_nocache = new \V8\FunctionTemplate($isolate, function (\V8\FunctionCallbackInfo $info) use (&$loaded_no_cache, &$code) {
$isolate = $info->getIsolate();
$context = $info->getContext();
$module = $info->arguments()[0]->toString($context)->value();
if (!isset($loaded_no_cache[$module])) {
$new_context = new \V8\Context($isolate, new \V8\ObjectTemplate($isolate));
$script = new \V8\Script($new_context, new \V8\StringValue($isolate, $code[$module]), new \V8\ScriptOrigin($module));
$loaded_no_cache[$module] = $script;
}
$info->getReturnValue()->set($loaded_no_cache[$module]->Run($context));
});
$global_template = new V8\ObjectTemplate($isolate);
$global_template->set(new \V8\StringValue($isolate, 'require'), $require_func_tpl_nocache, \V8\PropertyAttribute::DONT_DELETE);
$context = new V8\Context($isolate, $global_template);
$v8_helper->injectConsoleLog($context);
$JS = '
var test = require("test.js");
console.log(test.foo);
test.foo = "changed";
console.log(test.foo);
var test2 = require("test.js");
console.log(test2.foo);
';
$file_name2 = 'experiment.js';
$helper->header('Test require() (no cache)');
$script2 = new V8\Script($context, new \V8\StringValue($isolate, $JS), new \V8\ScriptOrigin($file_name2));
$res2 = $script2->run($context);
?>
--EXPECT--
Test require() (with cache):
----------------------------
unchanged
changed
changed
Test require() (no cache):
--------------------------
unchanged
changed
unchanged