40819d75349dfaed0393b506e85d0d2425a76439
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSModuleRecord.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 "JSModuleRecord.h"
28
29 #include "Error.h"
30 #include "Interpreter.h"
31 #include "JSCInlines.h"
32 #include "JSModuleEnvironment.h"
33 #include "JSModuleNamespaceObject.h"
34 #include "UnlinkedModuleProgramCodeBlock.h"
35
36 namespace JSC {
37
38 const ClassInfo JSModuleRecord::s_info = { "ModuleRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(JSModuleRecord) };
39
40
41 Structure* JSModuleRecord::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
42 {
43     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
44 }
45
46 JSModuleRecord* JSModuleRecord::create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
47 {
48     JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);
49     instance->finishCreation(exec, vm);
50     return instance;
51 }
52 JSModuleRecord::JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
53     : Base(vm, structure, moduleKey)
54     , m_sourceCode(sourceCode)
55     , m_declaredVariables(declaredVariables)
56     , m_lexicalVariables(lexicalVariables)
57 {
58 }
59
60 void JSModuleRecord::destroy(JSCell* cell)
61 {
62     JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell);
63     thisObject->JSModuleRecord::~JSModuleRecord();
64 }
65
66 void JSModuleRecord::finishCreation(ExecState* exec, VM& vm)
67 {
68     Base::finishCreation(exec, vm);
69     ASSERT(inherits(info()));
70 }
71
72 void JSModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
73 {
74     JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell);
75     Base::visitChildren(thisObject, visitor);
76     visitor.append(&thisObject->m_moduleProgramExecutable);
77 }
78
79 void JSModuleRecord::link(ExecState* exec)
80 {
81     VM& vm = exec->vm();
82     auto scope = DECLARE_THROW_SCOPE(vm);
83
84     ModuleProgramExecutable* executable = ModuleProgramExecutable::create(exec, sourceCode());
85     if (!executable) {
86         throwSyntaxError(exec, scope);
87         return;
88     }
89     m_moduleProgramExecutable.set(vm, this, executable);
90     instantiateDeclarations(exec, executable);
91 }
92
93 void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecutable* moduleProgramExecutable)
94 {
95     VM& vm = exec->vm();
96     auto scope = DECLARE_THROW_SCOPE(vm);
97
98     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
99
100     SymbolTable* symbolTable = moduleProgramExecutable->moduleEnvironmentSymbolTable();
101     JSModuleEnvironment* moduleEnvironment = JSModuleEnvironment::create(vm, exec->lexicalGlobalObject(), exec->lexicalGlobalObject(), symbolTable, jsTDZValue(), this);
102
103     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
104     // section 15.2.1.16.4 step 9.
105     // Ensure all the indirect exports are correctly resolved to unique bindings.
106     // Even if we avoided duplicate exports in the parser, still ambiguous exports occur due to the star export (`export * from "mod"`).
107     // When we see this type of ambiguity for the indirect exports here, throw a syntax error.
108     for (const auto& pair : exportEntries()) {
109         const ExportEntry& exportEntry = pair.value;
110         if (exportEntry.type == JSModuleRecord::ExportEntry::Type::Indirect) {
111             Resolution resolution = resolveExport(exec, exportEntry.exportName);
112             switch (resolution.type) {
113             case Resolution::Type::NotFound:
114                 throwSyntaxError(exec, scope, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' is not found."));
115                 return;
116
117             case Resolution::Type::Ambiguous:
118                 throwSyntaxError(exec, scope, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));
119                 return;
120
121             case Resolution::Type::Error:
122                 throwSyntaxError(exec, scope, makeString("Indirectly exported binding name 'default' cannot be resolved by star export entries."));
123                 return;
124
125             case Resolution::Type::Resolved:
126                 break;
127             }
128         }
129     }
130
131     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
132     // section 15.2.1.16.4 step 12.
133     // Instantiate namespace objects and initialize the bindings with them if required.
134     // And ensure that all the imports correctly resolved to unique bindings.
135     for (const auto& pair : importEntries()) {
136         const ImportEntry& importEntry = pair.value;
137         AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
138         if (importEntry.isNamespace(vm)) {
139             JSModuleNamespaceObject* namespaceObject = importedModule->getModuleNamespace(exec);
140             RETURN_IF_EXCEPTION(scope, void());
141             bool putResult = false;
142             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, importEntry.localName, namespaceObject, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);
143         } else {
144             Resolution resolution = importedModule->resolveExport(exec, importEntry.importName);
145             switch (resolution.type) {
146             case Resolution::Type::NotFound:
147                 throwSyntaxError(exec, scope, makeString("Importing binding name '", String(importEntry.importName.impl()), "' is not found."));
148                 return;
149
150             case Resolution::Type::Ambiguous:
151                 throwSyntaxError(exec, scope, makeString("Importing binding name '", String(importEntry.importName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));
152                 return;
153
154             case Resolution::Type::Error:
155                 throwSyntaxError(exec, scope, makeString("Importing binding name 'default' cannot be resolved by star export entries."));
156                 return;
157
158             case Resolution::Type::Resolved:
159                 break;
160             }
161         }
162     }
163
164     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
165     // section 15.2.1.16.4 step 14.
166     // Module environment contains the heap allocated "var", "function", "let", "const", and "class".
167     // When creating the environment, we initialized all the slots with empty, it's ok for lexical values.
168     // But for "var" and "function", we should initialize it with undefined. They are contained in the declared variables.
169     for (const auto& variable : declaredVariables()) {
170         SymbolTableEntry entry = symbolTable->get(variable.key.get());
171         VarOffset offset = entry.varOffset();
172         if (!offset.isStack()) {
173             bool putResult = false;
174             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromUid(exec, variable.key.get()), jsUndefined(), /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);
175         }
176     }
177
178     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
179     // section 15.2.1.16.4 step 16-a-iv.
180     // Initialize heap allocated function declarations.
181     // They can be called before the body of the module is executed under circular dependencies.
182     UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedModuleProgramCodeBlock();
183     for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
184         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
185         SymbolTableEntry entry = symbolTable->get(unlinkedFunctionExecutable->name().impl());
186         VarOffset offset = entry.varOffset();
187         if (!offset.isStack()) {
188             ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
189             if (vm.typeProfiler() || vm.controlFlowProfiler()) {
190                 vm.functionHasExecutedCache()->insertUnexecutedRange(moduleProgramExecutable->sourceID(),
191                     unlinkedFunctionExecutable->typeProfilingStartOffset(),
192                     unlinkedFunctionExecutable->typeProfilingEndOffset());
193             }
194             JSFunction* function = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, moduleProgramExecutable->source()), moduleEnvironment);
195             bool putResult = false;
196             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, unlinkedFunctionExecutable->name(), function, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);
197         }
198     }
199
200     m_moduleEnvironment.set(vm, this, moduleEnvironment);
201 }
202
203 JSValue JSModuleRecord::evaluate(ExecState* exec)
204 {
205     if (!m_moduleProgramExecutable)
206         return jsUndefined();
207     JSValue result = exec->interpreter()->execute(m_moduleProgramExecutable.get(), exec, m_moduleEnvironment.get());
208     m_moduleProgramExecutable.clear();
209     return result;
210 }
211
212 } // namespace JSC