Skip to content

Commit

Permalink
Merge branch 'main' into teodor/embedding
Browse files Browse the repository at this point in the history
  • Loading branch information
edusperoni authored Jun 26, 2024
2 parents 0a15501 + 4cd869d commit 6055045
Show file tree
Hide file tree
Showing 34 changed files with 1,371 additions and 75 deletions.
1 change: 1 addition & 0 deletions NativeScript/JSIRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright © 2022 Progress. All rights reserved.
//

#pragma once
#import <Foundation/Foundation.h>
#import "v8runtime/V8Runtime.h"
#include "runtime/Runtime.h"
Expand Down
8 changes: 8 additions & 0 deletions NativeScript/jsi/decorator.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
Array createArray(size_t length) override {
return plain_.createArray(length);
};
ArrayBuffer createArrayBuffer(
std::shared_ptr<MutableBuffer> buffer) override {
return plain_.createArrayBuffer(std::move(buffer));
};
size_t size(const Array& a) override {
return plain_.size(a);
};
Expand Down Expand Up @@ -671,6 +675,10 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
Around around{with_};
return RD::createArray(length);
};
ArrayBuffer createArrayBuffer(
std::shared_ptr<MutableBuffer> buffer) override {
return RD::createArrayBuffer(std::move(buffer));
};
size_t size(const Array& a) override {
Around around{with_};
return RD::size(a);
Expand Down
16 changes: 16 additions & 0 deletions NativeScript/jsi/jsi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,22 @@ inline ArrayBuffer Object::getArrayBuffer(Runtime& runtime) && {
return ArrayBuffer(value);
}


inline TypedArray Object::getTypedArray(Runtime &runtime) const &{
assert(runtime.isTypedArray(*this));
(void) runtime; // when assert is disabled we need to mark this as used
return TypedArray(runtime.cloneObject(ptr_));
}

inline TypedArray Object::getTypedArray(Runtime &runtime) &&{
assert(runtime.isTypedArray(*this));
(void) runtime; // when assert is disabled we need to mark this as used
Runtime::PointerValue *value = ptr_;
ptr_ = nullptr;
return TypedArray(value);
}


inline Function Object::getFunction(Runtime& runtime) const& {
assert(runtime.isFunction(*this));
return Function(runtime.cloneObject(ptr_));
Expand Down
2 changes: 2 additions & 0 deletions NativeScript/jsi/jsi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ Value callGlobalFunction(Runtime& runtime, const char* name, const Value& arg) {

Buffer::~Buffer() = default;

MutableBuffer::~MutableBuffer() = default;

PreparedJavaScript::~PreparedJavaScript() = default;

Value HostObject::get(Runtime&, const PropNameID&) {
Expand Down
184 changes: 184 additions & 0 deletions NativeScript/jsi/jsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ class JSI_EXPORT Buffer {
virtual const uint8_t* data() const = 0;
};

/// Base class for buffers of data that need to be passed to the runtime. The
/// result of size() and data() must not change after construction. However, the
/// region pointed to by data() may be modified by the user or the runtime. The
/// user must ensure that access to the contents of the buffer is properly
/// synchronised.
class JSI_EXPORT MutableBuffer {
public:
virtual ~MutableBuffer();
virtual size_t size() const = 0;
virtual uint8_t* data() = 0;
};

class JSI_EXPORT StringBuffer : public Buffer {
public:
StringBuffer(std::string s) : s_(std::move(s)) {}
Expand Down Expand Up @@ -80,6 +92,7 @@ class Instrumentation;
class Scope;
class JSIException;
class JSError;
class TypedArray;

/// A function which has this type can be registered as a function
/// callable from JavaScript using Function::createFromHostFunction().
Expand Down Expand Up @@ -251,6 +264,8 @@ class JSI_EXPORT Runtime {
friend class Value;
friend class Scope;
friend class JSError;
friend class TypedArray;


// Potential optimization: avoid the cloneFoo() virtual dispatch,
// and instead just fix the number of fields, and copy them, since
Expand Down Expand Up @@ -307,18 +322,40 @@ class JSI_EXPORT Runtime {

virtual bool isArray(const Object&) const = 0;
virtual bool isArrayBuffer(const Object&) const = 0;
virtual bool isArrayBufferView(const Object&) const = 0;
virtual bool isTypedArray(const Object&) const = 0;
virtual bool isInt8Array(const Object&) const = 0;
virtual bool isUint8Array(const Object&) const = 0;
virtual bool isUint8ClampedArray(const Object&) const = 0;
virtual bool isInt16Array(const Object&) const = 0;
virtual bool isUint16Array(const Object&) const = 0;
virtual bool isInt32Array(const Object&) const = 0;
virtual bool isUint32Array(const Object&) const = 0;
virtual bool isFloat32Array(const Object&) const = 0;
virtual bool isBigInt64Array(const Object&) const = 0;
virtual bool isBigUint64Array(const Object&) const = 0;
virtual bool isFloat64Array(const Object&) const = 0;
virtual bool isFunction(const Object&) const = 0;
virtual bool isHostObject(const jsi::Object&) const = 0;
virtual bool isHostFunction(const jsi::Function&) const = 0;
virtual Array getPropertyNames(const Object&) = 0;

virtual WeakObject createWeakObject(const Object&) = 0;
virtual Value lockWeakObject(WeakObject&) = 0;

virtual uint64_t uint64Value(const BigInt&, bool *lossless) const = 0;
virtual int64_t int64Value(const BigInt&, bool *lossless) const = 0;


virtual Array createArray(size_t length) = 0;
virtual ArrayBuffer createArrayBuffer(
std::shared_ptr<MutableBuffer> buffer) = 0;
virtual size_t size(const Array&) = 0;
virtual size_t size(const ArrayBuffer&) = 0;
virtual size_t size(const TypedArray&) = 0;
virtual uint8_t* data(const ArrayBuffer&) = 0;
virtual uint8_t* data(const TypedArray&) = 0;
virtual size_t offset(const TypedArray&) = 0;
virtual Value getValueAtIndex(const Array&, size_t i) = 0;
virtual void setValueAtIndexImpl(Array&, size_t i, const Value& value) = 0;

Expand Down Expand Up @@ -493,6 +530,26 @@ class JSI_EXPORT BigInt : public Pointer {

BigInt(BigInt&& other) = default;
BigInt& operator=(BigInt&& other) = default;


/**
* Returns the value of this BigInt as an unsigned 64-bit integer.
* If `lossless` is provided, it will reflect whether the return value was
* truncated or wrapped around. In particular, it is set to `false` if this
* BigInt is negative.
*/
uint64_t Uint64Value(Runtime& runtime, bool* lossless = nullptr) const {
return runtime.uint64Value(*this, lossless);
}

/**
* Returns the value of this BigInt as a signed 64-bit integer.
* If `lossless` is provided, it will reflect whether this BigInt was
* truncated or not.
*/
int64_t Int64Value(Runtime& runtime, bool* lossless = nullptr) const {
return runtime.int64Value(*this, lossless);
}

friend class Runtime;
friend class Value;
Expand Down Expand Up @@ -641,6 +698,86 @@ class JSI_EXPORT Object : public Pointer {
bool isArrayBuffer(Runtime& runtime) const {
return runtime.isArrayBuffer(*this);
}


/// \return true iff the Object is an isArrayBufferView. If so, then \c
/// getArrayBuffer() will succeed.
bool isArrayBufferView(Runtime& runtime) const {
return runtime.isArrayBufferView(*this);
}

/// \return true iff the Object is an isTypedArray. If so, then \c
/// getArrayBuffer() will succeed.
bool isTypedArray(Runtime& runtime) const {
return runtime.isTypedArray(*this);
}


/// \return true iff the Object is an isInt8Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isInt8Array(Runtime& runtime) const {
return runtime.isInt8Array(*this);
}

/// \return true iff the Object is an isUint8Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isUint8Array(Runtime& runtime) const {
return runtime.isUint8Array(*this);
}

/// \return true iff the Object is an isUint8ClampedArray. If so, then \c
/// getArrayBuffer() will succeed.
bool isUint8ClampedArray(Runtime& runtime) const {
return runtime.isUint8ClampedArray(*this);
}

/// \return true iff the Object is an isInt16Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isInt16Array(Runtime& runtime) const {
return runtime.isInt16Array(*this);
}

/// \return true iff the Object is an isUint16Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isUint16Array(Runtime& runtime) const {
return runtime.isUint16Array(*this);
}

/// \return true iff the Object is an isInt32Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isInt32Array(Runtime& runtime) const {
return runtime.isInt32Array(*this);
}

/// \return true iff the Object is an isUint32Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isUint32Array(Runtime& runtime) const {
return runtime.isUint32Array(*this);
}

/// \return true iff the Object is an isFloat32Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isFloat32Array(Runtime& runtime) const {
return runtime.isFloat32Array(*this);
}

/// \return true iff the Object is an isBigInt64Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isBigInt64Array(Runtime& runtime) const {
return runtime.isBigInt64Array(*this);
}

/// \return true iff the Object is an isBigUint64Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isBigUint64Array(Runtime& runtime) const {
return runtime.isBigUint64Array(*this);
}

/// \return true iff the Object is an isFloat64Array. If so, then \c
/// getArrayBuffer() will succeed.
bool isFloat64Array(Runtime& runtime) const {
return runtime.isFloat64Array(*this);
}

/// \return true iff the Object is callable. If so, then \c
/// getFunction will succeed.
Expand Down Expand Up @@ -679,6 +816,16 @@ class JSI_EXPORT Object : public Pointer {
/// \return an ArrayBuffer instance which refers to the same underlying
/// object. If \c isArrayBuffer() would return false, this will assert.
ArrayBuffer getArrayBuffer(Runtime& runtime) &&;


/// \return an TypedArray instance which refers to the same underlying
/// object. If \c isTypedArray() would return false, this will assert.
TypedArray getTypedArray(Runtime& runtime) const&;

/// \return an TypedArray instance which refers to the same underlying
/// object. If \c isTypedArray() would return false, this will assert.
TypedArray getTypedArray(Runtime& runtime) &&;


/// \return a Function instance which refers to the same underlying
/// object. If \c isFunction() would return false, this will assert.
Expand Down Expand Up @@ -828,6 +975,8 @@ class JSI_EXPORT ArrayBuffer : public Object {
public:
ArrayBuffer(ArrayBuffer&&) = default;
ArrayBuffer& operator=(ArrayBuffer&&) = default;
ArrayBuffer(Runtime& runtime, std::shared_ptr<MutableBuffer> buffer)
: ArrayBuffer(runtime.createArrayBuffer(std::move(buffer))) {}

/// \return the size of the ArrayBuffer, according to its byteLength property.
/// (C++ naming convention)
Expand All @@ -850,6 +999,41 @@ class JSI_EXPORT ArrayBuffer : public Object {
ArrayBuffer(Runtime::PointerValue* value) : Object(value) {}
};


/// Represents a TypedArray
class JSI_EXPORT TypedArray : public Object {
public:
TypedArray(TypedArray &&) = default;

TypedArray &operator=(TypedArray &&) = default;

/// \return the size of the TypedArray ArrayBuffer, according to its byteLength property.
/// (C++ naming convention)
size_t size(Runtime &runtime) {
return runtime.size(*this);
}

size_t offset(Runtime &runtime) const {
return runtime.offset(*this);
}

size_t length(Runtime &runtime) const {
return runtime.size(*this);
}

uint8_t *data(Runtime &runtime) {
return runtime.data(*this);
}

private:
friend class Object;

friend class Value;

TypedArray(Runtime::PointerValue *value) : Object(value) {}
};


/// Represents a JS Object which is guaranteed to be Callable.
class JSI_EXPORT Function : public Object {
public:
Expand Down
8 changes: 4 additions & 4 deletions NativeScript/runtime/ConcurrentQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ void ConcurrentQueue::Initialize(CFRunLoopRef runLoop, void (*performWork)(void*
CFRunLoopAddSource(this->runLoop_, this->runLoopTasksSource_, kCFRunLoopCommonModes);
}

void ConcurrentQueue::Push(std::string message) {
void ConcurrentQueue::Push(std::shared_ptr<worker::Message> message) {
if (this->runLoopTasksSource_ != nullptr && !CFRunLoopSourceIsValid(this->runLoopTasksSource_)) {
return;
}
Expand All @@ -27,12 +27,12 @@ void ConcurrentQueue::Push(std::string message) {
this->SignalAndWakeUp();
}

std::vector<std::string> ConcurrentQueue::PopAll() {
std::vector<std::shared_ptr<worker::Message>> ConcurrentQueue::PopAll() {
std::unique_lock<std::mutex> mlock(this->mutex_);
std::vector<std::string> messages;
std::vector<std::shared_ptr<worker::Message>> messages;

while (!this->messagesQueue_.empty()) {
std::string message = this->messagesQueue_.front();
std::shared_ptr<worker::Message> message = this->messagesQueue_.front();
this->messagesQueue_.pop();
messages.push_back(message);
}
Expand Down
7 changes: 4 additions & 3 deletions NativeScript/runtime/ConcurrentQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
#include <string>
#include <queue>
#include <mutex>
#include "Message.hpp"

namespace tns {

struct ConcurrentQueue {
public:
void Initialize(CFRunLoopRef runLoop, void (*performWork)(void*), void* info);
void Push(std::string message);
std::vector<std::string> PopAll();
void Push(std::shared_ptr<worker::Message> message);
std::vector<std::shared_ptr<worker::Message>> PopAll();
void Terminate();
private:
std::queue<std::string> messagesQueue_;
std::queue<std::shared_ptr<worker::Message>> messagesQueue_;
CFRunLoopSourceRef runLoopTasksSource_ = nullptr;
CFRunLoopRef runLoop_ = nullptr;
bool terminated = false;
Expand Down
6 changes: 3 additions & 3 deletions NativeScript/runtime/DataWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -654,12 +654,12 @@ class ExtVectorWrapper: public BaseDataWrapper {

class WorkerWrapper: public BaseDataWrapper {
public:
WorkerWrapper(v8::Isolate* mainIsolate, std::function<void (v8::Isolate*, v8::Local<v8::Object> thiz, std::string)> onMessage);
WorkerWrapper(v8::Isolate* mainIsolate, std::function<void (v8::Isolate*, v8::Local<v8::Object> thiz, std::shared_ptr<worker::Message>)> onMessage);

void Start(std::shared_ptr<v8::Persistent<v8::Value>> poWorker, std::function<v8::Isolate* ()> func);
void CallOnErrorHandlers(v8::TryCatch& tc);
void PassUncaughtExceptionFromWorkerToMain(v8::Local<v8::Context> context, v8::TryCatch& tc, bool async = true);
void PostMessage(std::string message);
void PostMessage(std::shared_ptr<worker::Message> message);
void Close();
void Terminate();

Expand Down Expand Up @@ -691,7 +691,7 @@ class WorkerWrapper: public BaseDataWrapper {
std::atomic<bool> isTerminating_;
bool isDisposed_;
bool isWeak_;
std::function<void (v8::Isolate*, v8::Local<v8::Object> thiz, std::string)> onMessage_;
std::function<void (v8::Isolate*, v8::Local<v8::Object> thiz, std::shared_ptr<worker::Message>)> onMessage_;
std::shared_ptr<v8::Persistent<v8::Value>> poWorker_;
ConcurrentQueue queue_;
static std::atomic<int> nextId_;
Expand Down
Loading

0 comments on commit 6055045

Please sign in to comment.