@nocobase/plugin-workflow-javascript 2.1.0-beta.10 → 2.1.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/externalVersion.js +4 -4
  2. package/dist/node_modules/isolated-vm/.clang-tidy +13 -0
  3. package/dist/node_modules/isolated-vm/.dockerignore +9 -0
  4. package/dist/node_modules/isolated-vm/Dockerfile.alpine +9 -0
  5. package/dist/node_modules/isolated-vm/Dockerfile.debian +12 -0
  6. package/dist/node_modules/isolated-vm/LICENSE +13 -0
  7. package/dist/node_modules/isolated-vm/binding.gyp +120 -0
  8. package/dist/node_modules/isolated-vm/include.js +3 -0
  9. package/dist/node_modules/isolated-vm/inspector-example.js +59 -0
  10. package/dist/node_modules/isolated-vm/isolated-vm.d.ts +820 -0
  11. package/dist/node_modules/isolated-vm/isolated-vm.js +1 -0
  12. package/dist/node_modules/isolated-vm/native-example/binding.gyp +23 -0
  13. package/dist/node_modules/isolated-vm/native-example/example.cc +61 -0
  14. package/dist/node_modules/isolated-vm/native-example/package.json +13 -0
  15. package/dist/node_modules/isolated-vm/native-example/usage.js +35 -0
  16. package/dist/node_modules/isolated-vm/out/isolated_vm.node +0 -0
  17. package/dist/node_modules/isolated-vm/package.json +1 -0
  18. package/dist/node_modules/isolated-vm/src/external_copy/error.h +33 -0
  19. package/dist/node_modules/isolated-vm/src/external_copy/external_copy.cc +509 -0
  20. package/dist/node_modules/isolated-vm/src/external_copy/external_copy.h +117 -0
  21. package/dist/node_modules/isolated-vm/src/external_copy/serializer.cc +85 -0
  22. package/dist/node_modules/isolated-vm/src/external_copy/serializer.h +136 -0
  23. package/dist/node_modules/isolated-vm/src/external_copy/serializer_nortti.cc +73 -0
  24. package/dist/node_modules/isolated-vm/src/external_copy/string.cc +124 -0
  25. package/dist/node_modules/isolated-vm/src/external_copy/string.h +28 -0
  26. package/dist/node_modules/isolated-vm/src/isolate/allocator.h +32 -0
  27. package/dist/node_modules/isolated-vm/src/isolate/allocator_nortti.cc +142 -0
  28. package/dist/node_modules/isolated-vm/src/isolate/class_handle.h +334 -0
  29. package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.cc +220 -0
  30. package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.h +100 -0
  31. package/dist/node_modules/isolated-vm/src/isolate/environment.cc +626 -0
  32. package/dist/node_modules/isolated-vm/src/isolate/environment.h +381 -0
  33. package/dist/node_modules/isolated-vm/src/isolate/executor.cc +198 -0
  34. package/dist/node_modules/isolated-vm/src/isolate/executor.h +183 -0
  35. package/dist/node_modules/isolated-vm/src/isolate/external.h +64 -0
  36. package/dist/node_modules/isolated-vm/src/isolate/functor_runners.h +97 -0
  37. package/dist/node_modules/isolated-vm/src/isolate/generic/array.h +145 -0
  38. package/dist/node_modules/isolated-vm/src/isolate/generic/callbacks.h +272 -0
  39. package/dist/node_modules/isolated-vm/src/isolate/generic/error.h +140 -0
  40. package/dist/node_modules/isolated-vm/src/isolate/generic/extract_params.h +145 -0
  41. package/dist/node_modules/isolated-vm/src/isolate/generic/handle_cast.h +257 -0
  42. package/dist/node_modules/isolated-vm/src/isolate/generic/read_option.h +47 -0
  43. package/dist/node_modules/isolated-vm/src/isolate/holder.cc +88 -0
  44. package/dist/node_modules/isolated-vm/src/isolate/holder.h +63 -0
  45. package/dist/node_modules/isolated-vm/src/isolate/inspector.cc +200 -0
  46. package/dist/node_modules/isolated-vm/src/isolate/inspector.h +70 -0
  47. package/dist/node_modules/isolated-vm/src/isolate/node_wrapper.h +15 -0
  48. package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.cc +22 -0
  49. package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.h +46 -0
  50. package/dist/node_modules/isolated-vm/src/isolate/remote_handle.h +164 -0
  51. package/dist/node_modules/isolated-vm/src/isolate/run_with_timeout.h +171 -0
  52. package/dist/node_modules/isolated-vm/src/isolate/runnable.h +29 -0
  53. package/dist/node_modules/isolated-vm/src/isolate/scheduler.cc +191 -0
  54. package/dist/node_modules/isolated-vm/src/isolate/scheduler.h +165 -0
  55. package/dist/node_modules/isolated-vm/src/isolate/specific.h +35 -0
  56. package/dist/node_modules/isolated-vm/src/isolate/stack_trace.cc +219 -0
  57. package/dist/node_modules/isolated-vm/src/isolate/stack_trace.h +24 -0
  58. package/dist/node_modules/isolated-vm/src/isolate/strings.h +127 -0
  59. package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.cc +385 -0
  60. package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.h +136 -0
  61. package/dist/node_modules/isolated-vm/src/isolate/transferable.h +15 -0
  62. package/dist/node_modules/isolated-vm/src/isolate/util.h +45 -0
  63. package/dist/node_modules/isolated-vm/src/isolate/v8_inspector_wrapper.h +12 -0
  64. package/dist/node_modules/isolated-vm/src/isolate/v8_version.h +12 -0
  65. package/dist/node_modules/isolated-vm/src/isolated_vm.h +71 -0
  66. package/dist/node_modules/isolated-vm/src/lib/covariant.h +50 -0
  67. package/dist/node_modules/isolated-vm/src/lib/lockable.h +178 -0
  68. package/dist/node_modules/isolated-vm/src/lib/suspend.h +106 -0
  69. package/dist/node_modules/isolated-vm/src/lib/thread_pool.cc +98 -0
  70. package/dist/node_modules/isolated-vm/src/lib/thread_pool.h +45 -0
  71. package/dist/node_modules/isolated-vm/src/lib/timer.cc +233 -0
  72. package/dist/node_modules/isolated-vm/src/lib/timer.h +36 -0
  73. package/dist/node_modules/isolated-vm/src/module/callback.cc +151 -0
  74. package/dist/node_modules/isolated-vm/src/module/callback.h +64 -0
  75. package/dist/node_modules/isolated-vm/src/module/context_handle.cc +241 -0
  76. package/dist/node_modules/isolated-vm/src/module/context_handle.h +35 -0
  77. package/dist/node_modules/isolated-vm/src/module/evaluation.cc +109 -0
  78. package/dist/node_modules/isolated-vm/src/module/evaluation.h +99 -0
  79. package/dist/node_modules/isolated-vm/src/module/external_copy_handle.cc +119 -0
  80. package/dist/node_modules/isolated-vm/src/module/external_copy_handle.h +64 -0
  81. package/dist/node_modules/isolated-vm/src/module/isolate.cc +136 -0
  82. package/dist/node_modules/isolated-vm/src/module/isolate_handle.cc +611 -0
  83. package/dist/node_modules/isolated-vm/src/module/isolate_handle.h +47 -0
  84. package/dist/node_modules/isolated-vm/src/module/lib_handle.cc +77 -0
  85. package/dist/node_modules/isolated-vm/src/module/lib_handle.h +28 -0
  86. package/dist/node_modules/isolated-vm/src/module/module_handle.cc +475 -0
  87. package/dist/node_modules/isolated-vm/src/module/module_handle.h +68 -0
  88. package/dist/node_modules/isolated-vm/src/module/native_module_handle.cc +104 -0
  89. package/dist/node_modules/isolated-vm/src/module/native_module_handle.h +49 -0
  90. package/dist/node_modules/isolated-vm/src/module/reference_handle.cc +636 -0
  91. package/dist/node_modules/isolated-vm/src/module/reference_handle.h +106 -0
  92. package/dist/node_modules/isolated-vm/src/module/script_handle.cc +107 -0
  93. package/dist/node_modules/isolated-vm/src/module/script_handle.h +37 -0
  94. package/dist/node_modules/isolated-vm/src/module/session_handle.cc +173 -0
  95. package/dist/node_modules/isolated-vm/src/module/session_handle.h +31 -0
  96. package/dist/node_modules/isolated-vm/src/module/transferable.cc +268 -0
  97. package/dist/node_modules/isolated-vm/src/module/transferable.h +42 -0
  98. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.0.0.h +360 -0
  99. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.3.0.h +376 -0
  100. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v20.0.0.h +397 -0
  101. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v22.0.0.h +419 -0
  102. package/dist/node_modules/winston-transport/package.json +1 -1
  103. package/dist/server/IsolatedVm.js +75 -0
  104. package/dist/server/ScriptInstruction.d.ts +6 -0
  105. package/dist/server/ScriptInstruction.js +11 -1
  106. package/dist/server/Vm.js +42 -27
  107. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ (function(){var e={290:function(e,r,_){e.exports=_(794).ivm},794:function(e,r,_){e.exports=require(_.ab+"out/isolated_vm.node")}};var r={};function __nccwpck_require__(_){var i=r[_];if(i!==undefined){return i.exports}var t=r[_]={exports:{}};var a=true;try{e[_](t,t.exports,__nccwpck_require__);a=false}finally{if(a)delete r[_]}return t.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var _=__nccwpck_require__(290);module.exports=_})();
@@ -0,0 +1,23 @@
1
+ {
2
+ 'targets': [
3
+ {
4
+ 'target_name': 'isolated-native-example',
5
+ 'cflags_cc!': [ '-fno-exceptions' ],
6
+ 'xcode_settings': {
7
+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
8
+ },
9
+ 'msvs_settings': {
10
+ 'VCCLCompilerTool': {
11
+ 'ExceptionHandling': '1',
12
+ },
13
+ },
14
+ 'include_dirs': [
15
+ '<!(node -e "require(\'nan\')")',
16
+ '<!(node -e "require(\'isolated-vm/include\')")',
17
+ ],
18
+ 'sources': [
19
+ 'example.cc',
20
+ ],
21
+ },
22
+ ],
23
+ }
@@ -0,0 +1,61 @@
1
+ // Example module w/ async function
2
+
3
+ #include <nan.h> // You don't have to use nan, but it's supported
4
+ #include <isolated_vm.h>
5
+
6
+ #include <chrono>
7
+ #include <thread>
8
+
9
+ // `using namespace` is omitted to better show which interfaces exist where.
10
+
11
+ // `Runnable` is used for async function calls. It is possible that `Run` will never actually be
12
+ // called, in the case the isolate is disposed. You should make sure to cleanup in the destructor
13
+ // instead of `Run`.
14
+ struct TimeoutCallback : public isolated_vm::Runnable {
15
+ // `RemoteHandle` should be used instead of `v8::Persistent` or `nan::Persistent`
16
+ isolated_vm::RemoteHandle<v8::Context> context;
17
+ isolated_vm::RemoteHandle<v8::Function> fn;
18
+
19
+ TimeoutCallback(
20
+ isolated_vm::RemoteHandle<v8::Context> context,
21
+ isolated_vm::RemoteHandle<v8::Function> fn
22
+ ) :
23
+ context(std::move(context)),
24
+ fn(std::move(fn)) {}
25
+
26
+ void Run() override {
27
+ // `v8::Locker` and `v8::HandleScope` are already set up and the isolate is entered. All that is
28
+ // left to do is enter a context.
29
+ v8::Context::Scope context_scope(*context);
30
+ v8::Local<v8::Function> local_fn = *fn;
31
+ v8::Local<v8::Value> argv[0];
32
+ Nan::Call(local_fn, v8::Local<v8::Object>::Cast(Nan::Undefined()), 0, argv);
33
+ }
34
+ };
35
+
36
+ NAN_METHOD(timeout) {
37
+ isolated_vm::IsolateHolder isolate_holder = isolated_vm::IsolateHolder::GetCurrent();
38
+ isolated_vm::RemoteHandle<v8::Context> context(v8::Isolate::GetCurrent()->GetCurrentContext());
39
+ isolated_vm::RemoteHandle<v8::Function> fn(v8::Local<v8::Function>::Cast(info[0]));
40
+
41
+ uint32_t ms = Nan::To<uint32_t>(info[1]).FromJust();
42
+ std::thread timeout_thread([=]() mutable {
43
+ // Note that in this closure it is not safe to call into v8! The only thing you can do is
44
+ // schedule a task.
45
+ std::this_thread::sleep_for(std::chrono::milliseconds(ms));
46
+ isolate_holder.ScheduleTask(std::make_unique<TimeoutCallback>(std::move(context), std::move(fn)));
47
+ });
48
+ timeout_thread.detach();
49
+
50
+ info.GetReturnValue().Set(Nan::Undefined());
51
+ }
52
+
53
+ ISOLATED_VM_MODULE void InitForContext(v8::Isolate* isolate, v8::Local<v8::Context> context, v8::Local<v8::Object> target) {
54
+ Nan::Set(target, Nan::New("timeout").ToLocalChecked(), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(timeout)).ToLocalChecked());
55
+ }
56
+
57
+ NAN_MODULE_INIT(init) {
58
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
59
+ InitForContext(isolate, isolate->GetCurrentContext(), target);
60
+ }
61
+ NODE_MODULE(native, init);
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "native-example",
3
+ "version": "1.0.0",
4
+ "main": "build/Release/isolated-native-example",
5
+ "scripts": {
6
+ "install": "node-gyp rebuild --release"
7
+ },
8
+ "license": "ISC",
9
+ "gypfile": true,
10
+ "dependencies": {
11
+ "nan": "^2.10.0"
12
+ }
13
+ }
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+ const ivm = require('isolated-vm');
3
+
4
+ // You *must* require the extension in nodejs first.
5
+ require('.');
6
+
7
+ // `NativeModule` constructor takes a full path to a native module. `require.resolve` handles that
8
+ // for us, and finds the module path from `package.json`.
9
+ const example = new ivm.NativeModule(require.resolve('.'));
10
+
11
+ // Create an isolate like normal
12
+ let isolate = new ivm.Isolate;
13
+ let context = isolate.createContextSync();
14
+ let global = context.global;
15
+
16
+ // Now you can load this module into the isolate. `create` or `createSync` call `InitForContext` in
17
+ // C++ which returns a reference to this module for a specific context. The return value is an
18
+ // instance of `ivm.Reference` which is just the same object that you would get by doing
19
+ // `require('native-example')` in plain nodejs. The compiled native module is also compatible with
20
+ // plain nodejs as well.
21
+ global.setSync('module', example.createSync(context).derefInto());
22
+
23
+ // Create unsafe log function
24
+ global.setSync('log', new ivm.Reference(function(...args) {
25
+ console.log(...args);
26
+ }));
27
+
28
+ // Now we can test the function
29
+ let script = isolate.compileScriptSync(`module.timeout(function() {
30
+ log.apply(0, [ "Timeout triggered" ]);
31
+ }, 1000);`);
32
+ console.log("Before runSync");
33
+ script.runSync(context);
34
+ console.log("After runSync");
35
+ // logs: 123
@@ -0,0 +1 @@
1
+ {"name":"isolated-vm","version":"5.0.4","description":"Access to multiple isolates","main":"isolated-vm.js","types":"isolated-vm.d.ts","engines":{"node":">=18.0.0"},"scripts":{"install":"prebuild-install || (node-gyp rebuild --release -j max && node-gyp clean)","rebuild":"node-gyp rebuild --release -j max","lint":"find src -name '*.cc' | xargs -n1 clang-tidy","test":"node test.js"},"dependencies":{"prebuild-install":"^7.1.2"},"devDependencies":{"isolated-vm":".","prebuild":"^13.0.1"},"binary":{"module_path":"out"},"repository":{"type":"git","url":"git+https://github.com/laverdet/isolated-vm.git"},"author":"https://github.com/laverdet/","license":"ISC","gypfile":true,"bugs":{"url":"https://github.com/laverdet/isolated-vm/issues"},"homepage":"https://github.com/laverdet/isolated-vm#readme","_lastModified":"2026-04-08T08:19:15.155Z"}
@@ -0,0 +1,33 @@
1
+ #pragma once
2
+ #include "external_copy.h"
3
+ #include "./string.h"
4
+
5
+ namespace ivm {
6
+
7
+ /**
8
+ * Make a special case for errors so if someone throws then a similar error will come out the other
9
+ * side.
10
+ */
11
+ class ExternalCopyError : public ExternalCopy {
12
+ friend class ExternalCopy;
13
+ public:
14
+ enum class ErrorType { Error, RangeError, ReferenceError, SyntaxError, TypeError, CustomError };
15
+
16
+ ExternalCopyError(
17
+ ErrorType error_type,
18
+ ExternalCopyString name,
19
+ ExternalCopyString message,
20
+ ExternalCopyString stack
21
+ );
22
+ ExternalCopyError(ErrorType error_type, const char* message, const std::string& stack = "");
23
+
24
+ auto CopyInto(bool transfer_in = false) -> v8::Local<v8::Value> final;
25
+
26
+ private:
27
+ ErrorType error_type;
28
+ ExternalCopyString name;
29
+ ExternalCopyString message;
30
+ ExternalCopyString stack;
31
+ };
32
+
33
+ } // namespace ivm
@@ -0,0 +1,509 @@
1
+ #include "external_copy.h"
2
+ #include "error.h"
3
+ #include "serializer.h"
4
+ #include "./string.h"
5
+
6
+ #include "isolate/allocator.h"
7
+ #include "isolate/environment.h"
8
+ #include "isolate/functor_runners.h"
9
+ #include "isolate/util.h"
10
+ #include "isolate/v8_version.h"
11
+
12
+ #include <algorithm>
13
+ #include <cstring>
14
+
15
+ using namespace v8;
16
+
17
+ namespace ivm {
18
+ namespace {
19
+
20
+ /**
21
+ * This is used for Number (several C++ types), or Boolean.
22
+ */
23
+ template <class Type>
24
+ struct ExternalCopyTemplateCtor {
25
+ template <class Native>
26
+ static auto New(Isolate* isolate, Native value) -> Local<Value> {
27
+ return Type::New(isolate, value);
28
+ }
29
+ };
30
+
31
+ template <>
32
+ struct ExternalCopyTemplateCtor<Uint32> {
33
+ static auto New(Isolate* isolate, uint32_t value) -> Local<Value> {
34
+ return Uint32::NewFromUnsigned(isolate, value);
35
+ }
36
+ };
37
+
38
+ template <class Type, class Native>
39
+ class ExternalCopyTemplate : public ExternalCopy {
40
+ public:
41
+ explicit ExternalCopyTemplate(Local<Value> value) :
42
+ ExternalCopy{sizeof(ExternalCopyTemplate)},
43
+ value{value.As<Type>()->Value()} {}
44
+
45
+ auto CopyInto(bool /*transfer_in*/ = false) -> Local<Value> final {
46
+ return ExternalCopyTemplateCtor<Type>::New(Isolate::GetCurrent(), value);
47
+ }
48
+
49
+ private:
50
+ const Native value;
51
+ };
52
+
53
+ /**
54
+ * BigInt data
55
+ */
56
+ struct ExternalCopyBigInt : public ExternalCopy {
57
+ public:
58
+ explicit ExternalCopyBigInt(Local<BigInt> value) {
59
+ int word_count = value->WordCount();
60
+ words.resize(word_count);
61
+ value->ToWordsArray(&sign_bit, &word_count, words.data());
62
+ }
63
+
64
+ auto CopyInto(bool /*transfer_in*/ = false) -> Local<Value> final {
65
+ return Unmaybe(BigInt::NewFromWords(
66
+ Isolate::GetCurrent()->GetCurrentContext(), sign_bit, words.size(), words.data()));
67
+ }
68
+
69
+ private:
70
+ int sign_bit = 0;
71
+ std::vector<uint64_t> words;
72
+ };
73
+
74
+ /**
75
+ * null and undefined
76
+ */
77
+ class ExternalCopyNull : public ExternalCopy {
78
+ public:
79
+ auto CopyInto(bool /*transfer_in*/ = false) -> Local<Value> final {
80
+ return Null(Isolate::GetCurrent());
81
+ }
82
+ };
83
+
84
+ class ExternalCopyUndefined : public ExternalCopy {
85
+ public:
86
+ auto CopyInto(bool /*transfer_in*/ = false) -> v8::Local<v8::Value> final {
87
+ return Undefined(Isolate::GetCurrent());
88
+ }
89
+ };
90
+
91
+ // Global size counter
92
+ std::atomic<size_t> total_allocated_size {0};
93
+
94
+ } // anonymous namespace
95
+
96
+ /**
97
+ * ExternalCopy implementation
98
+ */
99
+ ExternalCopy::ExternalCopy(int size) : size{size} {
100
+ total_allocated_size += size;
101
+ }
102
+
103
+ ExternalCopy::ExternalCopy(ExternalCopy&& that) noexcept : size{std::exchange(that.size, 0)} {}
104
+
105
+ ExternalCopy::~ExternalCopy() {
106
+ total_allocated_size -= size;
107
+ }
108
+
109
+ auto ExternalCopy::operator= (ExternalCopy&& that) noexcept -> ExternalCopy& {
110
+ size = std::exchange(that.size, 0);
111
+ return *this;
112
+ }
113
+
114
+ auto ExternalCopy::Copy(Local<Value> value, bool transfer_out, ArrayRange transfer_list)
115
+ -> std::unique_ptr<ExternalCopy> {
116
+ std::unique_ptr<ExternalCopy> copy = CopyIfPrimitive(value);
117
+ if (copy) {
118
+ return copy;
119
+ } else if (value->IsArrayBuffer()) {
120
+ Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(value);
121
+ if (!transfer_out) {
122
+ transfer_out = std::find(transfer_list.begin(), transfer_list.end(), array_buffer) != transfer_list.end();
123
+ }
124
+ if (transfer_out) {
125
+ return ExternalCopyArrayBuffer::Transfer(array_buffer);
126
+ } else {
127
+ return std::make_unique<ExternalCopyArrayBuffer>(array_buffer);
128
+ }
129
+ } else if (value->IsSharedArrayBuffer()) {
130
+ return std::make_unique<ExternalCopySharedArrayBuffer>(value.As<SharedArrayBuffer>());
131
+ } else if (value->IsArrayBufferView()) {
132
+ Local<ArrayBufferView> view = value.As<ArrayBufferView>();
133
+ using ViewType = ExternalCopyArrayBufferView::ViewType;
134
+ ViewType type;
135
+ if (view->IsUint8Array()) {
136
+ type = ViewType::Uint8;
137
+ } else if (view->IsUint8ClampedArray()) {
138
+ type = ViewType::Uint8Clamped;
139
+ } else if (view->IsInt8Array()) {
140
+ type = ViewType::Int8;
141
+ } else if (view->IsUint16Array()) {
142
+ type = ViewType::Uint16;
143
+ } else if (view->IsInt16Array()) {
144
+ type = ViewType::Int16;
145
+ } else if (view->IsUint32Array()) {
146
+ type = ViewType::Uint32;
147
+ } else if (view->IsInt32Array()) {
148
+ type = ViewType::Int32;
149
+ } else if (view->IsFloat32Array()) {
150
+ type = ViewType::Float32;
151
+ } else if (view->IsFloat64Array()) {
152
+ type = ViewType::Float64;
153
+ } else if (view->IsBigInt64Array()) {
154
+ type = ViewType::BigInt64;
155
+ } else if (view->IsBigUint64Array()) {
156
+ type = ViewType::BigUint64;
157
+ } else if (view->IsDataView()) {
158
+ type = ViewType::DataView;
159
+ } else {
160
+ assert(false);
161
+ }
162
+
163
+ // Sometimes TypedArrays don't actually have a real buffer allocated for them. The call to
164
+ // `Buffer()` below will force v8 to attempt to create a buffer if it doesn't exist, and if
165
+ // there is an allocation failure it will crash the process.
166
+ if (!view->HasBuffer()) {
167
+ auto* allocator = IsolateEnvironment::GetCurrent().GetLimitedAllocator();
168
+ if (allocator != nullptr && !allocator->Check(view->ByteLength())) {
169
+ throw RuntimeRangeError("Array buffer allocation failed");
170
+ }
171
+ }
172
+
173
+ // `Buffer()` returns a Local<ArrayBuffer> but it may be a Local<SharedArrayBuffer>
174
+ Local<Object> tmp = view->Buffer();
175
+ if (tmp->IsArrayBuffer()) {
176
+ Local<ArrayBuffer> array_buffer = tmp.As<ArrayBuffer>();
177
+ if (!transfer_out) {
178
+ transfer_out = std::find(transfer_list.begin(), transfer_list.end(), array_buffer) != transfer_list.end();
179
+ }
180
+ // Grab byte_offset and byte_length before the transfer because "neutering" the array buffer will null these out
181
+ size_t byte_offset = view->ByteOffset();
182
+ size_t byte_length = view->ByteLength();
183
+ std::unique_ptr<ExternalCopyArrayBuffer> external_buffer;
184
+ if (transfer_out) {
185
+ external_buffer = ExternalCopyArrayBuffer::Transfer(array_buffer);
186
+ } else {
187
+ external_buffer = std::make_unique<ExternalCopyArrayBuffer>(array_buffer);
188
+ }
189
+ return std::make_unique<ExternalCopyArrayBufferView>(std::move(external_buffer), type, byte_offset, byte_length);
190
+ } else {
191
+ assert(tmp->IsSharedArrayBuffer());
192
+ Local<SharedArrayBuffer> array_buffer = tmp.As<SharedArrayBuffer>();
193
+ return std::make_unique<ExternalCopyArrayBufferView>(std::make_unique<ExternalCopySharedArrayBuffer>(array_buffer), type, view->ByteOffset(), view->ByteLength());
194
+ }
195
+ } else if (value->IsObject()) {
196
+ return std::make_unique<ExternalCopySerialized>(value.As<Object>(), transfer_list);
197
+ } else {
198
+ throw RuntimeTypeError("Unsupported type");
199
+ }
200
+ }
201
+
202
+ namespace {
203
+ auto CopyIfPrimitiveImpl(Local<Value> value) -> std::unique_ptr<ExternalCopy> {
204
+ if (value->IsString()) {
205
+ return std::make_unique<ExternalCopyString>(value.As<String>());
206
+ } else if (value->IsNumber()) {
207
+ if (value->IsUint32()) {
208
+ return std::make_unique<ExternalCopyTemplate<Uint32, uint32_t>>(value);
209
+ } else if (value->IsInt32()) {
210
+ return std::make_unique<ExternalCopyTemplate<Int32, int32_t>>(value);
211
+ } else {
212
+ // This handles Infinity, -Infinity, NaN
213
+ return std::make_unique<ExternalCopyTemplate<Number, double>>(value);
214
+ }
215
+ } else if (value->IsBigInt()) {
216
+ return std::make_unique<ExternalCopyBigInt>(value.As<BigInt>());
217
+ } else if (value->IsBoolean()) {
218
+ return std::make_unique<ExternalCopyTemplate<Boolean, bool>>(value);
219
+ } else if (value->IsNull()) {
220
+ return std::make_unique<ExternalCopyNull>();
221
+ } else if (value->IsUndefined()) {
222
+ return std::make_unique<ExternalCopyUndefined>();
223
+ }
224
+ return {};
225
+ }
226
+ }
227
+
228
+ auto ExternalCopy::CopyIfPrimitive(Local<Value> value) -> std::unique_ptr<ExternalCopy> {
229
+ if (!value->IsObject()) {
230
+ return CopyIfPrimitiveImpl(value);
231
+ }
232
+ return {};
233
+ }
234
+
235
+ auto ExternalCopy::CopyThrownValue(Local<Value> value) -> std::unique_ptr<ExternalCopy> {
236
+ if (value->IsObject()) {
237
+
238
+ // Detect which subclass of Error was thrown (no better way to do this??)
239
+ Isolate* isolate = Isolate::GetCurrent();
240
+ Local<Object> object = Local<Object>::Cast(value);
241
+ std::string name = *String::Utf8Value{isolate, object->GetConstructorName()};
242
+ auto error_type = ExternalCopyError::ErrorType::CustomError;
243
+ if (name == "Error") {
244
+ error_type = ExternalCopyError::ErrorType::Error;
245
+ } else if (name == "RangeError") {
246
+ error_type = ExternalCopyError::ErrorType::RangeError;
247
+ } else if (name == "ReferenceError") {
248
+ error_type = ExternalCopyError::ErrorType::ReferenceError;
249
+ } else if (name == "SyntaxError") {
250
+ error_type = ExternalCopyError::ErrorType::SyntaxError;
251
+ } else if (name == "TypeError") {
252
+ error_type = ExternalCopyError::ErrorType::TypeError;
253
+ }
254
+
255
+ // Get error properties
256
+ Local<Context> context = isolate->GetCurrentContext();
257
+ TryCatch try_catch{isolate};
258
+ auto get_property = [&](Local<Object> object, const char* key) {
259
+ try {
260
+ Local<Value> value = Unmaybe(object->Get(context, v8_string(key)));
261
+ if (!value->IsUndefined()) {
262
+ return ExternalCopyString{Unmaybe(value->ToString(context))};
263
+ }
264
+ } catch (const RuntimeError& cc_err) {
265
+ try_catch.Reset();
266
+ }
267
+ return ExternalCopyString{};
268
+ };
269
+ ExternalCopyString message_copy = get_property(object, "message");
270
+ ExternalCopyString stack_copy = get_property(object, "stack");
271
+
272
+ // Return external error copy if this looked like an error
273
+ if (error_type != ExternalCopyError::ErrorType::CustomError || message_copy || stack_copy) {
274
+ ExternalCopyString name_copy;
275
+ if (!message_copy) {
276
+ message_copy = ExternalCopyString{""};
277
+ }
278
+ if (error_type == ExternalCopyError::ErrorType::CustomError) {
279
+ name_copy = get_property(object, "name");
280
+ }
281
+ return std::make_unique<ExternalCopyError>(error_type, std::move(name_copy), std::move(message_copy), std::move(stack_copy));
282
+ }
283
+ }
284
+ auto primitive_value = CopyIfPrimitiveImpl(value);
285
+ if (primitive_value) {
286
+ return primitive_value;
287
+ }
288
+ return std::make_unique<ExternalCopyError>(
289
+ ExternalCopyError::ErrorType::Error,
290
+ "An object was thrown from supplied code within isolated-vm, but that object was not an instance of `Error`."
291
+ );
292
+ }
293
+
294
+ auto ExternalCopy::CopyIntoCheckHeap(bool transfer_in) -> Local<Value> {
295
+ IsolateEnvironment::HeapCheck heap_check{IsolateEnvironment::GetCurrent()};
296
+ auto value = CopyInto(transfer_in);
297
+ heap_check.Epilogue();
298
+ return value;
299
+ }
300
+
301
+ auto ExternalCopy::TotalExternalSize() -> int {
302
+ return total_allocated_size;
303
+ }
304
+
305
+ void ExternalCopy::UpdateSize(int size) {
306
+ total_allocated_size -= this->size - size;
307
+ this->size = size;
308
+ }
309
+
310
+ /**
311
+ * ExternalCopyError implementation
312
+ */
313
+ ExternalCopyError::ExternalCopyError(
314
+ ErrorType error_type,
315
+ ExternalCopyString name,
316
+ ExternalCopyString message,
317
+ ExternalCopyString stack
318
+ ) :
319
+ error_type{error_type},
320
+ name{std::move(name)},
321
+ message{std::move(message)},
322
+ stack{std::move(stack)} {}
323
+
324
+ ExternalCopyError::ExternalCopyError(ErrorType error_type, const char* message, const std::string& stack) :
325
+ ExternalCopy{sizeof(ExternalCopyError)},
326
+ error_type{error_type},
327
+ message{ExternalCopyString{message}},
328
+ stack{stack.empty() ? ExternalCopyString{} : ExternalCopyString{stack}} {}
329
+
330
+ auto ExternalCopyError::CopyInto(bool /*transfer_in*/) -> Local<Value> {
331
+
332
+ // First make the exception w/ correct + message
333
+ Local<Context> context = Isolate::GetCurrent()->GetCurrentContext();
334
+ Local<String> message = Local<String>::Cast(this->message.CopyInto(false));
335
+ Local<Value> handle;
336
+ switch (error_type) {
337
+ default:
338
+ handle = Exception::Error(message);
339
+ if (name) {
340
+ Unmaybe(handle.As<Object>()->DefineOwnProperty(context, StringTable::Get().name, name.CopyInto(), PropertyAttribute::DontEnum));
341
+ }
342
+ break;
343
+ case ErrorType::RangeError:
344
+ handle = Exception::RangeError(message);
345
+ break;
346
+ case ErrorType::ReferenceError:
347
+ handle = Exception::ReferenceError(message);
348
+ break;
349
+ case ErrorType::SyntaxError:
350
+ handle = Exception::SyntaxError(message);
351
+ break;
352
+ case ErrorType::TypeError:
353
+ handle = Exception::TypeError(message);
354
+ break;
355
+ }
356
+
357
+ // Now add stack information
358
+ if (this->stack) {
359
+ Local<String> stack = Local<String>::Cast(this->stack.CopyInto(false));
360
+ Unmaybe(Local<Object>::Cast(handle)->Set(context, StringTable::Get().stack, stack));
361
+ }
362
+ return handle;
363
+ }
364
+
365
+ /**
366
+ * ExternalCopyAnyBuffer implementation
367
+ */
368
+ namespace {
369
+ void Detach(Local<ArrayBuffer> handle) {
370
+ handle->Detach();
371
+ }
372
+ auto IsDetachable(Local<ArrayBuffer> handle) {
373
+ return handle->IsDetachable();
374
+ }
375
+ } // anonymous namespace
376
+
377
+
378
+
379
+ /**
380
+ * ExternalCopyArrayBuffer implementation
381
+ */
382
+ ExternalCopyArrayBuffer::ExternalCopyArrayBuffer(const void* data, size_t length) :
383
+ ExternalCopyAnyBuffer{ArrayBuffer::NewBackingStore(
384
+ std::malloc(length), length,
385
+ [](void* data, size_t /*length*/, void* /*param*/) { std::free(data); },
386
+ nullptr)}
387
+ {
388
+ std::memcpy((*backing_store.read())->Data(), data, length);
389
+ }
390
+
391
+ ExternalCopyArrayBuffer::ExternalCopyArrayBuffer(Local<ArrayBuffer> handle) :
392
+ ExternalCopyArrayBuffer{
393
+ handle->GetBackingStore()->Data(),
394
+ handle->ByteLength()
395
+ } {}
396
+
397
+ auto ExternalCopyArrayBuffer::Transfer(Local<ArrayBuffer> handle) -> std::unique_ptr<ExternalCopyArrayBuffer> {
398
+ if (!IsDetachable(handle)) {
399
+ throw RuntimeGenericError("Array buffer is invalid");
400
+ }
401
+ auto backing_store = handle->GetBackingStore();
402
+ Detach(handle);
403
+ return std::make_unique<ExternalCopyArrayBuffer>(std::move(backing_store));
404
+ }
405
+
406
+ auto ExternalCopyArrayBuffer::CopyInto(bool transfer_in) -> Local<Value> {
407
+ if (transfer_in) {
408
+ auto backing_store = std::exchange(*this->backing_store.write(), {});
409
+ if (!backing_store) {
410
+ throw RuntimeGenericError("Array buffer is invalid");
411
+ }
412
+ UpdateSize(0);
413
+ size_t size = backing_store->ByteLength();
414
+ auto handle = ArrayBuffer::New(Isolate::GetCurrent(), std::move(backing_store));
415
+ auto* allocator = IsolateEnvironment::GetCurrent().GetLimitedAllocator();
416
+ if (allocator != nullptr) {
417
+ allocator->Track(handle, size);
418
+ }
419
+ return handle;
420
+ } else {
421
+ auto* allocator = IsolateEnvironment::GetCurrent().GetLimitedAllocator();
422
+ auto backing_store = *this->backing_store.read();
423
+ if (!backing_store) {
424
+ throw RuntimeGenericError("Array buffer is invalid");
425
+ }
426
+ auto size = backing_store->ByteLength();
427
+ if (allocator != nullptr && !allocator->Check(size)) {
428
+ // ArrayBuffer::New will crash the process if there is an allocation failure, so we check
429
+ // here.
430
+ throw RuntimeRangeError("Array buffer allocation failed");
431
+ }
432
+ auto handle = ArrayBuffer::New(Isolate::GetCurrent(), size);
433
+ auto* data = handle->GetBackingStore()->Data();
434
+ std::memcpy(data, backing_store->Data(), size);
435
+ return handle;
436
+ }
437
+ }
438
+
439
+ /**
440
+ * ExternalCopySharedArrayBuffer implementation
441
+ */
442
+ ExternalCopySharedArrayBuffer::ExternalCopySharedArrayBuffer(Local<SharedArrayBuffer> handle) :
443
+ ExternalCopyAnyBuffer{handle->GetBackingStore()} {}
444
+
445
+ auto ExternalCopySharedArrayBuffer::CopyInto(bool /*transfer_in*/) -> Local<Value> {
446
+ auto backing_store = *this->backing_store.read();
447
+ size_t size = backing_store->ByteLength();
448
+ auto handle = SharedArrayBuffer::New(Isolate::GetCurrent(), std::move(backing_store));
449
+ auto* allocator = IsolateEnvironment::GetCurrent().GetLimitedAllocator();
450
+ if (allocator != nullptr) {
451
+ allocator->Track(handle, size);
452
+ }
453
+ return handle;
454
+ }
455
+
456
+ /**
457
+ * ExternalCopyArrayBufferView implementation
458
+ */
459
+ ExternalCopyArrayBufferView::ExternalCopyArrayBufferView(
460
+ std::unique_ptr<ExternalCopyAnyBuffer> buffer,
461
+ ViewType type, size_t byte_offset, size_t byte_length
462
+ ) :
463
+ ExternalCopy(sizeof(ExternalCopyArrayBufferView)),
464
+ buffer(std::move(buffer)),
465
+ type(type),
466
+ byte_offset(byte_offset), byte_length(byte_length) {}
467
+
468
+ template <typename T>
469
+ auto NewTypedArrayView(Local<T> buffer, ExternalCopyArrayBufferView::ViewType type, size_t byte_offset, size_t byte_length) -> Local<Value> {
470
+ switch (type) {
471
+ case ExternalCopyArrayBufferView::ViewType::Uint8:
472
+ return Uint8Array::New(buffer, byte_offset, byte_length >> 0);
473
+ case ExternalCopyArrayBufferView::ViewType::Uint8Clamped:
474
+ return Uint8ClampedArray::New(buffer, byte_offset, byte_length >> 0);
475
+ case ExternalCopyArrayBufferView::ViewType::Int8:
476
+ return Int8Array::New(buffer, byte_offset, byte_length >> 0);
477
+ case ExternalCopyArrayBufferView::ViewType::Uint16:
478
+ return Uint16Array::New(buffer, byte_offset, byte_length >> 1);
479
+ case ExternalCopyArrayBufferView::ViewType::Int16:
480
+ return Int16Array::New(buffer, byte_offset, byte_length >> 1);
481
+ case ExternalCopyArrayBufferView::ViewType::Uint32:
482
+ return Uint32Array::New(buffer, byte_offset, byte_length >> 2);
483
+ case ExternalCopyArrayBufferView::ViewType::Int32:
484
+ return Int32Array::New(buffer, byte_offset, byte_length >> 2);
485
+ case ExternalCopyArrayBufferView::ViewType::Float32:
486
+ return Float32Array::New(buffer, byte_offset, byte_length >> 2);
487
+ case ExternalCopyArrayBufferView::ViewType::Float64:
488
+ return Float64Array::New(buffer, byte_offset, byte_length >> 3);
489
+ case ExternalCopyArrayBufferView::ViewType::BigInt64:
490
+ return BigInt64Array::New(buffer, byte_offset, byte_length >> 3);
491
+ case ExternalCopyArrayBufferView::ViewType::BigUint64:
492
+ return BigUint64Array::New(buffer, byte_offset, byte_length >> 3);
493
+ case ExternalCopyArrayBufferView::ViewType::DataView:
494
+ return DataView::New(buffer, byte_offset, byte_length);
495
+ default:
496
+ throw std::exception();
497
+ }
498
+ }
499
+
500
+ auto ExternalCopyArrayBufferView::CopyInto(bool transfer_in) -> Local<Value> {
501
+ Local<Value> buffer = this->buffer->CopyInto(transfer_in);
502
+ if (buffer->IsArrayBuffer()) {
503
+ return NewTypedArrayView(buffer.As<ArrayBuffer>(), type, byte_offset, byte_length);
504
+ } else {
505
+ return NewTypedArrayView(buffer.As<SharedArrayBuffer>(), type, byte_offset, byte_length);
506
+ }
507
+ }
508
+
509
+ } // namespace ivm