Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 1 file). Show all
Unified · Split
| @@ -1361,28 +1361,22 @@ void ScriptEngine::print(const QString& message) { · 1360 unmodified lines | ||
| 1361 | 1361 | QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& relativeTo) { |
| 1362 | 1362 | QUrl defaultScriptsLoc = defaultScriptsLocation(); |
| 1363 | 1363 | QUrl url(moduleId); |
| 1364 | + ExceptionEmitter tryCatcher(this, __FUNCTION__); | |
| 1364 | 1365 | |
| 1365 | − // helper to generate an exception and return a null string | |
| 1366 | − auto resolverException = [=](const QString& detail, const QString& type = "Error") -> QString { | |
| 1367 | − auto displayId = moduleId; | |
| 1368 | − if (displayId.length() > MAX_DEBUG_VALUE_LENGTH) { | |
| 1369 | − displayId = displayId.mid(0, MAX_DEBUG_VALUE_LENGTH) + "..."; | |
| 1370 | − } | |
| 1371 | − currentContext()->throwValue(makeError( | |
| 1372 | − QString("Cannot find module '%1' (%2)") | |
| 1373 | − .arg(displayId) | |
| 1374 | − .arg(detail), type)); | |
| 1375 | − return QString(); | |
| 1376 | − }; | |
| 1366 | + auto displayId = moduleId; | |
| 1367 | + if (displayId.length() > MAX_DEBUG_VALUE_LENGTH) { | |
| 1368 | + displayId = displayId.mid(0, MAX_DEBUG_VALUE_LENGTH) + "..."; | |
| 1369 | + } | |
| 1370 | + auto message = QString("Cannot find module '%1' (%2)").arg(displayId); | |
| 1371 | + auto ctx = currentContext(); | |
| 1377 | 1372 | |
| 1378 | 1373 | // de-fuzz the input a little by restricting to rational sizes |
| 1379 | 1374 | auto idLength = url.toString().length(); |
| 1380 | 1375 | if (idLength < 1 || idLength > MAX_MODULE_ID_LENTGH) { |
| 1381 | − return resolverException( | |
| 1382 | − QString("rejecting invalid module id size (%1 chars [1,%2])") | |
| 1383 | − .arg(idLength).arg(MAX_MODULE_ID_LENTGH), | |
| 1384 | − "RangeError" | |
| 1385 | − ); | |
| 1376 | + auto details = QString("rejecting invalid module id size (%1 chars [1,%2])") | |
| 1377 | + .arg(idLength).arg(MAX_MODULE_ID_LENTGH); | |
| 1378 | + ctx->throwValue(makeError(message.arg(details), "RangeError")); | |
| 1379 | + return nullptr; | |
| 1386 | 1380 | } |
| 1387 | 1381 | |
| 1388 | 1382 | // this regex matches: absolute, dotted or path-like URLs |
| @@ -1402,12 +1396,14 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re · 13 unmodified lines | ||
| 1402 | 1396 | url = defaultScriptsLoc; |
| 1403 | 1397 | url.setPath(systemModulePath); |
| 1404 | 1398 | if (!QFileInfo(url.toLocalFile()).isFile()) { |
| 1405 | − return resolverException("system module not found"); | |
| 1399 | + ctx->throwValue(makeError(message.arg("system module not found"))); | |
| 1400 | + return nullptr; | |
| 1406 | 1401 | } |
| 1407 | 1402 | } |
| 1408 | 1403 | |
| 1409 | 1404 | if (url.isRelative()) { |
| 1410 | − return resolverException("could not resolve module id"); | |
| 1405 | + ctx->throwValue(makeError(message.arg("could not resolve module id"))); | |
| 1406 | + return nullptr; | |
| 1411 | 1407 | } |
| 1412 | 1408 | |
| 1413 | 1409 | // if it looks like a local file, verify that it's an allowed path and really a file |
| @@ -1420,18 +1416,21 @@ QString ScriptEngine::_requireResolve(const QString& moduleId, const QString& re · 6 unmodified lines | ||
| 1420 | 1416 | |
| 1421 | 1417 | bool disallowOutsideFiles = !defaultScriptsLocation().isParentOf(canonical) && !currentSandboxURL.isLocalFile(); |
| 1422 | 1418 | if (disallowOutsideFiles && !PathUtils::isDescendantOf(canonical, currentSandboxURL)) { |
| 1423 | − return resolverException( | |
| 1419 | + ctx->throwValue(makeError(message.arg( | |
| 1424 | 1420 | QString("path '%1' outside of origin script '%2' '%3'") |
| 1425 | 1421 | .arg(PathUtils::stripFilename(url)) |
| 1426 | 1422 | .arg(PathUtils::stripFilename(currentSandboxURL)) |
| 1427 | 1423 | .arg(canonical.toString()) |
| 1428 | − ); | |
| 1424 | + ))); | |
| 1425 | + return nullptr; | |
| 1429 | 1426 | } |
| 1430 | 1427 | if (!file.exists()) { |
| 1431 | − return resolverException("path does not exist: " + url.toLocalFile()); | |
| 1428 | + ctx->throwValue(makeError(message.arg("path does not exist: " + url.toLocalFile()))); | |
| 1429 | + return nullptr; | |
| 1432 | 1430 | } |
| 1433 | 1431 | if (!file.isFile()) { |
| 1434 | − return resolverException("path is not a file: " + url.toLocalFile()); | |
| 1432 | + ctx->throwValue(makeError(message.arg("path is not a file: " + url.toLocalFile()))); | |
| 1433 | + return nullptr; | |
| 1435 | 1434 | } |
| 1436 | 1435 | } |
| 1437 | 1436 | |
| @@ -1611,6 +1610,7 @@ QScriptValue ScriptEngine::require(const QString& moduleId) { · 173 unmodified lines | ||
| 1611 | 1610 | // serialize require calls so the ordering/caching works correctly across multiple Entities |
| 1612 | 1611 | // note: this is a Recursive mutex so nested require's should not affected |
| 1613 | 1612 | QMutexLocker locker(&_requireLock); |
| 1613 | + ExceptionEmitter tryCatcher(this, __FUNCTION__); | |
| 1614 | 1614 | // _requireDepth++; |
| 1615 | 1615 | // QObject autoDecrement;connect(&autoDecrement, &QObject::destroyed, this, [this](){ _requireDepth--; }); |
| 1616 | 1616 | |
| @@ -1632,7 +1632,7 @@ QScriptValue ScriptEngine::require(const QString& moduleId) { · 15 unmodified lines | ||
| 1632 | 1632 | |
| 1633 | 1633 | // start by resolving the moduleId into a fully-qualified path/URL |
| 1634 | 1634 | QString modulePath = _requireResolve(moduleId); |
| 1635 | − if (hasUncaughtException()) { | |
| 1635 | + if (modulePath.isNull() || tryCatcher.hasPending()) { | |
| 1636 | 1636 | // the resolver already threw an exception -- bail early |
| 1637 | 1637 | return nullValue(); |
| 1638 | 1638 | } |