Showing the changes to libraries/script-engine/src/v8/ScriptEngineV8.cpp (1 of 1 file). Show all
Unified · Split
| @@ -625,6 +625,9 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 624 unmodified lines | |||
| 625 | qCDebug(shared) << QString("[%1] evaluateInClosure %2").arg(isEvaluating()).arg(shortName); | 625 | qCDebug(shared) << QString("[%1] evaluateInClosure %2").arg(isEvaluating()).arg(shortName); |
| 626 | #endif | 626 | #endif |
| 627 | { | 627 | { |
| 628 | ScriptContextV8Wrapper scriptContext(this, getContext(), currentContext()->parentContext()); | ||
| 629 | ScriptContextGuard scriptContextGuard(&scriptContext); | ||
| 630 | |||
| 628 | v8::TryCatch tryCatch(getIsolate()); | 631 | v8::TryCatch tryCatch(getIsolate()); |
| 629 | // Since V8 cannot use arbitrary object as global object, objects from main global need to be copied to closure's global object | 632 | // Since V8 cannot use arbitrary object as global object, objects from main global need to be copied to closure's global object |
| 630 | auto globalObjectContents = _globalObjectContents.Get(_v8Isolate); | 633 | auto globalObjectContents = _globalObjectContents.Get(_v8Isolate); |
| @@ -649,12 +652,77 @@ ScriptValue ScriptEngineV8::evaluateInClosure(const ScriptValue& _closure, · 18 unmodified lines | |||
| 649 | // "Script" API is context-dependent, so it needs to be recreated for each new context | 652 | // "Script" API is context-dependent, so it needs to be recreated for each new context |
| 650 | registerGlobalObject("Script", new ScriptManagerScriptingInterface(_manager), ScriptEngine::ScriptOwnership); | 653 | registerGlobalObject("Script", new ScriptManagerScriptingInterface(_manager), ScriptEngine::ScriptOwnership); |
| 651 | 654 | ||
| 655 | // Script.require properties need to be copied, since that's where the Script.require cache is | ||
| 656 | // Get source and destination Script.require objects | ||
| 657 | try { | ||
| 658 | v8::Local<v8::Value> oldScriptObjectValue; | ||
| 659 | if (!globalObjectContents | ||
| 660 | ->Get(closureContext, v8::String::NewFromUtf8(_v8Isolate, "Script").ToLocalChecked()) | ||
| 661 | .ToLocal(&oldScriptObjectValue)) { | ||
| 662 | throw(QString("evaluateInClosure: Script API object does not exist in calling script")); | ||
| 663 | } | ||
| 664 | if (!oldScriptObjectValue->IsObject()) { | ||
| 665 | throw(QString("evaluateInClosure: Script API object invalid in calling script")); | ||
| 666 | } | ||
| 667 | v8::Local<v8::Object> oldScriptObject = v8::Local<v8::Object>::Cast(oldScriptObjectValue); | ||
| 668 | |||
| 669 | v8::Local<v8::Value> oldRequireObjectValue; | ||
| 670 | if (!oldScriptObject->Get(closureContext, v8::String::NewFromUtf8(_v8Isolate, "require").ToLocalChecked()) | ||
| 671 | .ToLocal(&oldRequireObjectValue)) { | ||
| 672 | throw(QString("evaluateInClosure: Script.require API object does not exist in calling script")); | ||
| 673 | } | ||
| 674 | if (!oldRequireObjectValue->IsObject()) { | ||
| 675 | throw(QString("evaluateInClosure: Script.require API object invalid in calling script")); | ||
| 676 | } | ||
| 677 | v8::Local<v8::Object> oldRequireObject = v8::Local<v8::Object>::Cast(oldRequireObjectValue); | ||
| 678 | |||
| 679 | v8::Local<v8::Value> newScriptObjectValue; | ||
| 680 | if (!closureContext->Global() | ||
| 681 | ->Get(closureContext, v8::String::NewFromUtf8(_v8Isolate, "Script").ToLocalChecked()) | ||
| 682 | .ToLocal(&newScriptObjectValue)) { | ||
| 683 | Q_ASSERT(false); // This should never happen | ||
| 684 | } | ||
| 685 | if (!newScriptObjectValue->IsObject()) { | ||
| 686 | Q_ASSERT(false); // This should never happen | ||
| 687 | } | ||
| 688 | v8::Local<v8::Object> newScriptObject = v8::Local<v8::Object>::Cast(newScriptObjectValue); | ||
| 689 | |||
| 690 | v8::Local<v8::Value> newRequireObjectValue; | ||
| 691 | if (!newScriptObject->Get(closureContext, v8::String::NewFromUtf8(_v8Isolate, "require").ToLocalChecked()) | ||
| 692 | .ToLocal(&newRequireObjectValue)) { | ||
| 693 | Q_ASSERT(false); // This should never happen | ||
| 694 | } | ||
| 695 | if (!newRequireObjectValue->IsObject()) { | ||
| 696 | Q_ASSERT(false); // This should never happen | ||
| 697 | } | ||
| 698 | v8::Local<v8::Object> newRequireObject = v8::Local<v8::Object>::Cast(newRequireObjectValue); | ||
| 699 | |||
| 700 | auto requireMemberNames = | ||
| 701 | oldRequireObject->GetPropertyNames(oldRequireObject->CreationContext()).ToLocalChecked(); | ||
| 702 | for (size_t i = 0; i < requireMemberNames->Length(); i++) { | ||
| 703 | auto name = requireMemberNames->Get(closureContext, i).ToLocalChecked(); | ||
| 704 | v8::Local<v8::Value> oldObject; | ||
| 705 | if (!oldRequireObject->Get(oldRequireObject->CreationContext(), name).ToLocal(&oldObject)) { | ||
| 706 | Q_ASSERT(false); // This should never happen, the property has been reported as existing | ||
| 707 | } | ||
| 708 | if (!newRequireObject->Set(closureContext, name,oldObject).FromMaybe(false)) { | ||
| 709 | Q_ASSERT(false); | ||
| 710 | } | ||
| 711 | } | ||
| 712 | } catch (QString exception) { | ||
| 713 | raiseException(exception); | ||
| 714 | popContext(); | ||
| 715 | _evaluatingCounter--; | ||
| 716 | return nullValue(); | ||
| 717 | } | ||
| 718 | |||
| 652 | auto maybeResult = program.constGet()->GetUnboundScript()->BindToCurrentContext()->Run(closureContext); | 719 | auto maybeResult = program.constGet()->GetUnboundScript()->BindToCurrentContext()->Run(closureContext); |
| 653 | v8::Local<v8::Value> v8Result; | 720 | v8::Local<v8::Value> v8Result; |
| 654 | if (!maybeResult.ToLocal(&v8Result)) { | 721 | if (!maybeResult.ToLocal(&v8Result)) { |
| 655 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); | 722 | v8::String::Utf8Value utf8Value(getIsolate(), tryCatch.Exception()); |
| 656 | QString errorMessage = QString(__FUNCTION__) + " hasCaught:" + QString(*utf8Value) + "\n" | 723 | QString errorMessage = QString(__FUNCTION__) + " hasCaught:" + QString(*utf8Value) + "\n" |
| 657 | + "tryCatch details:" + formatErrorMessageFromTryCatch(tryCatch); | 724 | + "tryCatch details:" + formatErrorMessageFromTryCatch(tryCatch); |
| 725 | v8Result = v8::Null(_v8Isolate); | ||
| 658 | if (_manager) { | 726 | if (_manager) { |
| 659 | _manager->scriptErrorMessage(errorMessage); | 727 | _manager->scriptErrorMessage(errorMessage); |
| 660 | } else { | 728 | } else { |