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