V8 threading safetyu improvements

This commit is contained in:
ksuprynowicz 2023-01-27 19:06:19 +01:00
parent 5099e68b56
commit 6bd8a8d503
8 changed files with 107 additions and 25 deletions

View file

@ -1107,6 +1107,10 @@ ScriptContextV8Pointer ScriptEngineV8::pushContext(v8::Local<v8::Context> &conte
Q_ASSERT(!_contexts.isEmpty()); Q_ASSERT(!_contexts.isEmpty());
ScriptContextPointer parent = _contexts.last(); ScriptContextPointer parent = _contexts.last();
_contexts.append(std::make_shared<ScriptContextV8Wrapper>(this, context, ScriptContextPointer())); _contexts.append(std::make_shared<ScriptContextV8Wrapper>(this, context, ScriptContextPointer()));
v8::Context::Scope contextScope(context);
static volatile int debug_context_id = 1;
context->Global()->Set(context, v8::String::NewFromUtf8(_v8Isolate, "debug_context_id").ToLocalChecked(), v8::Integer::New(_v8Isolate, debug_context_id));
debug_context_id++;
return _contexts.last(); return _contexts.last();
} }

View file

@ -440,7 +440,10 @@ void ScriptObjectV8Proxy::v8Set(v8::Local<v8::Name> name, v8::Local<v8::Value> v
V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V8ScriptString& name, uint id) { V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V8ScriptString& name, uint id) {
v8::Locker locker(_engine->getIsolate());
v8::Isolate::Scope isolateScope(_engine->getIsolate());
v8::HandleScope handleScope(_engine->getIsolate()); v8::HandleScope handleScope(_engine->getIsolate());
v8::Context::Scope contextScope(_engine->getContext());
QObject* qobject = _object; QObject* qobject = _object;
if (!qobject) { if (!qobject) {
_engine->getIsolate()->ThrowError("Referencing deleted native object"); _engine->getIsolate()->ThrowError("Referencing deleted native object");
@ -509,7 +512,10 @@ V8ScriptValue ScriptObjectV8Proxy::property(const V8ScriptValue& object, const V
} }
void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) { void ScriptObjectV8Proxy::setProperty(V8ScriptValue& object, const V8ScriptString& name, uint id, const V8ScriptValue& value) {
v8::Locker locker(_engine->getIsolate());
v8::Isolate::Scope isolateScope(_engine->getIsolate());
v8::HandleScope handleScope(_engine->getIsolate()); v8::HandleScope handleScope(_engine->getIsolate());
v8::Context::Scope contextScope(_engine->getContext());
if (!(id & PROPERTY_TYPE)) return; if (!(id & PROPERTY_TYPE)) return;
QObject* qobject = _object; QObject* qobject = _object;
if (!qobject) { if (!qobject) {
@ -548,6 +554,10 @@ ScriptVariantV8Proxy::ScriptVariantV8Proxy(ScriptEngineV8* engine, const QVarian
} }
V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue proto) { V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVariant& variant, V8ScriptValue proto) {
v8::Locker locker(engine->getIsolate());
v8::Isolate::Scope isolateScope(engine->getIsolate());
v8::HandleScope handleScope(engine->getIsolate());
v8::Context::Scope contextScope(engine->getContext());
ScriptObjectV8Proxy* protoProxy = ScriptObjectV8Proxy::unwrapProxy(proto); ScriptObjectV8Proxy* protoProxy = ScriptObjectV8Proxy::unwrapProxy(proto);
if (!protoProxy) { if (!protoProxy) {
Q_ASSERT(protoProxy); Q_ASSERT(protoProxy);
@ -566,7 +576,7 @@ V8ScriptValue ScriptVariantV8Proxy::newVariant(ScriptEngineV8* engine, const QVa
} }
ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) { ScriptVariantV8Proxy* ScriptVariantV8Proxy::unwrapProxy(const V8ScriptValue& val) {
// V8TODO // V8TODO V8ScriptValue should have link to engine instead maybe?
v8::HandleScope handleScope(const_cast<v8::Isolate*>(val.constGetIsolate())); v8::HandleScope handleScope(const_cast<v8::Isolate*>(val.constGetIsolate()));
auto v8Value = val.constGet(); auto v8Value = val.constGet();
if (!v8Value->IsObject()) { if (!v8Value->IsObject()) {
@ -599,6 +609,10 @@ ScriptMethodV8Proxy::~ScriptMethodV8Proxy() {
V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime, V8ScriptValue ScriptMethodV8Proxy::newMethod(ScriptEngineV8* engine, QObject* object, V8ScriptValue lifetime,
const QList<QMetaMethod>& metas, int numMaxParams) { const QList<QMetaMethod>& metas, int numMaxParams) {
v8::Locker locker(engine->getIsolate());
v8::Isolate::Scope isolateScope(engine->getIsolate());
v8::HandleScope handleScope(engine->getIsolate());
v8::Context::Scope contextScope(engine->getContext());
auto methodDataTemplate = v8::ObjectTemplate::New(engine->getIsolate()); auto methodDataTemplate = v8::ObjectTemplate::New(engine->getIsolate());
methodDataTemplate->SetInternalFieldCount(2); methodDataTemplate->SetInternalFieldCount(2);
auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked(); auto methodData = methodDataTemplate->NewInstance(engine->getContext()).ToLocalChecked();
@ -632,7 +646,11 @@ QString ScriptMethodV8Proxy::fullName() const {
}*/ }*/
void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo<v8::Value>& arguments) { void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo<v8::Value>& arguments) {
v8::Locker locker(arguments.GetIsolate());
v8::Isolate::Scope isolateScope(arguments.GetIsolate());
v8::HandleScope handleScope(arguments.GetIsolate()); v8::HandleScope handleScope(arguments.GetIsolate());
Q_ASSERT(!arguments.GetIsolate()->GetCurrentContext().IsEmpty());
v8::Context::Scope contextScope(arguments.GetIsolate()->GetCurrentContext());
if (!arguments.Data()->IsObject()) { if (!arguments.Data()->IsObject()) {
arguments.GetIsolate()->ThrowError("Method value is not an object"); arguments.GetIsolate()->ThrowError("Method value is not an object");
return; return;
@ -655,14 +673,19 @@ void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo<v8::Value>& ar
} }
void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& arguments) { void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& arguments) {
v8::Locker locker(_engine->getIsolate());
v8::Isolate::Scope isolateScope(_engine->getIsolate());
v8::HandleScope handleScope(_engine->getIsolate());
v8::Context::Scope contextScope(_engine->getContext());
QObject* qobject = _object; QObject* qobject = _object;
v8::Isolate *isolate = arguments.GetIsolate(); v8::Isolate *isolate = arguments.GetIsolate();
Q_ASSERT(isolate == _engine->getIsolate());
if (!qobject) { if (!qobject) {
isolate->ThrowError("Referencing deleted native object"); isolate->ThrowError("Referencing deleted native object");
return; return;
} }
v8::HandleScope handleScope(_engine->getIsolate()); //v8::HandleScope handleScope(_engine->getIsolate());
int scriptNumArgs = arguments.Length(); int scriptNumArgs = arguments.Length();
int numArgs = std::min(scriptNumArgs, _numMaxParams); int numArgs = std::min(scriptNumArgs, _numMaxParams);
@ -1052,7 +1075,8 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu
callback->Call(_engine->getContext(), v8This, numArgs, args); callback->Call(_engine->getContext(), v8This, numArgs, args);
if (tryCatch.HasCaught()) { if (tryCatch.HasCaught()) {
qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \"" qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \""
<< _engine->formatErrorMessageFromTryCatch(tryCatch) << "This: " << conn.thisValue.get()->IsObject(); << _engine->formatErrorMessageFromTryCatch(tryCatch)
<< "\nThis provided: " << conn.thisValue.get()->IsObject();
} }
} }
@ -1065,6 +1089,10 @@ int ScriptSignalV8Proxy::discoverMetaCallIdx() {
} }
ScriptSignalV8Proxy::ConnectionList::iterator ScriptSignalV8Proxy::findConnection(V8ScriptValue thisObject, V8ScriptValue callback) { ScriptSignalV8Proxy::ConnectionList::iterator ScriptSignalV8Proxy::findConnection(V8ScriptValue thisObject, V8ScriptValue callback) {
v8::Locker locker(_engine->getIsolate());
v8::Isolate::Scope isolateScope(_engine->getIsolate());
v8::HandleScope handleScope(_engine->getIsolate());
v8::Context::Scope contextScope(_engine->getContext());
auto iterOut = resultWithReadLock<ScriptSignalV8Proxy::ConnectionList::iterator>([&]{ auto iterOut = resultWithReadLock<ScriptSignalV8Proxy::ConnectionList::iterator>([&]{
ConnectionList::iterator iter; ConnectionList::iterator iter;
for (iter = _connections.begin(); iter != _connections.end(); ++iter) { for (iter = _connections.begin(); iter != _connections.end(); ++iter) {
@ -1083,14 +1111,18 @@ ScriptSignalV8Proxy::ConnectionList::iterator ScriptSignalV8Proxy::findConnectio
}*/ }*/
void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) { void ScriptSignalV8Proxy::connect(ScriptValue arg0, ScriptValue arg1) {
QObject* qobject = _object;
v8::Isolate *isolate = _engine->getIsolate(); v8::Isolate *isolate = _engine->getIsolate();
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
QObject* qobject = _object;
if (!qobject) { if (!qobject) {
isolate->ThrowError("Referencing deleted native object"); isolate->ThrowError("Referencing deleted native object");
return; return;
} }
v8::HandleScope handleScope(isolate); //v8::HandleScope handleScope(isolate);
// untangle the arguments // untangle the arguments
V8ScriptValue callback(isolate, v8::Null(isolate)); V8ScriptValue callback(isolate, v8::Null(isolate));
@ -1194,7 +1226,10 @@ void ScriptSignalV8Proxy::disconnect(ScriptValue arg0, ScriptValue arg1) {
isolate->ThrowError("Referencing deleted native object"); isolate->ThrowError("Referencing deleted native object");
return; return;
} }
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext());
// untangle the arguments // untangle the arguments
V8ScriptValue callback(isolate, v8::Null(isolate)); V8ScriptValue callback(isolate, v8::Null(isolate));

View file

@ -242,7 +242,8 @@ bool ScriptValueV8Wrapper::hasProperty(const QString& name) const {
v8::Local<v8::Value> resultLocal; v8::Local<v8::Value> resultLocal;
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked(); v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet()); const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet());
if (object->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) { //V8TODO: Which context?
if (object->Get(_engine->getContext(), key).ToLocal(&resultLocal)) {
return true; return true;
} else { } else {
return false; return false;
@ -264,7 +265,9 @@ ScriptValue ScriptValueV8Wrapper::property(const QString& name, const ScriptValu
v8::Local<v8::Value> resultLocal; v8::Local<v8::Value> resultLocal;
v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked(); v8::Local<v8::String> key = v8::String::NewFromUtf8(_engine->getIsolate(), name.toStdString().c_str(),v8::NewStringType::kNormal).ToLocalChecked();
const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet()); const v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(_value.constGet());
if (object->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) { //V8TODO: Which context?
if (object->Get(_engine->getContext(), key).ToLocal(&resultLocal)) {
//if (object->Get(_value.constGetContext(), key).ToLocal(&resultLocal)) {
V8ScriptValue result(_engine->getIsolate(), resultLocal); V8ScriptValue result(_engine->getIsolate(), resultLocal);
return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result))); return ScriptValue(new ScriptValueV8Wrapper(_engine, std::move(result)));
} else { } else {
@ -374,7 +377,9 @@ void ScriptValueV8Wrapper::setProperty(quint32 arrayIndex, const ScriptValue& va
V8ScriptValue unwrapped = fullUnwrap(value); V8ScriptValue unwrapped = fullUnwrap(value);
if(_value.constGet()->IsObject()) { if(_value.constGet()->IsObject()) {
auto object = v8::Local<v8::Object>::Cast(_value.get()); auto object = v8::Local<v8::Object>::Cast(_value.get());
v8::Maybe<bool> retVal(object->Set(_value.getContext(), arrayIndex, unwrapped.constGet())); //V8TODO: I don't know which context to use here
v8::Maybe<bool> retVal(object->Set(_engine->getContext(), arrayIndex, unwrapped.constGet()));
//v8::Maybe<bool> retVal(object->Set(_value.getContext(), arrayIndex, unwrapped.constGet()));
if (retVal.IsJust() ? !retVal.FromJust() : true){ if (retVal.IsJust() ? !retVal.FromJust() : true){
qDebug(scriptengine) << "Failed to set property"; qDebug(scriptengine) << "Failed to set property";
} }
@ -395,7 +400,9 @@ void ScriptValueV8Wrapper::setPrototype(const ScriptValue& prototype) {
if (unwrappedPrototype) { if (unwrappedPrototype) {
if(unwrappedPrototype->toV8Value().constGet()->IsObject() && _value.constGet()->IsObject()) { if(unwrappedPrototype->toV8Value().constGet()->IsObject() && _value.constGet()->IsObject()) {
auto object = v8::Local<v8::Object>::Cast(_value.get()); auto object = v8::Local<v8::Object>::Cast(_value.get());
v8::Maybe<bool> retVal = object->SetPrototype(_value.getContext(), unwrappedPrototype->toV8Value().constGet()); //V8TODO: I don't know which context to use here
v8::Maybe<bool> retVal = object->SetPrototype(_engine->getContext(), unwrappedPrototype->toV8Value().constGet());
//v8::Maybe<bool> retVal = object->SetPrototype(_value.getContext(), unwrappedPrototype->toV8Value().constGet());
if (retVal.IsJust() ? !retVal.FromJust() : true){ if (retVal.IsJust() ? !retVal.FromJust() : true){
qDebug(scriptengine) << "Failed to assign prototype"; qDebug(scriptengine) << "Failed to assign prototype";
} }
@ -431,7 +438,7 @@ qint32 ScriptValueV8Wrapper::toInt32() const {
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext()); v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Integer> integer; v8::Local<v8::Integer> integer;
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(&integer)) { if (!_value.constGet()->ToInteger(_engine->getContext()).ToLocal(&integer)) {
Q_ASSERT(false); Q_ASSERT(false);
} }
return static_cast<int32_t>((integer)->Value()); return static_cast<int32_t>((integer)->Value());
@ -444,7 +451,7 @@ double ScriptValueV8Wrapper::toInteger() const {
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext()); v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Integer> integer; v8::Local<v8::Integer> integer;
if (!_value.constGet()->ToInteger(_value.constGetContext()).ToLocal(&integer)) { if (!_value.constGet()->ToInteger(_engine->getContext()).ToLocal(&integer)) {
Q_ASSERT(false); Q_ASSERT(false);
} }
return (integer)->Value(); return (integer)->Value();
@ -457,7 +464,7 @@ double ScriptValueV8Wrapper::toNumber() const {
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext()); v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Number> number; v8::Local<v8::Number> number;
if (!_value.constGet()->ToNumber(_value.constGetContext()).ToLocal(&number)) { if (!_value.constGet()->ToNumber(_engine->getContext()).ToLocal(&number)) {
Q_ASSERT(false); Q_ASSERT(false);
} }
return number->Value(); return number->Value();
@ -481,7 +488,7 @@ quint16 ScriptValueV8Wrapper::toUInt16() const {
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext()); v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Uint32> integer; v8::Local<v8::Uint32> integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(&integer)) { if (!_value.constGet()->ToUint32(_engine->getContext()).ToLocal(&integer)) {
Q_ASSERT(false); Q_ASSERT(false);
} }
return static_cast<uint16_t>(integer->Value()); return static_cast<uint16_t>(integer->Value());
@ -494,7 +501,7 @@ quint32 ScriptValueV8Wrapper::toUInt32() const {
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(_engine->getContext()); v8::Context::Scope contextScope(_engine->getContext());
v8::Local<v8::Uint32> integer; v8::Local<v8::Uint32> integer;
if (!_value.constGet()->ToUint32(_value.constGetContext()).ToLocal(&integer)) { if (!_value.constGet()->ToUint32(_engine->getContext()).ToLocal(&integer)) {
Q_ASSERT(false); Q_ASSERT(false);
} }
return integer->Value(); return integer->Value();
@ -532,11 +539,17 @@ bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const {
if (!unwrappedOther) { if (!unwrappedOther) {
return false; return false;
}else{ }else{
if (_value.constGet()->Equals(unwrappedOther->toV8Value().constGetContext(), unwrappedOther->toV8Value().constGet()).IsNothing()) { // V8TODO: which context needs to be used here?
if (_value.constGet()->Equals(_engine->getContext(), unwrappedOther->toV8Value().constGet()).IsNothing()) {
return false;
} else {
return _value.constGet()->Equals(_engine->getContext(), unwrappedOther->toV8Value().constGet()).FromJust();
}
/*if (_value.constGet()->Equals(unwrappedOther->toV8Value().constGetContext(), unwrappedOther->toV8Value().constGet()).IsNothing()) {
return false; return false;
} else { } else {
return _value.constGet()->Equals(unwrappedOther->toV8Value().constGetContext(), unwrappedOther->toV8Value().constGet()).FromJust(); return _value.constGet()->Equals(unwrappedOther->toV8Value().constGetContext(), unwrappedOther->toV8Value().constGet()).FromJust();
} }*/
} }
} }

View file

@ -32,6 +32,11 @@ public:
_context.Reset(isolate, isolate->GetCurrentContext()); _context.Reset(isolate, isolate->GetCurrentContext());
_value.reset(new v8::UniquePersistent<T>(_isolate, std::move(value))); _value.reset(new v8::UniquePersistent<T>(_isolate, std::move(value)));
}; };
/*V8ScriptValueTemplate(const V8ScriptValueTemplate &copied) {
;
}*/
v8::Local<T> get() { v8::Local<T> get() {
v8::EscapableHandleScope handleScope(_isolate); v8::EscapableHandleScope handleScope(_isolate);
return handleScope.Escape(_value.get()->Get(_isolate)); return handleScope.Escape(_value.get()->Get(_isolate));
@ -47,14 +52,18 @@ public:
const v8::Local<v8::Context> constGetContext() const { const v8::Local<v8::Context> constGetContext() const {
v8::EscapableHandleScope handleScope(_isolate); v8::EscapableHandleScope handleScope(_isolate);
return handleScope.Escape(_context.Get(_isolate)); Q_ASSERT(!_isolate->GetCurrentContext().IsEmpty());
return handleScope.Escape(_isolate->GetCurrentContext());
//return handleScope.Escape(_context.Get(_isolate));
}; };
const v8::Isolate* constGetIsolate() const { return _isolate;}; const v8::Isolate* constGetIsolate() const { return _isolate;};
v8::Isolate* getIsolate() { return _isolate;}; v8::Isolate* getIsolate() { return _isolate;};
//v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>>& getContext() { return _context;}; //v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>>& getContext() { return _context;};
v8::Local<v8::Context> getContext() { v8::Local<v8::Context> getContext() {
v8::EscapableHandleScope handleScope(_isolate); v8::EscapableHandleScope handleScope(_isolate);
return handleScope.Escape(_context.Get(_isolate)); Q_ASSERT(!_isolate->GetCurrentContext().IsEmpty());
return handleScope.Escape(_isolate->GetCurrentContext());
//return handleScope.Escape(_context.Get(_isolate));
}; };
void reset(v8::Isolate *isolate, v8::Local<T>) {}; void reset(v8::Isolate *isolate, v8::Local<T>) {};
private: private:

View file

@ -11,15 +11,14 @@
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
"use strict";
/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EditTools, EditVoxels, EntityListTool, Vec3, SelectionManager, /* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EditTools, EditVoxels, EntityListTool, Vec3, SelectionManager,
Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera,
progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow,
keyUpEventFromUIWindow:true */ keyUpEventFromUIWindow:true */
(function() { // BEGIN LOCAL_SCOPE //(function() { // BEGIN LOCAL_SCOPE
"use strict";
var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton";
@ -3181,6 +3180,7 @@ function zoneSortOrder(a, b) {
return 0; return 0;
} }
//print("getParentState added");
function getParentState(id) { function getParentState(id) {
var state = "NONE"; var state = "NONE";
var properties = Entities.getEntityProperties(id, ["parentID"]); var properties = Entities.getEntityProperties(id, ["parentID"]);
@ -3199,6 +3199,8 @@ function getParentState(id) {
return state; return state;
} }
//print("Global object after getParentState" + JSON.stringify(globalThis));
function getDomainOnlyChildrenIDs(id) { function getDomainOnlyChildrenIDs(id) {
var allChildren = Entities.getChildrenIDs(id); var allChildren = Entities.getChildrenIDs(id);
var realChildren = []; var realChildren = [];
@ -3264,4 +3266,4 @@ function rotateAsNextClickedSurface() {
} }
} }
}()); // END LOCAL_SCOPE //}()); // END LOCAL_SCOPE

View file

@ -217,7 +217,7 @@ var EntityListTool = function(shouldUseEditTabletApp) {
} else if (properties.type === "Image") { } else if (properties.type === "Image") {
url = properties.imageURL; url = properties.imageURL;
} }
//print("Global object before getParentState call: " + JSON.stringify(globalThis));
var parentStatus = getParentState(ids[i]); var parentStatus = getParentState(ids[i]);
var parentState = ""; var parentState = "";
if (parentStatus === "PARENT") { if (parentStatus === "PARENT") {
@ -297,7 +297,7 @@ var EntityListTool = function(shouldUseEditTabletApp) {
} }
var onWebEventReceived = function(data) { var onWebEventReceived = function(data) {
print("entityList.js onWebEventReceived: " + data); //print("entityList.js onWebEventReceived: " + data);
try { try {
data = JSON.parse(data); data = JSON.parse(data);
} catch(e) { } catch(e) {

View file

@ -2,6 +2,10 @@
Script.include("./005b_included.js"); Script.include("./005b_included.js");
//var requireTest = Script.require("http://oaktown.pl/scripts/004b_require_module.js");
var testObject = new TestObject();
function functionInMainFile () { function functionInMainFile () {
print("In main file"); print("In main file");
} }

View file

@ -5,4 +5,19 @@ function functionInInclude() {
functionInMainFile(); functionInMainFile();
} }
var TestObject = function(shouldUseEditTabletApp) {
var requireTest = Script.require("http://oaktown.pl/scripts/004b_require_module.js");
var onEvent = function(data) {
that.thatFunction();
}
var that = {};
that.thatFunction = function() {
functionInMainFile();
}
Script.update.connect(onEvent);
}
functionInMainFile(); functionInMainFile();
//Script.setInterval(functionInInclude, 1000);