ShellModuleObjectWrapper.cpp (24798B)
1 /* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 2 * -*- */ 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 #include "shell/ShellModuleObjectWrapper.h" 8 9 #include "mozilla/Maybe.h" 10 #include "mozilla/Span.h" 11 12 #include "jsapi.h" // JS_GetProperty, JS::Call, JS_NewPlainObject, JS_DefineProperty 13 14 #include "builtin/ModuleObject.h" // js::ModuleObject 15 #include "js/CallAndConstruct.h" // JS::Call 16 #include "js/CallArgs.h" // JS::CallArgs 17 #include "js/CallNonGenericMethod.h" // CallNonGenericMethod 18 #include "js/Class.h" // JSClass, JSCLASS_* 19 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin 20 #include "js/ErrorReport.h" // JS_ReportErrorASCII 21 #include "js/PropertyAndElement.h" // JS_GetProperty 22 #include "js/PropertySpec.h" // JSPropertySpec, JS_PSG, JS_PS_END, JSFunctionSpec, JS_FN, JS_FN_END 23 #include "js/RootingAPI.h" // JS::Rooted, JS::Handle, JS::MutableHandle 24 #include "js/Value.h" // JS::Value 25 #include "vm/ArrayObject.h" // ArrayObject, NewDenseFullyAllocatedArray 26 #include "vm/GlobalObject.h" // DefinePropertiesAndFunctions 27 #include "vm/JSFunction.h" // JSFunction 28 #include "vm/JSObject.h" // JSObject 29 #include "vm/List.h" // ListObject 30 #include "vm/NativeObject.h" // NativeObject 31 #include "vm/Stack.h" // FixedInvokeArgs 32 33 #include "vm/NativeObject-inl.h" // NativeObject::ensureDenseInitializedLength 34 35 using namespace js; 36 using namespace js::shell; 37 38 using mozilla::Span; 39 40 #define DEFINE_CLASS_IMPL(CLASS) \ 41 CLASS* Shell##CLASS##Wrapper::get() { \ 42 return &getReservedSlot(TargetSlot).toObject().as<CLASS>(); \ 43 } \ 44 /* static */ const JSClass Shell##CLASS##Wrapper::class_ = { \ 45 "Shell" #CLASS "Wrapper", \ 46 JSCLASS_HAS_RESERVED_SLOTS(Shell##CLASS##Wrapper::SlotCount)}; \ 47 MOZ_ALWAYS_INLINE bool IsShell##CLASS##Wrapper(JS::Handle<JS::Value> v) { \ 48 return v.isObject() && v.toObject().is<Shell##CLASS##Wrapper>(); \ 49 } 50 51 #define DEFINE_CLASS(CLASS) \ 52 class Shell##CLASS##Wrapper : public js::NativeObject { \ 53 public: \ 54 using Target = CLASS; \ 55 enum ModuleSlot { TargetSlot = 0, SlotCount }; \ 56 static const JSClass class_; \ 57 static Shell##CLASS##Wrapper* create(JSContext* cx, \ 58 JS::Handle<CLASS*> obj); \ 59 CLASS* get(); \ 60 }; \ 61 DEFINE_CLASS_IMPL(CLASS) 62 63 #define DEFINE_NATIVE_CLASS_IMPL(CLASS) \ 64 CLASS* Shell##CLASS##Wrapper::get() { \ 65 return static_cast<CLASS*>(getReservedSlot(TargetSlot).toPrivate()); \ 66 } \ 67 /* static */ const JSClass Shell##CLASS##Wrapper::class_ = { \ 68 "Shell" #CLASS "Wrapper", \ 69 JSCLASS_HAS_RESERVED_SLOTS(Shell##CLASS##Wrapper::SlotCount)}; \ 70 MOZ_ALWAYS_INLINE bool IsShell##CLASS##Wrapper(JS::Handle<JS::Value> v) { \ 71 return v.isObject() && v.toObject().is<Shell##CLASS##Wrapper>(); \ 72 } 73 74 #define DEFINE_NATIVE_CLASS(CLASS) \ 75 class Shell##CLASS##Wrapper : public js::NativeObject { \ 76 public: \ 77 using Target = CLASS; \ 78 enum ModuleSlot { OwnerSlot = 0, TargetSlot, SlotCount }; \ 79 static const JSClass class_; \ 80 static Shell##CLASS##Wrapper* create(JSContext* cx, \ 81 JS::Handle<JSObject*> owner, \ 82 CLASS* obj); \ 83 CLASS* get(); \ 84 }; \ 85 DEFINE_NATIVE_CLASS_IMPL(CLASS) 86 87 DEFINE_CLASS(ModuleRequestObject) 88 DEFINE_NATIVE_CLASS(ImportEntry) 89 DEFINE_NATIVE_CLASS(ExportEntry) 90 DEFINE_NATIVE_CLASS(RequestedModule) 91 // NOTE: We don't need wrapper for IndirectBindingMap and ModuleNamespaceObject 92 DEFINE_CLASS_IMPL(ModuleObject) 93 94 #undef DEFINE_CLASS 95 #undef DEFINE_CLASS_IMPL 96 #undef DEFINE_NATIVE_CLASS 97 #undef DEFINE_NATIVE_CLASS_IMPL 98 99 bool IdentFilter(JSContext* cx, JS::Handle<JS::Value> from, 100 JS::MutableHandle<JS::Value> to) { 101 to.set(from); 102 return true; 103 } 104 105 bool GetModuleStatusName(JSContext* cx, JS::Handle<JS::Value> from, 106 JS::MutableHandle<JS::Value> to) { 107 if (!from.isInt32()) { 108 return false; 109 } 110 111 const char* statusStr = nullptr; 112 switch (static_cast<ModuleStatus>(from.toInt32())) { 113 case ModuleStatus::New: 114 statusStr = "New"; 115 break; 116 case ModuleStatus::Unlinked: 117 statusStr = "Unlinked"; 118 break; 119 case ModuleStatus::Linking: 120 statusStr = "Linking"; 121 break; 122 case ModuleStatus::Linked: 123 statusStr = "Linked"; 124 break; 125 case ModuleStatus::Evaluating: 126 statusStr = "Evaluating"; 127 break; 128 case ModuleStatus::EvaluatingAsync: 129 statusStr = "EvaluatingAsync"; 130 break; 131 case ModuleStatus::Evaluated: 132 statusStr = "Evaluated"; 133 break; 134 default: 135 MOZ_CRASH("Unknown ModuleStatus value"); 136 } 137 138 JS::Rooted<JSString*> str(cx, JS_NewStringCopyZ(cx, statusStr)); 139 if (!str) { 140 return false; 141 } 142 143 to.setString(str); 144 return true; 145 } 146 147 template <class T> 148 bool SingleFilter(JSContext* cx, JS::Handle<JS::Value> from, 149 JS::MutableHandle<JS::Value> to) { 150 using TargetT = typename T::Target; 151 152 if (!from.isObject() || !from.toObject().is<TargetT>()) { 153 to.set(from); 154 return true; 155 } 156 157 JS::Rooted<TargetT*> obj(cx, &from.toObject().as<TargetT>()); 158 JS::Rooted<T*> filtered(cx, T::create(cx, obj)); 159 if (!filtered) { 160 return false; 161 } 162 to.setObject(*filtered); 163 return true; 164 } 165 166 template <class T> 167 bool ArrayFilter(JSContext* cx, JS::Handle<JS::Value> from, 168 JS::MutableHandle<JS::Value> to) { 169 using TargetT = typename T::Target; 170 171 if (!from.isObject() || !from.toObject().is<ArrayObject>()) { 172 to.set(from); 173 return true; 174 } 175 176 JS::Rooted<ArrayObject*> fromArray(cx, &from.toObject().as<ArrayObject>()); 177 uint32_t length = fromArray->length(); 178 JS::Rooted<ArrayObject*> toArray(cx, NewDenseFullyAllocatedArray(cx, length)); 179 if (!toArray) { 180 return false; 181 } 182 183 toArray->ensureDenseInitializedLength(0, length); 184 185 for (uint32_t i = 0; i < length; i++) { 186 JS::Rooted<JS::Value> item(cx, fromArray->getDenseElement(i)); 187 JS::Rooted<TargetT*> req(cx, &item.toObject().as<TargetT>()); 188 JS::Rooted<T*> filtered(cx, T::create(cx, req)); 189 if (!filtered) { 190 return false; 191 } 192 toArray->initDenseElement(i, ObjectValue(*filtered)); 193 } 194 to.setObject(*toArray); 195 return true; 196 } 197 198 template <class T> 199 bool ListToArrayFilter(JSContext* cx, JS::Handle<JS::Value> from, 200 JS::MutableHandle<JS::Value> to) { 201 using TargetT = typename T::Target; 202 203 if (!from.isObject() || !from.toObject().is<ListObject>()) { 204 to.set(from); 205 return true; 206 } 207 208 JS::Rooted<ListObject*> fromList(cx, &from.toObject().as<ListObject>()); 209 uint32_t length = fromList->length(); 210 JS::Rooted<ArrayObject*> toArray(cx, NewDenseFullyAllocatedArray(cx, length)); 211 if (!toArray) { 212 return false; 213 } 214 215 toArray->ensureDenseInitializedLength(0, length); 216 217 for (uint32_t i = 0; i < length; i++) { 218 JS::Rooted<JS::Value> item(cx, fromList->get(i)); 219 JS::Rooted<TargetT*> req(cx, &item.toObject().as<TargetT>()); 220 JS::Rooted<T*> filtered(cx, T::create(cx, req)); 221 if (!filtered) { 222 return false; 223 } 224 toArray->initDenseElement(i, ObjectValue(*filtered)); 225 } 226 to.setObject(*toArray); 227 return true; 228 } 229 230 static Value StringOrNullValue(JSString* maybeString) { 231 if (!maybeString) { 232 return NullValue(); 233 } 234 235 return StringValue(maybeString); 236 } 237 238 static Value Uint32Value(uint32_t x) { 239 MOZ_ASSERT(x <= INT32_MAX); 240 return Int32Value(x); 241 } 242 243 static Value Uint32OrUndefinedValue(mozilla::Maybe<uint32_t> x) { 244 if (x.isNothing()) { 245 return UndefinedValue(); 246 } 247 248 return Uint32Value(x.value()); 249 } 250 251 static Value AsyncEvaluationOrderInt32Value(AsyncEvaluationOrder x) { 252 if (x.isUnset()) { 253 return Int32Value(-1); 254 } 255 if (x.isDone()) { 256 return Int32Value(-2); 257 } 258 return Uint32Value(x.get()); 259 } 260 261 static Value ColumnNumberOneOriginValue(JS::ColumnNumberOneOrigin x) { 262 uint32_t column = x.oneOriginValue(); 263 MOZ_ASSERT(column <= INT32_MAX); 264 return Int32Value(column); 265 } 266 267 static Value StatusValue(ModuleStatus status) { 268 return Int32Value(int32_t(status)); 269 } 270 271 static Value ObjectOrUndefinedValue(JSObject* object) { 272 if (!object) { 273 return UndefinedValue(); 274 } 275 276 return ObjectValue(*object); 277 } 278 279 template <class T, typename RawGetterT, typename FilterT> 280 bool ShellModuleWrapperGetter(JSContext* cx, const JS::CallArgs& args, 281 RawGetterT rawGetter, FilterT filter) { 282 JS::Rooted<T*> wrapper(cx, &args.thisv().toObject().as<T>()); 283 if constexpr (std::is_same_v<T, ShellModuleObjectWrapper>) { 284 if (!wrapper->get()->hasCyclicModuleFields()) { 285 args.rval().set(UndefinedValue()); 286 return true; 287 } 288 } 289 290 JS::Rooted<JS::Value> raw(cx, rawGetter(wrapper->get())); 291 292 JS::Rooted<JS::Value> filtered(cx); 293 if (!filter(cx, raw, &filtered)) { 294 return false; 295 } 296 297 args.rval().set(filtered); 298 return true; 299 } 300 301 #define DEFINE_GETTER_FUNCTIONS(CLASS, PROP, TO_VALUE, FILTER) \ 302 static Value Shell##CLASS##Wrapper_##PROP##Getter_raw(CLASS* obj) { \ 303 return TO_VALUE(obj->PROP()); \ 304 } \ 305 static bool Shell##CLASS##Wrapper_##PROP##Getter_impl( \ 306 JSContext* cx, const JS::CallArgs& args) { \ 307 return ShellModuleWrapperGetter<Shell##CLASS##Wrapper>( \ 308 cx, args, Shell##CLASS##Wrapper_##PROP##Getter_raw, FILTER); \ 309 } \ 310 static bool Shell##CLASS##Wrapper_##PROP##Getter(JSContext* cx, \ 311 unsigned argc, Value* vp) { \ 312 JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \ 313 return CallNonGenericMethod<IsShell##CLASS##Wrapper, \ 314 Shell##CLASS##Wrapper_##PROP##Getter_impl>( \ 315 cx, args); \ 316 } 317 318 template <class T> 319 bool SpanToArrayFilter(JSContext* cx, JS::Handle<JSObject*> owner, 320 Span<const typename T::Target> from, 321 JS::MutableHandle<JS::Value> to) { 322 size_t length = from.Length(); 323 JS::Rooted<ArrayObject*> toArray(cx, NewDenseFullyAllocatedArray(cx, length)); 324 if (!toArray) { 325 return false; 326 } 327 328 toArray->ensureDenseInitializedLength(0, length); 329 330 for (uint32_t i = 0; i < length; i++) { 331 auto* element = const_cast<typename T::Target*>(&from[i]); 332 JS::Rooted<T*> filtered(cx, T::create(cx, owner, element)); 333 if (!filtered) { 334 return false; 335 } 336 toArray->initDenseElement(i, ObjectValue(*filtered)); 337 } 338 339 to.setObject(*toArray); 340 return true; 341 } 342 343 template <class T, typename RawGetterT, typename FilterT> 344 bool ShellModuleNativeWrapperGetter(JSContext* cx, const JS::CallArgs& args, 345 RawGetterT rawGetter, FilterT filter) { 346 JS::Rooted<T*> wrapper(cx, &args.thisv().toObject().as<T>()); 347 if constexpr (std::is_same_v<T, ShellModuleObjectWrapper>) { 348 if (!wrapper->get()->hasCyclicModuleFields()) { 349 args.rval().set(UndefinedValue()); 350 return true; 351 } 352 } 353 354 JS::Rooted<typename T::Target*> owner(cx, wrapper->get()); 355 356 JS::Rooted<JS::Value> filtered(cx); 357 if (!filter(cx, owner, rawGetter(owner), &filtered)) { 358 return false; 359 } 360 361 args.rval().set(filtered); 362 return true; 363 } 364 365 bool ModuleTypeToString(JSContext* cx, JS::Handle<JSObject*> owner, 366 JS::ModuleType moduleType, 367 JS::MutableHandle<JS::Value> to) { 368 switch (moduleType) { 369 case JS::ModuleType::Unknown: 370 to.setString(cx->names().unknown); 371 break; 372 case JS::ModuleType::JavaScript: 373 to.setString(cx->names().js); 374 break; 375 case JS::ModuleType::JSON: 376 to.setString(cx->names().json); 377 break; 378 case JS::ModuleType::CSS: 379 MOZ_ASSERT_UNREACHABLE("CSS modules are not supported in the shell"); 380 break; 381 case JS::ModuleType::Bytes: 382 to.setString(cx->names().bytes); 383 break; 384 } 385 386 MOZ_ASSERT(!to.isUndefined()); 387 return true; 388 } 389 390 #define DEFINE_NATIVE_GETTER_FUNCTIONS(CLASS, PROP, FILTER) \ 391 static auto Shell##CLASS##Wrapper_##PROP##Getter_raw(CLASS* obj) { \ 392 return obj->PROP(); \ 393 } \ 394 static bool Shell##CLASS##Wrapper_##PROP##Getter_impl( \ 395 JSContext* cx, const JS::CallArgs& args) { \ 396 return ShellModuleNativeWrapperGetter<Shell##CLASS##Wrapper>( \ 397 cx, args, Shell##CLASS##Wrapper_##PROP##Getter_raw, FILTER); \ 398 } \ 399 static bool Shell##CLASS##Wrapper_##PROP##Getter(JSContext* cx, \ 400 unsigned argc, Value* vp) { \ 401 JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \ 402 return CallNonGenericMethod<IsShell##CLASS##Wrapper, \ 403 Shell##CLASS##Wrapper_##PROP##Getter_impl>( \ 404 cx, args); \ 405 } 406 407 DEFINE_GETTER_FUNCTIONS(ModuleRequestObject, specifier, StringOrNullValue, 408 IdentFilter) 409 DEFINE_GETTER_FUNCTIONS(ModuleRequestObject, getFirstUnsupportedAttributeKey, 410 StringOrNullValue, IdentFilter) 411 DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleRequestObject, moduleType, 412 ModuleTypeToString); 413 414 static const JSPropertySpec ShellModuleRequestObjectWrapper_accessors[] = { 415 JS_PSG("specifier", ShellModuleRequestObjectWrapper_specifierGetter, 0), 416 JS_PSG("moduleType", ShellModuleRequestObjectWrapper_moduleTypeGetter, 0), 417 JS_PSG( 418 "firstUnsupportedAttributeKey", 419 ShellModuleRequestObjectWrapper_getFirstUnsupportedAttributeKeyGetter, 420 0), 421 JS_PS_END, 422 }; 423 424 DEFINE_GETTER_FUNCTIONS(ImportEntry, moduleRequest, ObjectOrNullValue, 425 SingleFilter<ShellModuleRequestObjectWrapper>) 426 DEFINE_GETTER_FUNCTIONS(ImportEntry, importName, StringOrNullValue, IdentFilter) 427 DEFINE_GETTER_FUNCTIONS(ImportEntry, localName, StringValue, IdentFilter) 428 DEFINE_GETTER_FUNCTIONS(ImportEntry, lineNumber, Uint32Value, IdentFilter) 429 DEFINE_GETTER_FUNCTIONS(ImportEntry, columnNumber, ColumnNumberOneOriginValue, 430 IdentFilter) 431 432 static const JSPropertySpec ShellImportEntryWrapper_accessors[] = { 433 JS_PSG("moduleRequest", ShellImportEntryWrapper_moduleRequestGetter, 0), 434 JS_PSG("importName", ShellImportEntryWrapper_importNameGetter, 0), 435 JS_PSG("localName", ShellImportEntryWrapper_localNameGetter, 0), 436 JS_PSG("lineNumber", ShellImportEntryWrapper_lineNumberGetter, 0), 437 JS_PSG("columnNumber", ShellImportEntryWrapper_columnNumberGetter, 0), 438 JS_PS_END, 439 }; 440 441 DEFINE_GETTER_FUNCTIONS(ExportEntry, exportName, StringOrNullValue, IdentFilter) 442 DEFINE_GETTER_FUNCTIONS(ExportEntry, moduleRequest, ObjectOrNullValue, 443 SingleFilter<ShellModuleRequestObjectWrapper>) 444 DEFINE_GETTER_FUNCTIONS(ExportEntry, importName, StringOrNullValue, IdentFilter) 445 DEFINE_GETTER_FUNCTIONS(ExportEntry, localName, StringOrNullValue, IdentFilter) 446 DEFINE_GETTER_FUNCTIONS(ExportEntry, lineNumber, Uint32Value, IdentFilter) 447 DEFINE_GETTER_FUNCTIONS(ExportEntry, columnNumber, ColumnNumberOneOriginValue, 448 IdentFilter) 449 450 static const JSPropertySpec ShellExportEntryWrapper_accessors[] = { 451 JS_PSG("exportName", ShellExportEntryWrapper_exportNameGetter, 0), 452 JS_PSG("moduleRequest", ShellExportEntryWrapper_moduleRequestGetter, 0), 453 JS_PSG("importName", ShellExportEntryWrapper_importNameGetter, 0), 454 JS_PSG("localName", ShellExportEntryWrapper_localNameGetter, 0), 455 JS_PSG("lineNumber", ShellExportEntryWrapper_lineNumberGetter, 0), 456 JS_PSG("columnNumber", ShellExportEntryWrapper_columnNumberGetter, 0), 457 JS_PS_END, 458 }; 459 460 DEFINE_GETTER_FUNCTIONS(RequestedModule, moduleRequest, ObjectOrNullValue, 461 SingleFilter<ShellModuleRequestObjectWrapper>) 462 DEFINE_GETTER_FUNCTIONS(RequestedModule, lineNumber, Uint32Value, IdentFilter) 463 DEFINE_GETTER_FUNCTIONS(RequestedModule, columnNumber, 464 ColumnNumberOneOriginValue, IdentFilter) 465 466 static const JSPropertySpec ShellRequestedModuleWrapper_accessors[] = { 467 JS_PSG("moduleRequest", ShellRequestedModuleWrapper_moduleRequestGetter, 0), 468 JS_PSG("lineNumber", ShellRequestedModuleWrapper_lineNumberGetter, 0), 469 JS_PSG("columnNumber", ShellRequestedModuleWrapper_columnNumberGetter, 0), 470 JS_PS_END, 471 }; 472 473 DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, ObjectOrNullValue, 474 IdentFilter) 475 DEFINE_GETTER_FUNCTIONS(ModuleObject, status, StatusValue, GetModuleStatusName) 476 DEFINE_GETTER_FUNCTIONS(ModuleObject, maybeEvaluationError, Value, IdentFilter) 477 DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, requestedModules, 478 SpanToArrayFilter<ShellRequestedModuleWrapper>) 479 DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, importEntries, 480 SpanToArrayFilter<ShellImportEntryWrapper>) 481 DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, 482 SpanToArrayFilter<ShellExportEntryWrapper>) 483 DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, indirectExportEntries, 484 SpanToArrayFilter<ShellExportEntryWrapper>) 485 DEFINE_NATIVE_GETTER_FUNCTIONS(ModuleObject, starExportEntries, 486 SpanToArrayFilter<ShellExportEntryWrapper>) 487 DEFINE_GETTER_FUNCTIONS(ModuleObject, maybeDfsAncestorIndex, 488 Uint32OrUndefinedValue, IdentFilter) 489 DEFINE_GETTER_FUNCTIONS(ModuleObject, hasTopLevelAwait, BooleanValue, 490 IdentFilter) 491 DEFINE_GETTER_FUNCTIONS(ModuleObject, maybeTopLevelCapability, 492 ObjectOrUndefinedValue, IdentFilter) 493 DEFINE_GETTER_FUNCTIONS(ModuleObject, asyncEvaluationOrder, 494 AsyncEvaluationOrderInt32Value, IdentFilter) 495 DEFINE_GETTER_FUNCTIONS(ModuleObject, asyncParentModules, ObjectOrNullValue, 496 ListToArrayFilter<ShellModuleObjectWrapper>) 497 DEFINE_GETTER_FUNCTIONS(ModuleObject, maybePendingAsyncDependencies, 498 Uint32OrUndefinedValue, IdentFilter) 499 500 static const JSPropertySpec ShellModuleObjectWrapper_accessors[] = { 501 JS_PSG("namespace", ShellModuleObjectWrapper_namespace_Getter, 0), 502 JS_PSG("status", ShellModuleObjectWrapper_statusGetter, 0), 503 JS_PSG("evaluationError", 504 ShellModuleObjectWrapper_maybeEvaluationErrorGetter, 0), 505 JS_PSG("requestedModules", ShellModuleObjectWrapper_requestedModulesGetter, 506 0), 507 JS_PSG("importEntries", ShellModuleObjectWrapper_importEntriesGetter, 0), 508 JS_PSG("localExportEntries", 509 ShellModuleObjectWrapper_localExportEntriesGetter, 0), 510 JS_PSG("indirectExportEntries", 511 ShellModuleObjectWrapper_indirectExportEntriesGetter, 0), 512 JS_PSG("starExportEntries", 513 ShellModuleObjectWrapper_starExportEntriesGetter, 0), 514 JS_PSG("dfsAncestorIndex", 515 ShellModuleObjectWrapper_maybeDfsAncestorIndexGetter, 0), 516 JS_PSG("hasTopLevelAwait", ShellModuleObjectWrapper_hasTopLevelAwaitGetter, 517 0), 518 JS_PSG("topLevelCapability", 519 ShellModuleObjectWrapper_maybeTopLevelCapabilityGetter, 0), 520 JS_PSG("asyncEvaluationOrder", 521 ShellModuleObjectWrapper_asyncEvaluationOrderGetter, 0), 522 JS_PSG("asyncParentModules", 523 ShellModuleObjectWrapper_asyncParentModulesGetter, 0), 524 JS_PSG("pendingAsyncDependencies", 525 ShellModuleObjectWrapper_maybePendingAsyncDependenciesGetter, 0), 526 JS_PS_END, 527 }; 528 529 #undef DEFINE_GETTER_FUNCTIONS 530 #undef DEFINE_NATIVE_GETTER_FUNCTIONS 531 532 #define DEFINE_CREATE(CLASS, ACCESSORS, FUNCTIONS) \ 533 /* static */ \ 534 Shell##CLASS##Wrapper* Shell##CLASS##Wrapper::create( \ 535 JSContext* cx, JS::Handle<CLASS*> target) { \ 536 JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &class_)); \ 537 if (!obj) { \ 538 return nullptr; \ 539 } \ 540 if (!DefinePropertiesAndFunctions(cx, obj, ACCESSORS, FUNCTIONS)) { \ 541 return nullptr; \ 542 } \ 543 auto* wrapper = &obj->as<Shell##CLASS##Wrapper>(); \ 544 wrapper->initReservedSlot(TargetSlot, ObjectValue(*target)); \ 545 return wrapper; \ 546 } 547 548 #define DEFINE_NATIVE_CREATE(CLASS, ACCESSORS, FUNCTIONS) \ 549 /* static */ \ 550 Shell##CLASS##Wrapper* Shell##CLASS##Wrapper::create( \ 551 JSContext* cx, JS::Handle<JSObject*> owner, CLASS* target) { \ 552 JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &class_)); \ 553 if (!obj) { \ 554 return nullptr; \ 555 } \ 556 if (!DefinePropertiesAndFunctions(cx, obj, ACCESSORS, FUNCTIONS)) { \ 557 return nullptr; \ 558 } \ 559 auto* wrapper = &obj->as<Shell##CLASS##Wrapper>(); \ 560 wrapper->initReservedSlot(OwnerSlot, ObjectValue(*owner)); \ 561 wrapper->initReservedSlot(TargetSlot, PrivateValue(target)); \ 562 return wrapper; \ 563 } 564 565 DEFINE_CREATE(ModuleRequestObject, ShellModuleRequestObjectWrapper_accessors, 566 nullptr) 567 568 DEFINE_NATIVE_CREATE(ImportEntry, ShellImportEntryWrapper_accessors, nullptr) 569 DEFINE_NATIVE_CREATE(ExportEntry, ShellExportEntryWrapper_accessors, nullptr) 570 DEFINE_NATIVE_CREATE(RequestedModule, ShellRequestedModuleWrapper_accessors, 571 nullptr) 572 573 #undef DEFINE_CREATE 574 #undef DEFINE_NATIVE_CREATE 575 576 JS::ModuleType ShellModuleObjectWrapper::getModuleType() { 577 return static_cast<JS::ModuleType>(getReservedSlot(ModuleTypeSlot).toInt32()); 578 } 579 580 ShellModuleObjectWrapper* ShellModuleObjectWrapper::create( 581 JSContext* cx, JS::Handle<ModuleObject*> target, 582 JS::ModuleType moduleType) { 583 JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &class_)); 584 if (!obj) { 585 return nullptr; 586 } 587 if (!DefinePropertiesAndFunctions(cx, obj, ShellModuleObjectWrapper_accessors, 588 nullptr)) { 589 return nullptr; 590 } 591 auto* wrapper = &obj->as<ShellModuleObjectWrapper>(); 592 wrapper->initReservedSlot(TargetSlot, ObjectValue(*target)); 593 wrapper->initReservedSlot(ModuleTypeSlot, 594 Int32Value(static_cast<int32_t>(moduleType))); 595 return wrapper; 596 }