WebKit Bugzilla
Attachment 362464 Details for
Bug 194517
: Update JSScript SPI based on feedback
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
b-backup.diff (text/plain), 59.72 KB, created by
Saam Barati
on 2019-02-19 18:01:19 PST
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2019-02-19 18:01:19 PST
Size:
59.72 KB
patch
obsolete
>Index: Source/JavaScriptCore/config.h >=================================================================== >--- Source/JavaScriptCore/config.h (revision 241767) >+++ Source/JavaScriptCore/config.h (working copy) >@@ -25,6 +25,7 @@ > > #define JSC_API_AVAILABLE(...) > #define JSC_CLASS_AVAILABLE(...) JS_EXPORT >+#define JSC_API_DEPRECATED(...) > // Use zero since it will be less than any possible version number. > #define JSC_MAC_VERSION_TBA 0 > #define JSC_IOS_VERSION_TBA 0 >Index: Source/JavaScriptCore/API/JSAPIGlobalObject.h >=================================================================== >--- Source/JavaScriptCore/API/JSAPIGlobalObject.h (revision 241767) >+++ Source/JavaScriptCore/API/JSAPIGlobalObject.h (working copy) >@@ -27,6 +27,9 @@ > > #include "JSGlobalObject.h" > >+OBJC_CLASS JSScript; >+OBJC_CLASS NSURL; >+ > namespace JSC { > > class JSAPIGlobalObject : public JSGlobalObject { >@@ -55,6 +58,8 @@ public: > static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue); > static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue); > >+ JSValue loadAndEvaluateJSScriptModule(JSScript *script); >+ > private: > JSAPIGlobalObject(VM& vm, Structure* structure) > : Base(vm, structure, &s_globalObjectMethodTable) >Index: Source/JavaScriptCore/API/JSAPIGlobalObject.mm >=================================================================== >--- Source/JavaScriptCore/API/JSAPIGlobalObject.mm (revision 241767) >+++ Source/JavaScriptCore/API/JSAPIGlobalObject.mm (working copy) >@@ -34,8 +34,10 @@ > #import "Error.h" > #import "Exception.h" > #import "JSContextInternal.h" >+#import "JSInternalPromise.h" > #import "JSInternalPromiseDeferred.h" > #import "JSNativeStdFunction.h" >+#import "JSPromiseDeferred.h" > #import "JSScriptInternal.h" > #import "JSSourceCode.h" > #import "JSValueInternal.h" >@@ -74,13 +76,20 @@ Identifier JSAPIGlobalObject::moduleLoad > ASSERT_UNUSED(globalObject, globalObject == exec->lexicalGlobalObject()); > ASSERT(key.isString() || key.isSymbol()); > String name = key.toWTFString(exec); >+ dataLogLn("resolving '", name, "'"); > >- URL referrerURL(URL(), jsCast<JSString*>(referrer)->tryGetValue()); >- RELEASE_ASSERT(referrerURL.isValid()); >- >- URL url = URL(referrerURL, name); >- if (url.isValid()) >- return Identifier::fromString(exec, url); >+ if (JSString* referrerString = jsDynamicCast<JSString*>(vm, referrer)) { >+ URL referrerURL(URL(), referrerString->value(exec)); >+ RELEASE_ASSERT(referrerURL.isValid()); >+ >+ URL url = URL(referrerURL, name); >+ if (url.isValid()) >+ return Identifier::fromString(exec, url); >+ } else { >+ URL url = URL(URL(), name); >+ if (url.isValid()) >+ return Identifier::fromString(exec, url); >+ } > > throwVMError(exec, scope, "Could not form valid URL from identifier and base"_s); > return { }; >@@ -162,9 +171,9 @@ JSInternalPromise* JSAPIGlobalObject::mo > return deferred->reject(exec, createError(exec, "No module loader provided.")); > > auto deferredPromise = Strong<JSInternalPromiseDeferred>(vm, deferred); >- auto strongKey = Strong<JSString>(vm, jsSecureCast<JSString*>(vm, key)); > auto* resolve = JSNativeStdFunction::create(vm, globalObject, 1, "resolve", [=] (ExecState* exec) { > // This captures the globalObject but that's ok because our structure keeps it alive anyway. >+ VM& vm = exec->vm(); > JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject->globalExec())]; > id script = valueToObject(context, toRef(exec, exec->argument(0))); > >@@ -175,7 +184,25 @@ JSInternalPromise* JSAPIGlobalObject::mo > return encodedJSUndefined(); > } > >- args.append([static_cast<JSScript *>(script) jsSourceCode:moduleKey]); >+ JSScript* jsScript = static_cast<JSScript *>(script); >+ >+ JSSourceCode* source = [jsScript jsSourceCode]; >+ if (UNLIKELY([jsScript type] != kJSScriptTypeModule)) { >+ args.append(createTypeError(exec, makeString("The JSScript that was provided did not have expected type of kJSScriptTypeModule."))); >+ call(exec, deferredPromise->JSPromiseDeferred::reject(), args, "This should never be seen..."); >+ return encodedJSUndefined(); >+ } >+ >+ String oldModuleKey { [[jsScript sourceURL] absoluteString] }; >+ dataLogLn("old key=", oldModuleKey, " newKey=", moduleKey); >+ if (UNLIKELY(Identifier::fromString(&vm, oldModuleKey) != moduleKey)) { >+ dataLogLn("rejecting because old key != newKey"); >+ args.append(createTypeError(exec, makeString("The same JSScript was provided for two different identifiers, previously: ", oldModuleKey, " and now: ", moduleKey.string()))); >+ call(exec, deferredPromise->JSPromiseDeferred::reject(), args, "This should never be seen..."); >+ return encodedJSUndefined(); >+ } >+ >+ args.append(source); > call(exec, deferredPromise->JSPromiseDeferred::resolve(), args, "This should never be seen..."); > return encodedJSUndefined(); > }); >@@ -210,6 +237,24 @@ JSObject* JSAPIGlobalObject::moduleLoade > return metaProperties; > } > >+JSValue JSAPIGlobalObject::loadAndEvaluateJSScriptModule(JSScript *script) >+{ >+ ASSERT(script.type == kJSScriptTypeModule); >+ VM& vm = this->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ //auto key = Identifier::fromString(&vm, [[script sourceURL] absoluteString]); >+ auto key = String { [[script sourceURL] absoluteString] }; >+ dataLogLn("loadAndEvaluateJSScriptModule, key=", key); >+ JSInternalPromise* promise = loadAndEvaluateModule(globalExec(), key, jsUndefined(), jsUndefined()); >+ //promise->then(); >+ RETURN_IF_EXCEPTION(scope, { }); >+ auto result = JSPromiseDeferred::tryCreate(globalExec(), this); >+ RETURN_IF_EXCEPTION(scope, { }); >+ result->resolve(globalExec(), promise); >+ return result->promise(); >+} >+ > } > > #endif // JSC_OBJC_API_ENABLED >Index: Source/JavaScriptCore/API/JSBase.cpp >=================================================================== >--- Source/JavaScriptCore/API/JSBase.cpp (revision 241767) >+++ Source/JavaScriptCore/API/JSBase.cpp (working copy) >@@ -25,6 +25,7 @@ > > #include "config.h" > #include "JSBase.h" >+#include "JSBaseInternal.h" > #include "JSBasePrivate.h" > > #include "APICast.h" >@@ -47,25 +48,15 @@ > > using namespace JSC; > >-JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) >+JSValueRef JSEvaluateScriptInternal(const JSLockHolder&, ExecState* exec, JSContextRef ctx, JSObjectRef thisObject, const SourceCode& source, JSValueRef* exception) > { >- if (!ctx) { >- ASSERT_NOT_REACHED(); >- return 0; >- } >- ExecState* exec = toJS(ctx); >- VM& vm = exec->vm(); >- JSLockHolder locker(vm); >+ UNUSED_PARAM(ctx); > > JSObject* jsThisObject = toJS(thisObject); > >- startingLineNumber = std::max(1, startingLineNumber); >- > // evaluate sets "this" to the global object if it is NULL >+ VM& vm = exec->vm(); > JSGlobalObject* globalObject = vm.vmEntryGlobalObject(exec); >- auto sourceURLString = sourceURL ? sourceURL->string() : String(); >- SourceCode source = makeSource(script->string(), SourceOrigin { sourceURLString }, URL({ }, sourceURLString), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber())); >- > NakedPtr<Exception> evaluationException; > JSValue returnValue = profiledEvaluate(globalObject->globalExec(), ProfilingReason::API, source, jsThisObject, evaluationException); > >@@ -80,7 +71,7 @@ JSValueRef JSEvaluateScript(JSContextRef > // We could stash it in the inspector in case an inspector is ever opened. > globalObject->inspectorController().reportAPIException(exec, evaluationException); > #endif >- return 0; >+ return nullptr; > } > > if (returnValue) >@@ -90,6 +81,24 @@ JSValueRef JSEvaluateScript(JSContextRef > return toRef(exec, jsUndefined()); > } > >+JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) >+{ >+ if (!ctx) { >+ ASSERT_NOT_REACHED(); >+ return nullptr; >+ } >+ ExecState* exec = toJS(ctx); >+ VM& vm = exec->vm(); >+ JSLockHolder locker(vm); >+ >+ startingLineNumber = std::max(1, startingLineNumber); >+ >+ auto sourceURLString = sourceURL ? sourceURL->string() : String(); >+ SourceCode source = makeSource(script->string(), SourceOrigin { sourceURLString }, URL({ }, sourceURLString), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber())); >+ >+ return JSEvaluateScriptInternal(locker, exec, ctx, thisObject, source, exception); >+} >+ > bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) > { > if (!ctx) { >Index: Source/JavaScriptCore/API/JSBaseInternal.h >=================================================================== >--- Source/JavaScriptCore/API/JSBaseInternal.h (nonexistent) >+++ Source/JavaScriptCore/API/JSBaseInternal.h (working copy) >@@ -0,0 +1,36 @@ >+/* >+ * Copyright (C) 2019 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. >+ */ >+ >+#pragma once >+ >+#include <JavaScriptCore/JSBase.h> >+#include <JavaScriptCore/WebKitAvailability.h> >+ >+namespace JSC { >+class JSLockHolder; >+class ExecState; >+} >+ >+extern "C" JSValueRef JSEvaluateScriptInternal(const JSC::JSLockHolder&, JSC::ExecState*, JSContextRef, JSObjectRef thisObject, const JSC::SourceCode&, JSValueRef* exception); >Index: Source/JavaScriptCore/API/JSContext.mm >=================================================================== >--- Source/JavaScriptCore/API/JSContext.mm (revision 241767) >+++ Source/JavaScriptCore/API/JSContext.mm (working copy) >@@ -27,6 +27,7 @@ > > #import "APICast.h" > #import "Completion.h" >+#import "JSBaseInternal.h" > #import "JSCInlines.h" > #import "JSContextInternal.h" > #import "JSContextPrivate.h" >@@ -103,17 +104,47 @@ - (JSValue *)evaluateScript:(NSString *) > return [self evaluateScript:script withSourceURL:nil]; > } > >-- (JSValue *)evaluateScript:(NSString *)script withSourceURL:(NSURL *)sourceURL >+static JSValue *evaluateScript(JSContext *context, RefPtr<OpaqueJSString> source, RefPtr<OpaqueJSString> url) > { > JSValueRef exceptionValue = nullptr; >+ JSValueRef result = JSEvaluateScript(context->m_context, source.get(), nullptr, url.get(), 0, &exceptionValue); >+ >+ if (exceptionValue) >+ return [context valueFromNotifyException:exceptionValue]; >+ return [JSValue valueWithJSValueRef:result inContext:context]; >+} >+ >+- (JSValue *)evaluateScript:(NSString *)script withSourceURL:(NSURL *)sourceURL >+{ > auto scriptJS = OpaqueJSString::tryCreate(script); > auto sourceURLJS = OpaqueJSString::tryCreate([sourceURL absoluteString]); >- JSValueRef result = JSEvaluateScript(m_context, scriptJS.get(), nullptr, sourceURLJS.get(), 0, &exceptionValue); >+ return evaluateScript(self, scriptJS, sourceURLJS); >+} > >- if (exceptionValue) >- return [self valueFromNotifyException:exceptionValue]; >+- (JSValue *)evaluateJSScript:(JSScript *)script >+{ >+ if (script.type == kJSScriptTypeProgram) { >+ auto* jsSourceCode = [script jsSourceCode]; > >- return [JSValue valueWithJSValueRef:result inContext:self]; >+ JSC::ExecState* exec = toJS(m_context); >+ JSC::VM& vm = exec->vm(); >+ JSC::JSLockHolder locker(vm); >+ >+ JSValueRef exceptionValue = nullptr; >+ JSValueRef result = JSEvaluateScriptInternal(locker, exec, m_context, nullptr, jsSourceCode->sourceCode(), &exceptionValue); >+ >+ if (exceptionValue) >+ return [self valueFromNotifyException:exceptionValue]; >+ return [JSValue valueWithJSValueRef:result inContext:self]; >+ } >+ >+ JSC::ExecState* exec = toJS(m_context); >+ JSC::VM& vm = exec->vm(); >+ auto* globalObject = JSC::jsDynamicCast<JSC::JSAPIGlobalObject*>(vm, exec->lexicalGlobalObject()); >+ if (!globalObject) >+ return [JSValue valueWithNewPromiseRejectedWithReason:[JSValue valueWithNewErrorFromMessage:@"Context does not support module loading" inContext:self] inContext:self]; >+ >+ return [JSValue valueWithJSValueRef:toRef(vm, globalObject->loadAndEvaluateJSScriptModule(script)) inContext:self]; > } > > - (void)setException:(JSValue *)value >@@ -300,6 +331,11 @@ - (BOOL)boolFromNotifyException:(JSValue > return NO; > } > >+- (JSValue *)valueFromNotifyExceptionWithString:(String&)string >+{ >+ return [self valueFromNotifyException:[JSValue valueWithNewErrorFromMessage:string inContext:self].JSValueRef]; >+} >+ > - (void)beginCallbackWithData:(CallbackData *)callbackData calleeValue:(JSValueRef)calleeValue thisValue:(JSValueRef)thisValue argumentCount:(size_t)argumentCount arguments:(const JSValueRef *)arguments > { > Thread& thread = Thread::current(); >Index: Source/JavaScriptCore/API/JSContextPrivate.h >=================================================================== >--- Source/JavaScriptCore/API/JSContextPrivate.h (revision 241767) >+++ Source/JavaScriptCore/API/JSContextPrivate.h (working copy) >@@ -74,6 +74,16 @@ > /*! @abstract The delegate the context will use when trying to load a module. Note, this delegate will be ignored for contexts returned by UIWebView. */ > @property (nonatomic, weak) id <JSModuleLoaderDelegate> moduleLoaderDelegate JSC_API_AVAILABLE(macosx(JSC_MAC_TBA), ios(JSC_IOS_TBA)); > >+/*! >+ @method >+ @abstract Run a JSScript. >+ @param script the JSScript to evaluate. >+ @discussion If the provided JSScript was created with JSScriptTypeProgram, the script will run synchronously and return the result of evaluation. >+ >+ Otherwise, if the script was created with JSScriptTypeModule, the module will be run asynchronously and will return a promise resolved when the module and any transitive dependencies are loaded. The module loader will treat the script as if it had been returned from a delegate call to moduleLoaderDelegate. This mirrors the JavaScript dynamic import operation. >+ */ >+- (JSValue *)evaluateJSScript:(JSScript *)script; >+ > @end > > #endif >Index: Source/JavaScriptCore/API/JSScript.h >=================================================================== >--- Source/JavaScriptCore/API/JSScript.h (revision 241767) >+++ Source/JavaScriptCore/API/JSScript.h (working copy) >@@ -31,6 +31,18 @@ NS_ASSUME_NONNULL_BEGIN > > @class JSVirtualMachine; > >+/*! >+ @enum JSScriptType >+ @abstract A constant identifying the execution type of a JSScript. >+ @constant kJSScriptTypeProgram The type of a normal JavaScript program. >+ @constant kJSScriptTypeModule The type of a module JavaScript program. >+ */ >+typedef NS_ENUM(NSInteger, JSScriptType) { >+ kJSScriptTypeProgram, >+ kJSScriptTypeModule, >+}; >+ >+ > JSC_CLASS_AVAILABLE(macosx(JSC_MAC_TBA), ios(JSC_IOS_TBA)) > @interface JSScript : NSObject > >@@ -41,7 +53,7 @@ JSC_CLASS_AVAILABLE(macosx(JSC_MAC_TBA), > @param vm The JSVirtualMachine the script can be evaluated in. > @result The new script. > */ >-+ (nullable instancetype)scriptWithSource:(NSString *)source inVirtualMachine:(JSVirtualMachine *)vm; >++ (nullable instancetype)scriptWithSource:(NSString *)source inVirtualMachine:(JSVirtualMachine *)vm /*JSC_API_DEPRECATED(macosx(JSC_MAC_TBA), ios(JSC_IOS_TBA))*/; > > /*! > @method >@@ -55,13 +67,43 @@ JSC_CLASS_AVAILABLE(macosx(JSC_MAC_TBA), > > If the file at filePath is not ascii this method will return nil. > */ >-+ (nullable instancetype)scriptFromASCIIFile:(NSURL *)filePath inVirtualMachine:(JSVirtualMachine *)vm withCodeSigning:(nullable NSURL *)codeSigningPath andBytecodeCache:(nullable NSURL *)cachePath; >- >++ (nullable instancetype)scriptFromASCIIFile:(NSURL *)filePath inVirtualMachine:(JSVirtualMachine *)vm withCodeSigning:(nullable NSURL *)codeSigningPath andBytecodeCache:(nullable NSURL *)cachePath /*JSC_API_DEPRECATED(macosx(JSC_MAC_TBA), ios(JSC_IOS_TBA))*/; > > /*! > This is deprecated and is equivalent to scriptFromASCIIFile:inVirtualMachine:withCodeSigning:andBytecodeCache:. > */ >-+ (nullable instancetype)scriptFromUTF8File:(NSURL *)filePath inVirtualMachine:(JSVirtualMachine *)vm withCodeSigning:(nullable NSURL *)codeSigningPath andBytecodeCache:(nullable NSURL *)cachePath; >++ (nullable instancetype)scriptFromUTF8File:(NSURL *)filePath inVirtualMachine:(JSVirtualMachine *)vm withCodeSigning:(nullable NSURL *)codeSigningPath andBytecodeCache:(nullable NSURL *)cachePath /*JSC_API_DEPRECATED(macosx(JSC_MAC_TBA), ios(JSC_IOS_TBA))*/; >+ >+/*! >+ @method >+ @abstract Create a JSScript for the specified virtual machine. >+ @param type The type of JavaScript source. >+ @param vm The JSVirtualMachine the script can be evaluated in. >+ @param sourceURL The source URL to associate with this script. For modules, this is the module identifier. >+ @param source The source code to use when the script is evaluated by the JS vm. >+ @param cachePath A URL containing the path where the VM should cache for future execution. >+ @param error A description of why the script could not be created if the result is nil. >+ @result The new script. >+ */ >++ (nullable instancetype)scriptOfType:(JSScriptType)type inVirtualMachine:(JSVirtualMachine *)vm withSourceURL:(NSURL *)sourceURL andSource:(NSString *)source andBytecodeCache:(nullable NSURL *)cachePath error:(out NSError * _Nullable * _Nullable)error; >+ >+/*! >+ @method >+ @abstract Create a JSScript for the specified virtual machine with a path to a codesigning and bytecode caching. >+ @param type The type of JavaScript source. >+ @param vm The JSVirtualMachine the script can be evaluated in. >+ @param filePath A URL containing the path to a JS source code file on disk. >+ @param sourceURL The source URL to associate with this script. For modules, this is the module identifier. >+ @param cachePath A URL containing the path where the VM should cache for future execution. >+ @param error A description of why the script could not be created if the result is nil. >+ @result The new script. >+ @discussion The files at filePath and cachePath should not be externally modified for the lifecycle of vm. This method will file back the memory for the source. >+ >+ If the file at filePath is not ascii this method will return nil. >+ */ >++ (nullable instancetype)scriptOfType:(JSScriptType)type inVirtualMachine:(JSVirtualMachine *)vm memoryMappedFromASCIIFile:(NSURL *)filePath withSourceURL:(NSURL *)sourceURL andBytecodeCache:(nullable NSURL *)cachePath error:(out NSError * _Nullable * _Nullable)error; >+ >+- (BOOL)cacheBytecodeWithError:(out NSError * _Nullable * _Nullable)error; > > @end > >Index: Source/JavaScriptCore/API/JSScript.mm >=================================================================== >--- Source/JavaScriptCore/API/JSScript.mm (revision 241767) >+++ Source/JavaScriptCore/API/JSScript.mm (working copy) >@@ -36,12 +36,16 @@ > #import "ParserError.h" > #import "Symbol.h" > #include <sys/stat.h> >+#include <wtf/FileSystem.h> > > #if JSC_OBJC_API_ENABLED > > @implementation JSScript { > __weak JSVirtualMachine* m_virtualMachine; >+ JSScriptType m_type; >+ FileSystem::MappedFileData m_mappedSource; > String m_source; >+ RetainPtr<NSURL> m_sourceURL; > RetainPtr<NSURL> m_cachePath; > JSC::CachedBytecode m_cachedBytecode; > JSC::Strong<JSC::JSSourceCode> m_jsSourceCode; >@@ -116,6 +120,53 @@ + (instancetype)scriptFromUTF8File:(NSUR > return [JSScript scriptFromASCIIFile:filePath inVirtualMachine:vm withCodeSigning:codeSigningPath andBytecodeCache:cachePath]; > } > >+static JSScript *createError(NSString *message, NSError** error) >+{ >+ if (error) >+ *error = [NSError errorWithDomain:@"JSScriptErrorDomain" code:1 userInfo:@{ @"message": message }]; >+ return nil; >+} >+ >++ (instancetype)scriptOfType:(JSScriptType)type inVirtualMachine:(JSVirtualMachine *)vm withSourceURL:(NSURL *)sourceURL andSource:(NSString *)source andBytecodeCache:(NSURL *)cachePath error:(out NSError **)error >+{ >+ UNUSED_PARAM(error); >+ JSScript *result = [[[JSScript alloc] init] autorelease]; >+ result->m_virtualMachine = vm; >+ result->m_type = type; >+ result->m_source = source; >+ result->m_sourceURL = sourceURL; >+ result->m_cachePath = cachePath; >+ [result readCache]; >+ return result; >+} >+ >++ (instancetype)scriptOfType:(JSScriptType)type inVirtualMachine:(JSVirtualMachine *)vm memoryMappedFromASCIIFile:(NSURL *)filePath withSourceURL:(NSURL *)sourceURL andBytecodeCache:(NSURL *)cachePath error:(out NSError **)error >+{ >+ UNUSED_PARAM(error); >+ URL filePathURL([filePath absoluteURL]); >+ if (!filePathURL.isLocalFile()) >+ return createError([NSString stringWithFormat:@"File path %@ is not a local file", static_cast<NSString *>(filePathURL)], error); >+ >+ bool success = false; >+ String systemPath = filePathURL.fileSystemPath(); >+ FileSystem::MappedFileData fileData(systemPath, success); >+ if (!success) >+ return createError([NSString stringWithFormat:@"File at path %@ could not be mapped.", static_cast<NSString *>(systemPath)], error); >+ >+ if (!charactersAreAllASCII(reinterpret_cast<const LChar*>(fileData.data()), fileData.size())) >+ return createError([NSString stringWithFormat:@"Not all characters in file at %@ are ASCII.", static_cast<NSString *>(systemPath)], error); >+ >+ JSScript *result = [[[JSScript alloc] init] autorelease]; >+ result->m_virtualMachine = vm; >+ result->m_type = type; >+ result->m_source = String(StringImpl::createWithoutCopying(bitwise_cast<const LChar*>(fileData.data()), fileData.size())); >+ result->m_mappedSource = WTFMove(fileData); >+ result->m_sourceURL = sourceURL; >+ result->m_cachePath = cachePath; >+ [result readCache]; >+ return result; >+} >+ > - (void)dealloc > { > if (m_cachedBytecode.size() && !m_cachedBytecode.owned()) >@@ -152,22 +203,14 @@ - (void)readCache > m_cachedBytecode = JSC::CachedBytecode { buffer, size }; > } > >-- (void)writeCache >+- (BOOL)cacheBytecodeWithError:(NSError **)error > { >- if (m_cachedBytecode.size() || !m_cachePath) >- return; >- >- JSC::ParserError error; >- m_cachedBytecode = JSC::generateModuleBytecode(m_virtualMachine.vm, m_jsSourceCode->sourceCode(), error); >- if (error.isValid()) >- return; >- int fd = open([m_cachePath path].UTF8String, O_CREAT | O_WRONLY, 0666); >- if (fd == -1) >- return; >- int rc = flock(fd, LOCK_EX | LOCK_NB); >- if (!rc) >- write(fd, m_cachedBytecode.data(), m_cachedBytecode.size()); >- close(fd); >+ String errorString { }; >+ [self writeCache:errorString]; >+ if (!errorString.isNull()) >+ return !!createError(errorString, error); >+ >+ return YES; > } > > @end >@@ -189,24 +232,80 @@ - (const JSC::CachedBytecode*)cachedByte > return &m_cachedBytecode; > } > >-- (JSC::JSSourceCode*)jsSourceCode:(const JSC::Identifier&)moduleKey >+- (NSURL *)sourceURL >+{ >+ if (!m_sourceURL) >+ dataLogLn("No source URL!"); >+ return m_sourceURL.get(); >+} >+ >+- (JSScriptType)type > { >- if (m_jsSourceCode) { >- ASSERT(moduleKey.impl() == m_moduleKey); >+ return m_type; >+} >+ >+- (JSC::JSSourceCode*)jsSourceCode >+{ >+ if (m_jsSourceCode) > return m_jsSourceCode.get(); >- } > > JSC::VM& vm = m_virtualMachine.vm; >+ JSC::JSLockHolder locker(vm); >+ > TextPosition startPosition { }; >- Ref<JSScriptSourceProvider> sourceProvider = JSScriptSourceProvider::create(self, JSC::SourceOrigin(moduleKey.string()), URL({ }, moduleKey.string()), TextPosition(), JSC::SourceProviderSourceType::Module); >+ >+ String url = String { [[self sourceURL] absoluteString] }; >+ dataLogLn("jsSourceCode URL=", url); >+ auto type = m_type == kJSScriptTypeModule ? JSC::SourceProviderSourceType::Module : JSC::SourceProviderSourceType::Program; >+ Ref<JSScriptSourceProvider> sourceProvider = JSScriptSourceProvider::create(self, JSC::SourceOrigin(url), URL({ }, url), startPosition, type); > JSC::SourceCode sourceCode(WTFMove(sourceProvider), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()); > JSC::JSSourceCode* jsSourceCode = JSC::JSSourceCode::create(vm, WTFMove(sourceCode)); > m_jsSourceCode.set(vm, jsSourceCode); >- [self writeCache]; > return jsSourceCode; > } > >-@end >+- (BOOL)writeCache:(String&)error >+{ >+ if (m_cachedBytecode.size()) { >+ dataLogLn("Already have cached bytecode!"); >+ return YES; >+ } >+ >+ if (!m_cachePath) { >+ error = "no cache path provided"; >+ return NO; >+ } >+ >+ JSC::ParserError parserError; >+ switch (m_type) { >+ case kJSScriptTypeModule: >+ m_cachedBytecode = JSC::generateModuleBytecode(m_virtualMachine.vm, [self jsSourceCode]->sourceCode(), parserError); >+ break; >+ case kJSScriptTypeProgram: >+ m_cachedBytecode = JSC::generateBytecode(m_virtualMachine.vm, [self jsSourceCode]->sourceCode(), parserError); >+ break; >+ } >+ >+ if (parserError.isValid()) { >+ m_cachedBytecode = { }; >+ error = "unable to generate complete bytecode"; >+ return NO; >+ } >+ int fd = open([m_cachePath path].UTF8String, O_CREAT | O_WRONLY, 0666); >+ if (fd == -1) { >+ error = makeString("Unable to open file: ", [m_cachePath path].UTF8String, " due to error: ", strerror(errno)); >+ return NO; >+ } >+ int returnCode = flock(fd, LOCK_EX | LOCK_NB); >+ if (returnCode) >+ error = "Unable to lock the cache file; it may already be in use."; >+ else >+ write(fd, m_cachedBytecode.data(), m_cachedBytecode.size()); >+ dataLogLn("Wrote cached bytecode!"); >+ close(fd); >+ return !returnCode; >+} > >+@end > > #endif >Index: Source/JavaScriptCore/API/JSScriptInternal.h >=================================================================== >--- Source/JavaScriptCore/API/JSScriptInternal.h (revision 241767) >+++ Source/JavaScriptCore/API/JSScriptInternal.h (working copy) >@@ -46,8 +46,11 @@ class String; > > - (unsigned)hash; > - (const WTF::String&)source; >-- (const JSC::CachedBytecode*)cachedBytecode; >-- (JSC::JSSourceCode*)jsSourceCode:(const JSC::Identifier&)moduleKey; >+- (nullable const JSC::CachedBytecode*)cachedBytecode; >+- (JSC::JSSourceCode*)jsSourceCode; >+- (BOOL)writeCache:(String&)error; >+- (NSURL *)sourceURL; >+- (JSScriptType)type; > > @end > >Index: Source/JavaScriptCore/API/JSScriptSourceProvider.mm >=================================================================== >--- Source/JavaScriptCore/API/JSScriptSourceProvider.mm (revision 241767) >+++ Source/JavaScriptCore/API/JSScriptSourceProvider.mm (working copy) >@@ -42,7 +42,10 @@ StringView JSScriptSourceProvider::sourc > > const JSC::CachedBytecode* JSScriptSourceProvider::cachedBytecode() const > { >- return [m_script.get() cachedBytecode]; >+ auto* result = [m_script.get() cachedBytecode]; >+ if (result) >+ dataLogLn("returning non-null cached bytecode!"); >+ return result; > } > > #endif // JSC_OBJC_API_ENABLED >Index: Source/JavaScriptCore/API/tests/testIncludes.m >=================================================================== >--- Source/JavaScriptCore/API/tests/testIncludes.m (revision 241767) >+++ Source/JavaScriptCore/API/tests/testIncludes.m (working copy) >@@ -27,6 +27,7 @@ > // Since we include files that haven't passed through the rewriter we need to handle the non-rewritten values... > #define JSC_API_AVAILABLE(...) > #define JSC_CLASS_AVAILABLE(...) >+#define JSC_API_DEPRECATED(...) > #define JSC_MAC_VERSION_TBA 0 > #define JSC_IOS_VERSION_TBA 0 > >Index: Source/JavaScriptCore/API/tests/testapi.c >=================================================================== >--- Source/JavaScriptCore/API/tests/testapi.c (revision 241767) >+++ Source/JavaScriptCore/API/tests/testapi.c (working copy) >@@ -67,7 +67,7 @@ > #endif > > #if JSC_OBJC_API_ENABLED >-void testObjectiveCAPI(void); >+void testObjectiveCAPI(const char*); > #endif > > int testCAPIViaCpp(const char* filter); >@@ -1380,11 +1380,11 @@ int main(int argc, char* argv[]) > SetErrorMode(0); > #endif > >+ const char* filter = argc > 1 ? argv[1] : NULL; > #if JSC_OBJC_API_ENABLED >- testObjectiveCAPI(); >+ testObjectiveCAPI(filter); > #endif > >- const char* filter = argc > 1 ? argv[1] : NULL; > RELEASE_ASSERT(!testCAPIViaCpp(filter)); > if (filter) > return 0; >Index: Source/JavaScriptCore/API/tests/testapi.mm >=================================================================== >--- Source/JavaScriptCore/API/tests/testapi.mm (revision 241767) >+++ Source/JavaScriptCore/API/tests/testapi.mm (working copy) >@@ -41,12 +41,14 @@ > #import "Regress141275.h" > #import "Regress141809.h" > >+#import <libproc.h> > #import <pthread.h> > #import <vector> > #import <wtf/MemoryFootprint.h> > #import <wtf/Optional.h> > #import <wtf/DataLog.h> > >+ > extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef); > extern "C" void JSSynchronousEdenCollectForDebugging(JSContextRef); > >@@ -54,7 +56,7 @@ extern "C" bool _Block_has_signature(id) > extern "C" const char * _Block_signature(id); > > extern int failed; >-extern "C" void testObjectiveCAPI(void); >+extern "C" void testObjectiveCAPI(const char*); > extern "C" void checkResult(NSString *, bool); > > #if JSC_OBJC_API_ENABLED >@@ -1985,9 +1987,9 @@ static void testBytecodeCache() > @autoreleasepool { > NSURL* tempDirectory = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES]; > >- NSString* fooSource = @"import { n } from \"../foo.js\"; export let foo = n;"; >- NSString* barSource = @"import \"otherDirectory/baz.js\"; export let n = null;"; >- NSString* bazSource = @"import { foo } from \"../directory/bar.js\"; globalThis.ran = null; export let exp = foo;"; >+ NSString* fooSource = @"import \"otherDirectory/baz.js\"; export let n = null;"; >+ NSString* barSource = @"import { n } from \"../foo.js\"; export let foo = () => n;"; >+ NSString* bazSource = @"import { foo } from \"../directory/bar.js\"; globalThis.ran = null; export let exp = foo();"; > > NSURL* fooPath = [tempDirectory URLByAppendingPathComponent:@"foo.js"]; > NSURL* barPath = [tempDirectory URLByAppendingPathComponent:@"bar.js"]; >@@ -2023,12 +2025,14 @@ static void testBytecodeCache() > } > > NSFileManager* fileManager = [NSFileManager defaultManager]; >- [fileManager removeItemAtURL:fooPath error:nil]; >- [fileManager removeItemAtURL:barPath error:nil]; >- [fileManager removeItemAtURL:bazPath error:nil]; >- [fileManager removeItemAtURL:fooCachePath error:nil]; >- [fileManager removeItemAtURL:barCachePath error:nil]; >- [fileManager removeItemAtURL:bazCachePath error:nil]; >+ BOOL removedAll = true; >+ removedAll &= [fileManager removeItemAtURL:fooPath error:nil]; >+ removedAll &= [fileManager removeItemAtURL:barPath error:nil]; >+ removedAll &= [fileManager removeItemAtURL:bazPath error:nil]; >+ removedAll &= [fileManager removeItemAtURL:fooCachePath error:nil]; >+ removedAll &= [fileManager removeItemAtURL:barCachePath error:nil]; >+ removedAll &= [fileManager removeItemAtURL:bazCachePath error:nil]; >+ checkResult(@"Removed all temp files created", removedAll); > } > } > >@@ -2078,7 +2082,7 @@ - (void)context:(JSContext *)context fet > > @end > >-static void testLoadBasicFile() >+static void testLoadBasicFileLegacySPI() > { > @autoreleasepool { > auto *context = [JSContextFileLoaderDelegate newContext]; >@@ -2089,34 +2093,163 @@ static void testLoadBasicFile() > } > } > >-void testObjectiveCAPI() >+ >+@interface JSContextMemoryMappedLoaderDelegate : JSContext <JSModuleLoaderDelegate> >+ >++ (instancetype)newContext; >+ >+@end >+ >+@implementation JSContextMemoryMappedLoaderDelegate { >+} >+ >++ (instancetype)newContext >+{ >+ auto *result = [[JSContextMemoryMappedLoaderDelegate alloc] init]; >+ return result; >+} >+ >+- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject >+{ >+ NSURL *filePath = [NSURL URLWithString:[identifier toString]]; >+ dataLogLn("inside fetchModuleForIdentifier"); >+ NSLog(@"file path=%@", filePath); >+ auto *script = [JSScript scriptOfType:kJSScriptTypeModule inVirtualMachine:context.virtualMachine memoryMappedFromASCIIFile:filePath withSourceURL:filePath andBytecodeCache:nil error:nil]; >+ if (script) >+ [resolve callWithArguments:@[script]]; >+ else >+ [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Unable to create Script" inContext:context]]]; >+} >+ >+@end >+ >+static void testLoadBasicFile() >+{ >+ size_t count = proc_pidinfo(getpid(), PROC_PIDLISTFDS, 0, 0, 0); >+ @autoreleasepool { >+ auto *context = [JSContextMemoryMappedLoaderDelegate newContext]; >+ context.moduleLoaderDelegate = context; >+ JSValue *promise = [context evaluateScript:@"import('./basic.js');" withSourceURL:resolvePathToScripts()]; >+ JSValue *null = [JSValue valueWithNullInContext:context]; >+ size_t afterCount = proc_pidinfo(getpid(), PROC_PIDLISTFDS, 0, 0, 0); >+ checkResult(@"JSScript should not hold a file descriptor", count == afterCount); >+ checkModuleCodeRan(context, promise, null); >+ } >+ size_t after = proc_pidinfo(getpid(), PROC_PIDLISTFDS, 0, 0, 0); >+ checkResult(@"File descriptor count sholudn't change after context is dealloced", count == after); >+} >+ >+@interface JSContextAugmentedLoaderDelegate : JSContext <JSModuleLoaderDelegate> >+ >++ (instancetype)newContext; >+ >+@end >+ >+@implementation JSContextAugmentedLoaderDelegate { >+} >+ >++ (instancetype)newContext >+{ >+ auto *result = [[JSContextAugmentedLoaderDelegate alloc] init]; >+ return result; >+} >+ >+- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject >+{ >+ UNUSED_PARAM(reject); >+ >+ NSURL *filePath = [NSURL URLWithString:[identifier toString]]; >+ NSString *pathString = [filePath absoluteString]; >+ if ([pathString containsString:@"basic.js"] || [pathString containsString:@"foo.js"]) { >+ auto *script = [JSScript scriptOfType:kJSScriptTypeModule inVirtualMachine:context.virtualMachine memoryMappedFromASCIIFile:filePath withSourceURL:filePath andBytecodeCache:nil error:nil]; >+ RELEASE_ASSERT(script); >+ [resolve callWithArguments:@[script]]; >+ return; >+ } >+ >+ if ([pathString containsString:@"bar.js"]) { >+ auto *script = [JSScript scriptOfType:kJSScriptTypeModule inVirtualMachine:context.virtualMachine withSourceURL:[NSURL fileURLWithPath:@"/not/path/to/bar.js"] andSource:@"" andBytecodeCache:nil error:nil]; >+ RELEASE_ASSERT(script); >+ [resolve callWithArguments:@[script]]; >+ return; >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+@end >+ >+static void testJSScriptURL() >+{ >+ @autoreleasepool { >+ auto *context = [JSContextAugmentedLoaderDelegate newContext]; >+ context.moduleLoaderDelegate = context; >+ NSURL *basic = [NSURL URLWithString:@"./basic.js" relativeToURL:resolvePathToScripts()]; >+ JSScript *script1 = [JSScript scriptOfType:kJSScriptTypeModule inVirtualMachine:context.virtualMachine memoryMappedFromASCIIFile:basic withSourceURL:basic andBytecodeCache:nil error:nil]; >+ >+ JSValue *result1 = [context evaluateJSScript:script1]; >+ JSValue *null = [JSValue valueWithNullInContext:context]; >+ checkModuleCodeRan(context, result1, null); >+ >+ NSURL *foo = [NSURL URLWithString:@"./foo.js" relativeToURL:resolvePathToScripts()]; >+ JSScript *script2 = [JSScript scriptOfType:kJSScriptTypeModule inVirtualMachine:context.virtualMachine memoryMappedFromASCIIFile:foo withSourceURL:foo andBytecodeCache:nil error:nil]; >+ RELEASE_ASSERT(script2); >+ JSValue *result2 = [context evaluateJSScript:script2]; >+ >+ __block bool wasRejected = false; >+ [result2 invokeMethod:@"catch" withArguments:@[^(JSValue *reason) { >+ wasRejected = [reason isObject]; >+ }]]; >+ >+ checkResult(@"Module JSScript imported with different identifiers is rejected", wasRejected); >+ } >+} >+ >+#define RUN(test) do { \ >+ if (!shouldRun(#test)) \ >+ break; \ >+ NSLog(@"%s...\n", #test); \ >+ test; \ >+ NSLog(@"%s: done.\n", #test); \ >+ } while (false) >+ >+void testObjectiveCAPI(const char* filter) > { > NSLog(@"Testing Objective-C API"); > >- checkNegativeNSIntegers(); >- runJITThreadLimitTests(); >+ auto shouldRun = [&] (const char* test) -> bool { >+ if (filter) >+ return strcasestr(test, filter); >+ return true; >+ }; >+ >+ RUN(checkNegativeNSIntegers()); >+ RUN(runJITThreadLimitTests()); >+ >+ RUN(testLoaderResolvesAbsoluteScriptURL()); >+ RUN(testFetch()); >+ RUN(testFetchWithTwoCycle()); >+ RUN(testFetchWithThreeCycle()); >+ RUN(testImportModuleTwice()); >+ RUN(testBytecodeCache()); > >- testLoaderResolvesAbsoluteScriptURL(); >- testFetch(); >- testFetchWithTwoCycle(); >- testFetchWithThreeCycle(); >- testImportModuleTwice(); >- testBytecodeCache(); >+ RUN(testLoaderRejectsNilScriptURL()); >+ RUN(testLoaderRejectsFailedFetch()); > >- testLoaderRejectsNilScriptURL(); >- testLoaderRejectsFailedFetch(); >+ RUN(testJSScriptURL()); > > // File loading >- testLoadBasicFile(); >+ RUN(testLoadBasicFileLegacySPI()); >+ RUN(testLoadBasicFile()); > >- promiseWithExecutor(Resolution::ResolveEager); >- promiseWithExecutor(Resolution::RejectEager); >- promiseWithExecutor(Resolution::ResolveLate); >- promiseWithExecutor(Resolution::RejectLate); >- promiseRejectOnJSException(); >- promiseCreateResolved(); >- promiseCreateRejected(); >- parallelPromiseResolveTest(); >+ RUN(promiseWithExecutor(Resolution::ResolveEager)); >+ RUN(promiseWithExecutor(Resolution::RejectEager)); >+ RUN(promiseWithExecutor(Resolution::ResolveLate)); >+ RUN(promiseWithExecutor(Resolution::RejectLate)); >+ RUN(promiseRejectOnJSException()); >+ RUN(promiseCreateResolved()); >+ RUN(promiseCreateRejected()); >+ RUN(parallelPromiseResolveTest()); > > testObjectiveCAPIMain(); > } >Index: Source/JavaScriptCore/API/tests/testapiScripts/foo.js >=================================================================== >--- Source/JavaScriptCore/API/tests/testapiScripts/foo.js (nonexistent) >+++ Source/JavaScriptCore/API/tests/testapiScripts/foo.js (working copy) >@@ -0,0 +1,26 @@ >+/* >+ * Copyright (C) 2019 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 "./bar.js"; >Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 241767) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -884,6 +884,7 @@ > 52B311011975B4670080857C /* TypeLocationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B311001975B4670080857C /* TypeLocationCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 52C952B719A289850069B386 /* TypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C952B619A289850069B386 /* TypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 52D13091221CE176009C836C /* foo.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 52D1308F221CE03A009C836C /* foo.js */; }; > 52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; }; > 530A66B91FA3E78B0026A545 /* UnifiedSource3-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 530A66B11FA3E77A0026A545 /* UnifiedSource3-mm.mm */; }; > 530A66BA1FA3E78B0026A545 /* UnifiedSource4-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 530A66B81FA3E77E0026A545 /* UnifiedSource4-mm.mm */; }; >@@ -1160,6 +1161,7 @@ > 797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 7980C16D1E3A940E00B71615 /* DFGRegisteredStructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 7980C16B1E3A940E00B71615 /* DFGRegisteredStructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 7986943B1F8C0ACC009232AE /* StructureCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 7986943A1F8C0AC8009232AE /* StructureCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 79872C48221BBAF3008C6969 /* JSBaseInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 79872C47221BBAED008C6969 /* JSBaseInternal.h */; }; > 798937791DCAB57300F8D4FB /* JSFixedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 798937771DCAB57300F8D4FB /* JSFixedArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 79A090801D768465008B889B /* HashMapImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A0907E1D768465008B889B /* HashMapImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -2028,6 +2030,7 @@ > dstPath = testapiScripts; > dstSubfolderSpec = 16; > files = ( >+ 52D13091221CE176009C836C /* foo.js in Copy Support Script */, > 53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */, > FECB8B2A1D25CB5A006F2463 /* testapi-function-overrides.js in Copy Support Script */, > 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */, >@@ -3376,6 +3379,7 @@ > 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeType.h; sourceTree = "<group>"; }; > 52C952B619A289850069B386 /* TypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeProfiler.h; sourceTree = "<group>"; }; > 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = "<group>"; }; >+ 52D1308F221CE03A009C836C /* foo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = foo.js; sourceTree = "<group>"; }; > 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyWrapperFunction.cpp; path = js/WebAssemblyWrapperFunction.cpp; sourceTree = "<group>"; }; > 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyWrapperFunction.h; path = js/WebAssemblyWrapperFunction.h; sourceTree = "<group>"; }; > 530A63401FA3E31C0026A545 /* SourcesCocoa.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SourcesCocoa.txt; sourceTree = "<group>"; }; >@@ -3771,6 +3775,7 @@ > 7980C16B1E3A940E00B71615 /* DFGRegisteredStructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRegisteredStructureSet.h; path = dfg/DFGRegisteredStructureSet.h; sourceTree = "<group>"; }; > 798694391F8C0AC7009232AE /* StructureCache.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StructureCache.cpp; sourceTree = "<group>"; }; > 7986943A1F8C0AC8009232AE /* StructureCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StructureCache.h; sourceTree = "<group>"; }; >+ 79872C47221BBAED008C6969 /* JSBaseInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSBaseInternal.h; sourceTree = "<group>"; }; > 798937761DCAB57300F8D4FB /* JSFixedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFixedArray.cpp; sourceTree = "<group>"; }; > 798937771DCAB57300F8D4FB /* JSFixedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFixedArray.h; sourceTree = "<group>"; }; > 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PCToOriginMap.h; path = b3/B3PCToOriginMap.h; sourceTree = "<group>"; }; >@@ -5991,6 +5996,7 @@ > C2CF39BF16E15A8100DD69BE /* JSAPIWrapperObject.mm */, > 1421359A0A677F4F00A8195E /* JSBase.cpp */, > 142711380A460BBB0080EEEA /* JSBase.h */, >+ 79872C47221BBAED008C6969 /* JSBaseInternal.h */, > 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */, > 1440F8AD0A508D200005F061 /* JSCallbackConstructor.cpp */, > 1440F8AC0A508D200005F061 /* JSCallbackConstructor.h */, >@@ -6335,6 +6341,7 @@ > isa = PBXGroup; > children = ( > 53C3D5E421ECE6CE0087FDFC /* basic.js */, >+ 52D1308F221CE03A009C836C /* foo.js */, > ); > name = testapiScripts; > path = API/tests/testapiScripts; >@@ -9750,6 +9757,7 @@ > 0FF42748158EBE91004CB9FF /* udis86_syn.h in Headers */, > 0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */, > A7E5AB391799E4B200D2833D /* UDis86Disassembler.h in Headers */, >+ 79872C48221BBAF3008C6969 /* JSBaseInternal.h in Headers */, > A7A8AF4117ADB5F3005AB174 /* Uint16Array.h in Headers */, > 866739D313BFDE710023D87C /* Uint16WithFraction.h in Headers */, > A7A8AF4217ADB5F3005AB174 /* Uint32Array.h in Headers */, >Index: Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >=================================================================== >--- Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h (revision 241767) >+++ Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h (working copy) >@@ -191,7 +191,7 @@ public: > > private: > UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, CompactVariableMap::Handle, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor); >- UnlinkedFunctionExecutable(Decoder&, VariableEnvironment&, const CachedFunctionExecutable&); >+ UnlinkedFunctionExecutable(Decoder&, CompactVariableMap::Handle, const CachedFunctionExecutable&); > > unsigned m_firstLineOffset; > unsigned m_lineCount; >Index: Source/JavaScriptCore/parser/VariableEnvironment.h >=================================================================== >--- Source/JavaScriptCore/parser/VariableEnvironment.h (revision 241767) >+++ Source/JavaScriptCore/parser/VariableEnvironment.h (working copy) >@@ -125,6 +125,9 @@ private: > class CompactVariableEnvironment { > WTF_MAKE_FAST_ALLOCATED; > WTF_MAKE_NONCOPYABLE(CompactVariableEnvironment); >+ >+ friend class CachedCompactVariableEnvironment; >+ > public: > CompactVariableEnvironment(const VariableEnvironment&); > VariableEnvironment toVariableEnvironment() const; >@@ -133,6 +136,8 @@ public: > unsigned hash() const { return m_hash; } > > private: >+ CompactVariableEnvironment() = default; >+ > Vector<RefPtr<UniquedStringImpl>> m_variables; > Vector<VariableEnvironmentEntry> m_variableMetadata; > unsigned m_hash; >@@ -174,6 +179,8 @@ struct CompactVariableMapKey { > } > > private: >+ friend class CachedCompactVariableMapKey; >+ > CompactVariableEnvironment* m_environment; > }; > >@@ -202,8 +209,12 @@ template<> struct HashTraits<JSC::Compac > namespace JSC { > > class CompactVariableMap : public RefCounted<CompactVariableMap> { >+ friend class CachedCompactVariableMap; >+ > public: > class Handle { >+ friend class CachedCompactVariableMapHandle; >+ > public: > Handle() = default; > >Index: Source/JavaScriptCore/runtime/CachedTypes.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/CachedTypes.cpp (revision 241767) >+++ Source/JavaScriptCore/runtime/CachedTypes.cpp (working copy) >@@ -215,9 +215,10 @@ class Decoder { > WTF_FORBID_HEAP_ALLOCATION; > > public: >- Decoder(VM& vm, const void* baseAddress, size_t size) >+ Decoder(VM& vm, const void* baseAddress, size_t size, URL&& sourceURLOverride) > : m_vm(vm) > , m_baseAddress(reinterpret_cast<const uint8_t*>(baseAddress)) >+ , m_sourceURLOverride(WTFMove(sourceURLOverride)) > #ifndef NDEBUG > , m_size(size) > #endif >@@ -259,9 +260,12 @@ public: > m_finalizers.add(offset, fn); > } > >+ const URL& sourceURLOverride() { return m_sourceURLOverride; } >+ > private: > VM& m_vm; > const uint8_t* m_baseAddress; >+ URL m_sourceURLOverride; > #ifndef NDEBUG > size_t m_size; > #endif >@@ -878,6 +882,98 @@ private: > CachedHashMap<CachedRefPtr<CachedUniquedStringImpl>, VariableEnvironmentEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, VariableEnvironmentEntryHashTraits> m_map; > }; > >+class CachedCompactVariableEnvironment : public CachedObject<CompactVariableEnvironment> { >+public: >+ void encode(Encoder& encoder, const CompactVariableEnvironment& env) >+ { >+ m_variables.encode(encoder, env.m_variables); >+ m_variableMetadata.encode(encoder, env.m_variableMetadata); >+ m_hash = env.m_hash; >+ m_isEverythingCaptured = env.m_isEverythingCaptured; >+ } >+ >+ void decode(Decoder& decoder, CompactVariableEnvironment& env) const >+ { >+ m_variables.decode(decoder, env.m_variables); >+ m_variableMetadata.decode(decoder, env.m_variableMetadata); >+ env.m_hash = m_hash; >+ env.m_isEverythingCaptured = m_isEverythingCaptured; >+ } >+ >+ CompactVariableEnvironment* decode(Decoder& decoder) const >+ { >+ CompactVariableEnvironment* env = new CompactVariableEnvironment; >+ decode(decoder, *env); >+ return env; >+ } >+ >+private: >+ CachedVector<CachedRefPtr<CachedUniquedStringImpl>> m_variables; >+ CachedVector<VariableEnvironmentEntry> m_variableMetadata; >+ unsigned m_hash; >+ bool m_isEverythingCaptured; >+}; >+ >+class CachedCompactVariableMapKey : public CachedObject<CompactVariableMapKey> { >+public: >+ void encode(Encoder& encoder, const CompactVariableMapKey& key) >+ { >+ m_environment.encode(encoder, key.m_environment); >+ } >+ >+ void decode(Decoder& decoder, CompactVariableMapKey& key) const >+ { >+ key.m_environment = m_environment.decode(decoder); >+ } >+ >+private: >+ CachedPtr<CachedCompactVariableEnvironment> m_environment; >+}; >+ >+class CachedCompactVariableMap : public CachedObject<CompactVariableMap> { >+public: >+ void encode(Encoder& encoder, const CompactVariableMap& map) >+ { >+ m_map.encode(encoder, map.m_map); >+ } >+ >+ void decode(Decoder& decoder, CompactVariableMap& map) const >+ { >+ m_map.decode(decoder, map.m_map); >+ } >+ >+ CompactVariableMap* decode(Decoder& decoder) const >+ { >+ CompactVariableMap* map = new CompactVariableMap; >+ decode(decoder, *map); >+ return map; >+ } >+ >+private: >+ CachedHashMap<CachedCompactVariableMapKey, unsigned> m_map; >+}; >+ >+class CachedCompactVariableMapHandle : public CachedObject<CompactVariableMap::Handle> { >+public: >+ void encode(Encoder& encoder, const CompactVariableMap::Handle& handle) >+ { >+ m_environment.encode(encoder, handle.m_environment); >+ m_map.encode(encoder, handle.m_map); >+ } >+ >+ CompactVariableMap::Handle decode(Decoder& decoder) const >+ { >+ CompactVariableMap::Handle handle; >+ handle.m_environment = m_environment.decode(decoder); >+ handle.m_map = m_map.decode(decoder); >+ return handle; >+ } >+ >+private: >+ CachedPtr<CachedCompactVariableEnvironment> m_environment; >+ CachedRefPtr<CachedCompactVariableMap> m_map; >+}; >+ > template<typename T, typename Source = SourceType<T>> > class CachedArray : public VariableLengthObject<Source*> { > public: >@@ -1301,10 +1397,16 @@ public: > { > String decodedSource = m_source.decode(decoder); > SourceOrigin decodedSourceOrigin = m_sourceOrigin.decode(decoder); >- String decodedURL = m_url.decode(decoder); >+ String decodedURLString = m_url.decode(decoder); >+ URL sourceURL; >+ if (decoder.sourceURLOverride()) { >+ decodedSourceOrigin = SourceOrigin { decoder.sourceURLOverride() }; >+ sourceURL = decoder.sourceURLOverride(); >+ } else >+ sourceURL = URL(URL(), decodedURLString); > TextPosition decodedStartPosition = m_startPosition.decode(decoder); > >- Ref<StringSourceProvider> sourceProvider = StringSourceProvider::create(decodedSource, decodedSourceOrigin, URL(URL(), decodedURL), decodedStartPosition, sourceType); >+ Ref<StringSourceProvider> sourceProvider = StringSourceProvider::create(decodedSource, decodedSourceOrigin, WTFMove(sourceURL), decodedStartPosition, sourceType); > Base::decode(decoder, sourceProvider.get()); > return &sourceProvider.leakRef(); > } >@@ -1517,7 +1619,7 @@ private: > CachedIdentifier m_ecmaName; > CachedIdentifier m_inferredName; > >- CachedVariableEnvironment m_parentScopeTDZVariables; >+ CachedCompactVariableMapHandle m_parentScopeTDZVariables; > > CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall; > CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct; >@@ -1852,7 +1954,7 @@ ALWAYS_INLINE void CachedFunctionExecuta > m_ecmaName.encode(encoder, executable.ecmaName()); > m_inferredName.encode(encoder, executable.inferredName()); > >- m_parentScopeTDZVariables.encode(encoder, executable.parentScopeTDZVariables()); >+ m_parentScopeTDZVariables.encode(encoder, executable.m_parentScopeTDZVariables); > > m_unlinkedCodeBlockForCall.encode(encoder, executable.m_unlinkedCodeBlockForCall); > m_unlinkedCodeBlockForConstruct.encode(encoder, executable.m_unlinkedCodeBlockForConstruct); >@@ -1860,10 +1962,8 @@ ALWAYS_INLINE void CachedFunctionExecuta > > ALWAYS_INLINE UnlinkedFunctionExecutable* CachedFunctionExecutable::decode(Decoder& decoder) const > { >- VariableEnvironment env; >- m_parentScopeTDZVariables.decode(decoder, env); >- >- UnlinkedFunctionExecutable* executable = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(decoder.vm().heap)) UnlinkedFunctionExecutable(decoder, env, *this); >+ CompactVariableMap::Handle env = m_parentScopeTDZVariables.decode(decoder); >+ UnlinkedFunctionExecutable* executable = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(decoder.vm().heap)) UnlinkedFunctionExecutable(decoder, WTFMove(env), *this); > executable->finishCreation(decoder.vm()); > > m_unlinkedCodeBlockForCall.decode(decoder, executable->m_unlinkedCodeBlockForCall, executable); >@@ -1872,7 +1972,7 @@ ALWAYS_INLINE UnlinkedFunctionExecutable > return executable; > } > >-ALWAYS_INLINE UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(Decoder& decoder, VariableEnvironment& parentScopeTDZVariables, const CachedFunctionExecutable& cachedExecutable) >+ALWAYS_INLINE UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(Decoder& decoder, CompactVariableMap::Handle parentScopeTDZVariables, const CachedFunctionExecutable& cachedExecutable) > : Base(decoder.vm(), decoder.vm().unlinkedFunctionExecutableStructure.get()) > , m_firstLineOffset(cachedExecutable.firstLineOffset()) > , m_lineCount(cachedExecutable.lineCount()) >@@ -1902,7 +2002,7 @@ ALWAYS_INLINE UnlinkedFunctionExecutable > , m_ecmaName(cachedExecutable.ecmaName(decoder)) > , m_inferredName(cachedExecutable.inferredName(decoder)) > >- , m_parentScopeTDZVariables(decoder.vm().m_compactVariableMap->get(parentScopeTDZVariables)) >+ , m_parentScopeTDZVariables(WTFMove(parentScopeTDZVariables)) > > , m_rareData(cachedExecutable.rareData(decoder)) > { >@@ -2080,19 +2180,24 @@ std::pair<MallocPtr<uint8_t>, size_t> en > return encoder.release(); > } > >-UnlinkedCodeBlock* decodeCodeBlockImpl(VM& vm, const SourceCodeKey& key, const void* buffer, size_t size) >+UnlinkedCodeBlock* decodeCodeBlockImpl(VM& vm, const SourceCodeKey& key, const void* buffer, size_t size, URL&& sourceURLOverride) > { > const auto* cachedEntry = reinterpret_cast<const GenericCacheEntry*>(buffer); >- Decoder decoder(vm, buffer, size); >+ Decoder decoder(vm, buffer, size, WTFMove(sourceURLOverride)); > std::pair<SourceCodeKey, UnlinkedCodeBlock*> entry; > { > DeferGC deferGC(vm.heap); >- if (!cachedEntry->decode(decoder, entry)) >+ if (!cachedEntry->decode(decoder, entry)) { >+ dataLogLn("can't decode codeblock 1!"); > return nullptr; >+ } > } > >- if (entry.first != key) >+ if (entry.first != key) { >+ dataLogLn("can't decode codeblock 2!"); > return nullptr; >+ } >+ dataLogLn("Returning decoded CodeBlock"); > return entry.second; > } > >Index: Source/JavaScriptCore/runtime/CachedTypes.h >=================================================================== >--- Source/JavaScriptCore/runtime/CachedTypes.h (revision 241767) >+++ Source/JavaScriptCore/runtime/CachedTypes.h (working copy) >@@ -27,6 +27,7 @@ > > #include "JSCast.h" > #include <wtf/MallocPtr.h> >+#include <wtf/URL.h> > > namespace JSC { > >@@ -34,13 +35,13 @@ class SourceCodeKey; > class UnlinkedCodeBlock; > > std::pair<MallocPtr<uint8_t>, size_t> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*); >-UnlinkedCodeBlock* decodeCodeBlockImpl(VM&, const SourceCodeKey&, const void*, size_t); >+UnlinkedCodeBlock* decodeCodeBlockImpl(VM&, const SourceCodeKey&, const void*, size_t, URL&&); > > > template<typename UnlinkedCodeBlockType> >-UnlinkedCodeBlockType* decodeCodeBlock(VM& vm, const SourceCodeKey& key, const void* buffer, size_t size) >+UnlinkedCodeBlockType* decodeCodeBlock(VM& vm, const SourceCodeKey& key, const void* buffer, size_t size, URL&& sourceURLOverride = URL()) > { >- return jsCast<UnlinkedCodeBlockType*>(decodeCodeBlockImpl(vm, key, buffer, size)); >+ return jsCast<UnlinkedCodeBlockType*>(decodeCodeBlockImpl(vm, key, buffer, size, WTFMove(sourceURLOverride))); > } > > } // namespace JSC
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 194517
:
361720
|
361924
|
362351
|
362364
|
362365
|
362414
|
362464
|
362473
|
362579
|
362626
|
362635
|
362644
|
362653
|
362654
|
362656
|
362657
|
362663