Fix exception scope verification failures in miscellaneous files.
[WebKit-https.git] / Source / JavaScriptCore / runtime / ModuleLoaderPrototype.cpp
1 /*
2  * Copyright (C) 2015-2016 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ModuleLoaderPrototype.h"
28
29 #include "BuiltinNames.h"
30 #include "CodeProfiling.h"
31 #include "Error.h"
32 #include "Exception.h"
33 #include "JSCInlines.h"
34 #include "JSGlobalObjectFunctions.h"
35 #include "JSInternalPromise.h"
36 #include "JSInternalPromiseDeferred.h"
37 #include "JSMap.h"
38 #include "JSModuleEnvironment.h"
39 #include "JSModuleLoader.h"
40 #include "JSModuleRecord.h"
41 #include "ModuleAnalyzer.h"
42 #include "Nodes.h"
43 #include "Parser.h"
44 #include "ParserError.h"
45
46 namespace JSC {
47
48 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeParseModule(ExecState*);
49 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeRequestedModules(ExecState*);
50 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeEvaluate(ExecState*);
51 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeModuleDeclarationInstantiation(ExecState*);
52 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeResolve(ExecState*);
53 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeFetch(ExecState*);
54 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeTranslate(ExecState*);
55 static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeInstantiate(ExecState*);
56
57 }
58
59 #include "ModuleLoaderPrototype.lut.h"
60
61 namespace JSC {
62
63 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ModuleLoaderPrototype);
64
65 const ClassInfo ModuleLoaderPrototype::s_info = { "ModuleLoader", &Base::s_info, &moduleLoaderPrototypeTable, CREATE_METHOD_TABLE(ModuleLoaderPrototype) };
66
67 /* Source for ModuleLoaderPrototype.lut.h
68 @begin moduleLoaderPrototypeTable
69     setStateToMax                  JSBuiltin                                           DontEnum|Function 2
70     newRegistryEntry               JSBuiltin                                           DontEnum|Function 1
71     ensureRegistered               JSBuiltin                                           DontEnum|Function 1
72     forceFulfillPromise            JSBuiltin                                           DontEnum|Function 2
73     fulfillFetch                   JSBuiltin                                           DontEnum|Function 2
74     fulfillTranslate               JSBuiltin                                           DontEnum|Function 2
75     fulfillInstantiate             JSBuiltin                                           DontEnum|Function 2
76     commitInstantiated             JSBuiltin                                           DontEnum|Function 3
77     instantiation                  JSBuiltin                                           DontEnum|Function 3
78     requestFetch                   JSBuiltin                                           DontEnum|Function 2
79     requestTranslate               JSBuiltin                                           DontEnum|Function 2
80     requestInstantiate             JSBuiltin                                           DontEnum|Function 2
81     requestSatisfy                 JSBuiltin                                           DontEnum|Function 2
82     requestInstantiateAll          JSBuiltin                                           DontEnum|Function 2
83     requestLink                    JSBuiltin                                           DontEnum|Function 2
84     requestReady                   JSBuiltin                                           DontEnum|Function 2
85     link                           JSBuiltin                                           DontEnum|Function 2
86     moduleDeclarationInstantiation moduleLoaderPrototypeModuleDeclarationInstantiation DontEnum|Function 2
87     moduleEvaluation               JSBuiltin                                           DontEnum|Function 2
88     evaluate                       moduleLoaderPrototypeEvaluate                       DontEnum|Function 3
89     provide                        JSBuiltin                                           DontEnum|Function 3
90     loadAndEvaluateModule          JSBuiltin                                           DontEnum|Function 3
91     loadModule                     JSBuiltin                                           DontEnum|Function 3
92     linkAndEvaluateModule          JSBuiltin                                           DontEnum|Function 2
93     parseModule                    moduleLoaderPrototypeParseModule                    DontEnum|Function 2
94     requestedModules               moduleLoaderPrototypeRequestedModules               DontEnum|Function 1
95     resolve                        moduleLoaderPrototypeResolve                        DontEnum|Function 2
96     fetch                          moduleLoaderPrototypeFetch                          DontEnum|Function 2
97     translate                      moduleLoaderPrototypeTranslate                      DontEnum|Function 3
98     instantiate                    moduleLoaderPrototypeInstantiate                    DontEnum|Function 3
99 @end
100 */
101
102 ModuleLoaderPrototype::ModuleLoaderPrototype(VM& vm, Structure* structure)
103     : JSNonFinalObject(vm, structure)
104 {
105 }
106
107 // ------------------------------ Functions --------------------------------
108
109 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeParseModule(ExecState* exec)
110 {
111     VM& vm = exec->vm();
112     auto scope = DECLARE_THROW_SCOPE(vm);
113
114     const Identifier moduleKey = exec->argument(0).toPropertyKey(exec);
115     RETURN_IF_EXCEPTION(scope, encodedJSValue());
116
117     String source = exec->argument(1).toString(exec)->value(exec);
118     RETURN_IF_EXCEPTION(scope, encodedJSValue());
119
120     SourceCode sourceCode = makeSource(source, moduleKey.impl(), TextPosition::minimumPosition(), SourceProviderSourceType::Module);
121
122     CodeProfiling profile(sourceCode);
123
124     ParserError error;
125     std::unique_ptr<ModuleProgramNode> moduleProgramNode = parse<ModuleProgramNode>(
126         &vm, sourceCode, Identifier(), JSParserBuiltinMode::NotBuiltin,
127         JSParserStrictMode::Strict, JSParserScriptMode::Module, SourceParseMode::ModuleAnalyzeMode, SuperBinding::NotNeeded, error);
128
129     if (error.isValid()) {
130         throwVMError(exec, scope, error.toErrorObject(exec->lexicalGlobalObject(), sourceCode));
131         return JSValue::encode(jsUndefined());
132     }
133     ASSERT(moduleProgramNode);
134
135     ModuleAnalyzer moduleAnalyzer(exec, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
136     RETURN_IF_EXCEPTION(scope, encodedJSValue());
137     JSModuleRecord* moduleRecord = moduleAnalyzer.analyze(*moduleProgramNode);
138
139     return JSValue::encode(moduleRecord);
140 }
141
142 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeRequestedModules(ExecState* exec)
143 {
144     VM& vm = exec->vm();
145     auto scope = DECLARE_THROW_SCOPE(vm);
146     JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(exec->argument(0));
147     if (!moduleRecord) {
148         scope.release();
149         return JSValue::encode(constructEmptyArray(exec, nullptr));
150     }
151
152     JSArray* result = constructEmptyArray(exec, nullptr, moduleRecord->requestedModules().size());
153     RETURN_IF_EXCEPTION(scope, encodedJSValue());
154     size_t i = 0;
155     for (auto& key : moduleRecord->requestedModules()) {
156         result->putDirectIndex(exec, i++, jsString(exec, key.get()));
157         RETURN_IF_EXCEPTION(scope, encodedJSValue());
158     }
159     return JSValue::encode(result);
160 }
161
162 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeModuleDeclarationInstantiation(ExecState* exec)
163 {
164     VM& vm = exec->vm();
165     auto scope = DECLARE_THROW_SCOPE(vm);
166     JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(exec->argument(0));
167     if (!moduleRecord)
168         return JSValue::encode(jsUndefined());
169
170     if (Options::dumpModuleLoadingState())
171         dataLog("Loader [link] ", moduleRecord->moduleKey(), "\n");
172
173     moduleRecord->link(exec);
174     RETURN_IF_EXCEPTION(scope, encodedJSValue());
175
176     return JSValue::encode(jsUndefined());
177 }
178
179 // ------------------------------ Hook Functions ---------------------------
180
181 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeResolve(ExecState* exec)
182 {
183     // Hook point, Loader.resolve.
184     // https://whatwg.github.io/loader/#browser-resolve
185     // Take the name and resolve it to the unique identifier for the resource location.
186     // For example, take the "jquery" and return the URL for the resource.
187     JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(exec->thisValue());
188     if (!loader)
189         return JSValue::encode(jsUndefined());
190     return JSValue::encode(loader->resolve(exec, exec->argument(0), exec->argument(1), exec->argument(2)));
191 }
192
193 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeFetch(ExecState* exec)
194 {
195     // Hook point, Loader.fetch
196     // https://whatwg.github.io/loader/#browser-fetch
197     // Take the key and fetch the resource actually.
198     // For example, JavaScriptCore shell can provide the hook fetching the resource
199     // from the local file system.
200     JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(exec->thisValue());
201     if (!loader)
202         return JSValue::encode(jsUndefined());
203     return JSValue::encode(loader->fetch(exec, exec->argument(0), exec->argument(1)));
204 }
205
206 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeTranslate(ExecState* exec)
207 {
208     // Hook point, Loader.translate
209     // https://whatwg.github.io/loader/#browser-translate
210     // Take the key and the fetched source code and translate it to the ES6 source code.
211     // Typically it is used by the transpilers.
212     JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(exec->thisValue());
213     if (!loader)
214         return JSValue::encode(jsUndefined());
215     return JSValue::encode(loader->translate(exec, exec->argument(0), exec->argument(1), exec->argument(2)));
216 }
217
218 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeInstantiate(ExecState* exec)
219 {
220     // Hook point, Loader.instantiate
221     // https://whatwg.github.io/loader/#browser-instantiate
222     // Take the key and the translated source code, and instantiate the module record
223     // by parsing the module source code.
224     // It has the chance to provide the optional module instance that is different from
225     // the ordinary one.
226     JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(exec->thisValue());
227     if (!loader)
228         return JSValue::encode(jsUndefined());
229     return JSValue::encode(loader->instantiate(exec, exec->argument(0), exec->argument(1), exec->argument(2)));
230 }
231
232 // ------------------- Additional Hook Functions ---------------------------
233
234 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeEvaluate(ExecState* exec)
235 {
236     // To instrument and retrieve the errors raised from the module execution,
237     // we inserted the hook point here.
238
239     JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(exec->thisValue());
240     if (!loader)
241         return JSValue::encode(jsUndefined());
242     return JSValue::encode(loader->evaluate(exec, exec->argument(0), exec->argument(1), exec->argument(2)));
243 }
244
245 } // namespace JSC