Showing the changes to libraries/script-engine/src/v8/ScriptEngineV8.cpp (1 of 8 files). Show all
Unified · Split
| @@ -113,6 +113,8 @@ ScriptValue ScriptEngineV8::makeError(const ScriptValue& _other, const QString& · 112 unmodified lines | ||
| 113 | 113 | if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { |
| 114 | 114 | return nullValue(); |
| 115 | 115 | } |
| 116 | + v8::Locker locker(_v8Isolate); | |
| 117 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 116 | 118 | v8::HandleScope handleScope(_v8Isolate); |
| 117 | 119 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 118 | 120 | return nullValue(); |
| @@ -138,6 +140,8 @@ ScriptValue ScriptEngineV8::checkScriptSyntax(ScriptProgramPointer program) { · 19 unmodified lines | ||
| 138 | 140 | if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { |
| 139 | 141 | return nullValue(); |
| 140 | 142 | } |
| 143 | + v8::Locker locker(_v8Isolate); | |
| 144 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 141 | 145 | v8::HandleScope handleScope(_v8Isolate); |
| 142 | 146 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 143 | 147 | ScriptSyntaxCheckResultPointer syntaxCheck = program->checkSyntax(); |
| @@ -194,6 +198,8 @@ ScriptValue ScriptEngineV8::cloneUncaughtException(const QString& extraDetail) { · 50 unmodified lines | ||
| 194 | 198 | if (!hasUncaughtException()) { |
| 195 | 199 | return nullValue(); |
| 196 | 200 | } |
| 201 | + v8::Locker locker(_v8Isolate); | |
| 202 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 197 | 203 | v8::HandleScope handleScope(_v8Isolate); |
| 198 | 204 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 199 | 205 | return nullValue(); |
| @@ -343,7 +349,8 @@ V8ScriptValue Lambda::call() { · 143 unmodified lines | ||
| 343 | 349 | |
| 344 | 350 | #ifdef DEBUG_JS |
| 345 | 351 | void ScriptEngineV8::_debugDump(const QString& header, const V8ScriptValue& object, const QString& footer) { |
| 346 | − if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { | |
| 352 | + // V8TODO | |
| 353 | + /*if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { | |
| 347 | 354 | return; |
| 348 | 355 | } |
| 349 | 356 | if (!header.isEmpty()) { |
| @@ -360,7 +367,7 @@ void ScriptEngineV8::_debugDump(const QString& header, const V8ScriptValue& obje · 10 unmodified lines | ||
| 360 | 367 | } |
| 361 | 368 | if (!footer.isEmpty()) { |
| 362 | 369 | qCDebug(shared) << footer; |
| 363 | − } | |
| 370 | + }*/ | |
| 364 | 371 | } |
| 365 | 372 | #endif |
| 366 | 373 | |
| @@ -370,7 +377,7 @@ v8::Platform* ScriptEngineV8::getV8Platform() { · 3 unmodified lines | ||
| 370 | 377 | } |
| 371 | 378 | |
| 372 | 379 | ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) : |
| 373 | − _scriptManager(scriptManager), _isEvaluating(false) | |
| 380 | + _scriptManager(scriptManager), _evaluatingCounter(0) | |
| 374 | 381 | //V8TODO |
| 375 | 382 | //_arrayBufferClass(new ArrayBufferClass(this)) |
| 376 | 383 | { |
| @@ -395,7 +402,8 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) : · 18 unmodified lines | ||
| 395 | 402 | v8::Isolate::CreateParams isolateParams; |
| 396 | 403 | isolateParams.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); |
| 397 | 404 | _v8Isolate = v8::Isolate::New(isolateParams); |
| 398 | − _v8Isolate->Enter(); | |
| 405 | + v8::Locker locker(_v8Isolate); | |
| 406 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 399 | 407 | v8::HandleScope handleScope(_v8Isolate); |
| 400 | 408 | v8::Local<v8::Context> context = v8::Context::New(_v8Isolate); |
| 401 | 409 | Q_ASSERT(!context.IsEmpty()); |
| @@ -447,6 +455,8 @@ void ScriptEngineV8::registerEnum(const QString& enumName, QMetaEnum newEnum) { · 45 unmodified lines | ||
| 447 | 455 | qCCritical(scriptengine) << "registerEnum called on invalid enum with name " << enumName; |
| 448 | 456 | return; |
| 449 | 457 | } |
| 458 | + v8::Locker locker(_v8Isolate); | |
| 459 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 450 | 460 | v8::HandleScope handleScope(_v8Isolate); |
| 451 | 461 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 452 | 462 | |
| @@ -467,6 +477,8 @@ void ScriptEngineV8::registerValue(const QString& valueName, V8ScriptValue value · 14 unmodified lines | ||
| 467 | 477 | Q_ARG(V8ScriptValue, value)); |
| 468 | 478 | return; |
| 469 | 479 | } |
| 480 | + v8::Locker locker(_v8Isolate); | |
| 481 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 470 | 482 | v8::HandleScope handleScope(_v8Isolate); |
| 471 | 483 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 472 | 484 | QStringList pathToValue = valueName.split("."); |
| @@ -514,34 +526,36 @@ void ScriptEngineV8::registerGlobalObject(const QString& name, QObject* object) · 41 unmodified lines | ||
| 514 | 526 | #ifdef THREAD_DEBUGGING |
| 515 | 527 | qCDebug(scriptengine) << "ScriptEngineV8::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name; |
| 516 | 528 | #endif |
| 517 | − bool is_isolate_exit_needed = false; | |
| 529 | + /*bool is_isolate_exit_needed = false; | |
| 518 | 530 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { |
| 519 | 531 | // V8TODO: Theoretically only script thread should access this, so it should be safe |
| 520 | 532 | _v8Locker.reset(new v8::Locker(_v8Isolate)); |
| 521 | 533 | _v8Isolate->Enter(); |
| 522 | 534 | is_isolate_exit_needed = true; |
| 523 | − } | |
| 524 | − { | |
| 525 | − v8::HandleScope handleScope(_v8Isolate); | |
| 526 | − Q_ASSERT(_v8Isolate->IsCurrent()); | |
| 527 | − v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 528 | − v8::Local<v8::Object> v8GlobalObject = getContext()->Global(); | |
| 529 | − v8::Local<v8::String> v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); | |
| 530 | − | |
| 531 | − // V8TODO: Is IsEmpty check enough or IsValid is needed too? | |
| 532 | − if (!v8GlobalObject->Get(getContext(), v8Name).IsEmpty()) { | |
| 533 | − if (object) { | |
| 534 | − V8ScriptValue value = ScriptObjectV8Proxy::newQObject(this, object, ScriptEngine::QtOwnership); | |
| 535 | − v8GlobalObject->Set(getContext(), v8Name, value.get()); | |
| 536 | − } else { | |
| 537 | − v8GlobalObject->Set(getContext(), v8Name, v8::Null(_v8Isolate)); | |
| 538 | − } | |
| 535 | + }*/ | |
| 536 | + //{ | |
| 537 | + v8::Locker locker(_v8Isolate); | |
| 538 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 539 | + v8::HandleScope handleScope(_v8Isolate); | |
| 540 | + Q_ASSERT(_v8Isolate->IsCurrent()); | |
| 541 | + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 542 | + v8::Local<v8::Object> v8GlobalObject = getContext()->Global(); | |
| 543 | + v8::Local<v8::String> v8Name = v8::String::NewFromUtf8(_v8Isolate, name.toStdString().c_str()).ToLocalChecked(); | |
| 544 | + | |
| 545 | + // V8TODO: Is IsEmpty check enough or IsValid is needed too? | |
| 546 | + if (!v8GlobalObject->Get(getContext(), v8Name).IsEmpty()) { | |
| 547 | + if (object) { | |
| 548 | + V8ScriptValue value = ScriptObjectV8Proxy::newQObject(this, object, ScriptEngine::QtOwnership); | |
| 549 | + v8GlobalObject->Set(getContext(), v8Name, value.get()); | |
| 550 | + } else { | |
| 551 | + v8GlobalObject->Set(getContext(), v8Name, v8::Null(_v8Isolate)); | |
| 539 | 552 | } |
| 540 | 553 | } |
| 541 | − if (is_isolate_exit_needed) { | |
| 554 | + //} | |
| 555 | + /*if (is_isolate_exit_needed) { | |
| 542 | 556 | _v8Isolate->Exit(); |
| 543 | 557 | _v8Locker.reset(nullptr); |
| 544 | − } | |
| 558 | + }*/ | |
| 545 | 559 | } |
| 546 | 560 | |
| 547 | 561 | void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { |
| @@ -561,26 +575,28 @@ void ScriptEngineV8::registerFunction(const QString& name, ScriptEngine::Functio · 13 unmodified lines | ||
| 561 | 575 | qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name; |
| 562 | 576 | #endif |
| 563 | 577 | |
| 564 | − bool is_isolate_exit_needed = false; | |
| 578 | + /*bool is_isolate_exit_needed = false; | |
| 565 | 579 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { |
| 566 | 580 | // V8TODO: Theoretically only script thread should access this, so it should be safe |
| 567 | 581 | _v8Locker.reset(new v8::Locker(_v8Isolate)); |
| 568 | 582 | _v8Isolate->Enter(); |
| 569 | 583 | is_isolate_exit_needed = true; |
| 570 | 584 | } |
| 571 | − { | |
| 585 | + {*/ | |
| 572 | 586 | //auto scriptFun = static_cast<ScriptValueV8Wrapper*>(newFunction(functionSignature, numArguments).ptr())->toV8Value().constGet(); |
| 573 | − v8::HandleScope handleScope(_v8Isolate); | |
| 574 | − v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 575 | − auto scriptFun = newFunction(functionSignature, numArguments); | |
| 587 | + v8::Locker locker(_v8Isolate); | |
| 588 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 589 | + v8::HandleScope handleScope(_v8Isolate); | |
| 590 | + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 591 | + auto scriptFun = newFunction(functionSignature, numArguments); | |
| 576 | 592 | |
| 577 | − //getContext()->Global().Set(); | |
| 578 | − globalObject().setProperty(name, scriptFun); | |
| 579 | − } | |
| 593 | + //getContext()->Global().Set(); | |
| 594 | + globalObject().setProperty(name, scriptFun); | |
| 595 | + /*} | |
| 580 | 596 | if (is_isolate_exit_needed) { |
| 581 | 597 | _v8Isolate->Exit(); |
| 582 | 598 | _v8Locker.reset(nullptr); |
| 583 | − } | |
| 599 | + }*/ | |
| 584 | 600 | } |
| 585 | 601 | |
| 586 | 602 | void ScriptEngineV8::registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) { |
| @@ -598,26 +614,28 @@ void ScriptEngineV8::registerFunction(const QString& parent, const QString& name · 11 unmodified lines | ||
| 598 | 614 | qCDebug(scriptengine) << "ScriptEngineV8::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name; |
| 599 | 615 | #endif |
| 600 | 616 | |
| 601 | − bool is_isolate_exit_needed = false; | |
| 617 | + /*bool is_isolate_exit_needed = false; | |
| 602 | 618 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { |
| 603 | 619 | // V8TODO: Theoretically only script thread should access this, so it should be safe |
| 604 | 620 | _v8Locker.reset(new v8::Locker(_v8Isolate)); |
| 605 | 621 | _v8Isolate->Enter(); |
| 606 | 622 | is_isolate_exit_needed = true; |
| 607 | 623 | } |
| 608 | − { | |
| 609 | − v8::HandleScope handleScope(_v8Isolate); | |
| 610 | − v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 611 | − ScriptValue object = globalObject().property(parent); | |
| 612 | − if (object.isValid()) { | |
| 613 | − ScriptValue scriptFun = newFunction(functionSignature, numArguments); | |
| 614 | − object.setProperty(name, scriptFun); | |
| 615 | − } | |
| 624 | + {*/ | |
| 625 | + v8::Locker locker(_v8Isolate); | |
| 626 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 627 | + v8::HandleScope handleScope(_v8Isolate); | |
| 628 | + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 629 | + ScriptValue object = globalObject().property(parent); | |
| 630 | + if (object.isValid()) { | |
| 631 | + ScriptValue scriptFun = newFunction(functionSignature, numArguments); | |
| 632 | + object.setProperty(name, scriptFun); | |
| 616 | 633 | } |
| 634 | + /*} | |
| 617 | 635 | if (is_isolate_exit_needed) { |
| 618 | 636 | _v8Isolate->Exit(); |
| 619 | 637 | _v8Locker.reset(nullptr); |
| 620 | − } | |
| 638 | + }*/ | |
| 621 | 639 | } |
| 622 | 640 | |
| 623 | 641 | void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, |
| @@ -638,14 +656,16 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun · 14 unmodified lines | ||
| 638 | 656 | qCDebug(scriptengine) << "ScriptEngineV8::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent; |
| 639 | 657 | #endif |
| 640 | 658 | |
| 641 | − bool is_isolate_exit_needed = false; | |
| 659 | + /*bool is_isolate_exit_needed = false; | |
| 642 | 660 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { |
| 643 | 661 | // V8TODO: Theoretically only script thread should access this, so it should be safe |
| 644 | 662 | _v8Locker.reset(new v8::Locker(_v8Isolate)); |
| 645 | 663 | _v8Isolate->Enter(); |
| 646 | 664 | is_isolate_exit_needed = true; |
| 647 | 665 | } |
| 648 | − { | |
| 666 | + {*/ | |
| 667 | + v8::Locker locker(_v8Isolate); | |
| 668 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 649 | 669 | v8::HandleScope handleScope(_v8Isolate); |
| 650 | 670 | v8::Context::Scope contextScope(getContext()); |
| 651 | 671 | |
| @@ -717,11 +737,11 @@ void ScriptEngineV8::registerGetterSetter(const QString& name, ScriptEngine::Fun · 65 unmodified lines | ||
| 717 | 737 | //globalObject().setProperty(name, setterFunction, ScriptValue::PropertySetter); |
| 718 | 738 | //globalObject().setProperty(name, getterFunction, ScriptValue::PropertyGetter); |
| 719 | 739 | } |
| 720 | − } | |
| 740 | + /*} | |
| 721 | 741 | if (is_isolate_exit_needed) { |
| 722 | 742 | _v8Isolate->Exit(); |
| 723 | 743 | _v8Locker.reset(nullptr); |
| 724 | − } | |
| 744 | + }*/ | |
| 725 | 745 | } |
| 726 | 746 | |
| 727 | 747 | ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, |
| @@ -730,42 +750,59 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 2 unmodified lines | ||
| 730 | 750 | if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) { |
| 731 | 751 | return nullValue(); |
| 732 | 752 | } |
| 733 | − Q_ASSERT(!isEvaluating()); | |
| 734 | − _isEvaluating = true; | |
| 753 | + _evaluatingCounter++; | |
| 754 | + v8::Locker locker(_v8Isolate); | |
| 755 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 735 | 756 | v8::HandleScope handleScope(_v8Isolate); |
| 736 | − v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 737 | − ScriptProgramV8Wrapper* unwrappedProgram = ScriptProgramV8Wrapper::unwrap(_program); | |
| 738 | − if (unwrappedProgram == nullptr) { | |
| 739 | − _isEvaluating = false; | |
| 740 | − return nullValue(); | |
| 741 | − } | |
| 742 | − const V8ScriptProgram& program = unwrappedProgram->toV8Value(); | |
| 743 | 757 | |
| 744 | − const auto fileName = unwrappedProgram->fileName(); | |
| 745 | − const auto shortName = QUrl(fileName).fileName(); | |
| 758 | + v8::Local<v8::Object> closureObject; | |
| 759 | + //v8::Local<v8::Value> oldGlobal; | |
| 760 | + v8::Local<v8::Value> closureGlobal; | |
| 761 | + ScriptValueV8Wrapper* unwrappedClosure; | |
| 762 | + ScriptProgramV8Wrapper* unwrappedProgram; | |
| 746 | 763 | |
| 747 | − ScriptValueV8Wrapper* unwrappedClosure = ScriptValueV8Wrapper::unwrap(_closure); | |
| 748 | − if (unwrappedClosure == nullptr) { | |
| 749 | − _isEvaluating = false; | |
| 750 | − return nullValue(); | |
| 751 | − } | |
| 752 | − const V8ScriptValue& closure = unwrappedClosure->toV8Value(); | |
| 753 | − if (!closure.constGet()->IsObject()) { | |
| 754 | − _isEvaluating = false; | |
| 755 | − return nullValue(); | |
| 756 | − } | |
| 757 | − const v8::Local<v8::Object> closureObject = v8::Local<v8::Object>::Cast(closure.constGet()); | |
| 764 | + { | |
| 765 | + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 766 | + unwrappedProgram = ScriptProgramV8Wrapper::unwrap(_program); | |
| 767 | + if (unwrappedProgram == nullptr) { | |
| 768 | + _evaluatingCounter--; | |
| 769 | + qDebug(scriptengine) << "Cannot unwrap program for closure"; | |
| 770 | + Q_ASSERT(false); | |
| 771 | + return nullValue(); | |
| 772 | + } | |
| 773 | + // V8TODO: is another context switch necessary after unwrapping closure? | |
| 758 | 774 | |
| 759 | − v8::Local<v8::Value> oldGlobal; | |
| 760 | − v8::Local<v8::Value> closureGlobal; | |
| 761 | − if (!closureObject->Get(closure.constGetContext() ,v8::String::NewFromUtf8(_v8Isolate, "global").ToLocalChecked()).ToLocal(&closureGlobal)) { | |
| 762 | − _isEvaluating = false; | |
| 763 | − return nullValue(); | |
| 764 | − } | |
| 775 | + const auto fileName = unwrappedProgram->fileName(); | |
| 776 | + const auto shortName = QUrl(fileName).fileName(); | |
| 765 | 777 | |
| 766 | − _v8Context.Get(_v8Isolate)->Exit(); | |
| 767 | − _v8Context.Get(_v8Isolate)->DetachGlobal(); | |
| 768 | − oldGlobal = _v8Context.Get(_v8Isolate)->Global(); | |
| 778 | + unwrappedClosure = ScriptValueV8Wrapper::unwrap(_closure); | |
| 779 | + if (unwrappedClosure == nullptr) { | |
| 780 | + _evaluatingCounter--; | |
| 781 | + qDebug(scriptengine) << "Cannot unwrap closure"; | |
| 782 | + Q_ASSERT(false); | |
| 783 | + return nullValue(); | |
| 784 | + } | |
| 785 | + | |
| 786 | + const V8ScriptValue& closure = unwrappedClosure->toV8Value(); | |
| 787 | + const V8ScriptProgram& program = unwrappedProgram->toV8Value(); | |
| 788 | + if (!closure.constGet()->IsObject()) { | |
| 789 | + _evaluatingCounter--; | |
| 790 | + qDebug(scriptengine) << "Unwrapped closure is not an object"; | |
| 791 | + Q_ASSERT(false); | |
| 792 | + return nullValue(); | |
| 793 | + } | |
| 794 | + closureObject = v8::Local<v8::Object>::Cast(closure.constGet()); | |
| 795 | + | |
| 796 | + if (!closureObject->Get(closure.constGetContext(), v8::String::NewFromUtf8(_v8Isolate, "global").ToLocalChecked()) | |
| 797 | + .ToLocal(&closureGlobal)) { | |
| 798 | + _evaluatingCounter--; | |
| 799 | + qDebug(scriptengine) << "Cannot get global from unwrapped closure"; | |
| 800 | + Q_ASSERT(false); | |
| 801 | + return nullValue(); | |
| 802 | + } | |
| 803 | + } | |
| 804 | + //_v8Context.Get(_v8Isolate)->DetachGlobal(); | |
| 805 | + //oldGlobal = _v8Context.Get(_v8Isolate)->Global(); | |
| 769 | 806 | v8::Local<v8::Context> closureContext; |
| 770 | 807 | |
| 771 | 808 | if (closureGlobal->IsObject()) { |
| @@ -775,61 +812,71 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 3 unmodified lines | ||
| 775 | 812 | closureContext = v8::Context::New(_v8Isolate, nullptr, v8::Local<v8::ObjectTemplate>(), closureGlobal); |
| 776 | 813 | //setGlobalObject(global); |
| 777 | 814 | } else { |
| 778 | − closureContext = v8::Context::New(_v8Isolate, nullptr, v8::Local<v8::ObjectTemplate>(), oldGlobal); | |
| 815 | + closureContext = v8::Context::New(_v8Isolate); | |
| 779 | 816 | } |
| 780 | 817 | |
| 818 | + ScriptValue result; | |
| 781 | 819 | //auto context = pushContext(); |
| 782 | − | |
| 783 | − v8::Local<v8::Value> thiz; | |
| 784 | − // V8TODO: not sure if "this" doesn't exist or is empty in some cases | |
| 785 | − if (!closureObject->Get(closure.constGetContext() ,v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked()).ToLocal(&thiz)) { | |
| 786 | − _isEvaluating = false; | |
| 787 | − return nullValue(); | |
| 788 | − } | |
| 789 | − //thiz = closure.property("this"); | |
| 790 | − if (thiz->IsObject()) { | |
| 820 | + { | |
| 821 | + v8::Context::Scope contextScope(closureContext); | |
| 822 | + const V8ScriptValue& closure = unwrappedClosure->toV8Value(); | |
| 823 | + if (!unwrappedProgram->compile()) { | |
| 824 | + qDebug(scriptengine) << "Can't compile script for evaluating in closure"; | |
| 825 | + Q_ASSERT(false); | |
| 826 | + return nullValue(); | |
| 827 | + } | |
| 828 | + const V8ScriptProgram& program = unwrappedProgram->toV8Value(); | |
| 829 | + | |
| 830 | + v8::Local<v8::Value> thiz; | |
| 831 | + // V8TODO: not sure if "this" doesn't exist or is empty in some cases | |
| 832 | + if (!closureObject->Get(closure.constGetContext(), v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked()) | |
| 833 | + .ToLocal(&thiz)) { | |
| 834 | + _evaluatingCounter--; | |
| 835 | + qDebug(scriptengine) << "Empty this object in closure"; | |
| 836 | + Q_ASSERT(false); | |
| 837 | + return nullValue(); | |
| 838 | + } | |
| 839 | + //thiz = closure.property("this"); | |
| 840 | + if (thiz->IsObject()) { | |
| 791 | 841 | #ifdef DEBUG_JS |
| 792 | − qCDebug(shared) << " setting this = closure.this" << shortName; | |
| 842 | + qCDebug(shared) << " setting this = closure.this" << shortName; | |
| 793 | 843 | #endif |
| 794 | − //V8TODO I don't know how to do this in V8, will adding "this" to global object work? | |
| 795 | − closureContext->Global()->Set(closureContext, v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked(), thiz); | |
| 796 | − //context->setThisObject(thiz); | |
| 797 | − } | |
| 844 | + //V8TODO I don't know how to do this in V8, will adding "this" to global object work? | |
| 845 | + closureContext->Global()->Set(closureContext, v8::String::NewFromUtf8(_v8Isolate, "this").ToLocalChecked(), thiz); | |
| 846 | + //context->setThisObject(thiz); | |
| 847 | + } | |
| 798 | 848 | |
| 799 | − //context->pushScope(closure); | |
| 849 | + //context->pushScope(closure); | |
| 800 | 850 | #ifdef DEBUG_JS |
| 801 | − qCDebug(shared) << QString("[%1] evaluateInClosure %2").arg(isEvaluating()).arg(shortName); | |
| 851 | + qCDebug(shared) << QString("[%1] evaluateInClosure %2").arg(isEvaluating()).arg(shortName); | |
| 802 | 852 | #endif |
| 803 | − ScriptValue result; | |
| 804 | − { | |
| 805 | − v8::TryCatch tryCatch(getIsolate()); | |
| 806 | − auto maybeResult = program.constGet()->Run(closureContext); | |
| 807 | − v8::Local<v8::Value> v8Result; | |
| 808 | − if (!maybeResult.ToLocal(&v8Result)) { | |
| 809 | − v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); | |
| 810 | − QString errorMessage = QString(*utf8Value); | |
| 811 | − qWarning() << __FUNCTION__ << "---------- hasCaught:" << errorMessage; | |
| 812 | − //V8TODO: better error reporting | |
| 813 | − } | |
| 853 | + { | |
| 854 | + v8::TryCatch tryCatch(getIsolate()); | |
| 855 | + auto maybeResult = program.constGet()->Run(closureContext); | |
| 856 | + v8::Local<v8::Value> v8Result; | |
| 857 | + if (!maybeResult.ToLocal(&v8Result)) { | |
| 858 | + v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); | |
| 859 | + QString errorMessage = QString(*utf8Value); | |
| 860 | + qWarning(scriptengine) << __FUNCTION__ << "---------- hasCaught:" << errorMessage; | |
| 861 | + //V8TODO: better error reporting | |
| 862 | + } | |
| 814 | 863 | |
| 815 | − if (hasUncaughtException()) { | |
| 816 | − auto err = cloneUncaughtException(__FUNCTION__); | |
| 864 | + if (hasUncaughtException()) { | |
| 865 | + auto err = cloneUncaughtException(__FUNCTION__); | |
| 817 | 866 | #ifdef DEBUG_JS_EXCEPTIONS |
| 818 | − qCWarning(shared) << __FUNCTION__ << "---------- hasCaught:" << err.toString() << result.toString(); | |
| 819 | − err.setProperty("_result", result); | |
| 867 | + qCWarning(shared) << __FUNCTION__ << "---------- hasCaught:" << err.toString() << result.toString(); | |
| 868 | + err.setProperty("_result", result); | |
| 820 | 869 | #endif |
| 821 | − result = err; | |
| 822 | − } else { | |
| 823 | − result = ScriptValue(new ScriptValueV8Wrapper(this, V8ScriptValue(_v8Isolate, v8Result))); | |
| 870 | + result = err; | |
| 871 | + } else { | |
| 872 | + result = ScriptValue(new ScriptValueV8Wrapper(this, V8ScriptValue(_v8Isolate, v8Result))); | |
| 873 | + } | |
| 824 | 874 | } |
| 825 | − } | |
| 826 | 875 | #ifdef DEBUG_JS |
| 827 | − qCDebug(shared) << QString("[%1] //evaluateInClosure %2").arg(isEvaluating()).arg(shortName); | |
| 876 | + qCDebug(shared) << QString("[%1] //evaluateInClosure %2").arg(isEvaluating()).arg(shortName); | |
| 828 | 877 | #endif |
| 829 | − //popContext(); | |
| 830 | − closureContext->Exit(); | |
| 831 | − _v8Context.Get(_v8Isolate)->Enter(); | |
| 832 | − | |
| 878 | + //popContext(); | |
| 879 | + } | |
| 833 | 880 | //This is probably unnecessary in V8 |
| 834 | 881 | /*if (oldGlobal.isValid()) { |
| 835 | 882 | #ifdef DEBUG_JS |
| @@ -838,8 +885,8 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 2 unmodified lines | ||
| 838 | 885 | setGlobalObject(oldGlobal); |
| 839 | 886 | }*/ |
| 840 | 887 | |
| 841 | − //_v8Context.Get(_v8Isolate)->Enter(); | |
| 842 | − _isEvaluating = false; | |
| 888 | + closureContext->DetachGlobal(); | |
| 889 | + _evaluatingCounter--; | |
| 843 | 890 | return result; |
| 844 | 891 | } |
| 845 | 892 | |
| @@ -865,8 +912,9 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f · 19 unmodified lines | ||
| 865 | 912 | // Compile and check syntax |
| 866 | 913 | // V8TODO: Could these all be replaced with checkSyntax function from wrapper? |
| 867 | 914 | Q_ASSERT(!_v8Isolate->IsDead()); |
| 868 | − Q_ASSERT(!isEvaluating()); | |
| 869 | − _isEvaluating = true; | |
| 915 | + _evaluatingCounter++; | |
| 916 | + v8::Locker locker(_v8Isolate); | |
| 917 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 870 | 918 | v8::HandleScope handleScope(_v8Isolate); |
| 871 | 919 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 872 | 920 | v8::TryCatch tryCatch(getIsolate()); |
| @@ -896,7 +944,7 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f · 23 unmodified lines | ||
| 896 | 944 | auto err = makeError(newValue(errorMessage)); |
| 897 | 945 | raiseException(err); |
| 898 | 946 | maybeEmitUncaughtException("compile"); |
| 899 | − _isEvaluating = false; | |
| 947 | + _evaluatingCounter--; | |
| 900 | 948 | return err; |
| 901 | 949 | } |
| 902 | 950 | qCDebug(scriptengine) << "Script compilation succesful: " << fileName; |
| @@ -930,11 +978,11 @@ ScriptValue ScriptEngineV8::evaluate(const QString& sourceCode, const QString& f · 27 unmodified lines | ||
| 930 | 978 | //V8TODO |
| 931 | 979 | //raiseException(errorValue); |
| 932 | 980 | //maybeEmitUncaughtException("evaluate"); |
| 933 | − _isEvaluating = false; | |
| 981 | + _evaluatingCounter--; | |
| 934 | 982 | return errorValue; |
| 935 | 983 | } |
| 936 | 984 | V8ScriptValue resultValue(_v8Isolate, result); |
| 937 | − _isEvaluating = false; | |
| 985 | + _evaluatingCounter--; | |
| 938 | 986 | return ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultValue))); |
| 939 | 987 | } |
| 940 | 988 | |
| @@ -979,19 +1027,20 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro · 38 unmodified lines | ||
| 979 | 1027 | Q_ARG(const ScriptProgramPointer&, program)); |
| 980 | 1028 | return result; |
| 981 | 1029 | } |
| 982 | − Q_ASSERT(!isEvaluating()); | |
| 983 | − _isEvaluating = true; | |
| 984 | − bool is_isolate_exit_needed = false; | |
| 1030 | + _evaluatingCounter++; | |
| 1031 | + /*bool is_isolate_exit_needed = false; | |
| 985 | 1032 | if(!_v8Isolate->IsCurrent() && !_v8Locker) { |
| 986 | 1033 | // V8TODO: Theoretically only script thread should access this, so it should be safe |
| 987 | 1034 | _v8Locker.reset(new v8::Locker(_v8Isolate)); |
| 988 | 1035 | _v8Isolate->Enter(); |
| 989 | 1036 | is_isolate_exit_needed = true; |
| 990 | − } | |
| 1037 | + }*/ | |
| 991 | 1038 | ScriptValue errorValue; |
| 992 | 1039 | ScriptValue resultValue; |
| 993 | 1040 | bool hasFailed = false; |
| 994 | 1041 | { |
| 1042 | + v8::Locker locker(_v8Isolate); | |
| 1043 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 995 | 1044 | v8::HandleScope handleScope(_v8Isolate); |
| 996 | 1045 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 997 | 1046 | ScriptProgramV8Wrapper* unwrapped = ScriptProgramV8Wrapper::unwrap(program); |
| @@ -1039,11 +1088,11 @@ Q_INVOKABLE ScriptValue ScriptEngineV8::evaluate(const ScriptProgramPointer& pro · 41 unmodified lines | ||
| 1039 | 1088 | resultValue = ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultValueV8))); |
| 1040 | 1089 | } |
| 1041 | 1090 | } |
| 1042 | − _isEvaluating = false; | |
| 1043 | − if (is_isolate_exit_needed) { | |
| 1091 | + _evaluatingCounter--; | |
| 1092 | + /*if (is_isolate_exit_needed) { | |
| 1044 | 1093 | _v8Isolate->Exit(); |
| 1045 | 1094 | _v8Locker.reset(nullptr); |
| 1046 | − } | |
| 1095 | + }*/ | |
| 1047 | 1096 | if (hasFailed) { |
| 1048 | 1097 | return errorValue; |
| 1049 | 1098 | } else { |
| @@ -1066,6 +1115,8 @@ void ScriptEngineV8::updateMemoryCost(const qint64& deltaSize) { · 16 unmodified lines | ||
| 1066 | 1115 | // ScriptEngine implementation |
| 1067 | 1116 | |
| 1068 | 1117 | ScriptValue ScriptEngineV8::globalObject() const { |
| 1118 | + v8::Locker locker(_v8Isolate); | |
| 1119 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1069 | 1120 | v8::HandleScope handleScope(_v8Isolate); |
| 1070 | 1121 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1071 | 1122 | V8ScriptValue global(_v8Isolate, getConstContext()->Global());// = QScriptEngine::globalObject(); // can't cache the value as it may change |
| @@ -1077,6 +1128,8 @@ ScriptManager* ScriptEngineV8::manager() const { · 5 unmodified lines | ||
| 1077 | 1128 | } |
| 1078 | 1129 | |
| 1079 | 1130 | ScriptValue ScriptEngineV8::newArray(uint length) { |
| 1131 | + v8::Locker locker(_v8Isolate); | |
| 1132 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1080 | 1133 | v8::HandleScope handleScope(_v8Isolate); |
| 1081 | 1134 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1082 | 1135 | V8ScriptValue result(_v8Isolate, v8::Array::New(_v8Isolate, static_cast<int>(length))); |
| @@ -1084,6 +1137,8 @@ ScriptValue ScriptEngineV8::newArray(uint length) { · 1 unmodified line | ||
| 1084 | 1137 | } |
| 1085 | 1138 | |
| 1086 | 1139 | ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) { |
| 1140 | + v8::Locker locker(_v8Isolate); | |
| 1141 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1087 | 1142 | v8::HandleScope handleScope(_v8Isolate); |
| 1088 | 1143 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1089 | 1144 | //V8TODO: this will leak memory |
| @@ -1101,14 +1156,33 @@ ScriptValue ScriptEngineV8::newArrayBuffer(const QByteArray& message) { · 11 unmodified lines | ||
| 1101 | 1156 | } |
| 1102 | 1157 | |
| 1103 | 1158 | ScriptValue ScriptEngineV8::newObject() { |
| 1104 | − v8::HandleScope handleScope(_v8Isolate); | |
| 1105 | − v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 1106 | − V8ScriptValue result(_v8Isolate, v8::Object::New(_v8Isolate)); | |
| 1107 | − return ScriptValue(new ScriptValueV8Wrapper(this, std::move(result))); | |
| 1159 | + /*bool is_isolate_exit_needed = false; | |
| 1160 | + if(!_v8Isolate->IsCurrent() && !_v8Locker) { | |
| 1161 | + // V8TODO: Theoretically only script thread should access this, so it should be safe | |
| 1162 | + _v8Locker.reset(new v8::Locker(_v8Isolate)); | |
| 1163 | + _v8Isolate->Enter(); | |
| 1164 | + is_isolate_exit_needed = true; | |
| 1165 | + }*/ | |
| 1166 | + ScriptValue result; | |
| 1167 | + { | |
| 1168 | + v8::Locker locker(_v8Isolate); | |
| 1169 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1170 | + v8::HandleScope handleScope(_v8Isolate); | |
| 1171 | + v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); | |
| 1172 | + V8ScriptValue resultV8 = V8ScriptValue(_v8Isolate, v8::Object::New(_v8Isolate)); | |
| 1173 | + result = ScriptValue(new ScriptValueV8Wrapper(this, std::move(resultV8))); | |
| 1174 | + } | |
| 1175 | + /*if (is_isolate_exit_needed) { | |
| 1176 | + _v8Isolate->Exit(); | |
| 1177 | + _v8Locker.reset(nullptr); | |
| 1178 | + }*/ | |
| 1179 | + return result; | |
| 1108 | 1180 | } |
| 1109 | 1181 | |
| 1110 | 1182 | ScriptValue ScriptEngineV8::newMethod(QObject* object, V8ScriptValue lifetime, |
| 1111 | 1183 | const QList<QMetaMethod>& metas, int numMaxParams) { |
| 1184 | + v8::Locker locker(_v8Isolate); | |
| 1185 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1112 | 1186 | v8::HandleScope handleScope(_v8Isolate); |
| 1113 | 1187 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1114 | 1188 | V8ScriptValue result(ScriptMethodV8Proxy::newMethod(this, object, lifetime, metas, numMaxParams)); |
| @@ -1120,6 +1194,8 @@ ScriptProgramPointer ScriptEngineV8::newProgram(const QString& sourceCode, const · 5 unmodified lines | ||
| 1120 | 1194 | //V8TODO: should it be compiled on creation? |
| 1121 | 1195 | //V8ScriptProgram result(sourceCode, fileName); |
| 1122 | 1196 | |
| 1197 | + v8::Locker locker(_v8Isolate); | |
| 1198 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1123 | 1199 | v8::HandleScope handleScope(_v8Isolate); |
| 1124 | 1200 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1125 | 1201 | return std::make_shared<ScriptProgramV8Wrapper>(this, sourceCode, fileName); |
| @@ -1128,6 +1204,8 @@ ScriptProgramPointer ScriptEngineV8::newProgram(const QString& sourceCode, const · 2 unmodified lines | ||
| 1128 | 1204 | ScriptValue ScriptEngineV8::newQObject(QObject* object, |
| 1129 | 1205 | ScriptEngine::ValueOwnership ownership, |
| 1130 | 1206 | const ScriptEngine::QObjectWrapOptions& options) { |
| 1207 | + v8::Locker locker(_v8Isolate); | |
| 1208 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1131 | 1209 | v8::HandleScope handleScope(_v8Isolate); |
| 1132 | 1210 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1133 | 1211 | V8ScriptValue result = ScriptObjectV8Proxy::newQObject(this, object, ownership, options); |
| @@ -1135,6 +1213,8 @@ ScriptValue ScriptEngineV8::newQObject(QObject* object, · 1 unmodified line | ||
| 1135 | 1213 | } |
| 1136 | 1214 | |
| 1137 | 1215 | ScriptValue ScriptEngineV8::newValue(bool value) { |
| 1216 | + v8::Locker locker(_v8Isolate); | |
| 1217 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1138 | 1218 | v8::HandleScope handleScope(_v8Isolate); |
| 1139 | 1219 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1140 | 1220 | V8ScriptValue result(_v8Isolate, v8::Boolean::New(_v8Isolate, value)); |
| @@ -1142,6 +1222,8 @@ ScriptValue ScriptEngineV8::newValue(bool value) { · 1 unmodified line | ||
| 1142 | 1222 | } |
| 1143 | 1223 | |
| 1144 | 1224 | ScriptValue ScriptEngineV8::newValue(int value) { |
| 1225 | + v8::Locker locker(_v8Isolate); | |
| 1226 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1145 | 1227 | v8::HandleScope handleScope(_v8Isolate); |
| 1146 | 1228 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1147 | 1229 | V8ScriptValue result(_v8Isolate, v8::Integer::New(_v8Isolate, value)); |
| @@ -1149,6 +1231,8 @@ ScriptValue ScriptEngineV8::newValue(int value) { · 1 unmodified line | ||
| 1149 | 1231 | } |
| 1150 | 1232 | |
| 1151 | 1233 | ScriptValue ScriptEngineV8::newValue(uint value) { |
| 1234 | + v8::Locker locker(_v8Isolate); | |
| 1235 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1152 | 1236 | v8::HandleScope handleScope(_v8Isolate); |
| 1153 | 1237 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1154 | 1238 | V8ScriptValue result(_v8Isolate, v8::Uint32::New(_v8Isolate, value)); |
| @@ -1156,6 +1240,8 @@ ScriptValue ScriptEngineV8::newValue(uint value) { · 1 unmodified line | ||
| 1156 | 1240 | } |
| 1157 | 1241 | |
| 1158 | 1242 | ScriptValue ScriptEngineV8::newValue(double value) { |
| 1243 | + v8::Locker locker(_v8Isolate); | |
| 1244 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1159 | 1245 | v8::HandleScope handleScope(_v8Isolate); |
| 1160 | 1246 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1161 | 1247 | V8ScriptValue result(_v8Isolate, v8::Number::New(_v8Isolate, value)); |
| @@ -1163,6 +1249,8 @@ ScriptValue ScriptEngineV8::newValue(double value) { · 1 unmodified line | ||
| 1163 | 1249 | } |
| 1164 | 1250 | |
| 1165 | 1251 | ScriptValue ScriptEngineV8::newValue(const QString& value) { |
| 1252 | + v8::Locker locker(_v8Isolate); | |
| 1253 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1166 | 1254 | v8::HandleScope handleScope(_v8Isolate); |
| 1167 | 1255 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1168 | 1256 | v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.toStdString().c_str(), v8::NewStringType::kNormal).ToLocalChecked(); |
| @@ -1171,6 +1259,8 @@ ScriptValue ScriptEngineV8::newValue(const QString& value) { · 2 unmodified lines | ||
| 1171 | 1259 | } |
| 1172 | 1260 | |
| 1173 | 1261 | ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) { |
| 1262 | + v8::Locker locker(_v8Isolate); | |
| 1263 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1174 | 1264 | v8::HandleScope handleScope(_v8Isolate); |
| 1175 | 1265 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1176 | 1266 | v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value.latin1(), v8::NewStringType::kNormal).ToLocalChecked(); |
| @@ -1179,6 +1269,8 @@ ScriptValue ScriptEngineV8::newValue(const QLatin1String& value) { · 2 unmodified lines | ||
| 1179 | 1269 | } |
| 1180 | 1270 | |
| 1181 | 1271 | ScriptValue ScriptEngineV8::newValue(const char* value) { |
| 1272 | + v8::Locker locker(_v8Isolate); | |
| 1273 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1182 | 1274 | v8::HandleScope handleScope(_v8Isolate); |
| 1183 | 1275 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1184 | 1276 | v8::Local<v8::String> valueV8 = v8::String::NewFromUtf8(_v8Isolate, value, v8::NewStringType::kNormal).ToLocalChecked(); |
| @@ -1187,6 +1279,8 @@ ScriptValue ScriptEngineV8::newValue(const char* value) { · 2 unmodified lines | ||
| 1187 | 1279 | } |
| 1188 | 1280 | |
| 1189 | 1281 | ScriptValue ScriptEngineV8::newVariant(const QVariant& value) { |
| 1282 | + v8::Locker locker(_v8Isolate); | |
| 1283 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1190 | 1284 | v8::HandleScope handleScope(_v8Isolate); |
| 1191 | 1285 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1192 | 1286 | V8ScriptValue result = castVariantToValue(value); |
| @@ -1236,7 +1330,7 @@ bool ScriptEngineV8::hasUncaughtException() const { · 43 unmodified lines | ||
| 1236 | 1330 | |
| 1237 | 1331 | bool ScriptEngineV8::isEvaluating() const { |
| 1238 | 1332 | //return QScriptEngine::isEvaluating(); |
| 1239 | − return _isEvaluating; | |
| 1333 | + return _evaluatingCounter > 0; | |
| 1240 | 1334 | return false; |
| 1241 | 1335 | } |
| 1242 | 1336 | |
| @@ -1274,6 +1368,8 @@ ScriptValue ScriptEngineV8::newFunction(ScriptEngine::FunctionSignature fun, int · 31 unmodified lines | ||
| 1274 | 1368 | //auto functionTemplate = v8::FunctionTemplate::New(_v8Isolate, v8FunctionCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), length); |
| 1275 | 1369 | //auto functionData = v8::Object::New(_v8Isolate); |
| 1276 | 1370 | //functionData->setIn |
| 1371 | + v8::Locker locker(_v8Isolate); | |
| 1372 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1277 | 1373 | v8::HandleScope handleScope(_v8Isolate); |
| 1278 | 1374 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1279 | 1375 | auto functionDataTemplate = v8::ObjectTemplate::New(_v8Isolate); |
| @@ -1299,6 +1395,8 @@ void ScriptEngineV8::setObjectName(const QString& name) { · 19 unmodified lines | ||
| 1299 | 1395 | |
| 1300 | 1396 | //V8TODO |
| 1301 | 1397 | bool ScriptEngineV8::setProperty(const char* name, const QVariant& value) { |
| 1398 | + v8::Locker locker(_v8Isolate); | |
| 1399 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1302 | 1400 | v8::HandleScope handleScope(_v8Isolate); |
| 1303 | 1401 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1304 | 1402 | v8::Local<v8::Object> global = getContext()->Global(); |
| @@ -1322,14 +1420,14 @@ void ScriptEngineV8::setThread(QThread* thread) { · 17 unmodified lines | ||
| 1322 | 1420 | qDebug() << "Script engine " << objectName() << " exited isolate"; |
| 1323 | 1421 | } |
| 1324 | 1422 | Q_ASSERT(QObject::thread() == QThread::currentThread()); |
| 1325 | − if (_v8Locker) { | |
| 1423 | + /*if (_v8Locker) { | |
| 1326 | 1424 | _v8Locker.reset(); |
| 1327 | − } | |
| 1425 | + }*/ | |
| 1328 | 1426 | moveToThread(thread); |
| 1329 | 1427 | qDebug() << "Moved script engine " << objectName() << " to different thread"; |
| 1330 | 1428 | } |
| 1331 | 1429 | |
| 1332 | −void ScriptEngineV8::enterIsolateOnThisThread() { | |
| 1430 | +/*void ScriptEngineV8::enterIsolateOnThisThread() { | |
| 1333 | 1431 | Q_ASSERT(thread() == QThread::currentThread()); |
| 1334 | 1432 | Q_ASSERT(!_v8Locker); |
| 1335 | 1433 | _v8Locker.reset(new v8::Locker(_v8Isolate)); |
| @@ -1337,7 +1435,7 @@ void ScriptEngineV8::enterIsolateOnThisThread() { · 1 unmodified line | ||
| 1337 | 1435 | _v8Isolate->Enter(); |
| 1338 | 1436 | qDebug() << "Script engine " << objectName() << " entered isolate on a new thread"; |
| 1339 | 1437 | } |
| 1340 | −} | |
| 1438 | +}*/ | |
| 1341 | 1439 | |
| 1342 | 1440 | |
| 1343 | 1441 | ScriptValue ScriptEngineV8::uncaughtException() const { |
| @@ -1367,6 +1465,8 @@ bool ScriptEngineV8::raiseException(const ScriptValue& exception) { · 23 unmodified lines | ||
| 1367 | 1465 | } |
| 1368 | 1466 | |
| 1369 | 1467 | ScriptValue ScriptEngineV8::create(int type, const void* ptr) { |
| 1468 | + v8::Locker locker(_v8Isolate); | |
| 1469 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1370 | 1470 | v8::HandleScope handleScope(_v8Isolate); |
| 1371 | 1471 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1372 | 1472 | QVariant variant(type, ptr); |
| @@ -1375,6 +1475,8 @@ ScriptValue ScriptEngineV8::create(int type, const void* ptr) { · 2 unmodified lines | ||
| 1375 | 1475 | } |
| 1376 | 1476 | |
| 1377 | 1477 | QVariant ScriptEngineV8::convert(const ScriptValue& value, int typeId) { |
| 1478 | + v8::Locker locker(_v8Isolate); | |
| 1479 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1378 | 1480 | v8::HandleScope handleScope(_v8Isolate); |
| 1379 | 1481 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1380 | 1482 | ScriptValueV8Wrapper* unwrapped = ScriptValueV8Wrapper::unwrap(value); |
| @@ -1397,20 +1499,44 @@ QVariant ScriptEngineV8::convert(const ScriptValue& value, int typeId) { · 16 unmodified lines | ||
| 1397 | 1499 | } |
| 1398 | 1500 | |
| 1399 | 1501 | void ScriptEngineV8::compileTest() { |
| 1400 | − //v8::Locker locker(_v8Isolate); | |
| 1401 | − //v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1502 | + v8::Locker locker(_v8Isolate); | |
| 1503 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1402 | 1504 | v8::HandleScope handleScope(_v8Isolate); |
| 1403 | 1505 | v8::Context::Scope contextScope(_v8Context.Get(_v8Isolate)); |
| 1404 | 1506 | v8::Local<v8::Script> script; |
| 1405 | 1507 | v8::ScriptOrigin scriptOrigin(getIsolate(), v8::String::NewFromUtf8(getIsolate(),"test").ToLocalChecked()); |
| 1406 | 1508 | if (v8::Script::Compile(getContext(), v8::String::NewFromUtf8(getIsolate(), "print(\"hello world\");").ToLocalChecked(), &scriptOrigin).ToLocal(&script)) { |
| 1407 | − qCDebug(scriptengine) << "Compile test succesful"; | |
| 1509 | + qCDebug(scriptengine) << "Compile test successful"; | |
| 1408 | 1510 | } else { |
| 1409 | 1511 | qCDebug(scriptengine) << "Compile test failed"; |
| 1410 | 1512 | Q_ASSERT(false); |
| 1411 | 1513 | } |
| 1412 | 1514 | } |
| 1413 | 1515 | |
| 1516 | +QString ScriptEngineV8::scriptValueDebugDetails(ScriptValue &value) { | |
| 1517 | + V8ScriptValue v8Value = ScriptValueV8Wrapper::fullUnwrap(this, value); | |
| 1518 | + return scriptValueDebugDetailsV8(v8Value); | |
| 1519 | +} | |
| 1520 | + | |
| 1521 | +QString ScriptEngineV8::scriptValueDebugDetailsV8(const V8ScriptValue &v8Value) { | |
| 1522 | + v8::Locker locker(_v8Isolate); | |
| 1523 | + v8::Isolate::Scope isolateScope(_v8Isolate); | |
| 1524 | + v8::HandleScope handleScope(_v8Isolate); | |
| 1525 | + v8::Context::Scope contextScope(getContext()); | |
| 1526 | + | |
| 1527 | + QString parentValueQString(""); | |
| 1528 | + v8::Local<v8::String> parentValueString; | |
| 1529 | + if (v8Value.constGet()->ToDetailString(getContext()).ToLocal(&parentValueString)) { | |
| 1530 | + parentValueQString = QString(*v8::String::Utf8Value(_v8Isolate, parentValueString)); | |
| 1531 | + } | |
| 1532 | + QString JSONQString; | |
| 1533 | + v8::Local<v8::String> JSONString; | |
| 1534 | + if (v8::JSON::Stringify(getContext(), v8Value.constGet()).ToLocal(&JSONString)) { | |
| 1535 | + JSONQString = QString(*v8::String::Utf8Value(_v8Isolate, JSONString)); | |
| 1536 | + } | |
| 1537 | + return parentValueQString + QString(" JSON: ") + JSONQString; | |
| 1538 | +} | |
| 1539 | + | |
| 1414 | 1540 | /*QStringList ScriptEngineV8::getCurrentStackTrace() { |
| 1415 | 1541 | v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(_v8Isolate, 100); |
| 1416 | 1542 | QStringList backtrace; |