/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights
 * reserved.
 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/dom/ScriptLoader.h"

#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/ScriptSourceCode.h"
#include "bindings/core/v8/V8BindingForCore.h"
#include "core/HTMLNames.h"
#include "core/SVGNames.h"
#include "core/dom/ClassicPendingScript.h"
#include "core/dom/ClassicScript.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentParserTiming.h"
#include "core/dom/DocumentWriteIntervention.h"
#include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
#include "core/dom/Modulator.h"
#include "core/dom/ModulePendingScript.h"
#include "core/dom/Script.h"
#include "core/dom/ScriptElementBase.h"
#include "core/dom/ScriptRunner.h"
#include "core/dom/ScriptableDocumentParser.h"
#include "core/dom/Text.h"
#include "core/events/Event.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/SubresourceIntegrity.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/imports/HTMLImport.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/loader/modulescript/ModuleScriptFetchRequest.h"
#include "core/loader/resource/ScriptResource.h"
#include "platform/WebFrameScheduler.h"
#include "platform/loader/fetch/AccessControlStatus.h"
#include "platform/loader/fetch/FetchParameters.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/network/mime/MIMETypeRegistry.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/wtf/StdLibExtras.h"
#include "platform/wtf/text/StringBuilder.h"
#include "platform/wtf/text/StringHash.h"
#include "public/platform/WebCachePolicy.h"

namespace blink {

ScriptLoader::ScriptLoader(ScriptElementBase* element,
                           bool parser_inserted,
                           bool already_started,
                           bool created_during_document_write)
    : element_(element),
      start_line_number_(WTF::OrdinalNumber::BeforeFirst()),
      have_fired_load_(false),
      will_be_parser_executed_(false),
      will_execute_when_document_finished_parsing_(false),
      created_during_document_write_(created_during_document_write),
      async_exec_type_(ScriptRunner::kNone),
      document_write_intervention_(
          DocumentWriteIntervention::kDocumentWriteInterventionNone) {
  // https://html.spec.whatwg.org/#already-started
  // "The cloning steps for script elements must set the "already started"
  //  flag on the copy if it is set on the element being cloned."
  // TODO(hiroshige): Cloning is implemented together with
  // {HTML,SVG}ScriptElement::cloneElementWithoutAttributesAndChildren().
  // Clean up these later.
  if (already_started)
    already_started_ = true;

  if (parser_inserted) {
    // https://html.spec.whatwg.org/#parser-inserted
    // "It is set by the HTML parser and the XML parser
    //  on script elements they insert"
    parser_inserted_ = true;

    // https://html.spec.whatwg.org/#non-blocking
    // "It is unset by the HTML parser and the XML parser
    //  on script elements they insert."
    non_blocking_ = false;
  }

  if (parser_inserted &&
      element_->GetDocument().GetScriptableDocumentParser() &&
      !element_->GetDocument().IsInDocumentWrite()) {
    start_line_number_ =
        element_->GetDocument().GetScriptableDocumentParser()->LineNumber();
  }
}

ScriptLoader::~ScriptLoader() {}

DEFINE_TRACE(ScriptLoader) {
  visitor->Trace(element_);
  visitor->Trace(resource_);
  visitor->Trace(pending_script_);
  visitor->Trace(module_tree_client_);
  PendingScriptClient::Trace(visitor);
}

void ScriptLoader::SetFetchDocWrittenScriptDeferIdle() {
  DCHECK(!created_during_document_write_);
  document_write_intervention_ =
      DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle;
}

void ScriptLoader::DidNotifySubtreeInsertionsToDocument() {
  if (!parser_inserted_)
    PrepareScript();  // FIXME: Provide a real starting line number here.
}

void ScriptLoader::ChildrenChanged() {
  if (!parser_inserted_ && element_->IsConnected())
    PrepareScript();  // FIXME: Provide a real starting line number here.
}

void ScriptLoader::HandleSourceAttribute(const String& source_url) {
  if (IgnoresLoadRequest() || source_url.IsEmpty())
    return;

  PrepareScript();  // FIXME: Provide a real starting line number here.
}

void ScriptLoader::HandleAsyncAttribute() {
  // https://html.spec.whatwg.org/#non-blocking
  // "In addition, whenever a script element whose "non-blocking" flag is set
  //  has an async content attribute added, the element's "non-blocking" flag
  //  must be unset."
  non_blocking_ = false;
}

void ScriptLoader::DetachPendingScript() {
  if (!pending_script_)
    return;
  pending_script_->Dispose();
  pending_script_ = nullptr;
}

void ScriptLoader::DispatchErrorEvent() {
  element_->DispatchErrorEvent();
}

void ScriptLoader::DispatchLoadEvent() {
  element_->DispatchLoadEvent();
  SetHaveFiredLoadEvent(true);
}

namespace {

bool IsValidClassicScriptTypeAndLanguage(
    const String& type,
    const String& language,
    ScriptLoader::LegacyTypeSupport support_legacy_types) {
  // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used
  // here to maintain backwards compatibility with existing layout tests. The
  // specific violations are:
  // - Allowing type=javascript. type= should only support MIME types, such as
  //   text/javascript.
  // - Allowing a different set of languages for language= and type=. language=
  //   supports Javascript 1.1 and 1.4-1.6, but type= does not.
  if (type.IsEmpty()) {
    return language.IsEmpty() ||  // assume text/javascript.
           MIMETypeRegistry::IsSupportedJavaScriptMIMEType("text/" +
                                                           language) ||
           MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(language);
  } else if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(
                 type.StripWhiteSpace()) ||
             (support_legacy_types ==
                  ScriptLoader::kAllowLegacyTypeInTypeAttribute &&
              MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(type))) {
    return true;
  }

  return false;
}

}  // namespace

// Step 6 of https://html.spec.whatwg.org/#prepare-a-script
bool ScriptLoader::IsValidScriptTypeAndLanguage(
    const String& type,
    const String& language,
    LegacyTypeSupport support_legacy_types,
    ScriptType& out_script_type) {
  if (IsValidClassicScriptTypeAndLanguage(type, language,
                                          support_legacy_types)) {
    // - "If the script block's type string is an ASCII case-insensitive match
    //    for any JavaScript MIME type, the script's type is "classic"."
    // TODO(hiroshige): Annotate and/or cleanup this step.
    out_script_type = ScriptType::kClassic;
    return true;
  }

  if (RuntimeEnabledFeatures::moduleScriptsEnabled() && type == "module") {
    // - "If the script block's type string is an ASCII case-insensitive match
    //    for the string "module", the script's type is "module"."
    out_script_type = ScriptType::kModule;
    return true;
  }

  // - "If neither of the above conditions are true, then abort these steps
  //    at this point. No script is executed."
  return false;
}

bool ScriptLoader::BlockForNoModule(ScriptType script_type, bool nomodule) {
  return nomodule && script_type == ScriptType::kClassic &&
         RuntimeEnabledFeatures::moduleScriptsEnabled();
}

bool ScriptLoader::IsScriptTypeSupported(LegacyTypeSupport support_legacy_types,
                                         ScriptType& out_script_type) const {
  return IsValidScriptTypeAndLanguage(element_->TypeAttributeValue(),
                                      element_->LanguageAttributeValue(),
                                      support_legacy_types, out_script_type);
}

// https://html.spec.whatwg.org/#prepare-a-script
bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
                                 LegacyTypeSupport support_legacy_types) {
  // 1. "If the script element is marked as having "already started", then
  //     abort these steps at this point. The script is not executed."
  if (already_started_)
    return false;

  // 2. "If the element has its "parser-inserted" flag set, then
  //     set was-parser-inserted to true and unset the element's
  //     "parser-inserted" flag.
  //     Otherwise, set was-parser-inserted to false."
  bool was_parser_inserted;
  if (parser_inserted_) {
    was_parser_inserted = true;
    parser_inserted_ = false;
  } else {
    was_parser_inserted = false;
  }

  // 3. "If was-parser-inserted is true and the element does not have an
  //     async attribute, then set the element's "non-blocking" flag to true."
  if (was_parser_inserted && !element_->AsyncAttributeValue())
    non_blocking_ = true;

  // 4. "If the element has no src attribute, and its child nodes, if any,
  //     consist only of comment nodes and empty Text nodes,
  //     then abort these steps at this point. The script is not executed."
  // FIXME: HTML5 spec says we should check that all children are either
  // comments or empty text nodes.
  if (!element_->HasSourceAttribute() && !element_->HasChildren())
    return false;

  // 5. "If the element is not connected, then abort these steps.
  //     The script is not executed."
  if (!element_->IsConnected())
    return false;

  // 6. "Determine the script's type as follows:"
  // |script_type_| is set here.
  if (!IsScriptTypeSupported(support_legacy_types, script_type_))
    return false;

  // 7. "If was-parser-inserted is true,
  //     then flag the element as "parser-inserted" again,
  //     and set the element's "non-blocking" flag to false."
  if (was_parser_inserted) {
    parser_inserted_ = true;
    non_blocking_ = false;
  }

  // 8. "Set the element's "already started" flag."
  already_started_ = true;

  // 9. "If the element is flagged as "parser-inserted", but the element's
  // node document is not the Document of the parser that created the element,
  // then abort these steps."
  // FIXME: If script is parser inserted, verify it's still in the original
  // document.
  Document& element_document = element_->GetDocument();
  Document* context_document = element_document.ContextDocument();
  if (!element_document.ExecutingFrame())
    return false;
  if (!context_document || !context_document->ExecutingFrame())
    return false;

  // 10. "If scripting is disabled for the script element, then abort these
  //      steps at this point. The script is not executed."
  if (!context_document->CanExecuteScripts(kAboutToExecuteScript))
    return false;

  // 11. "If the script element has a nomodule content attribute
  //      and the script's type is "classic", then abort these steps.
  //      The script is not executed."
  if (BlockForNoModule(script_type_, element_->NomoduleAttributeValue()))
    return false;

  // 13.
  if (!IsScriptForEventSupported())
    return false;

  // 14. is handled below.

  // 15. "Let CORS setting be the current state of the element's
  //      crossorigin content attribute."
  CrossOriginAttributeValue cross_origin =
      GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue());

  // 16. is handled below.

  // 17. "If the script element has a nonce attribute,
  //      then let cryptographic nonce be that attribute's value.
  //      Otherwise, let cryptographic nonce be the empty string."
  String nonce;
  if (element_->IsNonceableElement())
    nonce = element_->nonce();

  // 18. is handled below.

  // 19. "Let parser state be "parser-inserted"
  //      if the script element has been flagged as "parser-inserted",
  //      and "not parser-inserted" otherwise."
  ParserDisposition parser_state =
      IsParserInserted() ? kParserInserted : kNotParserInserted;

  // 21. "If the element has a src content attribute, run these substeps:"
  if (element_->HasSourceAttribute()) {
    // 21.1. Let src be the value of the element's src attribute.
    String src =
        StripLeadingAndTrailingHTMLSpaces(element_->SourceAttributeValue());

    // 21.2. "If src is the empty string, queue a task to
    //        fire an event named error at the element, and abort these steps."
    if (src.IsEmpty()) {
      // TODO(hiroshige): Make this asynchronous. Currently we fire the error
      // event synchronously to keep the existing behavior.
      DispatchErrorEvent();
      return false;
    }

    // 21.3. "Set the element's from an external file flag."
    is_external_script_ = true;

    // 21.4. "Parse src relative to the element's node document."
    // TODO(hiroshige): Use CompleteURL(src) instead.
    KURL url = element_document.CompleteURL(element_->SourceAttributeValue());

    // 21.5. "If the previous step failed, queue a task to
    //        fire an event named error at the element, and abort these steps."
    if (!url.IsValid()) {
      // TODO(hiroshige): Make this asynchronous. Currently we fire the error
      // event synchronously to keep the existing behavior.
      DispatchErrorEvent();
      return false;
    }

    DCHECK(!resource_);
    DCHECK(!module_tree_client_);

    // 21.6. "Switch on the script's type:"
    if (GetScriptType() == ScriptType::kClassic) {
      // - "classic":

      // 14. "If the script element has a charset attribute,
      //      then let encoding be the result of
      //      getting an encoding from the value of the charset attribute."
      //     "If the script element does not have a charset attribute,
      //      or if getting an encoding failed, let encoding
      //      be the same as the encoding of the script element's node
      //      document."
      // TODO(hiroshige): Should we handle failure in getting an encoding?
      String encoding;
      if (!element_->CharsetAttributeValue().IsEmpty())
        encoding = element_->CharsetAttributeValue();
      else
        encoding = element_document.characterSet();

      // Step 16 is skipped because "module script credentials" is not used
      // for classic scripts.

      // 18. "If the script element has an integrity attribute,
      //      then let integrity metadata be that attribute's value.
      //      Otherwise, let integrity metadata be the empty string."
      String integrity_attr = element_->IntegrityAttributeValue();
      IntegrityMetadataSet integrity_metadata;
      if (!integrity_attr.IsEmpty()) {
        SubresourceIntegrity::ParseIntegrityAttribute(
            integrity_attr, integrity_metadata, &element_document);
      }

      if (!FetchClassicScript(url, element_document.Fetcher(), nonce,
                              integrity_metadata, parser_state, cross_origin,
                              element_document.GetSecurityOrigin(), encoding)) {
        // TODO(hiroshige): Make this asynchronous. Currently we fire the error
        // event synchronously to keep the existing behavior.
        DispatchErrorEvent();
        return false;
      }

      DCHECK(resource_);
      DCHECK(!module_tree_client_);
    } else {
      // - "module":

      // Steps 14 and 18 are skipped because they are not used in module
      // scripts.

      // 16. "Let module script credentials mode be determined by switching
      //      on CORS setting:"
      WebURLRequest::FetchCredentialsMode credentials_mode =
          WebURLRequest::kFetchCredentialsModeOmit;
      switch (cross_origin) {
        case kCrossOriginAttributeNotSet:
          credentials_mode = WebURLRequest::kFetchCredentialsModeOmit;
          break;
        case kCrossOriginAttributeAnonymous:
          credentials_mode = WebURLRequest::kFetchCredentialsModeSameOrigin;
          break;
        case kCrossOriginAttributeUseCredentials:
          credentials_mode = WebURLRequest::kFetchCredentialsModeInclude;
          break;
      }

      DCHECK(RuntimeEnabledFeatures::moduleScriptsEnabled());
      Modulator* modulator = Modulator::From(
          ToScriptStateForMainWorld(element_document.GetFrame()));
      FetchModuleScriptTree(url, modulator, nonce, parser_state,
                            credentials_mode);

      DCHECK(!resource_);
      DCHECK(module_tree_client_);
    }

    // "When the chosen algorithm asynchronously completes, set
    //  the script's script to the result. At that time, the script is ready."
    // When the script is ready, PendingScriptClient::pendingScriptFinished()
    // is used as the notification, and the action to take when
    // the script is ready is specified later, in
    // - ScriptLoader::PrepareScript(), or
    // - HTMLParserScriptRunner,
    // depending on the conditions in Step 23 of "prepare a script".
  }

  // 22. "If the element does not have a src content attribute,
  //      run these substeps:"
  if (!element_->HasSourceAttribute()) {
    // 22.1. "Let source text be the value of the text IDL attribute."
    // This step is done later:
    // - in ScriptLoader::pendingScript() (Step 23, 6th Clause),
    //   as Element::textFromChildren() in ScriptLoader::scriptContent(),
    // - in HTMLParserScriptRunner::processScriptElementInternal()
    //   (Duplicated code of Step 23, 6th Clause),
    //   as Element::textContent(),
    // - in XMLDocumentParser::endElementNs() (Step 23, 5th Clause),
    //   as Element::textFromChildren() in ScriptLoader::scriptContent(),
    // - PendingScript::getSource() (Indirectly used via
    //   HTMLParserScriptRunner::processScriptElementInternal(),
    //   Step 23, 5th Clause),
    //   as Element::textContent().
    // TODO(hiroshige): Make them merged or consistent.

    // 22.2. "Switch on the script's type:"
    switch (GetScriptType()) {
      // - "classic":
      case ScriptType::kClassic:
        // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic".
        break;

      // - "module":
      case ScriptType::kModule:
        // TODO(hiroshige): Implement inline module scripts.
        element_document.AddConsoleMessage(ConsoleMessage::Create(
            kJSMessageSource, kErrorMessageLevel,
            "Inline module script is not yet supported",
            SourceLocation::Create(element_document.Url().GetString(),
                                   script_start_position.line_.OneBasedInt(),
                                   script_start_position.column_.OneBasedInt(),
                                   nullptr)));
        return false;
    }
  }

  // [Intervention]
  // Since the asynchronous, low priority fetch for doc.written blocked
  // script is not for execution, return early from here. Watch for its
  // completion to be able to remove it from the memory cache.
  if (GetScriptType() == ScriptType::kClassic &&
      document_write_intervention_ ==
          DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
    pending_script_ = CreatePendingScript();
    pending_script_->WatchForLoad(this);
    return true;
  }

  // 23. "Then, follow the first of the following options that describes the
  //      situation:"

  // Three flags are used to instruct the caller of prepareScript() to execute
  // a part of Step 23, when |m_willBeParserExecuted| is true:
  // - |m_willBeParserExecuted|
  // - |m_willExecuteWhenDocumentFinishedParsing|
  // - |m_readyToBeParserExecuted|
  // TODO(hiroshige): Clean up the dependency.

  // 1st Clause:
  // - "If the script's type is "classic", and
  //    the element has a src attribute, and the element has a defer attribute,
  //    and the element has been flagged as "parser-inserted",
  //    and the element does not have an async attribute"
  // - "If the script's type is "module",
  //    and the element has been flagged as "parser-inserted",
  //    and the element does not have an async attribute"
  if ((GetScriptType() == ScriptType::kClassic &&
       element_->HasSourceAttribute() && element_->DeferAttributeValue() &&
       parser_inserted_ && !element_->AsyncAttributeValue()) ||
      (GetScriptType() == ScriptType::kModule && parser_inserted_ &&
       !element_->AsyncAttributeValue())) {
    // This clause is implemented by the caller-side of prepareScript():
    // - HTMLParserScriptRunner::requestDeferredScript(), and
    // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
    will_execute_when_document_finished_parsing_ = true;
    will_be_parser_executed_ = true;

    return true;
  }

  // 2nd Clause:
  // - "If the script's type is "classic",
  //    and the element has a src attribute,
  //    and the element has been flagged as "parser-inserted",
  //    and the element does not have an async attribute"
  // TODO(hiroshige): Check the script's type.
  if (GetScriptType() == ScriptType::kClassic &&
      element_->HasSourceAttribute() && parser_inserted_ &&
      !element_->AsyncAttributeValue()) {
    // This clause is implemented by the caller-side of prepareScript():
    // - HTMLParserScriptRunner::requestParsingBlockingScript()
    // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
    will_be_parser_executed_ = true;

    return true;
  }

  // 5th Clause:
  // TODO(hiroshige): Reorder the clauses to match the spec.
  // - "If the element does not have a src attribute,
  //    and the element has been flagged as "parser-inserted",
  //    and either the parser that created the script is an XML parser
  //      or it's an HTML parser whose script nesting level is not greater than
  //      one,
  //    and the Document of the HTML parser or XML parser that created
  //      the script element has a style sheet that is blocking scripts"
  // The last part "... has a style sheet that is blocking scripts"
  // is implemented in Document::isScriptExecutionReady().
  // Part of the condition check is done in
  // HTMLParserScriptRunner::processScriptElementInternal().
  // TODO(hiroshige): Clean up the split condition check.
  // We check that the type is "classic" here, because according to the spec
  // a "module" script doesn't reach the 5th Clause because the 4th Clause
  // catches all "module" scripts.
  if (GetScriptType() == ScriptType::kClassic &&
      !element_->HasSourceAttribute() && parser_inserted_ &&
      !element_document.IsScriptExecutionReady()) {
    // The former part of this clause is
    // implemented by the caller-side of prepareScript():
    // - HTMLParserScriptRunner::requestParsingBlockingScript()
    // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
    will_be_parser_executed_ = true;
    // "Set the element's "ready to be parser-executed" flag."
    ready_to_be_parser_executed_ = true;

    return true;
  }

  // 3rd Clause:
  // - "If the script's type is "classic",
  //    and the element has a src attribute,
  //    and the element does not have an async attribute,
  //    and the element does not have the "non-blocking" flag set"
  // - "If the script's type is "module",
  //    and the element does not have an async attribute,
  //    and the element does not have the "non-blocking" flag set"
  // TODO(hiroshige): Check the script's type and implement "module" case.
  if ((GetScriptType() == ScriptType::kClassic &&
       element_->HasSourceAttribute() && !element_->AsyncAttributeValue() &&
       !non_blocking_) ||
      (GetScriptType() == ScriptType::kModule &&
       !element_->AsyncAttributeValue() && !non_blocking_)) {
    // "Add the element to the end of the list of scripts that will execute
    // in order as soon as possible associated with the node document of the
    // script element at the time the prepare a script algorithm started."
    pending_script_ = CreatePendingScript();
    async_exec_type_ = ScriptRunner::kInOrder;
    // TODO(hiroshige): Here |contextDocument| is used as "node document"
    // while Step 14 uses |elementDocument| as "node document". Fix this.
    context_document->GetScriptRunner()->QueueScriptForExecution(
        this, async_exec_type_);
    // Note that watchForLoad can immediately call pendingScriptFinished.
    pending_script_->WatchForLoad(this);
    // The part "When the script is ready..." is implemented in
    // ScriptRunner::notifyScriptReady().
    // TODO(hiroshige): Annotate it.

    return true;
  }

  // 4th Clause:
  // - "If the script's type is "classic", and the element has a src attribute"
  // - "If the script's type is "module""
  if ((GetScriptType() == ScriptType::kClassic &&
       element_->HasSourceAttribute()) ||
      GetScriptType() == ScriptType::kModule) {
    // "The element must be added to the set of scripts that will execute
    //  as soon as possible of the node document of the script element at the
    //  time the prepare a script algorithm started."
    pending_script_ = CreatePendingScript();
    async_exec_type_ = ScriptRunner::kAsync;
    pending_script_->StartStreamingIfPossible(&element_->GetDocument(),
                                              ScriptStreamer::kAsync);
    // TODO(hiroshige): Here |contextDocument| is used as "node document"
    // while Step 14 uses |elementDocument| as "node document". Fix this.
    context_document->GetScriptRunner()->QueueScriptForExecution(
        this, async_exec_type_);
    // Note that watchForLoad can immediately call pendingScriptFinished.
    pending_script_->WatchForLoad(this);
    // The part "When the script is ready..." is implemented in
    // ScriptRunner::notifyScriptReady().
    // TODO(hiroshige): Annotate it.

    return true;
  }

  // 6th Clause:
  // - "Otherwise"
  // "Immediately execute the script block,
  //  even if other scripts are already executing."
  // Note: this block is also duplicated in
  // HTMLParserScriptRunner::processScriptElementInternal().
  // TODO(hiroshige): Merge the duplicated code.

  // This clause is executed only if the script's type is "classic"
  // and the element doesn't have a src attribute.
  DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
  DCHECK(!is_external_script_);

  // Reset line numbering for nested writes.
  TextPosition position = element_document.IsInDocumentWrite()
                              ? TextPosition()
                              : script_start_position;
  KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_)
                        ? element_document.Url()
                        : KURL();

  if (!ExecuteScript(ClassicScript::Create(
          ScriptSourceCode(ScriptContent(), script_url, position)))) {
    DispatchErrorEvent();
    return false;
  }

  return true;
}

bool ScriptLoader::FetchClassicScript(
    const KURL& url,
    ResourceFetcher* fetcher,
    const String& nonce,
    const IntegrityMetadataSet& integrity_metadata,
    ParserDisposition parser_state,
    CrossOriginAttributeValue cross_origin,
    SecurityOrigin* security_origin,
    const String& encoding) {
  // https://html.spec.whatwg.org/#prepare-a-script
  // 21.6, "classic":
  // "Fetch a classic script given url, settings, ..."
  ResourceRequest resource_request(url);

  FetchParameters::DeferOption defer = FetchParameters::kNoDefer;
  if (!parser_inserted_ || element_->AsyncAttributeValue() ||
      element_->DeferAttributeValue())
    defer = FetchParameters::kLazyLoad;

  // [Intervention]
  if (document_write_intervention_ ==
      DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
    resource_request.SetHTTPHeaderField(
        "Intervention",
        "<https://www.chromestatus.com/feature/5718547946799104>");
    defer = FetchParameters::kIdleLoad;
  }

  // [Intervention]
  // For users on slow connections, we want to avoid blocking the parser in
  // the main frame on script loads inserted via document.write, since it can
  // add significant delays before page content is displayed on the screen.
  if (MaybeDisallowFetchForDocWrittenScript(resource_request, defer,
                                            element_->GetDocument())) {
    document_write_intervention_ =
        DocumentWriteIntervention::kDoNotFetchDocWrittenScript;
  }

  FetchParameters params(resource_request, element_->InitiatorName());

  // "... cryptographic nonce, ..."
  params.SetContentSecurityPolicyNonce(nonce);

  // "... integrity metadata, ..."
  params.SetIntegrityMetadata(integrity_metadata);

  // "... parser state, ..."
  params.SetParserDisposition(parser_state);

  // "... CORS setting, ..."
  if (cross_origin != kCrossOriginAttributeNotSet) {
    params.SetCrossOriginAccessControl(security_origin, cross_origin);
  }

  // "... and encoding."
  params.SetCharset(encoding);

  // This DeferOption logic is only for classic scripts, as we always set
  // |kLazyLoad| for module scripts in ModuleScriptLoader.
  params.SetDefer(defer);

  resource_ = ScriptResource::Fetch(params, fetcher);

  if (!resource_)
    return false;

  return true;
}

void ScriptLoader::FetchModuleScriptTree(
    const KURL& url,
    Modulator* modulator,
    const String& nonce,
    ParserDisposition parser_state,
    WebURLRequest::FetchCredentialsMode credentials_mode) {
  // https://html.spec.whatwg.org/#prepare-a-script
  // 21.6, "module":
  //     "Fetch a module script graph given url, settings, "script",
  //      cryptographic nonce, parser state, and
  //      module script credentials mode."
  ModuleScriptFetchRequest module_request(url, nonce, parser_state,
                                          credentials_mode);

  module_tree_client_ = ModulePendingScriptTreeClient::Create();

  modulator->FetchTree(module_request, module_tree_client_);
}

PendingScript* ScriptLoader::CreatePendingScript() {
  switch (GetScriptType()) {
    case ScriptType::kClassic:
      CHECK(resource_);
      return ClassicPendingScript::Create(element_, resource_);
    case ScriptType::kModule:
      CHECK(module_tree_client_);
      return ModulePendingScript::Create(element_, module_tree_client_);
  }
  NOTREACHED();
  return nullptr;
}

bool ScriptLoader::ExecuteScript(const Script* script) {
  double script_exec_start_time = MonotonicallyIncreasingTime();
  bool result = DoExecuteScript(script);

  // NOTE: we do not check m_willBeParserExecuted here, since
  // m_willBeParserExecuted is false for inline scripts, and we want to
  // include inline script execution time as part of parser blocked script
  // execution time.
  if (async_exec_type_ == ScriptRunner::kNone)
    DocumentParserTiming::From(element_->GetDocument())
        .RecordParserBlockedOnScriptExecutionDuration(
            MonotonicallyIncreasingTime() - script_exec_start_time,
            WasCreatedDuringDocumentWrite());
  return result;
}

// https://html.spec.whatwg.org/#execute-the-script-block
// with additional support for HTML imports.
// Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(),
// i.e. load/error events are dispatched by the caller.
// Steps 3--7 are implemented here in doExecuteScript().
// TODO(hiroshige): Move event dispatching code to doExecuteScript().
bool ScriptLoader::DoExecuteScript(const Script* script) {
  DCHECK(already_started_);
  CHECK_EQ(script->GetScriptType(), GetScriptType());

  if (script->IsEmpty())
    return true;

  Document* element_document = &(element_->GetDocument());
  Document* context_document = element_document->ContextDocument();
  if (!context_document)
    return true;

  LocalFrame* frame = context_document->GetFrame();
  if (!frame)
    return true;

  if (!is_external_script_) {
    const ContentSecurityPolicy* csp =
        element_document->GetContentSecurityPolicy();
    bool should_bypass_main_world_csp =
        (frame->GetScriptController().ShouldBypassMainWorldCSP()) ||
        csp->AllowScriptWithHash(script->InlineSourceTextForCSP(),
                                 ContentSecurityPolicy::InlineType::kBlock);

    AtomicString nonce =
        element_->IsNonceableElement() ? element_->nonce() : g_null_atom;
    if (!should_bypass_main_world_csp &&
        !element_->AllowInlineScriptForCSP(nonce, start_line_number_,
                                           script->InlineSourceTextForCSP())) {
      return false;
    }
  }

  if (is_external_script_) {
    if (!script->CheckMIMETypeBeforeRunScript(
            context_document, element_->GetDocument().GetSecurityOrigin()))
      return false;
  }

  const bool is_imported_script = context_document != element_document;

  // 3. "If the script is from an external file,
  //     or the script's type is module",
  //     then increment the ignore-destructive-writes counter of the
  //     script element's node document. Let neutralized doc be that Document."
  IgnoreDestructiveWriteCountIncrementer
      ignore_destructive_write_count_incrementer(
          is_external_script_ ||
                  script->GetScriptType() == ScriptType::kModule ||
                  is_imported_script
              ? context_document
              : 0);

  // 4. "Let old script element be the value to which the script element's
  //     node document's currentScript object was most recently set."
  // This is implemented as push/popCurrentScript().

  // 5. "Switch on the script's type:"
  //    - "classic":
  //    1. "If the script element's root is not a shadow root,
  //        then set the script element's node document's currentScript
  //        attribute to the script element. Otherwise, set it to null."
  //    - "module":
  //    1. "Set the script element's node document's currentScript attribute
  //        to null."
  ScriptElementBase* current_script = nullptr;
  if (script->GetScriptType() == ScriptType::kClassic)
    current_script = element_;
  context_document->PushCurrentScript(current_script);

  //    - "classic":
  //    2. "Run the classic script given by the script's script."
  // Note: This is where the script is compiled and actually executed.
  //    - "module":
  //    2. "Run the module script given by the script's script."
  script->RunScript(frame, element_->GetDocument().GetSecurityOrigin());

  // 6. "Set the script element's node document's currentScript attribute
  //     to old script element."
  context_document->PopCurrentScript(current_script);

  return true;

  // 7. "Decrement the ignore-destructive-writes counter of neutralized doc,
  //     if it was incremented in the earlier step."
  // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer.
}

void ScriptLoader::Execute() {
  DCHECK(!will_be_parser_executed_);
  DCHECK(async_exec_type_ != ScriptRunner::kNone);
  DCHECK(pending_script_->IsExternal());
  bool error_occurred = false;
  Script* script = pending_script_->GetSource(KURL(), error_occurred);
  const bool wasCanceled = pending_script_->WasCanceled();
  DetachPendingScript();
  if (error_occurred) {
    DispatchErrorEvent();
  } else if (!wasCanceled) {
    if (ExecuteScript(script))
      DispatchLoadEvent();
    else
      DispatchErrorEvent();
  }
  resource_ = nullptr;
  module_tree_client_ = nullptr;
}

void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) {
  DCHECK(!will_be_parser_executed_);
  DCHECK_EQ(pending_script_, pending_script);
  DCHECK_EQ(pending_script_->GetScriptType(), GetScriptType());

  // We do not need this script in the memory cache. The primary goals of
  // sending this fetch request are to let the third party server know
  // about the document.write scripts intervention and populate the http
  // cache for subsequent uses.
  if (document_write_intervention_ ==
      DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
    DCHECK_EQ(pending_script_->GetScriptType(), ScriptType::kClassic);
    pending_script_->RemoveFromMemoryCache();
    pending_script_->StopWatchingForLoad();
    return;
  }

  DCHECK(async_exec_type_ != ScriptRunner::kNone);

  Document* context_document = element_->GetDocument().ContextDocument();
  if (!context_document) {
    DetachPendingScript();
    return;
  }

  if (ErrorOccurred()) {
    context_document->GetScriptRunner()->NotifyScriptLoadError(
        this, async_exec_type_);
    DetachPendingScript();
    DispatchErrorEvent();
    return;
  }
  context_document->GetScriptRunner()->NotifyScriptReady(this,
                                                         async_exec_type_);
  pending_script_->StopWatchingForLoad();
}

bool ScriptLoader::IgnoresLoadRequest() const {
  return already_started_ || is_external_script_ || parser_inserted_ ||
         !element_->IsConnected();
}

// Step 13 of https://html.spec.whatwg.org/#prepare-a-script
bool ScriptLoader::IsScriptForEventSupported() const {
  // 1. "Let for be the value of the for attribute."
  String event_attribute = element_->EventAttributeValue();
  // 2. "Let event be the value of the event attribute."
  String for_attribute = element_->ForAttributeValue();

  // "If the script element has an event attribute and a for attribute, and
  //  the script's type is "classic", then run these substeps:"
  // TODO(hiroshige): Check the script's type.
  if (event_attribute.IsNull() || for_attribute.IsNull())
    return true;

  // 3. "Strip leading and trailing ASCII whitespace from event and for."
  for_attribute = for_attribute.StripWhiteSpace();
  // 4. "If for is not an ASCII case-insensitive match for the string
  //     "window",
  //     then abort these steps at this point. The script is not executed."
  if (!DeprecatedEqualIgnoringCase(for_attribute, "window"))
    return false;
  event_attribute = event_attribute.StripWhiteSpace();
  // 5. "If event is not an ASCII case-insensitive match for either the
  //     string "onload" or the string "onload()",
  //     then abort these steps at this point. The script is not executed.
  return DeprecatedEqualIgnoringCase(event_attribute, "onload") ||
         DeprecatedEqualIgnoringCase(event_attribute, "onload()");
}

String ScriptLoader::ScriptContent() const {
  return element_->TextFromChildren();
}

}  // namespace blink
