Changeset 238391 in webkit
- Timestamp:
- Nov 19, 2018 11:09:53 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r238373 r238391 1 2018-11-19 Mark Lam <mark.lam@apple.com> 2 3 globalFuncImportModule() should return a promise when it clears exceptions. 4 https://bugs.webkit.org/show_bug.cgi?id=191792 5 <rdar://problem/46090763> 6 7 Reviewed by Michael Saboff. 8 9 * stress/global-import-function-should-return-a-promise-when-clearing-exceptions.js: Added. 10 1 11 2018-11-19 Guillaume Emont <guijemont@igalia.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r238388 r238391 1 2018-11-19 Mark Lam <mark.lam@apple.com> 2 3 globalFuncImportModule() should return a promise when it clears exceptions. 4 https://bugs.webkit.org/show_bug.cgi?id=191792 5 <rdar://problem/46090763> 6 7 Reviewed by Michael Saboff. 8 9 If we're clearing the exceptions in a CatchScope, then it means that we've handled 10 the exception, and is able to proceed in a normal manner. Hence, we should not 11 return the empty JSValue in this case: instead, we should return a Promise as 12 expected by import's API. 13 14 The only time when we can't return a promise is when we fail to create a Promise. 15 In that case, we should be propagating the exception. 16 17 Hence, globalFuncImportModule() contains a ThrowScope (for propagating the 18 exception that arises from failure to create the Promise) wrapping a CatchScope 19 (for catching any exception that arises from failure to execute the import). 20 21 Also fixed similar issues, and some exception check issues in JSModuleLoader and 22 the jsc shell. 23 24 * jsc.cpp: 25 (GlobalObject::moduleLoaderImportModule): 26 (GlobalObject::moduleLoaderFetch): 27 * runtime/JSGlobalObjectFunctions.cpp: 28 (JSC::globalFuncImportModule): 29 * runtime/JSModuleLoader.cpp: 30 (JSC::JSModuleLoader::loadAndEvaluateModule): 31 (JSC::JSModuleLoader::loadModule): 32 (JSC::JSModuleLoader::requestImportModule): 33 (JSC::JSModuleLoader::importModule): 34 (JSC::JSModuleLoader::resolve): 35 (JSC::JSModuleLoader::fetch): 36 (JSC::moduleLoaderParseModule): 37 (JSC::moduleLoaderResolveSync): 38 1 39 2018-11-19 Alex Christensen <achristensen@webkit.org> 2 40 -
trunk/Source/JavaScriptCore/jsc.cpp
r237823 r238391 802 802 { 803 803 VM& vm = globalObject->vm(); 804 auto scope = DECLARE_CATCH_SCOPE(vm); 805 806 auto rejectPromise = [&] (JSValue error) { 807 return JSInternalPromiseDeferred::create(exec, globalObject)->reject(exec, error); 804 auto throwScope = DECLARE_THROW_SCOPE(vm); 805 806 auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject); 807 RETURN_IF_EXCEPTION(throwScope, nullptr); 808 809 auto catchScope = DECLARE_CATCH_SCOPE(vm); 810 auto reject = [&] (JSValue rejectionReason) { 811 catchScope.clearException(); 812 auto result = deferred->reject(exec, rejectionReason); 813 catchScope.clearException(); 814 return result; 808 815 }; 809 816 810 817 if (sourceOrigin.isNull()) 811 return reject Promise(createError(exec, "Could not resolve the module specifier."_s));818 return reject(createError(exec, "Could not resolve the module specifier."_s)); 812 819 813 820 auto referrer = sourceOrigin.string(); 814 821 auto moduleName = moduleNameValue->value(exec); 815 if (UNLIKELY(scope.exception())) { 816 JSValue exception = scope.exception(); 817 scope.clearException(); 818 return rejectPromise(exception); 819 } 822 if (UNLIKELY(catchScope.exception())) 823 return reject(catchScope.exception()); 820 824 821 825 auto directoryName = extractDirectoryName(referrer.impl()); 822 826 if (!directoryName) 823 return reject Promise(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));827 return reject(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'."))); 824 828 825 829 auto result = JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), parameters, jsUndefined()); 826 scope.releaseAssertNoException(); 830 if (UNLIKELY(catchScope.exception())) 831 return reject(catchScope.exception()); 827 832 return result; 828 833 } … … 992 997 { 993 998 VM& vm = globalObject->vm(); 994 auto scope = DECLARE_CATCH_SCOPE(vm);999 auto throwScope = DECLARE_THROW_SCOPE(vm); 995 1000 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject); 1001 RETURN_IF_EXCEPTION(throwScope, nullptr); 1002 1003 auto catchScope = DECLARE_CATCH_SCOPE(vm); 1004 auto reject = [&] (JSValue rejectionReason) { 1005 catchScope.clearException(); 1006 auto result = deferred->reject(exec, rejectionReason); 1007 catchScope.clearException(); 1008 return result; 1009 }; 1010 996 1011 String moduleKey = key.toWTFString(exec); 997 if (UNLIKELY(scope.exception())) { 998 JSValue exception = scope.exception(); 999 scope.clearException(); 1000 return deferred->reject(exec, exception); 1001 } 1012 if (UNLIKELY(catchScope.exception())) 1013 return reject(catchScope.exception()); 1002 1014 1003 1015 // Here, now we consider moduleKey as the fileName. 1004 1016 Vector<uint8_t> buffer; 1005 if (!fetchModuleFromLocalFileSystem(moduleKey, buffer)) { 1006 auto result = deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'."))); 1007 scope.releaseAssertNoException(); 1008 return result; 1009 } 1017 if (!fetchModuleFromLocalFileSystem(moduleKey, buffer)) 1018 return reject(createError(exec, makeString("Could not open file '", moduleKey, "'."))); 1010 1019 1011 1020 #if ENABLE(WEBASSEMBLY) … … 1013 1022 if (buffer.size() >= 4) { 1014 1023 if (buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' && buffer[3] == 'm') { 1015 auto result = deferred->resolve(exec, JSSourceCode::create(vm, SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleKey }, moduleKey)))); 1016 scope.releaseAssertNoException(); 1024 auto source = SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleKey }, moduleKey)); 1025 catchScope.releaseAssertNoException(); 1026 auto sourceCode = JSSourceCode::create(vm, WTFMove(source)); 1027 catchScope.releaseAssertNoException(); 1028 auto result = deferred->resolve(exec, sourceCode); 1029 catchScope.clearException(); 1017 1030 return result; 1018 1031 } … … 1020 1033 #endif 1021 1034 1022 auto result = deferred->resolve(exec, JSSourceCode::create(vm, makeSource(stringFromUTF(buffer), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module))); 1023 scope.releaseAssertNoException(); 1035 auto sourceCode = JSSourceCode::create(vm, makeSource(stringFromUTF(buffer), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)); 1036 catchScope.releaseAssertNoException(); 1037 auto result = deferred->resolve(exec, sourceCode); 1038 catchScope.clearException(); 1024 1039 return result; 1025 1040 } -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r237714 r238391 784 784 { 785 785 VM& vm = exec->vm(); 786 auto throwScope = DECLARE_THROW_SCOPE(vm); 787 788 auto* globalObject = exec->lexicalGlobalObject(); 789 790 auto* promise = JSPromiseDeferred::create(exec, globalObject); 791 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 792 786 793 auto catchScope = DECLARE_CATCH_SCOPE(vm); 787 788 auto* globalObject = exec->lexicalGlobalObject(); 789 790 auto* promise = JSPromiseDeferred::create(exec, globalObject); 791 CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue()); 794 auto reject = [&] (JSValue rejectionReason) { 795 catchScope.clearException(); 796 promise->reject(exec, rejectionReason); 797 catchScope.clearException(); 798 return JSValue::encode(promise->promise()); 799 }; 792 800 793 801 auto sourceOrigin = exec->callerSourceOrigin(); 794 802 RELEASE_ASSERT(exec->argumentCount() == 1); 795 803 auto* specifier = exec->uncheckedArgument(0).toString(exec); 796 if (Exception* exception = catchScope.exception()) { 797 catchScope.clearException(); 798 promise->reject(exec, exception->value()); 799 CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue()); 800 return JSValue::encode(promise->promise()); 801 } 804 if (Exception* exception = catchScope.exception()) 805 return reject(exception->value()); 802 806 803 807 // We always specify parameters as undefined. Once dynamic import() starts accepting fetching parameters, … … 805 809 JSValue parameters = jsUndefined(); 806 810 auto* internalPromise = globalObject->moduleLoader()->importModule(exec, specifier, parameters, sourceOrigin); 807 if (Exception* exception = catchScope.exception()) { 808 catchScope.clearException(); 809 promise->reject(exec, exception->value()); 810 CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue()); 811 return JSValue::encode(promise->promise()); 812 } 811 if (Exception* exception = catchScope.exception()) 812 return reject(exception->value()); 813 813 promise->resolve(exec, internalPromise); 814 CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue()); 815 814 815 catchScope.clearException(); 816 816 return JSValue::encode(promise->promise()); 817 817 } -
trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp
r236697 r238391 1 1 /* 2 * Copyright (C) 2015-201 7Apple Inc. All Rights Reserved.2 * Copyright (C) 2015-2018 Apple Inc. All Rights Reserved. 3 3 * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>. 4 4 * … … 159 159 ASSERT(!arguments.hasOverflowed()); 160 160 161 RELEASE_AND_RETURN(scope, jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments))); 161 JSValue promise = call(exec, function, callType, callData, this, arguments); 162 RETURN_IF_EXCEPTION(scope, nullptr); 163 return jsCast<JSInternalPromise*>(promise); 162 164 } 163 165 … … 179 181 ASSERT(!arguments.hasOverflowed()); 180 182 181 RELEASE_AND_RETURN(scope, jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments))); 183 JSValue promise = call(exec, function, callType, callData, this, arguments); 184 RETURN_IF_EXCEPTION(scope, nullptr); 185 return jsCast<JSInternalPromise*>(promise); 182 186 } 183 187 … … 218 222 ASSERT(!arguments.hasOverflowed()); 219 223 220 RELEASE_AND_RETURN(scope, jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments))); 224 JSValue promise = call(exec, function, callType, callData, this, arguments); 225 RETURN_IF_EXCEPTION(scope, nullptr); 226 return jsCast<JSInternalPromise*>(promise); 221 227 } 222 228 … … 228 234 auto* globalObject = exec->lexicalGlobalObject(); 229 235 VM& vm = globalObject->vm(); 230 auto scope = DECLARE_CATCH_SCOPE(vm);236 auto throwScope = DECLARE_THROW_SCOPE(vm); 231 237 232 238 if (globalObject->globalObjectMethodTable()->moduleLoaderImportModule) 233 return globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, exec, this, moduleName, parameters, referrer);239 RELEASE_AND_RETURN(throwScope, globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, exec, this, moduleName, parameters, referrer)); 234 240 235 241 auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject); 242 RETURN_IF_EXCEPTION(throwScope, nullptr); 243 244 auto catchScope = DECLARE_CATCH_SCOPE(vm); 236 245 auto moduleNameString = moduleName->value(exec); 237 if (UNLIKELY( scope.exception())) {238 JSValue exception = scope.exception()->value();239 scope.clearException();246 if (UNLIKELY(catchScope.exception())) { 247 JSValue exception = catchScope.exception()->value(); 248 catchScope.clearException(); 240 249 deferred->reject(exec, exception); 250 catchScope.clearException(); 241 251 return deferred->promise(); 242 252 } 243 253 deferred->reject(exec, createError(exec, makeString("Could not import the module '", moduleNameString, "'."))); 254 catchScope.clearException(); 244 255 return deferred->promise(); 245 256 } … … 259 270 { 260 271 VM& vm = exec->vm(); 261 auto scope = DECLARE_CATCH_SCOPE(vm);272 auto throwScope = DECLARE_THROW_SCOPE(vm); 262 273 263 274 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, exec->lexicalGlobalObject()); 264 scope.releaseAssertNoException(); 275 RETURN_IF_EXCEPTION(throwScope, nullptr); 276 277 auto catchScope = DECLARE_CATCH_SCOPE(vm); 278 265 279 const Identifier moduleKey = resolveSync(exec, name, referrer, scriptFetcher); 266 if (UNLIKELY(scope.exception())) { 267 JSValue exception = scope.exception(); 268 scope.clearException(); 269 return deferred->reject(exec, exception); 280 if (UNLIKELY(catchScope.exception())) { 281 JSValue exception = catchScope.exception(); 282 catchScope.clearException(); 283 auto result = deferred->reject(exec, exception); 284 catchScope.clearException(); 285 return result; 270 286 } 271 287 auto result = deferred->resolve(exec, identifierToJSValue(vm, moduleKey)); 272 scope.releaseAssertNoException();288 catchScope.clearException(); 273 289 return result; 274 290 } … … 281 297 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 282 298 VM& vm = globalObject->vm(); 283 auto scope = DECLARE_CATCH_SCOPE(vm); 299 auto throwScope = DECLARE_THROW_SCOPE(vm); 300 284 301 if (globalObject->globalObjectMethodTable()->moduleLoaderFetch) 285 return globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, parameters, scriptFetcher); 302 RELEASE_AND_RETURN(throwScope, globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, parameters, scriptFetcher)); 303 286 304 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject); 305 RETURN_IF_EXCEPTION(throwScope, nullptr); 306 307 auto catchScope = DECLARE_CATCH_SCOPE(vm); 308 287 309 String moduleKey = key.toWTFString(exec); 288 if (UNLIKELY( scope.exception())) {289 JSValue exception = scope.exception()->value();290 scope.clearException();310 if (UNLIKELY(catchScope.exception())) { 311 JSValue exception = catchScope.exception()->value(); 312 catchScope.clearException(); 291 313 deferred->reject(exec, exception); 314 catchScope.clearException(); 292 315 return deferred->promise(); 293 316 } 294 317 deferred->reject(exec, createError(exec, makeString("Could not open the module '", moduleKey, "'."))); 318 catchScope.clearException(); 295 319 return deferred->promise(); 296 320 } … … 337 361 { 338 362 VM& vm = exec->vm(); 339 auto scope = DECLARE_CATCH_SCOPE(vm);363 auto throwScope = DECLARE_THROW_SCOPE(vm); 340 364 341 365 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, exec->lexicalGlobalObject()); 342 scope.releaseAssertNoException();343 344 auto reject = [&] {345 JSValue exception = scope.exception();346 scope.clearException();347 auto result = deferred->reject(exec, exception);348 scope.releaseAssertNoException();366 RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); 367 368 auto catchScope = DECLARE_CATCH_SCOPE(vm); 369 auto reject = [&] (JSValue rejectionReason) { 370 catchScope.clearException(); 371 auto result = deferred->reject(exec, rejectionReason); 372 catchScope.clearException(); 349 373 return JSValue::encode(result); 350 374 }; 351 375 352 376 const Identifier moduleKey = exec->argument(0).toPropertyKey(exec); 353 if (UNLIKELY( scope.exception()))354 return reject( );377 if (UNLIKELY(catchScope.exception())) 378 return reject(catchScope.exception()); 355 379 356 380 JSValue source = exec->argument(1); … … 369 393 &vm, sourceCode, Identifier(), JSParserBuiltinMode::NotBuiltin, 370 394 JSParserStrictMode::Strict, JSParserScriptMode::Module, SourceParseMode::ModuleAnalyzeMode, SuperBinding::NotNeeded, error); 371 if (error.isValid()) { 372 auto result = deferred->reject(exec, error.toErrorObject(exec->lexicalGlobalObject(), sourceCode)); 373 scope.releaseAssertNoException(); 374 return JSValue::encode(result); 375 } 395 if (error.isValid()) 396 return reject(error.toErrorObject(exec->lexicalGlobalObject(), sourceCode)); 376 397 ASSERT(moduleProgramNode); 377 398 378 399 ModuleAnalyzer moduleAnalyzer(exec, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables()); 379 if (UNLIKELY( scope.exception()))380 return reject( );400 if (UNLIKELY(catchScope.exception())) 401 return reject(catchScope.exception()); 381 402 382 403 auto result = deferred->resolve(exec, moduleAnalyzer.analyze(*moduleProgramNode)); 383 scope.releaseAssertNoException();404 catchScope.clearException(); 384 405 return JSValue::encode(result); 385 406 } … … 438 459 { 439 460 VM& vm = exec->vm(); 440 auto scope = DECLARE_ CATCH_SCOPE(vm);461 auto scope = DECLARE_THROW_SCOPE(vm); 441 462 442 463 JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue());
Note: See TracChangeset
for help on using the changeset viewer.