FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

/** * Copyright (C) 2019-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "JSAPIGlobalObject.h" #if JSC_OBJC_API_ENABLED #import "APICast.h" #import "CallFrameInlines.h" #import "Completion.h" #import "Error.h" #import "Exception.h" #import "GlobalObjectMethodTable.h" #import "IdentifierInlines.h" #import "JSContextInternal.h" #import "JSModuleLoader.h" #import "JSNativeStdFunction.h" #import "JSObjectInlines.h" #import "JSPromise.h" #import "JSScriptInternal.h" #import "JSSourceCode.h" #import "JSValueInternal.h" #import "JSVirtualMachineInternal.h" #import "JavaScriptCore.h" #import "ObjectConstructor.h" #import "SourceOrigin.h" #import "StrongInlines.h" #import "TopExceptionScope.h" #import #import namespace JSC { const GlobalObjectMethodTable* JSAPIGlobalObject::globalObjectMethodTable() { static constexpr GlobalObjectMethodTable table = { &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, &shouldInterruptScriptBeforeTimeout, &moduleLoaderImportModule, // moduleLoaderImportModule &moduleLoaderResolve, // moduleLoaderResolve &moduleLoaderFetch, // moduleLoaderFetch &moduleLoaderCreateImportMetaProperties, // moduleLoaderCreateImportMetaProperties &moduleLoaderEvaluate, // moduleLoaderEvaluate &promiseRejectionTracker, &reportUncaughtExceptionAtEventLoop, ¤tScriptExecutionOwner, &scriptExecutionStatus, &reportViolationForUnsafeEval, nullptr, // defaultLanguage nullptr, // compileStreaming nullptr, // instantiateStreaming &deriveShadowRealmGlobalObject, &codeForEval, &canCompileStrings, &trustedScriptStructure, }; return &table; }; void JSAPIGlobalObject::reportUncaughtExceptionAtEventLoop(JSGlobalObject* globalObject, Exception* exception) { JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject)]; [context notifyException:toRef(globalObject->vm(), exception->value())]; } static Expected computeValidImportSpecifier(const URL& base, const String& specifier) { URL absoluteURL(specifier); if (absoluteURL.isValid()) return absoluteURL; if (!specifier.startsWith('/') && !specifier.startsWith("./"_s) && !specifier.startsWith("../"_s)) return makeUnexpected(makeString("Module specifier: "_s, specifier, " does not start with \"/\", \"./\", or \"../\". Referenced from: "_s, base.string())); if (specifier.startsWith('/')) { absoluteURL = URL(URL("file://"_s), specifier); if (absoluteURL.isValid()) return absoluteURL; } if (base == URL()) return makeUnexpected("Could not determine the base URL for loading."_s); if (!base.isValid()) return makeUnexpected(makeString("Referrering script's url is not valid: "_s, base.string())); absoluteURL = URL(base, specifier); if (absoluteURL.isValid()) return absoluteURL; return makeUnexpected(makeString("Could not form valid URL from identifier and base. Tried:"_s, absoluteURL.string())); } Identifier JSAPIGlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, JSModuleLoader*, JSValue key, JSValue referrer, RefPtr, bool) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); ASSERT_UNUSED(globalObject, globalObject == globalObject); ASSERT(key.isString() || key.isSymbol()); String name = key.toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, { }); URL base; if (JSString* referrerString = dynamicDowncast(referrer)) { String value = referrerString->value(globalObject); RETURN_IF_EXCEPTION(scope, { }); // It can be invalid URL because dynamic-import will be resolved with caller's source origin (this becomes referrer), and it can be non valid URL. // But this is handled well in computeValidImportSpecifier. base = URL { { }, value }; } auto result = computeValidImportSpecifier(base, name); if (result) return Identifier::fromString(vm, result.value().string()); throwVMError(globalObject, scope, createError(globalObject, result.error())); return { }; } JSPromise* JSAPIGlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, JSModuleLoader*, JSString* specifierValue, RefPtr fetchParams, const SourceOrigin& sourceOrigin, bool deferred) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); auto reject = [&] (ThrowScope& scope) -> JSPromise* { auto* promise = JSPromise::create(vm, globalObject->promiseStructure()); return promise->rejectWithCaughtException(vm, scope); }; auto specifier = specifierValue->value(globalObject); RETURN_IF_EXCEPTION(scope, reject(scope)); Identifier originURL; if (const String& originString = sourceOrigin.string(); !originString.isNull()) originURL = Identifier::fromString(vm, originString); auto result = importModule(globalObject, Identifier::fromString(vm, specifier), originURL, WTF::move(fetchParams), nullptr, deferred); RETURN_IF_EXCEPTION(scope, reject(scope)); return result; } JSPromise* JSAPIGlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, JSModuleLoader*, JSValue key, RefPtr, RefPtr) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); ASSERT(globalObject == globalObject); JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject)]; JSPromise* promise = JSPromise::create(vm, globalObject->promiseStructure()); Identifier moduleKey = key.toPropertyKey(globalObject); RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(vm, scope)); if (![context moduleLoaderDelegate]) [[unlikely]] { scope.release(); promise->reject(vm, createError(globalObject, "No module loader provided."_s)); return promise; } auto* resolve = JSNativeStdFunction::create(vm, globalObject, 1, "resolve"_s, [promise, moduleKey] (JSGlobalObject* globalObject, CallFrame* callFrame) { // This captures the globalObject but that's ok because our structure keeps it alive anyway. VM& vm = globalObject->vm(); JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject)]; id script = valueToObject(context, toRef(globalObject, callFrame->argument(0))); auto rejectPromise = [&] (String message) { promise->reject(vm, createTypeError(globalObject, message)); return encodedJSUndefined(); }; if (![script isKindOfClass:[JSScript class]]) [[unlikely]] return rejectPromise("First argument of resolution callback is not a JSScript"_s); RetainPtr jsScript = static_cast(script); JSSourceCode* source = [jsScript.get() jsSourceCode]; if ([jsScript.get() type] != kJSScriptTypeModule) [[unlikely]] return rejectPromise("The JSScript that was provided did not have expected type of kJSScriptTypeModule."_s); NSURL *sourceURL = [jsScript.get() sourceURL]; String oldModuleKey { [sourceURL absoluteString] }; if (Identifier::fromString(vm, oldModuleKey) != moduleKey) [[unlikely]] return rejectPromise(makeString("The same JSScript was provided for two different identifiers, previously: "_s, oldModuleKey, " and now: "_s, moduleKey.string())); promise->resolve(globalObject, vm, source); return encodedJSUndefined(); }, promise); auto* reject = JSNativeStdFunction::create(vm, globalObject, 1, "reject"_s, [promise] (JSGlobalObject* globalObject, CallFrame* callFrame) { promise->reject(globalObject->vm(), callFrame->argument(0)); return encodedJSUndefined(); }, promise); [[context moduleLoaderDelegate] context:context fetchModuleForIdentifier:[::JSValue valueWithJSValueRef:toRef(globalObject, key) inContext:context] withResolveHandler:[::JSValue valueWithJSValueRef:toRef(globalObject, resolve) inContext:context] andRejectHandler:[::JSValue valueWithJSValueRef:toRef(globalObject, reject) inContext:context]]; if (context.exception) { scope.release(); promise->reject(vm, toJS(globalObject, [context.exception JSValueRef])); context.exception = nil; } return promise; } JSObject* JSAPIGlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, JSModuleLoader*, JSValue key, JSModuleRecord*, RefPtr) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSObject* metaProperties = constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()); RETURN_IF_EXCEPTION(scope, nullptr); metaProperties->putDirect(vm, Identifier::fromString(vm, "filename"_s), key); RETURN_IF_EXCEPTION(scope, nullptr); metaProperties->putDirect(vm, JSC::Identifier::fromString(vm, "url"_s), key); RETURN_IF_EXCEPTION(scope, nullptr); return metaProperties; } JSValue JSAPIGlobalObject::moduleLoaderEvaluate(JSGlobalObject* globalObject, JSModuleLoader* moduleLoader, JSValue key, JSValue moduleRecordValue, RefPtr scriptFetcher, JSValue sentValue, JSValue resumeMode) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject)]; id moduleLoaderDelegate = [context moduleLoaderDelegate]; NSURL *url = nil; if ([moduleLoaderDelegate respondsToSelector:@selector(willEvaluateModule:)] || [moduleLoaderDelegate respondsToSelector:@selector(didEvaluateModule:)]) { String moduleKey = key.toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, { }); url = [NSURL URLWithString:moduleKey.createNSString().get()]; } if ([moduleLoaderDelegate respondsToSelector:@selector(willEvaluateModule:)]) [moduleLoaderDelegate willEvaluateModule:url]; scope.release(); // FIXME: We should update the delegate callbacks for async modules. https://bugs.webkit.org/show_bug.cgi?id=222253 JSValue result = moduleLoader->evaluateNonVirtual(globalObject, key, moduleRecordValue, scriptFetcher, sentValue, resumeMode); if ([moduleLoaderDelegate respondsToSelector:@selector(didEvaluateModule:)]) [moduleLoaderDelegate didEvaluateModule:url]; return result; } JSValue JSAPIGlobalObject::loadAndEvaluateJSScriptModule(const JSLockHolder&, JSScript *script) { ASSERT(script.type == kJSScriptTypeModule); VM& vm = this->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Identifier key = Identifier::fromString(vm, String { [[script sourceURL] absoluteString] }); JSPromise* promise = importModule(this, key, { }, nullptr, nullptr); RETURN_IF_EXCEPTION(scope, { }); auto* result = JSPromise::create(vm, this->promiseStructure()); result->resolve(this, vm, promise); RETURN_IF_EXCEPTION(scope, { }); return result; } } #endif // JSC_OBJC_API_ENABLED

Back | FazBrowse Home | New Git URL