synthetic-module.cc 5.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/objects/synthetic-module.h"

#include "src/api/api-inl.h"
#include "src/builtins/accessors.h"
#include "src/objects/js-generator-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/shared-function-info.h"
13
#include "src/objects/synthetic-module-inl.h"
14 15 16 17 18 19 20
#include "src/utils/ostreams.h"

namespace v8 {
namespace internal {

// Implements SetSyntheticModuleBinding:
// https://heycam.github.io/webidl/#setsyntheticmoduleexport
21 22 23 24
Maybe<bool> SyntheticModule::SetExport(Isolate* isolate,
                                       Handle<SyntheticModule> module,
                                       Handle<String> export_name,
                                       Handle<Object> export_value) {
25 26
  Handle<ObjectHashTable> exports(module->exports(), isolate);
  Handle<Object> export_object(exports->Lookup(export_name), isolate);
27 28 29 30 31 32 33

  if (!export_object->IsCell()) {
    isolate->Throw(*isolate->factory()->NewReferenceError(
        MessageTemplate::kModuleExportUndefined, export_name));
    return Nothing<bool>();
  }

34
  // Spec step 2: Set the mutable binding of export_name to export_value
35
  Cell::cast(*export_object).set_value(*export_value);
36 37 38 39 40 41 42 43 44 45 46 47 48 49

  return Just(true);
}

void SyntheticModule::SetExportStrict(Isolate* isolate,
                                      Handle<SyntheticModule> module,
                                      Handle<String> export_name,
                                      Handle<Object> export_value) {
  Handle<ObjectHashTable> exports(module->exports(), isolate);
  Handle<Object> export_object(exports->Lookup(export_name), isolate);
  CHECK(export_object->IsCell());
  Maybe<bool> set_export_result =
      SetExport(isolate, module, export_name, export_value);
  CHECK(set_export_result.FromJust());
50 51 52 53 54 55 56
}

// Implements Synthetic Module Record's ResolveExport concrete method:
// https://heycam.github.io/webidl/#smr-resolveexport
MaybeHandle<Cell> SyntheticModule::ResolveExport(
    Isolate* isolate, Handle<SyntheticModule> module,
    Handle<String> module_specifier, Handle<String> export_name,
57 58
    MessageLocation loc, bool must_resolve) {
  Handle<Object> object(module->exports().Lookup(export_name), isolate);
59
  if (object->IsCell()) return Handle<Cell>::cast(object);
60

61
  if (!must_resolve) return MaybeHandle<Cell>();
62

63
  return isolate->ThrowAt<Cell>(
64 65 66
      isolate->factory()->NewSyntaxError(MessageTemplate::kUnresolvableExport,
                                         module_specifier, export_name),
      &loc);
67 68 69 70 71 72
}

// Implements Synthetic Module Record's Instantiate concrete method :
// https://heycam.github.io/webidl/#smr-instantiate
bool SyntheticModule::PrepareInstantiate(Isolate* isolate,
                                         Handle<SyntheticModule> module,
73
                                         v8::Local<v8::Context> context) {
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
  Handle<ObjectHashTable> exports(module->exports(), isolate);
  Handle<FixedArray> export_names(module->export_names(), isolate);
  // Spec step 7: For each export_name in module->export_names...
  for (int i = 0, n = export_names->length(); i < n; ++i) {
    // Spec step 7.1: Create a new mutable binding for export_name.
    // Spec step 7.2: Initialize the new mutable binding to undefined.
    Handle<Cell> cell =
        isolate->factory()->NewCell(isolate->factory()->undefined_value());
    Handle<String> name(String::cast(export_names->get(i)), isolate);
    CHECK(exports->Lookup(name).IsTheHole(isolate));
    exports = ObjectHashTable::Put(exports, name, cell);
  }
  module->set_exports(*exports);
  return true;
}

// Second step of module instantiation.  No real work to do for SyntheticModule
// as there are no imports or indirect exports to resolve;
// just update status.
bool SyntheticModule::FinishInstantiate(Isolate* isolate,
                                        Handle<SyntheticModule> module) {
95
  module->SetStatus(kLinked);
96 97 98 99 100 101 102
  return true;
}

// Implements Synthetic Module Record's Evaluate concrete method:
// https://heycam.github.io/webidl/#smr-evaluate
MaybeHandle<Object> SyntheticModule::Evaluate(Isolate* isolate,
                                              Handle<SyntheticModule> module) {
103 104 105 106 107 108 109 110 111 112 113
  module->SetStatus(kEvaluating);

  v8::Module::SyntheticModuleEvaluationSteps evaluation_steps =
      FUNCTION_CAST<v8::Module::SyntheticModuleEvaluationSteps>(
          module->evaluation_steps().foreign_address());
  v8::Local<v8::Value> result;
  if (!evaluation_steps(
           Utils::ToLocal(Handle<Context>::cast(isolate->native_context())),
           Utils::ToLocal(Handle<Module>::cast(module)))
           .ToLocal(&result)) {
    isolate->PromoteScheduledException();
114
    Module::RecordErrorUsingPendingException(isolate, module);
115 116 117 118
    return MaybeHandle<Object>();
  }

  module->SetStatus(kEvaluated);
119 120 121

  Handle<Object> result_from_callback = Utils::OpenHandle(*result);

122 123 124 125 126 127 128 129 130 131 132
  Handle<JSPromise> capability;
  if (result_from_callback->IsJSPromise()) {
    capability = Handle<JSPromise>::cast(result_from_callback);
  } else {
    // The host's evaluation steps should have returned a resolved Promise,
    // but as an allowance to hosts that have not yet finished the migration
    // to top-level await, create a Promise if the callback result didn't give
    // us one.
    capability = isolate->factory()->NewJSPromise();
    JSPromise::Resolve(capability, isolate->factory()->undefined_value())
        .ToHandleChecked();
133 134
  }

135 136
  module->set_top_level_capability(*capability);

137
  return result_from_callback;
138 139 140 141
}

}  // namespace internal
}  // namespace v8