Commit 797bef07 authored by Hiroshige Hayashizaki's avatar Hiroshige Hayashizaki Committed by Commit Bot

Evaluate child text content at the time of #prepare-a-script, not evaluation

Previously, classic inline script's source_text to be evaluated is taken
from the element's child text content at the time of evaluation.
However, according to the spec, this should be the element's
child text content at the time of #prepare-a-script.

This CL fixes this by taking the element's child text content in
ClassicPendingScript's constructor, which is called inside PrepareScript().

This affects the behavior if parser-inserted classic inline <script>'s
innerText is modified by JavaScript after <script> is inserted into DOM
before its evaluation, and I expect this is extremely rare and doesn't
have legitimate use cases.

Bug: 686281
Change-Id: I0ef67dd8b71403a7862f24d02394f89c6e916bfd
Reviewed-on: https://chromium-review.googlesource.com/1091912Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Commit-Queue: Hiroshige Hayashizaki <hiroshige@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567348}
parent 67b738e1
import time
def main(request, response):
time.sleep(1.0);
return [("Content-type", "text/javascript")], """
var s = document.getElementById('script0');
s.innerText = 't.unreached_func("This should not be evaluated")();';
"""
<!doctype html>
<head>
<meta charset=utf-8>
<title>Modify HTMLScriptElement's text after #prepare-a-script</title>
<link rel=help href="https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var t = async_test("Modify inline script element's text " +
"after prepare-a-script before evaluation");
</script>
<!-- This is "a style sheet that is blocking scripts" and thus ... -->
<link rel="stylesheet" href="resources/slow.py"></link>
<script src="resources/script-text-modifications.py" async></script>
<!-- This inline script becomes a parser-blocking script, and thus
the async script above is evaluated after script0 is inserted into DOM,
prepare-a-script'ed, and before its evaluation. -->
<script id="script0">
t.step(() => {
// When this is evaluated after the stylesheet is loaded,
// script0's innerText is modified by the async script above,
// but the evaluated script is still the original script here,
// not what is overwritten, because "child text content" is taken in
// #prepare-a-script and passed to "creating a classic script".
var s = document.getElementById('script0');
assert_equals(s.innerText,
't.unreached_func("This should not be evaluated")();',
"<script>'s innerText should be already modified");
assert_equals(s.text,
't.unreached_func("This should not be evaluated")();',
"<script>'s text should be already modified");
t.done();
});
</script>
......@@ -81,6 +81,8 @@ ClassicPendingScript::ClassicPendingScript(
options_(options),
base_url_for_inline_script_(
is_external ? KURL() : element->GetDocument().BaseURL()),
source_text_for_inline_script_(is_external ? String()
: element->TextFromChildren()),
source_location_type_(source_location_type),
is_external_(is_external),
ready_state_(is_external ? kWaitingForResource : kReady),
......@@ -252,7 +254,6 @@ ClassicScript* ClassicPendingScript::GetSource(const KURL& document_url,
error_occurred = ErrorOccurred();
if (!is_external_) {
SingleCachedMetadataHandler* cache_handler = nullptr;
String source = GetElement()->TextFromChildren();
// We only create an inline cache handler for html-embedded scripts, not
// for scripts produced by document.write, or not parser-inserted. This is
// because we expect those to be too dynamic to benefit from caching.
......@@ -262,10 +263,11 @@ ClassicScript* ClassicPendingScript::GetSource(const KURL& document_url,
// used for behavioural changes (and if yes, update its documentation), or
// otherwise trigger this behaviour differently.
if (source_location_type_ == ScriptSourceLocationType::kInline) {
cache_handler =
GetInlineCacheHandler(source, GetElement()->GetDocument());
cache_handler = GetInlineCacheHandler(source_text_for_inline_script_,
GetElement()->GetDocument());
}
ScriptSourceCode source_code(source, source_location_type_, cache_handler,
ScriptSourceCode source_code(source_text_for_inline_script_,
source_location_type_, cache_handler,
document_url, StartingPosition());
return ClassicScript::Create(source_code, base_url_for_inline_script_,
options_, kSharableCrossOrigin);
......
......@@ -119,6 +119,10 @@ class CORE_EXPORT ClassicPendingScript final : public PendingScript,
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url
const KURL base_url_for_inline_script_;
// "element's child text content" snapshot taken at
// #prepare-a-script (Step 4).
const String source_text_for_inline_script_;
const ScriptSourceLocationType source_location_type_;
const bool is_external_;
ReadyState ready_state_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment