159 lines
4.6 KiB
C++
159 lines
4.6 KiB
C++
#include "Extras/Utils/nutils.h"
|
|
|
|
#include <QApplication>
|
|
#include <QMetaType>
|
|
#include <QWidget>
|
|
#include <string>
|
|
|
|
#include "core/Component/component_wrap.h"
|
|
#include "core/FlexLayout/flexutils.h"
|
|
#include "core/YogaWidget/yogawidget.h"
|
|
|
|
bool extrautils::isNapiValueInt(Napi::Env& env, Napi::Value& num) {
|
|
return env.Global()
|
|
.Get("Number")
|
|
.ToObject()
|
|
.Get("isInteger")
|
|
.As<Napi::Function>()
|
|
.Call({num})
|
|
.ToBoolean()
|
|
.Value();
|
|
}
|
|
|
|
std::string extrautils::getNapiObjectClassName(Napi::Object& object) {
|
|
return object.Get("constructor")
|
|
.As<Napi::Object>()
|
|
.Get("name")
|
|
.As<Napi::String>()
|
|
.Utf8Value();
|
|
}
|
|
|
|
QVariant* extrautils::convertToQVariant(Napi::Env& env, Napi::Value& value) {
|
|
// Warning: Make sure you delete the QVariant fron this function upon use.
|
|
if (value.IsBoolean()) {
|
|
return new QVariant(value.As<Napi::Boolean>().Value());
|
|
|
|
} else if (value.IsNumber()) {
|
|
if (isNapiValueInt(env, value)) {
|
|
return new QVariant(value.As<Napi::Number>().Int32Value());
|
|
} else {
|
|
return new QVariant(value.As<Napi::Number>().DoubleValue());
|
|
}
|
|
|
|
} else if (value.IsString()) {
|
|
std::string stringValue = value.As<Napi::String>().Utf8Value();
|
|
return new QVariant(stringValue.c_str());
|
|
|
|
} else if (value.IsSymbol()) {
|
|
return new QVariant();
|
|
|
|
} else if (value.IsArray()) {
|
|
// Note: This assumes an array of strings.
|
|
Napi::Array array = value.As<Napi::Array>();
|
|
QStringList value;
|
|
uint32_t len = array.Length();
|
|
for (uint32_t i = 0; i < len; i++) {
|
|
if (array.Get(i).IsString()) {
|
|
std::string stringValue = array.Get(i).As<Napi::String>().Utf8Value();
|
|
value.append(QString::fromUtf8(stringValue.c_str()));
|
|
}
|
|
}
|
|
return new QVariant(value);
|
|
|
|
} else if (value.IsArrayBuffer()) {
|
|
// TODO: fix this
|
|
return new QVariant();
|
|
|
|
} else if (value.IsTypedArray()) {
|
|
// TODO: fix this
|
|
return new QVariant();
|
|
|
|
} else if (value.IsObject()) {
|
|
Napi::Object object = value.As<Napi::Object>();
|
|
std::string className = getNapiObjectClassName(object);
|
|
QMetaType type = QMetaType::fromName(className.c_str());
|
|
ComponentWrap* componentWrap =
|
|
Napi::ObjectWrap<ComponentWrap>::Unwrap(object);
|
|
return new QVariant(type, componentWrap->rawData);
|
|
|
|
} else if (value.IsFunction()) {
|
|
return new QVariant();
|
|
|
|
} else if (value.IsPromise()) {
|
|
return new QVariant();
|
|
|
|
} else if (value.IsUndefined()) {
|
|
return new QVariant();
|
|
|
|
} else if (value.IsNull()) {
|
|
return new QVariant();
|
|
|
|
} else if (value.IsBuffer()) {
|
|
// TODO: fix this
|
|
return new QVariant();
|
|
|
|
} else if (value.IsExternal()) {
|
|
QVariant* variant = value.As<Napi::External<QVariant>>().Data();
|
|
return variant;
|
|
|
|
} else {
|
|
return new QVariant();
|
|
}
|
|
}
|
|
|
|
void* extrautils::configureComponent(void* component) { return component; }
|
|
|
|
void* extrautils::configureQObject(QObject* object) {
|
|
return configureComponent(object);
|
|
}
|
|
|
|
void* extrautils::configureQWidget(QWidget* widget, bool isLeafNode) {
|
|
YogaWidget* yogaWidget = dynamic_cast<YogaWidget*>(widget);
|
|
if (yogaWidget) {
|
|
flexutils::configureFlexNode(widget, yogaWidget->getFlexNode(), isLeafNode);
|
|
}
|
|
return configureQObject(widget);
|
|
}
|
|
|
|
uint64_t extrautils::hashPointerTo53bit(const void* input) {
|
|
// Hash the address of the object down to something which will
|
|
// fit into the JS 53bit safe integer space.
|
|
uint64_t address = reinterpret_cast<uint64_t>(input);
|
|
uint64_t top8Bits = address & 0xff00000000000000u;
|
|
uint64_t foldedBits = (top8Bits >> 11) ^ address;
|
|
|
|
// Clear the top 8bits which we folded, now shift out the last 3 bits
|
|
// Pointers are aligned on 64bit architectures to at least 8bytes
|
|
// boundaries.
|
|
uint64_t result = (foldedBits & ~0xff00000000000000u) >> 3;
|
|
return result;
|
|
}
|
|
|
|
Napi::FunctionReference NUtilsWrap::constructor;
|
|
|
|
Napi::Object NUtilsWrap::init(Napi::Env env, Napi::Object exports) {
|
|
Napi::HandleScope scope(env);
|
|
char CLASSNAME[] = "NUtils";
|
|
Napi::Function func =
|
|
DefineClass(env, CLASSNAME,
|
|
{
|
|
StaticMethod("isNapiExternal",
|
|
&StaticNUtilsWrapMethods::isNapiExternal),
|
|
});
|
|
constructor = Napi::Persistent(func);
|
|
exports.Set(CLASSNAME, func);
|
|
return exports;
|
|
}
|
|
|
|
NUtilsWrap::NUtilsWrap(const Napi::CallbackInfo& info)
|
|
: Napi::ObjectWrap<NUtilsWrap>(info) {}
|
|
|
|
Napi::Value StaticNUtilsWrapMethods::isNapiExternal(
|
|
const Napi::CallbackInfo& info) {
|
|
Napi::Env env = info.Env();
|
|
if (info.Length() > 0 && info[0].IsExternal()) {
|
|
return Napi::Boolean::New(env, true);
|
|
}
|
|
return Napi::Boolean::New(env, false);
|
|
}
|