Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
3
* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef builtin_ModuleObject_h
8
#define builtin_ModuleObject_h
9
10
#include "mozilla/Maybe.h"
11
12
#include "jsapi.h"
13
14
#include "builtin/SelfHostingDefines.h"
15
#include "gc/ZoneAllocator.h"
16
#include "js/GCVector.h"
17
#include "js/Id.h"
18
#include "js/UniquePtr.h"
19
#include "vm/JSAtom.h"
20
#include "vm/NativeObject.h"
21
#include "vm/ProxyObject.h"
22
23
namespace js {
24
25
class ModuleEnvironmentObject;
26
class ModuleObject;
27
28
typedef Rooted<ModuleObject*> RootedModuleObject;
29
typedef Handle<ModuleObject*> HandleModuleObject;
30
typedef Rooted<ModuleEnvironmentObject*> RootedModuleEnvironmentObject;
31
typedef Handle<ModuleEnvironmentObject*> HandleModuleEnvironmentObject;
32
33
class ImportEntryObject : public NativeObject {
34
public:
35
enum {
36
ModuleRequestSlot = 0,
37
ImportNameSlot,
38
LocalNameSlot,
39
LineNumberSlot,
40
ColumnNumberSlot,
41
SlotCount
42
};
43
44
static const JSClass class_;
45
static bool isInstance(HandleValue value);
46
static ImportEntryObject* create(JSContext* cx, HandleAtom moduleRequest,
47
HandleAtom importName, HandleAtom localName,
48
uint32_t lineNumber, uint32_t columnNumber);
49
JSAtom* moduleRequest() const;
50
JSAtom* importName() const;
51
JSAtom* localName() const;
52
uint32_t lineNumber() const;
53
uint32_t columnNumber() const;
54
};
55
56
typedef Rooted<ImportEntryObject*> RootedImportEntryObject;
57
typedef Handle<ImportEntryObject*> HandleImportEntryObject;
58
59
class ExportEntryObject : public NativeObject {
60
public:
61
enum {
62
ExportNameSlot = 0,
63
ModuleRequestSlot,
64
ImportNameSlot,
65
LocalNameSlot,
66
LineNumberSlot,
67
ColumnNumberSlot,
68
SlotCount
69
};
70
71
static const JSClass class_;
72
static bool isInstance(HandleValue value);
73
static ExportEntryObject* create(JSContext* cx, HandleAtom maybeExportName,
74
HandleAtom maybeModuleRequest,
75
HandleAtom maybeImportName,
76
HandleAtom maybeLocalName,
77
uint32_t lineNumber, uint32_t columnNumber);
78
JSAtom* exportName() const;
79
JSAtom* moduleRequest() const;
80
JSAtom* importName() const;
81
JSAtom* localName() const;
82
uint32_t lineNumber() const;
83
uint32_t columnNumber() const;
84
};
85
86
typedef Rooted<ExportEntryObject*> RootedExportEntryObject;
87
typedef Handle<ExportEntryObject*> HandleExportEntryObject;
88
89
class RequestedModuleObject : public NativeObject {
90
public:
91
enum { ModuleSpecifierSlot = 0, LineNumberSlot, ColumnNumberSlot, SlotCount };
92
93
static const JSClass class_;
94
static bool isInstance(HandleValue value);
95
static RequestedModuleObject* create(JSContext* cx,
96
HandleAtom moduleSpecifier,
97
uint32_t lineNumber,
98
uint32_t columnNumber);
99
JSAtom* moduleSpecifier() const;
100
uint32_t lineNumber() const;
101
uint32_t columnNumber() const;
102
};
103
104
typedef Rooted<RequestedModuleObject*> RootedRequestedModuleObject;
105
typedef Handle<RequestedModuleObject*> HandleRequestedModuleObject;
106
107
class IndirectBindingMap {
108
public:
109
void trace(JSTracer* trc);
110
111
bool put(JSContext* cx, HandleId name,
112
HandleModuleEnvironmentObject environment, HandleId localName);
113
114
size_t count() const { return map_ ? map_->count() : 0; }
115
116
bool has(jsid name) const { return map_ ? map_->has(name) : false; }
117
118
bool lookup(jsid name, ModuleEnvironmentObject** envOut,
119
Shape** shapeOut) const;
120
121
template <typename Func>
122
void forEachExportedName(Func func) const {
123
if (!map_) {
124
return;
125
}
126
127
for (auto r = map_->all(); !r.empty(); r.popFront()) {
128
func(r.front().key());
129
}
130
}
131
132
private:
133
struct Binding {
134
Binding(ModuleEnvironmentObject* environment, Shape* shape);
135
HeapPtr<ModuleEnvironmentObject*> environment;
136
HeapPtr<Shape*> shape;
137
};
138
139
using Map = HashMap<PreBarrieredId, Binding, DefaultHasher<PreBarrieredId>,
140
ZoneAllocPolicy>;
141
142
mozilla::Maybe<Map> map_;
143
};
144
145
class ModuleNamespaceObject : public ProxyObject {
146
public:
147
enum ModuleNamespaceSlot { ExportsSlot = 0, BindingsSlot };
148
149
static bool isInstance(HandleValue value);
150
static ModuleNamespaceObject* create(JSContext* cx, HandleModuleObject module,
151
HandleObject exports,
152
UniquePtr<IndirectBindingMap> bindings);
153
154
ModuleObject& module();
155
JSObject& exports();
156
IndirectBindingMap& bindings();
157
158
bool addBinding(JSContext* cx, HandleAtom exportedName,
159
HandleModuleObject targetModule, HandleAtom localName);
160
161
private:
162
struct ProxyHandler : public BaseProxyHandler {
163
ProxyHandler();
164
165
bool getOwnPropertyDescriptor(
166
JSContext* cx, HandleObject proxy, HandleId id,
167
MutableHandle<PropertyDescriptor> desc) const override;
168
bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
169
Handle<PropertyDescriptor> desc,
170
ObjectOpResult& result) const override;
171
bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
172
MutableHandleIdVector props) const override;
173
bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
174
ObjectOpResult& result) const override;
175
bool getPrototype(JSContext* cx, HandleObject proxy,
176
MutableHandleObject protop) const override;
177
bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
178
ObjectOpResult& result) const override;
179
bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy,
180
bool* isOrdinary,
181
MutableHandleObject protop) const override;
182
bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
183
bool* succeeded) const override;
184
185
bool preventExtensions(JSContext* cx, HandleObject proxy,
186
ObjectOpResult& result) const override;
187
bool isExtensible(JSContext* cx, HandleObject proxy,
188
bool* extensible) const override;
189
bool has(JSContext* cx, HandleObject proxy, HandleId id,
190
bool* bp) const override;
191
bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
192
HandleId id, MutableHandleValue vp) const override;
193
bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
194
HandleValue receiver, ObjectOpResult& result) const override;
195
196
void trace(JSTracer* trc, JSObject* proxy) const override;
197
void finalize(JSFreeOp* fop, JSObject* proxy) const override;
198
199
static const char family;
200
};
201
202
bool hasBindings() const;
203
204
public:
205
static const ProxyHandler proxyHandler;
206
};
207
208
typedef Rooted<ModuleNamespaceObject*> RootedModuleNamespaceObject;
209
typedef Handle<ModuleNamespaceObject*> HandleModuleNamespaceObject;
210
211
struct FunctionDeclaration {
212
FunctionDeclaration(HandleAtom name, HandleFunction fun);
213
void trace(JSTracer* trc);
214
215
const HeapPtr<JSAtom*> name;
216
const HeapPtr<JSFunction*> fun;
217
};
218
219
// A vector of function bindings to be instantiated. This can be created in a
220
// helper thread zone and so can't use ZoneAllocPolicy.
221
using FunctionDeclarationVector =
222
GCVector<FunctionDeclaration, 0, SystemAllocPolicy>;
223
224
// Possible values for ModuleStatus are defined in SelfHostingDefines.h.
225
using ModuleStatus = int32_t;
226
227
class ModuleObject : public NativeObject {
228
public:
229
enum ModuleSlot {
230
ScriptSlot = 0,
231
EnvironmentSlot,
232
NamespaceSlot,
233
StatusSlot,
234
EvaluationErrorSlot,
235
MetaObjectSlot,
236
ScriptSourceObjectSlot,
237
RequestedModulesSlot,
238
ImportEntriesSlot,
239
LocalExportEntriesSlot,
240
IndirectExportEntriesSlot,
241
StarExportEntriesSlot,
242
ImportBindingsSlot,
243
FunctionDeclarationsSlot,
244
DFSIndexSlot,
245
DFSAncestorIndexSlot,
246
SlotCount
247
};
248
249
static_assert(EnvironmentSlot == MODULE_OBJECT_ENVIRONMENT_SLOT,
250
"EnvironmentSlot must match self-hosting define");
251
static_assert(StatusSlot == MODULE_OBJECT_STATUS_SLOT,
252
"StatusSlot must match self-hosting define");
253
static_assert(EvaluationErrorSlot == MODULE_OBJECT_EVALUATION_ERROR_SLOT,
254
"EvaluationErrorSlot must match self-hosting define");
255
static_assert(DFSIndexSlot == MODULE_OBJECT_DFS_INDEX_SLOT,
256
"DFSIndexSlot must match self-hosting define");
257
static_assert(DFSAncestorIndexSlot == MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT,
258
"DFSAncestorIndexSlot must match self-hosting define");
259
260
static const JSClass class_;
261
262
static bool isInstance(HandleValue value);
263
264
static ModuleObject* create(JSContext* cx);
265
void init(HandleScript script);
266
void setInitialEnvironment(
267
Handle<ModuleEnvironmentObject*> initialEnvironment);
268
void initImportExportData(HandleArrayObject requestedModules,
269
HandleArrayObject importEntries,
270
HandleArrayObject localExportEntries,
271
HandleArrayObject indiretExportEntries,
272
HandleArrayObject starExportEntries);
273
static bool Freeze(JSContext* cx, HandleModuleObject self);
274
#ifdef DEBUG
275
static bool AssertFrozen(JSContext* cx, HandleModuleObject self);
276
#endif
277
void fixEnvironmentsAfterRealmMerge();
278
279
JSScript* maybeScript() const;
280
JSScript* script() const;
281
Scope* enclosingScope() const;
282
ModuleEnvironmentObject& initialEnvironment() const;
283
ModuleEnvironmentObject* environment() const;
284
ModuleNamespaceObject* namespace_();
285
ModuleStatus status() const;
286
bool hadEvaluationError() const;
287
Value evaluationError() const;
288
JSObject* metaObject() const;
289
ScriptSourceObject* scriptSourceObject() const;
290
ArrayObject& requestedModules() const;
291
ArrayObject& importEntries() const;
292
ArrayObject& localExportEntries() const;
293
ArrayObject& indirectExportEntries() const;
294
ArrayObject& starExportEntries() const;
295
IndirectBindingMap& importBindings();
296
297
static bool Instantiate(JSContext* cx, HandleModuleObject self);
298
static bool Evaluate(JSContext* cx, HandleModuleObject self);
299
300
static ModuleNamespaceObject* GetOrCreateModuleNamespace(
301
JSContext* cx, HandleModuleObject self);
302
303
void setMetaObject(JSObject* obj);
304
305
// For BytecodeEmitter.
306
bool noteFunctionDeclaration(JSContext* cx, HandleAtom name,
307
HandleFunction fun);
308
309
// For intrinsic_InstantiateModuleFunctionDeclarations.
310
static bool instantiateFunctionDeclarations(JSContext* cx,
311
HandleModuleObject self);
312
313
// For intrinsic_ExecuteModule.
314
static bool execute(JSContext* cx, HandleModuleObject self,
315
MutableHandleValue rval);
316
317
// For intrinsic_NewModuleNamespace.
318
static ModuleNamespaceObject* createNamespace(JSContext* cx,
319
HandleModuleObject self,
320
HandleObject exports);
321
322
private:
323
static const JSClassOps classOps_;
324
325
static void trace(JSTracer* trc, JSObject* obj);
326
static void finalize(JSFreeOp* fop, JSObject* obj);
327
328
bool hasImportBindings() const;
329
FunctionDeclarationVector* functionDeclarations();
330
};
331
332
JSObject* GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
333
334
JSObject* CallModuleResolveHook(JSContext* cx, HandleValue referencingPrivate,
335
HandleString specifier);
336
337
JSObject* StartDynamicModuleImport(JSContext* cx, HandleScript script,
338
HandleValue specifier);
339
340
bool FinishDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate,
341
HandleString specifier, HandleObject promise);
342
343
} // namespace js
344
345
template <>
346
inline bool JSObject::is<js::ModuleNamespaceObject>() const {
347
return js::IsDerivedProxyObject(this,
348
&js::ModuleNamespaceObject::proxyHandler);
349
}
350
351
#endif /* builtin_ModuleObject_h */