Showing the changes to libraries/script-engine/src/v8/ScriptEngineV8.cpp (1 of 29 files). Show all
Unified · Split
| @@ -85,7 +85,7 @@ ScriptValue ScriptEngineV8::makeError(const ScriptValue& _other, const QString& · 84 unmodified lines | |||
| 85 | return nullValue(); | 85 | return nullValue(); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | //V8TODO | 88 | //V8TODO: do not remove until ScriptEngineV8::makeError is implemented |
| 89 | /* | 89 | /* |
| 90 | auto other = _other; | 90 | auto other = _other; |
| 91 | if (_other.constGet()->IsString()) { | 91 | if (_other.constGet()->IsString()) { |
| @@ -130,14 +130,12 @@ ScriptValue ScriptEngineV8::checkScriptSyntax(ScriptProgramPointer program) { · 38 unmodified lines | |||
| 130 | v8::HandleScope handleScope(_v8Isolate); | 130 | v8::HandleScope handleScope(_v8Isolate); |
| 131 | v8::Context::Scope contextScope(getContext()); | 131 | v8::Context::Scope contextScope(getContext()); |
| 132 | ScriptSyntaxCheckResultPointer syntaxCheck = program->checkSyntax(); | 132 | ScriptSyntaxCheckResultPointer syntaxCheck = program->checkSyntax(); |
| 133 | //V8TODO | ||
| 134 | if (syntaxCheck->state() != ScriptSyntaxCheckResult::Valid) { | 133 | if (syntaxCheck->state() != ScriptSyntaxCheckResult::Valid) { |
| 135 | auto err = globalObject().property("SyntaxError").construct(ScriptValueList({ newValue(syntaxCheck->errorMessage()) })); | 134 | auto err = globalObject().property("SyntaxError").construct(ScriptValueList({ newValue(syntaxCheck->errorMessage()) })); |
| 136 | err.setProperty("fileName", program->fileName()); | 135 | err.setProperty("fileName", program->fileName()); |
| 137 | err.setProperty("lineNumber", syntaxCheck->errorLineNumber()); | 136 | err.setProperty("lineNumber", syntaxCheck->errorLineNumber()); |
| 138 | err.setProperty("expressionBeginOffset", syntaxCheck->errorColumnNumber()); | 137 | err.setProperty("expressionBeginOffset", syntaxCheck->errorColumnNumber()); |
| 139 | err.setProperty("stack", syntaxCheck->errorBacktrace()); | 138 | err.setProperty("stack", syntaxCheck->errorBacktrace()); |
| 140 | //err.setProperty("stack", currentContext()->backtrace().join(ScriptManager::SCRIPT_BACKTRACE_SEP)); | ||
| 141 | { | 139 | { |
| 142 | const auto error = syntaxCheck->errorMessage(); | 140 | const auto error = syntaxCheck->errorMessage(); |
| 143 | const auto line = QString::number(syntaxCheck->errorLineNumber()); | 141 | const auto line = QString::number(syntaxCheck->errorLineNumber()); |
| @@ -150,32 +148,6 @@ ScriptValue ScriptEngineV8::checkScriptSyntax(ScriptProgramPointer program) { · 6 unmodified lines | |||
| 150 | } | 148 | } |
| 151 | return undefinedValue(); | 149 | return undefinedValue(); |
| 152 | } | 150 | } |
| 153 | /*ScriptValue ScriptEngineV8::lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber) { | ||
| 154 | if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { | ||
| 155 | return nullValue(); | ||
| 156 | } | ||
| 157 | //V8TODO | ||
| 158 | const auto syntaxCheck = checkSyntax(sourceCode); | ||
| 159 | if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { | ||
| 160 | auto err = QScriptEngine::globalObject().property("SyntaxError").construct(V8ScriptValueList({ syntaxCheck.errorMessage() })); | ||
| 161 | err.setProperty("fileName", fileName); | ||
| 162 | err.setProperty("lineNumber", syntaxCheck.errorLineNumber()); | ||
| 163 | err.setProperty("expressionBeginOffset", syntaxCheck.errorColumnNumber()); | ||
| 164 | err.setProperty("stack", currentContext()->backtrace().join(ScriptManager::SCRIPT_BACKTRACE_SEP)); | ||
| 165 | { | ||
| 166 | const auto error = syntaxCheck.errorMessage(); | ||
| 167 | const auto line = QString::number(syntaxCheck.errorLineNumber()); | ||
| 168 | const auto column = QString::number(syntaxCheck.errorColumnNumber()); | ||
| 169 | // for compatibility with legacy reporting | ||
| 170 | const auto message = QString("[SyntaxError] %1 in %2:%3(%4)").arg(error, fileName, line, column); | ||
| 171 | err.setProperty("formatted", message); | ||
| 172 | } | ||
| 173 | return ScriptValue(new ScriptValueV8Wrapper(this, std::move(err))); | ||
| 174 | } | ||
| 175 | return undefinedValue(); | ||
| 176 | }*/ | ||
| 177 | |||
| 178 | |||
| 179 | 151 | ||
| 180 | // Lambda | 152 | // Lambda |
| 181 | /*ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext*, ScriptEngineV8*)> operation, | 153 | /*ScriptValue ScriptEngineV8::newLambdaFunction(std::function<V8ScriptValue(V8ScriptContext*, ScriptEngineV8*)> operation, |
| @@ -264,8 +236,7 @@ v8::Platform* ScriptEngineV8::getV8Platform() { · 82 unmodified lines | |||
| 264 | } | 236 | } |
| 265 | 237 | ||
| 266 | ScriptEngineV8::ScriptEngineV8(ScriptManager *manager) : ScriptEngine(manager), _evaluatingCounter(0) | 238 | ScriptEngineV8::ScriptEngineV8(ScriptManager *manager) : ScriptEngine(manager), _evaluatingCounter(0) |
| 267 | //V8TODO | 239 | //V8TODO _arrayBufferClass(new ArrayBufferClass(this)) |
| 268 | //_arrayBufferClass(new ArrayBufferClass(this)) | ||
| 269 | { | 240 | { |
| 270 | _v8InitMutex.lock(); | 241 | _v8InitMutex.lock(); |
| 271 | std::call_once ( _v8InitOnceFlag, [ ]{ | 242 | std::call_once ( _v8InitOnceFlag, [ ]{ |
| @@ -289,7 +260,6 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager *manager) : ScriptEngine(manager), · 17 unmodified lines | |||
| 289 | #else | 260 | #else |
| 290 | v8::V8::SetFlagsFromString("--stack-size=256"); | 261 | v8::V8::SetFlagsFromString("--stack-size=256"); |
| 291 | #endif | 262 | #endif |
| 292 | //v8::V8::SetFlagsFromString("--stack-size=256 --single-threaded"); | ||
| 293 | v8::Platform* platform = getV8Platform(); | 263 | v8::Platform* platform = getV8Platform(); |
| 294 | v8::V8::InitializePlatform(platform); | 264 | v8::V8::InitializePlatform(platform); |
| 295 | v8::V8::Initialize(); qCDebug(scriptengine_v8) << "V8 platform initialized"; | 265 | v8::V8::Initialize(); qCDebug(scriptengine_v8) << "V8 platform initialized"; |
| @@ -317,18 +287,10 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager *manager) : ScriptEngine(manager), · 21 unmodified lines | |||
| 317 | registerSystemTypes(); | 287 | registerSystemTypes(); |
| 318 | 288 | ||
| 319 | // V8TODO: dispose of isolate on ScriptEngineV8 destruction | 289 | // V8TODO: dispose of isolate on ScriptEngineV8 destruction |
| 320 | //v8::UniquePersistent<v8::Value> null = v8::UniquePersistent<v8::Value>(_v8Isolate, v8::Null(_v8Isolate)); | ||
| 321 | //_nullValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(null))); | ||
| 322 | |||
| 323 | //V8ScriptValue undefined = v8::UniquePersistent<v8::Value>(_v8Isolate,v8::Undefined(_v8Isolate)); | ||
| 324 | //_undefinedValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(undefined))); | ||
| 325 | |||
| 326 | // V8TODO: | 290 | // V8TODO: |
| 327 | //QScriptEngine::setProcessEventsInterval(MSECS_PER_SECOND); | 291 | //QScriptEngine::setProcessEventsInterval(MSECS_PER_SECOND); |
| 328 | } | 292 | } |
| 329 | 293 | ||
| 330 | //_currentThread = QThread::currentThread(); | ||
| 331 | |||
| 332 | //if (_scriptManager) { | 294 | //if (_scriptManager) { |
| 333 | // V8TODO: port to V8 | 295 | // V8TODO: port to V8 |
| 334 | /*connect(this, &QScriptEngine::signalHandlerException, this, [this](const V8ScriptValue& exception) { | 296 | /*connect(this, &QScriptEngine::signalHandlerException, this, [this](const V8ScriptValue& exception) { |
| @@ -342,8 +304,6 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager *manager) : ScriptEngine(manager), · 7 unmodified lines | |||
| 342 | emit _scriptManager->unhandledException(ScriptValue(new ScriptValueV8Wrapper(this, std::move(thrown)))); | 304 | emit _scriptManager->unhandledException(ScriptValue(new ScriptValueV8Wrapper(this, std::move(thrown)))); |
| 343 | } | 305 | } |
| 344 | }, Qt::DirectConnection);*/ | 306 | }, Qt::DirectConnection);*/ |
| 345 | //moveToThread(scriptManager->thread()); | ||
| 346 | //setThread(scriptManager->thread()); | ||
| 347 | //} | 307 | //} |
| 348 | } | 308 | } |
| 349 | 309 | ||
| @@ -396,16 +356,11 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value · 46 unmodified lines | |||
| 396 | } | 356 | } |
| 397 | if (createProperty) { | 357 | if (createProperty) { |
| 398 | if (partsToGo > 0) { | 358 | if (partsToGo > 0) { |
| 399 | //This was commented out | 359 | v8::Local<v8::Object> partValue = v8::Object::New(_v8Isolate); |
| 400 | //QObject *object = new QObject; | ||
| 401 | v8::Local<v8::Object> partValue = v8::Object::New(_v8Isolate); //newQObject(object, QScriptEngine::ScriptOwnership); | ||
| 402 | //V8ScriptValue partValue = QScriptEngine::newArray(); //newQObject(object, QScriptEngine::ScriptOwnership); | ||
| 403 | if (!partObject->Set(context, pathPartV8, partValue).FromMaybe(false)) { | 360 | if (!partObject->Set(context, pathPartV8, partValue).FromMaybe(false)) { |
| 404 | Q_ASSERT(false); | 361 | Q_ASSERT(false); |
| 405 | } | 362 | } |
| 406 | } else { | 363 | } else { |
| 407 | //partObject = currentPath->ToObject(); | ||
| 408 | //V8TODO: do these still happen if asserts are disabled? | ||
| 409 | if (!partObject->Set(context, pathPartV8, value.constGet()).FromMaybe(false)) { | 364 | if (!partObject->Set(context, pathPartV8, value.constGet()).FromMaybe(false)) { |
| 410 | Q_ASSERT(false); | 365 | Q_ASSERT(false); |
| 411 | } | 366 | } |
| @@ -440,14 +395,6 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) · 28 unmodified lines | |||
| 440 | #ifdef THREAD_DEBUGGING | 395 | #ifdef THREAD_DEBUGGING |
| 441 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name; | 396 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name; |
| 442 | #endif | 397 | #endif |
| 443 | /*bool is_isolate_exit_needed = false; | ||
| 444 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { | ||
| 445 | // V8TODO: Theoretically only script thread should access this, so it should be safe | ||
| 446 | _v8Locker.reset(new v8::Locker(_v8Isolate)); | ||
| 447 | _v8Isolate->Enter(); | ||
| 448 | is_isolate_exit_needed = true; | ||
| 449 | }*/ | ||
| 450 | //{ | ||
| 451 | v8::Locker locker(_v8Isolate); | 398 | v8::Locker locker(_v8Isolate); |
| 452 | v8::Isolate::Scope isolateScope(_v8Isolate); | 399 | v8::Isolate::Scope isolateScope(_v8Isolate); |
| 453 | v8::HandleScope handleScope(_v8Isolate); | 400 | v8::HandleScope handleScope(_v8Isolate); |
| @@ -457,7 +404,6 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) · 3 unmodified lines | |||
| 457 | v8::Local<v8::Object> v8GlobalObject = getContext()->Global(); | 404 | v8::Local<v8::Object> v8GlobalObject = getContext()->Global(); |
| 458 | v8::Local<v8::String> v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); | 405 | v8::Local<v8::String> v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); |
| 459 | 406 | ||
| 460 | // V8TODO: Is IsEmpty check enough or IsValid is needed too? | ||
| 461 | if (!v8GlobalObject->Get(getContext(), v8Name).IsEmpty()) { | 407 | if (!v8GlobalObject->Get(getContext(), v8Name).IsEmpty()) { |
| 462 | if (object) { | 408 | if (object) { |
| 463 | V8ScriptValue value = ScriptObjectV8Proxy::newQObject(this, object, ScriptEngine::QtOwnership); | 409 | V8ScriptValue value = ScriptObjectV8Proxy::newQObject(this, object, ScriptEngine::QtOwnership); |
| @@ -470,16 +416,9 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) · 6 unmodified lines | |||
| 470 | } | 416 | } |
| 471 | } | 417 | } |
| 472 | } | 418 | } |
| 473 | //} | ||
| 474 | /*if (is_isolate_exit_needed) { | ||
| 475 | _v8Isolate->Exit(); | ||
| 476 | _v8Locker.reset(nullptr); | ||
| 477 | }*/ | ||
| 478 | } | 419 | } |
| 479 | 420 | ||
| 480 | void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { | 421 | void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { |
| 481 | //if (QThread::currentThread() != ) { | ||
| 482 | //} | ||
| 483 | if (QThread::currentThread() != thread()) { | 422 | if (QThread::currentThread() != thread()) { |
| 484 | #ifdef THREAD_DEBUGGING | 423 | #ifdef THREAD_DEBUGGING |
| 485 | qCDebug(scriptengine_v8) << "*** WARNING *** ScriptEngineV8::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; | 424 | qCDebug(scriptengine_v8) << "*** WARNING *** ScriptEngineV8::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name; |
| @@ -494,28 +433,13 @@ void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::Functio · 8 unmodified lines | |||
| 494 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name; | 433 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name; |
| 495 | #endif | 434 | #endif |
| 496 | 435 | ||
| 497 | /*bool is_isolate_exit_needed = false; | ||
| 498 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { | ||
| 499 | // V8TODO: Theoretically only script thread should access this, so it should be safe | ||
| 500 | _v8Locker.reset(new v8::Locker(_v8Isolate)); | ||
| 501 | _v8Isolate->Enter(); | ||
| 502 | is_isolate_exit_needed = true; | ||
| 503 | } | ||
| 504 | {*/ | ||
| 505 | //auto scriptFun = static_cast<ScriptValueV8Wrapper*>(newFunction(functionSignature, numArguments).ptr())->toV8Value().constGet(); | ||
| 506 | v8::Locker locker(_v8Isolate); | 436 | v8::Locker locker(_v8Isolate); |
| 507 | v8::Isolate::Scope isolateScope(_v8Isolate); | 437 | v8::Isolate::Scope isolateScope(_v8Isolate); |
| 508 | v8::HandleScope handleScope(_v8Isolate); | 438 | v8::HandleScope handleScope(_v8Isolate); |
| 509 | v8::Context::Scope contextScope(getContext()); | 439 | v8::Context::Scope contextScope(getContext()); |
| 510 | auto scriptFun = newFunction(functionSignature, numArguments); | 440 | auto scriptFun = newFunction(functionSignature, numArguments); |
| 511 | 441 | ||
| 512 | //getContext()->Global().Set(); | ||
| 513 | globalObject().setProperty(name, scriptFun); | 442 | globalObject().setProperty(name, scriptFun); |
| 514 | /*} | ||
| 515 | if (is_isolate_exit_needed) { | ||
| 516 | _v8Isolate->Exit(); | ||
| 517 | _v8Locker.reset(nullptr); | ||
| 518 | }*/ | ||
| 519 | } | 443 | } |
| 520 | 444 | ||
| 521 | void ScriptEngineV8::registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { | 445 | void ScriptEngineV8::registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { |
| @@ -533,14 +457,6 @@ void ScriptEngineV8::registerFunction(const QString& parent, const QString& name · 11 unmodified lines | |||
| 533 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name; | 457 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name; |
| 534 | #endif | 458 | #endif |
| 535 | 459 | ||
| 536 | /*bool is_isolate_exit_needed = false; | ||
| 537 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { | ||
| 538 | // V8TODO: Theoretically only script thread should access this, so it should be safe | ||
| 539 | _v8Locker.reset(new v8::Locker(_v8Isolate)); | ||
| 540 | _v8Isolate->Enter(); | ||
| 541 | is_isolate_exit_needed = true; | ||
| 542 | } | ||
| 543 | {*/ | ||
| 544 | v8::Locker locker(_v8Isolate); | 460 | v8::Locker locker(_v8Isolate); |
| 545 | v8::Isolate::Scope isolateScope(_v8Isolate); | 461 | v8::Isolate::Scope isolateScope(_v8Isolate); |
| 546 | v8::HandleScope handleScope(_v8Isolate); | 462 | v8::HandleScope handleScope(_v8Isolate); |
| @@ -550,11 +466,6 @@ void ScriptEngineV8::registerFunction(const QString& parent, const QString& name · 3 unmodified lines | |||
| 550 | ScriptValue scriptFun = newFunction(functionSignature, numArguments); | 466 | ScriptValue scriptFun = newFunction(functionSignature, numArguments); |
| 551 | object.setProperty(name, scriptFun); | 467 | object.setProperty(name, scriptFun); |
| 552 | } | 468 | } |
| 553 | /*} | ||
| 554 | if (is_isolate_exit_needed) { | ||
| 555 | _v8Isolate->Exit(); | ||
| 556 | _v8Locker.reset(nullptr); | ||
| 557 | }*/ | ||
| 558 | } | 469 | } |
| 559 | 470 | ||
| 560 | void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, | 471 | void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, |
| @@ -575,60 +486,17 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun · 14 unmodified lines | |||
| 575 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent; | 486 | qCDebug(scriptengine_v8) << "ScriptEngineV8::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent; |
| 576 | #endif | 487 | #endif |
| 577 | 488 | ||
| 578 | /*bool is_isolate_exit_needed = false; | ||
| 579 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { | ||
| 580 | // V8TODO: Theoretically only script thread should access this, so it should be safe | ||
| 581 | _v8Locker.reset(new v8::Locker(_v8Isolate)); | ||
| 582 | _v8Isolate->Enter(); | ||
| 583 | is_isolate_exit_needed = true; | ||
| 584 | } | ||
| 585 | {*/ | ||
| 586 | v8::Locker locker(_v8Isolate); | 489 | v8::Locker locker(_v8Isolate); |
| 587 | v8::Isolate::Scope isolateScope(_v8Isolate); | 490 | v8::Isolate::Scope isolateScope(_v8Isolate); |
| 588 | v8::HandleScope handleScope(_v8Isolate); | 491 | v8::HandleScope handleScope(_v8Isolate); |
| 589 | v8::Context::Scope contextScope(getContext()); | 492 | v8::Context::Scope contextScope(getContext()); |
| 590 | 493 | ||
| 591 | /*auto getterFunction = [](v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) { | ||
| 592 | //V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added? | ||
| 593 | v8::HandleScope handleScope(info.GetIsolate()); | ||
| 594 | auto context = info.GetIsolate()->GetCurrentContext(); | ||
| 595 | v8::Context::Scope contextScope(context); | ||
| 596 | auto object = v8::Local<v8::Object>::Cast(info.Data()); | ||
| 597 | Q_ASSERT(object->InternalFieldCount() == 2); | ||
| 598 | auto function = reinterpret_cast<ScriptEngine::FunctionSignature> | ||
| 599 | (object->GetAlignedPointerFromInternalField(0)); | ||
| 600 | ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*> | ||
| 601 | (object->GetAlignedPointerFromInternalField(1)); | ||
| 602 | ScriptContextV8Wrapper scriptContext(scriptEngine, &info); | ||
| 603 | //V8TODO: this scriptContext needs to have FunctionCallbackInfo added | ||
| 604 | ScriptValue result = function(&scriptContext, scriptEngine); | ||
| 605 | ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result); | ||
| 606 | info.GetReturnValue().Set(unwrapped->toV8Value().constGet()); | ||
| 607 | }; | ||
| 608 | auto setterFunction = [](v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) { | ||
| 609 | //V8TODO: is using GetCurrentContext ok, or context wrapper needs to be added? | ||
| 610 | v8::HandleScope handleScope(info.GetIsolate()); | ||
| 611 | auto context = info.GetIsolate()->GetCurrentContext(); | ||
| 612 | v8::Context::Scope contextScope(context); | ||
| 613 | auto object = v8::Local<v8::Object>::Cast(info.Data()); | ||
| 614 | Q_ASSERT(object->InternalFieldCount() == 2); | ||
| 615 | auto function = reinterpret_cast<ScriptEngine::FunctionSignature> | ||
| 616 | (object->GetAlignedPointerFromInternalField(0)); | ||
| 617 | ScriptEngineV8 *scriptEngine = reinterpret_cast<ScriptEngineV8*> | ||
| 618 | (object->GetAlignedPointerFromInternalField(1)); | ||
| 619 | ScriptContextV8Wrapper scriptContext(scriptEngine, &info); | ||
| 620 | //V8TODO: this scriptContext needs to have FunctionCallbackInfo added | ||
| 621 | ScriptValue result = function(&scriptContext, scriptEngine); | ||
| 622 | ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result); | ||
| 623 | };*/ | ||
| 624 | |||
| 625 | ScriptValue setterFunction = newFunction(setter, 1); | 494 | ScriptValue setterFunction = newFunction(setter, 1); |
| 626 | ScriptValue getterFunction = newFunction(getter); | 495 | ScriptValue getterFunction = newFunction(getter); |
| 627 | V8ScriptValue unwrappedGetter = ScriptValueV8Wrapper::fullUnwrap(this, getterFunction); | 496 | V8ScriptValue unwrappedGetter = ScriptValueV8Wrapper::fullUnwrap(this, getterFunction); |
| 628 | V8ScriptValue unwrappedSetter = ScriptValueV8Wrapper::fullUnwrap(this, setterFunction); | 497 | V8ScriptValue unwrappedSetter = ScriptValueV8Wrapper::fullUnwrap(this, setterFunction); |
| 629 | v8::PropertyDescriptor propertyDescriptor(unwrappedGetter.get(), unwrappedSetter.get()); | 498 | v8::PropertyDescriptor propertyDescriptor(unwrappedGetter.get(), unwrappedSetter.get()); |
| 630 | 499 | ||
| 631 | //V8TODO: Getters/setters are probably done in a different way in V8. Maybe object template is needed? | ||
| 632 | if (!parent.isNull() && !parent.isEmpty()) { | 500 | if (!parent.isNull() && !parent.isEmpty()) { |
| 633 | ScriptValue object = globalObject().property(parent); | 501 | ScriptValue object = globalObject().property(parent); |
| 634 | if (object.isValid()) { | 502 | if (object.isValid()) { |
| @@ -649,8 +517,6 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun · 14 unmodified lines | |||
| 649 | qCDebug(scriptengine_v8) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for parent: \"" | 517 | qCDebug(scriptengine_v8) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for parent: \"" |
| 650 | << parent << "\""; | 518 | << parent << "\""; |
| 651 | } | 519 | } |
| 652 | //object.setProperty(name, setterFunction, ScriptValue::PropertySetter); | ||
| 653 | //object.setProperty(name, getterFunction, ScriptValue::PropertyGetter); | ||
| 654 | } else { | 520 | } else { |
| 655 | qCDebug(scriptengine_v8) << "Parent object \"" << parent << "\" for registerGetterSetter \"" << name | 521 | qCDebug(scriptengine_v8) << "Parent object \"" << parent << "\" for registerGetterSetter \"" << name |
| 656 | << "\" is not valid: "; | 522 | << "\" is not valid: "; |
| @@ -661,14 +527,7 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun · 4 unmodified lines | |||
| 661 | if (!getContext()->Global()->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { | 527 | if (!getContext()->Global()->DefineProperty(getContext(), v8propertyName, propertyDescriptor).FromMaybe(false)) { |
| 662 | qCDebug(scriptengine_v8) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for global object"; | 528 | qCDebug(scriptengine_v8) << "DefineProperty failed for registerGetterSetter \"" << name << "\" for global object"; |
| 663 | } | 529 | } |
| 664 | //globalObject().setProperty(name, setterFunction, ScriptValue::PropertySetter); | ||
| 665 | //globalObject().setProperty(name, getterFunction, ScriptValue::PropertyGetter); | ||
| 666 | } | 530 | } |
| 667 | /*} | ||
| 668 | if (is_isolate_exit_needed) { | ||
| 669 | _v8Isolate->Exit(); | ||
| 670 | _v8Locker.reset(nullptr); | ||
| 671 | }*/ | ||
| 672 | } | 531 | } |
| 673 | 532 | ||
| 674 | v8::Local<v8::Context> ScriptEngineV8::getContext() { | 533 | v8::Local<v8::Context> ScriptEngineV8::getContext() { |
| @@ -721,11 +580,9 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 46 unmodified lines | |||
| 721 | storeGlobalObjectContents(); | 580 | storeGlobalObjectContents(); |
| 722 | 581 | ||
| 723 | v8::Local<v8::Object> closureObject; | 582 | v8::Local<v8::Object> closureObject; |
| 724 | //v8::Local<v8::Value> oldGlobal; | ||
| 725 | v8::Local<v8::Value> closureGlobal; | 583 | v8::Local<v8::Value> closureGlobal; |
| 726 | ScriptValueV8Wrapper* unwrappedClosure; | 584 | ScriptValueV8Wrapper* unwrappedClosure; |
| 727 | ScriptProgramV8Wrapper* unwrappedProgram; | 585 | ScriptProgramV8Wrapper* unwrappedProgram; |
| 728 | //v8::Local<v8::Context> oldContext = getContext(); | ||
| 729 | 586 | ||
| 730 | { | 587 | { |
| 731 | v8::Context::Scope contextScope(getContext()); | 588 | v8::Context::Scope contextScope(getContext()); |
| @@ -736,7 +593,6 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 4 unmodified lines | |||
| 736 | Q_ASSERT(false); | 593 | Q_ASSERT(false); |
| 737 | return nullValue(); | 594 | return nullValue(); |
| 738 | } | 595 | } |
| 739 | // V8TODO: is another context switch necessary after unwrapping closure? | ||
| 740 | 596 | ||
| 741 | const auto fileName = unwrappedProgram->fileName(); | 597 | const auto fileName = unwrappedProgram->fileName(); |
| 742 | const auto shortName = QUrl(fileName).fileName(); | 598 | const auto shortName = QUrl(fileName).fileName(); |
| @@ -750,7 +606,6 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 7 unmodified lines | |||
| 750 | } | 606 | } |
| 751 | 607 | ||
| 752 | const V8ScriptValue& closure = unwrappedClosure->toV8Value(); | 608 | const V8ScriptValue& closure = unwrappedClosure->toV8Value(); |
| 753 | //const V8ScriptProgram& program = unwrappedProgram->toV8Value(); | ||
| 754 | if (!closure.constGet()->IsObject()) { | 609 | if (!closure.constGet()->IsObject()) { |
| 755 | _evaluatingCounter--; | 610 | _evaluatingCounter--; |
| 756 | qCDebug(scriptengine_v8) << "Unwrapped closure is not an object"; | 611 | qCDebug(scriptengine_v8) << "Unwrapped closure is not an object"; |
| @@ -773,28 +628,13 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 16 unmodified lines | |||
| 773 | Q_ASSERT(false); | 628 | Q_ASSERT(false); |
| 774 | return nullValue(); | 629 | return nullValue(); |
| 775 | } | 630 | } |
| 776 | //qCDebug(scriptengine_v8) << "Closure global details:" << scriptValueDebugDetailsV8(V8ScriptValue(_v8Isolate, closureGlobal)); | ||
| 777 | } | 631 | } |
| 778 | //oldGlobal = _v8Context.Get(_v8Isolate)->Global(); | ||
| 779 | v8::Local<v8::Context> closureContext; | 632 | v8::Local<v8::Context> closureContext; |
| 780 | 633 | ||
| 781 | // V8TODO V8 cannot use arbitrary objects as global objects | ||
| 782 | /*if (closureGlobal->IsObject()) { | ||
| 783 | #ifdef DEBUG_JS | ||
| 784 | qCDebug(shared) << " setting global = closure.global" << shortName; | ||
| 785 | #endif | ||
| 786 | closureContext = v8::Context::New(_v8Isolate, nullptr, v8::Local<v8::ObjectTemplate>(), closureGlobal); | ||
| 787 | closureContext = v8::Context::New(_v8Isolate, nullptr, v8::Local<v8::ObjectTemplate>(), closureGlobal); | ||
| 788 | //setGlobalObject(global); | ||
| 789 | } else { | ||
| 790 | closureContext = v8::Context::New(_v8Isolate); | ||
| 791 | }*/ | ||
| 792 | closureContext = v8::Context::New(_v8Isolate); | 634 | closureContext = v8::Context::New(_v8Isolate); |
| 793 | pushContext(closureContext); | 635 | pushContext(closureContext); |
| 794 | 636 | ||
| 795 | ScriptValue result; | 637 | ScriptValue result; |
| 796 | //auto context = pushContext(); | ||
| 797 | |||
| 798 | // V8TODO: a lot of functions rely on _v8Context, which was not updated here | 638 | // V8TODO: a lot of functions rely on _v8Context, which was not updated here |
| 799 | // It might cause trouble | 639 | // It might cause trouble |
| 800 | { | 640 | { |
| @@ -809,27 +649,6 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 8 unmodified lines | |||
| 809 | const V8ScriptProgram& program = unwrappedProgram->toV8Value(); | 649 | const V8ScriptProgram& program = unwrappedProgram->toV8Value(); |
| 810 | 650 | ||
| 811 | v8::Local<v8::Value> thiz; | 651 | v8::Local<v8::Value> thiz; |
| 812 | // V8TODO: not sure if "this" is used at all here | ||
| 813 | /*if (!closureObject->Get(closure.constGetContext(), v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked()) | ||
| 814 | .ToLocal(&thiz)) { | ||
| 815 | _evaluatingCounter--; | ||
| 816 | qCDebug(scriptengine_v8) << "Empty this object in closure"; | ||
| 817 | Q_ASSERT(false); | ||
| 818 | return nullValue(); | ||
| 819 | }*/ | ||
| 820 | //thiz = closure.property("this"); | ||
| 821 | //qCDebug(scriptengine_v8) << "Closure this details:" << scriptValueDebugDetailsV8(V8ScriptValue(_v8Isolate, thiz)); | ||
| 822 | // V8TODO: | ||
| 823 | /*if (thiz->IsObject()) { | ||
| 824 | #ifdef DEBUG_JS | ||
| 825 | qCDebug(shared) << " setting this = closure.this" << shortName; | ||
| 826 | #endif | ||
| 827 | //V8TODO I don't know how to do this in V8, will adding "this" to global object work? | ||
| 828 | closureContext->Global()->Set(closureContext, v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked(), thiz); | ||
| 829 | //context->setThisObject(thiz); | ||
| 830 | }*/ | ||
| 831 | |||
| 832 | //context->pushScope(closure); | ||
| 833 | #ifdef DEBUG_JS | 652 | #ifdef DEBUG_JS |
| 834 | qCDebug(shared) << QString("[%1] evaluateInClosure %2").arg(isEvaluating()).arg(shortName); | 653 | qCDebug(shared) << QString("[%1] evaluateInClosure %2").arg(isEvaluating()).arg(shortName); |
| 835 | #endif | 654 | #endif |
| @@ -846,51 +665,22 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 10 unmodified lines | |||
| 846 | } | 665 | } |
| 847 | qCDebug(scriptengine_v8) << "ScriptEngineV8::evaluateInClosure: " << globalMemberNames->Length() << " objects added to global"; | 666 | qCDebug(scriptengine_v8) << "ScriptEngineV8::evaluateInClosure: " << globalMemberNames->Length() << " objects added to global"; |
| 848 | 667 | ||
| 849 | /*auto oldGlobalMemberNames = oldContext->Global()->GetPropertyNames(oldContext).ToLocalChecked(); | ||
| 850 | //auto oldGlobalMemberNames = oldContext->Global()->GetPropertyNames(closureContext).ToLocalChecked(); | ||
| 851 | for (size_t i = 0; i < oldGlobalMemberNames->Length(); i++) { | ||
| 852 | auto name = oldGlobalMemberNames->Get(closureContext, i).ToLocalChecked(); | ||
| 853 | //auto name = oldGlobalMemberNames->Get(oldContext, i).ToLocalChecked(); | ||
| 854 | if(!closureContext->Global()->Set(closureContext, name, oldContext->Global()->Get(oldContext, name).ToLocalChecked()).FromMaybe(false)) { | ||
| 855 | //if(!closureContext->Global()->Set(closureContext, name, oldContext->Global()->Get(closureContext, name).ToLocalChecked()).FromMaybe(false)) { | ||
| 856 | Q_ASSERT(false); | ||
| 857 | } | ||
| 858 | }*/ | ||
| 859 | // Objects from closure need to be copied to global object too | 668 | // Objects from closure need to be copied to global object too |
| 860 | // V8TODO: I'm not sure which context to use with Get | 669 | // V8TODO: I'm not sure which context to use with Get |
| 861 | auto closureMemberNames = closureObject->GetPropertyNames(closureContext).ToLocalChecked(); | 670 | auto closureMemberNames = closureObject->GetPropertyNames(closureContext).ToLocalChecked(); |
| 862 | //auto closureMemberNames = closureObject->GetPropertyNames(oldContext).ToLocalChecked(); | ||
| 863 | for (size_t i = 0; i < closureMemberNames->Length(); i++) { | 671 | for (size_t i = 0; i < closureMemberNames->Length(); i++) { |
| 864 | auto name = closureMemberNames->Get(closureContext, i).ToLocalChecked(); | 672 | auto name = closureMemberNames->Get(closureContext, i).ToLocalChecked(); |
| 865 | //auto name = closureMemberNames->Get(oldContext, i).ToLocalChecked(); | ||
| 866 | if(!closureContext->Global()->Set(closureContext, name, closureObject->Get(closureContext, name).ToLocalChecked()).FromMaybe(false)) { | 673 | if(!closureContext->Global()->Set(closureContext, name, closureObject->Get(closureContext, name).ToLocalChecked()).FromMaybe(false)) { |
| 867 | //if(!closureContext->Global()->Set(closureContext, name, closureObject->Get(oldContext, name).ToLocalChecked()).FromMaybe(false)) { | ||
| 868 | Q_ASSERT(false); | 674 | Q_ASSERT(false); |
| 869 | } | 675 | } |
| 870 | } | 676 | } |
| 871 | // List members of closure global object | ||
| 872 | //QString membersString(""); | ||
| 873 | /*if (closureContext->Global()->IsObject()) { | ||
| 874 | v8::Local<v8::String> membersStringV8; | ||
| 875 | v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(closureContext->Global()); | ||
| 876 | auto names = object->GetPropertyNames(closureContext).ToLocalChecked(); | ||
| 877 | if (v8::JSON::Stringify(closureContext, names).ToLocal(&membersStringV8)) { | ||
| 878 | membersString = QString(*v8::String::Utf8Value(_v8Isolate, membersStringV8)); | ||
| 879 | } | ||
| 880 | membersString = QString(*v8::String::Utf8Value(_v8Isolate, membersStringV8)); | ||
| 881 | } else { | ||
| 882 | membersString = QString(" Is not an object"); | ||
| 883 | }*/ | ||
| 884 | //qCDebug(scriptengine_v8) << "Closure global before run:" << membersString; | ||
| 885 | auto maybeResult = program.constGet()->GetUnboundScript()->BindToCurrentContext()->Run(closureContext); | 677 | auto maybeResult = program.constGet()->GetUnboundScript()->BindToCurrentContext()->Run(closureContext); |
| 886 | //qCDebug(scriptengine_v8) << "Closure after run:" << scriptValueDebugDetailsV8(closure); | ||
| 887 | v8::Local<v8::Value> v8Result; | 678 | v8::Local<v8::Value> v8Result; |
| 888 | if (!maybeResult.ToLocal(&v8Result)) { | 679 | if (!maybeResult.ToLocal(&v8Result)) { |
| 889 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); | 680 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); |
| 890 | QString errorMessage = QString(*utf8Value); | 681 | QString errorMessage = QString(*utf8Value); |
| 891 | qCWarning(scriptengine_v8) << __FUNCTION__ << "---------- hasCaught:" << errorMessage; | 682 | qCWarning(scriptengine_v8) << __FUNCTION__ << "---------- hasCaught:" << errorMessage; |
| 892 | qCWarning(scriptengine_v8) << __FUNCTION__ << "---------- tryCatch details:" << formatErrorMessageFromTryCatch(tryCatch); | 683 | qCWarning(scriptengine_v8) << __FUNCTION__ << "---------- tryCatch details:" << formatErrorMessageFromTryCatch(tryCatch); |
| 893 | //V8TODO: better error reporting | ||
| 894 | } | 684 | } |
| 895 | 685 | ||
| 896 | if (hasUncaughtException()) { | 686 | if (hasUncaughtException()) { |
| @@ -908,20 +698,12 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 11 unmodified lines | |||
| 908 | #endif | 698 | #endif |
| 909 | popContext(); | 699 | popContext(); |
| 910 | } | 700 | } |
| 911 | //This is probably unnecessary in V8 | ||
| 912 | /*if (oldGlobal.isValid()) { | ||
| 913 | #ifdef DEBUG_JS | ||
| 914 | qCDebug(shared) << " restoring global" << shortName; | ||
| 915 | #endif | ||
| 916 | setGlobalObject(oldGlobal); | ||
| 917 | }*/ | ||
| 918 | 701 | ||
| 919 | _evaluatingCounter--; | 702 | _evaluatingCounter--; |
| 920 | return result; | 703 | return result; |
| 921 | } | 704 | } |
| 922 | 705 | ||
| 923 | ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& fileName) { | 706 | ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& fileName) { |
| 924 | //V8TODO | ||
| 925 | 707 | ||
| 926 | if (QThread::currentThread() != thread()) { | 708 | if (QThread::currentThread() != thread()) { |
| 927 | ScriptValue result; | 709 | ScriptValue result; |
| @@ -936,7 +718,6 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f · 8 unmodified lines | |||
| 936 | return result; | 718 | return result; |
| 937 | } | 719 | } |
| 938 | // Compile and check syntax | 720 | // Compile and check syntax |
| 939 | // V8TODO: Could these all be replaced with checkSyntax function from wrapper? | ||
| 940 | Q_ASSERT(!_v8Isolate->IsDead()); | 721 | Q_ASSERT(!_v8Isolate->IsDead()); |
| 941 | _evaluatingCounter++; | 722 | _evaluatingCounter++; |
| 942 | v8::Locker locker(_v8Isolate); | 723 | v8::Locker locker(_v8Isolate); |
| @@ -953,26 +734,6 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f · 10 unmodified lines | |||
| 953 | return nullValue(); | 734 | return nullValue(); |
| 954 | } | 735 | } |
| 955 | } | 736 | } |
| 956 | //qCDebug(scriptengine_v8) << "Script compilation succesful: " << fileName; | ||
| 957 | |||
| 958 | //V8TODO | ||
| 959 | /*auto syntaxError = lintScript(sourceCode, fileName); | ||
| 960 | if (syntaxError.isError()) { | ||
| 961 | if (!isEvaluating()) { | ||
| 962 | syntaxError.setProperty("detail", "evaluate"); | ||
| 963 | } | ||
| 964 | raiseException(syntaxError); | ||
| 965 | maybeEmitUncaughtException("lint"); | ||
| 966 | return syntaxError; | ||
| 967 | }*/ | ||
| 968 | //V8TODO | ||
| 969 | /*if (script->IsNull()) { | ||
| 970 | // can this happen? | ||
| 971 | auto err = makeError(newValue("could not create V8ScriptProgram for " + fileName)); | ||
| 972 | raiseException(err); | ||
| 973 | maybeEmitUncaughtException("compile"); | ||
| 974 | return err; | ||
| 975 | }*/ | ||
| 976 | 737 | ||
| 977 | v8::Local<v8::Value> result; | 738 | v8::Local<v8::Value> result; |
| 978 | v8::TryCatch tryCatchRun(getIsolate()); | 739 | v8::TryCatch tryCatchRun(getIsolate()); |
| @@ -981,11 +742,6 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f · 2 unmodified lines | |||
| 981 | auto runError = tryCatchRun.Message(); | 742 | auto runError = tryCatchRun.Message(); |
| 982 | ScriptValue errorValue(new ScriptValueV8Wrapper(this, V8ScriptValue(this, runError->Get()))); | 743 | ScriptValue errorValue(new ScriptValueV8Wrapper(this, V8ScriptValue(this, runError->Get()))); |
| 983 | qCDebug(scriptengine_v8) << "Running script: \"" << fileName << "\" " << formatErrorMessageFromTryCatch(tryCatchRun); | 744 | qCDebug(scriptengine_v8) << "Running script: \"" << fileName << "\" " << formatErrorMessageFromTryCatch(tryCatchRun); |
| 984 | //V8TODO | ||
| 985 | |||
| 986 | |||
| 987 | //raiseException(errorValue); | ||
| 988 | //maybeEmitUncaughtException("evaluate"); | ||
| 989 | setUncaughtException(tryCatchRun, "script evaluation"); | 745 | setUncaughtException(tryCatchRun, "script evaluation"); |
| 990 | 746 | ||
| 991 | _evaluatingCounter--; | 747 | _evaluatingCounter--; |
| @@ -1020,7 +776,6 @@ void ScriptEngineV8::setUncaughtException(const v8::TryCatch &tryCatch, const QS · 28 unmodified lines | |||
| 1020 | 776 | ||
| 1021 | QString errorMessage = ""; | 777 | QString errorMessage = ""; |
| 1022 | QString errorBacktrace = ""; | 778 | QString errorBacktrace = ""; |
| 1023 | //v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); | ||
| 1024 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Message()->Get()); | 779 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Message()->Get()); |
| 1025 | 780 | ||
| 1026 | ex->errorMessage = QString(*utf8Value); | 781 | ex->errorMessage = QString(*utf8Value); |
| @@ -1068,7 +823,6 @@ QString ScriptEngineV8::formatErrorMessageFromTryCatch(v8::TryCatch &tryCatch) { · 41 unmodified lines | |||
| 1068 | int errorLineNumber = 0; | 823 | int errorLineNumber = 0; |
| 1069 | QString errorMessage = ""; | 824 | QString errorMessage = ""; |
| 1070 | QString errorBacktrace = ""; | 825 | QString errorBacktrace = ""; |
| 1071 | //v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); | ||
| 1072 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Message()->Get()); | 826 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Message()->Get()); |
| 1073 | errorMessage = QString(*utf8Value); | 827 | errorMessage = QString(*utf8Value); |
| 1074 | v8::Local<v8::Message> exceptionMessage = tryCatch.Message(); | 828 | v8::Local<v8::Message> exceptionMessage = tryCatch.Message(); |
| @@ -1181,13 +935,6 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro · 106 unmodified lines | |||
| 1181 | return result; | 935 | return result; |
| 1182 | } | 936 | } |
| 1183 | _evaluatingCounter++; | 937 | _evaluatingCounter++; |
| 1184 | /*bool is_isolate_exit_needed = false; | ||
| 1185 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { | ||
| 1186 | // V8TODO: Theoretically only script thread should access this, so it should be safe | ||
| 1187 | _v8Locker.reset(new v8::Locker(_v8Isolate)); | ||
| 1188 | _v8Isolate->Enter(); | ||
| 1189 | is_isolate_exit_needed = true; | ||
| 1190 | }*/ | ||
| 1191 | ScriptValue errorValue; | 938 | ScriptValue errorValue; |
| 1192 | ScriptValue resultValue; | 939 | ScriptValue resultValue; |
| 1193 | bool hasFailed = false; | 940 | bool hasFailed = false; |
| @@ -1213,14 +960,6 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro · 19 unmodified lines | |||
| 1213 | v8::Local<v8::Value> result; | 960 | v8::Local<v8::Value> result; |
| 1214 | if(!hasFailed) { | 961 | if(!hasFailed) { |
| 1215 | const V8ScriptProgram& v8Program = unwrapped->toV8Value(); | 962 | const V8ScriptProgram& v8Program = unwrapped->toV8Value(); |
| 1216 | // V8TODO | ||
| 1217 | /*if (qProgram.isNull()) { | ||
| 1218 | // can this happen? | ||
| 1219 | auto err = makeError(newValue("requested program is empty")); | ||
| 1220 | raiseException(err); | ||
| 1221 | maybeEmitUncaughtException("compile"); | ||
| 1222 | return err; | ||
| 1223 | }*/ | ||
| 1224 | 963 | ||
| 1225 | v8::TryCatch tryCatchRun(getIsolate()); | 964 | v8::TryCatch tryCatchRun(getIsolate()); |
| 1226 | if (!v8Program.constGet()->Run(getContext()).ToLocal(&result)) { | 965 | if (!v8Program.constGet()->Run(getContext()).ToLocal(&result)) { |
| @@ -1240,10 +979,6 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro · 13 unmodified lines | |||
| 1240 | } | 979 | } |
| 1241 | } | 980 | } |
| 1242 | _evaluatingCounter--; | 981 | _evaluatingCounter--; |
| 1243 | /*if (is_isolate_exit_needed) { | ||
| 1244 | _v8Isolate->Exit(); | ||
| 1245 | _v8Locker.reset(nullptr); | ||
| 1246 | }*/ | ||
| 1247 | if (hasFailed) { | 982 | if (hasFailed) { |
| 1248 | return errorValue; | 983 | return errorValue; |
| 1249 | } else { | 984 | } else { |
| @@ -1293,6 +1028,7 @@ ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) { · 43 unmodified lines | |||
| 1293 | std::shared_ptr<v8::BackingStore> backingStore(v8::ArrayBuffer::NewBackingStore(_v8Isolate, message.size())); | 1028 | std::shared_ptr<v8::BackingStore> backingStore(v8::ArrayBuffer::NewBackingStore(_v8Isolate, message.size())); |
| 1294 | std::memcpy(backingStore.get()->Data(), message.constData(), message.size()); | 1029 | std::memcpy(backingStore.get()->Data(), message.constData(), message.size()); |
| 1295 | auto arrayBuffer = v8::ArrayBuffer::New(_v8Isolate, backingStore); | 1030 | auto arrayBuffer = v8::ArrayBuffer::New(_v8Isolate, backingStore); |
| 1031 | //V8TODO: this needs to be finished and tested | ||
| 1296 | /*V8ScriptValue data = QScriptEngine::newVariant(QVariant::fromValue(message)); | 1032 | /*V8ScriptValue data = QScriptEngine::newVariant(QVariant::fromValue(message)); |
| 1297 | V8ScriptValue ctor = QScriptEngine::globalObject().property("ArrayBuffer"); | 1033 | V8ScriptValue ctor = QScriptEngine::globalObject().property("ArrayBuffer"); |
| 1298 | auto array = qscriptvalue_cast<ArrayBufferClass*>(ctor.data()); | 1034 | auto array = qscriptvalue_cast<ArrayBufferClass*>(ctor.data()); |
| @@ -1304,13 +1040,6 @@ ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) { · 5 unmodified lines | |||
| 1304 | } | 1040 | } |
| 1305 | 1041 | ||
| 1306 | ScriptValue ScriptEngineV8::newObject() { | 1042 | ScriptValue ScriptEngineV8::newObject() { |
| 1307 | /*bool is_isolate_exit_needed = false; | ||
| 1308 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { | ||
| 1309 | // V8TODO: Theoretically only script thread should access this, so it should be safe | ||
| 1310 | _v8Locker.reset(new v8::Locker(_v8Isolate)); | ||
| 1311 | _v8Isolate->Enter(); | ||
| 1312 | is_isolate_exit_needed = true; | ||
| 1313 | }*/ | ||
| 1314 | ScriptValue result; | 1043 | ScriptValue result; |
| 1315 | { | 1044 | { |
| 1316 | v8::Locker locker(_v8Isolate); | 1045 | v8::Locker locker(_v8Isolate); |
| @@ -1320,10 +1049,6 @@ ScriptValue ScriptEngineV8::newObject() { · 3 unmodified lines | |||
| 1320 | V8ScriptValue resultV8 = V8ScriptValue(this, v8::Object::New(_v8Isolate)); | 1049 | V8ScriptValue resultV8 = V8ScriptValue(this, v8::Object::New(_v8Isolate)); |
| 1321 | result = ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultV8))); | 1050 | result = ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultV8))); |
| 1322 | } | 1051 | } |
| 1323 | /*if (is_isolate_exit_needed) { | ||
| 1324 | _v8Isolate->Exit(); | ||
| 1325 | _v8Locker.reset(nullptr); | ||
| 1326 | }*/ | ||
| 1327 | return result; | 1052 | return result; |
| 1328 | } | 1053 | } |
| 1329 | 1054 | ||
| @@ -1338,10 +1063,6 @@ ScriptValue ScriptEngineV8::newMethod(QObject* object, V8ScriptValue lifetime, · 8 unmodified lines | |||
| 1338 | } | 1063 | } |
| 1339 | 1064 | ||
| 1340 | ScriptProgramPointer ScriptEngineV8::newProgram(const QString& sourceCode, const QString& fileName) { | 1065 | ScriptProgramPointer ScriptEngineV8::newProgram(const QString& sourceCode, const QString& fileName) { |
| 1341 | //V8TODO: is it used between isolates? | ||
| 1342 | //V8TODO: should it be compiled on creation? | ||
| 1343 | //V8ScriptProgram result(sourceCode, fileName); | ||
| 1344 | |||
| 1345 | v8::Locker locker(_v8Isolate); | 1066 | v8::Locker locker(_v8Isolate); |
| 1346 | v8::Isolate::Scope isolateScope(_v8Isolate); | 1067 | v8::Isolate::Scope isolateScope(_v8Isolate); |
| 1347 | v8::HandleScope handleScope(_v8Isolate); | 1068 | v8::HandleScope handleScope(_v8Isolate); |
| @@ -1453,20 +1174,8 @@ void ScriptEngineV8::clearExceptions() { · 105 unmodified lines | |||
| 1453 | } | 1174 | } |
| 1454 | 1175 | ||
| 1455 | ScriptContext* ScriptEngineV8::currentContext() const { | 1176 | ScriptContext* ScriptEngineV8::currentContext() const { |
| 1456 | //V8TODO | ||
| 1457 | /*V8ScriptContext* localCtx = QScriptEngine::currentContext(); | ||
| 1458 | if (!localCtx) { | ||
| 1459 | return nullptr; | ||
| 1460 | } | ||
| 1461 | if (!_currContext || _currContext->toV8Value() != localCtx) { | ||
| 1462 | _currContext = std::make_shared<ScriptContextV8Wrapper>(const_cast<ScriptEngineV8*>(this), localCtx); | ||
| 1463 | }*/ | ||
| 1464 | //_currContext = std::make_shared<ScriptContextV8Wrapper>(const_cast<ScriptEngineV8*>(this), localCtx); | ||
| 1465 | /*if (!_currContext) { | ||
| 1466 | // I'm not sure how to do this without discarding const | ||
| 1467 | _currContext = std::make_shared<ScriptContextV8Wrapper>(const_cast<ScriptEngineV8*>(this)); | ||
| 1468 | }*/ | ||
| 1469 | // V8TODO: add FunctionCallbackInfo or PropertyCallbackInfo when necessary | 1177 | // V8TODO: add FunctionCallbackInfo or PropertyCallbackInfo when necessary |
| 1178 | // Is it needed? | ||
| 1470 | return _contexts.last().get(); | 1179 | return _contexts.last().get(); |
| 1471 | } | 1180 | } |
| 1472 | 1181 | ||
| @@ -1482,16 +1191,6 @@ bool ScriptEngineV8::isEvaluating() const { · 9 unmodified lines | |||
| 1482 | 1191 | ||
| 1483 | ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int length) { | 1192 | ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int length) { |
| 1484 | //V8TODO is callee() used for anything? | 1193 | //V8TODO is callee() used for anything? |
| 1485 | /*auto innerFunc = [](V8ScriptContext* _context, QScriptEngine* _engine) -> V8ScriptValue { | ||
| 1486 | auto callee = _context->callee(); | ||
| 1487 | QVariant funAddr = callee.property("_func").toVariant(); | ||
| 1488 | ScriptEngine::FunctionSignature fun = reinterpret_cast<ScriptEngine::FunctionSignature>(funAddr.toULongLong()); | ||
| 1489 | ScriptEngineV8* engine = static_cast<ScriptEngineV8*>(_engine); | ||
| 1490 | ScriptContextV8Wrapper context(engine, _context); | ||
| 1491 | ScriptValue result = fun(&context, engine); | ||
| 1492 | ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(result); | ||
| 1493 | return unwrapped ? unwrapped->toV8Value() : V8ScriptValue(); | ||
| 1494 | };*/ | ||
| 1495 | 1194 | ||
| 1496 | v8::Locker locker(_v8Isolate); | 1195 | v8::Locker locker(_v8Isolate); |
| 1497 | v8::Isolate::Scope isolateScope(_v8Isolate); | 1196 | v8::Isolate::Scope isolateScope(_v8Isolate); |
| @@ -1518,23 +1217,12 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int · 20 unmodified lines | |||
| 1518 | info.GetReturnValue().Set(unwrapped->toV8Value().constGet()); | 1217 | info.GetReturnValue().Set(unwrapped->toV8Value().constGet()); |
| 1519 | } | 1218 | } |
| 1520 | }; | 1219 | }; |
| 1521 | //auto functionTemplate = v8::FunctionTemplate::New(_v8Isolate, v8FunctionCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), length); | ||
| 1522 | //auto functionData = v8::Object::New(_v8Isolate); | ||
| 1523 | //functionData->setIn | ||
| 1524 | auto functionDataTemplate = getFunctionDataTemplate(); | 1220 | auto functionDataTemplate = getFunctionDataTemplate(); |
| 1525 | //auto functionDataTemplate = v8::ObjectTemplate::New(_v8Isolate); | ||
| 1526 | //functionDataTemplate->SetInternalFieldCount(2); | ||
| 1527 | auto functionData = functionDataTemplate->NewInstance(getContext()).ToLocalChecked(); | 1221 | auto functionData = functionDataTemplate->NewInstance(getContext()).ToLocalChecked(); |
| 1528 | functionData->SetAlignedPointerInInternalField(0, reinterpret_cast<void*>(fun)); | 1222 | functionData->SetAlignedPointerInInternalField(0, reinterpret_cast<void*>(fun)); |
| 1529 | functionData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(this)); | 1223 | functionData->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(this)); |
| 1530 | //functionData->SetInternalField(3, v8::Null(_v8Isolate)); | ||
| 1531 | auto v8Function = v8::Function::New(getContext(), v8FunctionCallback, functionData, length).ToLocalChecked(); | 1224 | auto v8Function = v8::Function::New(getContext(), v8FunctionCallback, functionData, length).ToLocalChecked(); |
| 1532 | //auto functionObjectTemplate = functionTemplate->InstanceTemplate(); | 1225 | V8ScriptValue result(this, v8Function); |
| 1533 | //auto function = | ||
| 1534 | V8ScriptValue result(this, v8Function); // = QScriptEngine::newFunction(innerFunc, length); | ||
| 1535 | //auto funAddr = QScriptEngine::newVariant(QVariant(reinterpret_cast<qulonglong>(fun))); | ||
| 1536 | // V8TODO | ||
| 1537 | //result.setProperty("_func", funAddr, V8ScriptValue::PropertyFlags(V8ScriptValue::ReadOnly + V8ScriptValue::Undeletable + V8ScriptValue::SkipInEnumeration)); | ||
| 1538 | return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result))); | 1226 | return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result))); |
| 1539 | } | 1227 | } |
| 1540 | 1228 | ||
| @@ -1543,7 +1231,6 @@ void ScriptEngineV8::setObjectName(const QString& name) { · 2 unmodified lines | |||
| 1543 | QObject::setObjectName(name); | 1231 | QObject::setObjectName(name); |
| 1544 | } | 1232 | } |
| 1545 | 1233 | ||
| 1546 | //V8TODO | ||
| 1547 | bool ScriptEngineV8::setProperty(const char* name, const QVariant& value) { | 1234 | bool ScriptEngineV8::setProperty(const char* name, const QVariant& value) { |
| 1548 | v8::Locker locker(_v8Isolate); | 1235 | v8::Locker locker(_v8Isolate); |
| 1549 | v8::Isolate::Scope isolateScope(_v8Isolate); | 1236 | v8::Isolate::Scope isolateScope(_v8Isolate); |
| @@ -1570,24 +1257,10 @@ void ScriptEngineV8::setThread(QThread* thread) { · 20 unmodified lines | |||
| 1570 | qCDebug(scriptengine_v8) << "Script engine " << objectName() << " exited isolate"; | 1257 | qCDebug(scriptengine_v8) << "Script engine " << objectName() << " exited isolate"; |
| 1571 | } | 1258 | } |
| 1572 | Q_ASSERT(QObject::thread() == QThread::currentThread()); | 1259 | Q_ASSERT(QObject::thread() == QThread::currentThread()); |
| 1573 | /*if (_v8Locker) { | ||
| 1574 | _v8Locker.reset(); | ||
| 1575 | }*/ | ||
| 1576 | moveToThread(thread); | 1260 | moveToThread(thread); |
| 1577 | qCDebug(scriptengine_v8) << "Moved script engine " << objectName() << " to different thread"; | 1261 | qCDebug(scriptengine_v8) << "Moved script engine " << objectName() << " to different thread"; |
| 1578 | } | 1262 | } |
| 1579 | 1263 | ||
| 1580 | /*void ScriptEngineV8::enterIsolateOnThisThread() { | ||
| 1581 | Q_ASSERT(thread() == QThread::currentThread()); | ||
| 1582 | Q_ASSERT(!_v8Locker); | ||
| 1583 | _v8Locker.reset(new v8::Locker(_v8Isolate)); | ||
| 1584 | if (!_v8Isolate->IsCurrent()) { | ||
| 1585 | _v8Isolate->Enter(); | ||
| 1586 | qCDebug(scriptengine_v8) << "Script engine " << objectName() << " entered isolate on a new thread"; | ||
| 1587 | } | ||
| 1588 | }*/ | ||
| 1589 | |||
| 1590 | |||
| 1591 | std::shared_ptr<ScriptException> ScriptEngineV8::uncaughtException() const { | 1264 | std::shared_ptr<ScriptException> ScriptEngineV8::uncaughtException() const { |
| 1592 | if (_uncaughtException) { | 1265 | if (_uncaughtException) { |
| 1593 | return _uncaughtException->clone(); | 1266 | return _uncaughtException->clone(); |
| @@ -1601,8 +1274,7 @@ bool ScriptEngineV8::raiseException(const QString& error, const QString &reason) · 7 unmodified lines | |||
| 1601 | } | 1274 | } |
| 1602 | 1275 | ||
| 1603 | bool ScriptEngineV8::raiseException(const ScriptValue& exception, const QString &reason) { | 1276 | bool ScriptEngineV8::raiseException(const ScriptValue& exception, const QString &reason) { |
| 1604 | //V8TODO | 1277 | //V8TODO Im not sure how to finish these |
| 1605 | //Q_ASSERT(false); | ||
| 1606 | // qCCritical(scriptengine_v8) << "Script exception occurred: " << exception.toString(); | 1278 | // qCCritical(scriptengine_v8) << "Script exception occurred: " << exception.toString(); |
| 1607 | // ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(exception); | 1279 | // ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(exception); |
| 1608 | // V8ScriptValue qException = unwrapped ? unwrapped->toV8Value() : QScriptEngine::newVariant(exception.toVariant()); | 1280 | // V8ScriptValue qException = unwrapped ? unwrapped->toV8Value() : QScriptEngine::newVariant(exception.toVariant()); |
| @@ -1626,7 +1298,6 @@ bool ScriptEngineV8::raiseException(const V8ScriptValue& exception) { · 17 unmodified lines | |||
| 1626 | 1298 | ||
| 1627 | _v8Isolate->ThrowException(exception.constGet()); | 1299 | _v8Isolate->ThrowException(exception.constGet()); |
| 1628 | 1300 | ||
| 1629 | |||
| 1630 | /*if (QScriptEngine::currentContext()) { | 1301 | /*if (QScriptEngine::currentContext()) { |
| 1631 | // we have an active context / JS stack frame so throw the exception per usual | 1302 | // we have an active context / JS stack frame so throw the exception per usual |
| 1632 | QScriptEngine::currentContext()->throwValue(makeError(exception)); | 1303 | QScriptEngine::currentContext()->throwValue(makeError(exception)); |
| @@ -1741,15 +1412,6 @@ QString ScriptEngineV8::scriptValueDebugDetailsV8(const V8ScriptValue &v8Value) · 108 unmodified lines | |||
| 1741 | return parentValueQString + QString(" JSON: ") + JSONQString; | 1412 | return parentValueQString + QString(" JSON: ") + JSONQString; |
| 1742 | } | 1413 | } |
| 1743 | 1414 | ||
| 1744 | /*QStringList ScriptEngineV8::getCurrentStackTrace() { | ||
| 1745 | v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(_v8Isolate, 100); | ||
| 1746 | QStringList backtrace; | ||
| 1747 | for (int n = 0; n < stackTrace->GetFrameCount(); n++) { | ||
| 1748 | v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(_v8Isolate, n); | ||
| 1749 | |||
| 1750 | } | ||
| 1751 | }*/ | ||
| 1752 | |||
| 1753 | void ScriptEngineV8::logBacktrace(const QString &title) { | 1415 | void ScriptEngineV8::logBacktrace(const QString &title) { |
| 1754 | QStringList backtrace = currentContext()->backtrace(); | 1416 | QStringList backtrace = currentContext()->backtrace(); |
| 1755 | qCDebug(scriptengine_v8) << title; | 1417 | qCDebug(scriptengine_v8) << title; |