Bug 1226548 - Event listeners tooltip breaks the syntax in popup if there's a comment before event handler in JS code. r=ochameau

--HG--
rename : devtools/client/inspector/markup/test/browser_markup_events.js => devtools/client/inspector/markup/test/browser_markup_events1.js
rename : devtools/client/inspector/markup/test/doc_markup_events.html => devtools/client/inspector/markup/test/doc_markup_events1.html
This commit is contained in:
Michael Ratcliffe 2016-04-26 13:37:47 +01:00
Родитель 4b698b9d7c
Коммит 98177632d6
10 изменённых файлов: 620 добавлений и 156 удалений

Просмотреть файл

@ -7,7 +7,9 @@ support-files =
doc_markup_dragdrop.html doc_markup_dragdrop.html
doc_markup_dragdrop_autoscroll.html doc_markup_dragdrop_autoscroll.html
doc_markup_edit.html doc_markup_edit.html
doc_markup_events.html doc_markup_events1.html
doc_markup_events2.html
doc_markup_events3.html
doc_markup_events_form.html doc_markup_events_form.html
doc_markup_events_jquery.html doc_markup_events_jquery.html
doc_markup_events-overflow.html doc_markup_events-overflow.html
@ -62,7 +64,9 @@ skip-if = e10s # scratchpad.xul is not loading in e10s window
[browser_markup_dragdrop_invalidNodes.js] [browser_markup_dragdrop_invalidNodes.js]
[browser_markup_dragdrop_reorder.js] [browser_markup_dragdrop_reorder.js]
[browser_markup_dragdrop_tooltip.js] [browser_markup_dragdrop_tooltip.js]
[browser_markup_events.js] [browser_markup_events1.js]
[browser_markup_events2.js]
[browser_markup_events3.js]
[browser_markup_events_form.js] [browser_markup_events_form.js]
[browser_markup_events_jquery_1.0.js] [browser_markup_events_jquery_1.0.js]
[browser_markup_events_jquery_1.1.js] [browser_markup_events_jquery_1.1.js]

Просмотреть файл

@ -8,7 +8,7 @@
// Test that markup view event bubbles show the correct event info for DOM // Test that markup view event bubbles show the correct event info for DOM
// events. // events.
const TEST_URL = URL_ROOT + "doc_markup_events.html"; const TEST_URL = URL_ROOT + "doc_markup_events1.html";
loadHelperScript("helper_events_test_runner.js"); loadHelperScript("helper_events_test_runner.js");
@ -32,7 +32,7 @@ const TEST_DATA = [ // eslint-disable-line
expected: [ expected: [
{ {
type: "mouseover", type: "mouseover",
filename: TEST_URL + ":62", filename: TEST_URL + ":45",
attributes: [ attributes: [
"Capturing", "Capturing",
"DOM2" "DOM2"
@ -51,7 +51,7 @@ const TEST_DATA = [ // eslint-disable-line
expected: [ expected: [
{ {
type: "click", type: "click",
filename: TEST_URL + ":69", filename: TEST_URL + ":52",
attributes: [ attributes: [
"Bubbling", "Bubbling",
"DOM2" "DOM2"
@ -63,7 +63,7 @@ const TEST_DATA = [ // eslint-disable-line
}, },
{ {
type: "mouseup", type: "mouseup",
filename: TEST_URL + ":78", filename: TEST_URL + ":57",
attributes: [ attributes: [
"Bubbling", "Bubbling",
"DOM2" "DOM2"
@ -75,84 +75,6 @@ const TEST_DATA = [ // eslint-disable-line
} }
] ]
}, },
{
selector: "#DOM0",
expected: [
{
type: "click",
filename: TEST_URL,
attributes: [
"Bubbling",
"DOM0"
],
handler: "alert('hi')"
}
]
},
{
selector: "#handleevent",
expected: [
{
type: "click",
filename: TEST_URL + ":89",
attributes: [
"Bubbling",
"DOM2"
],
handler: "handleEvent: function(blah) {\n" +
" alert(\"handleEvent clicked\");\n" +
"}"
}
]
},
{
selector: "#fatarrow",
expected: [
{
type: "click",
filename: TEST_URL + ":57",
attributes: [
"Bubbling",
"DOM2"
],
handler: "event => {\n" +
" alert(\"Yay for the fat arrow!\");\n" +
"}"
}
]
},
{
selector: "#boundhe",
expected: [
{
type: "click",
filename: TEST_URL + ":101",
attributes: [
"Bubbling",
"DOM2"
],
handler: "handleEvent: function() {\n" +
" alert(\"boundHandleEvent clicked\");\n" +
"}"
}
]
},
{
selector: "#bound",
expected: [
{
type: "click",
filename: TEST_URL + ":74",
attributes: [
"Bubbling",
"DOM2"
],
handler: "function boundClickHandler(event) {\n" +
" alert(\"Bound event clicked\");\n" +
"}"
}
]
},
// #noevents tests check that dynamically added events are properly displayed // #noevents tests check that dynamically added events are properly displayed
// in the markupview // in the markupview
{ {
@ -169,7 +91,7 @@ const TEST_DATA = [ // eslint-disable-line
expected: [ expected: [
{ {
type: "click", type: "click",
filename: TEST_URL + ":106", filename: TEST_URL + ":72",
attributes: [ attributes: [
"Bubbling", "Bubbling",
"DOM2" "DOM2"
@ -190,6 +112,36 @@ const TEST_DATA = [ // eslint-disable-line
}, },
expected: [] expected: []
}, },
{
selector: "#DOM0",
expected: [
{
type: "click",
filename: TEST_URL,
attributes: [
"Bubbling",
"DOM0"
],
handler: "alert('DOM0')"
}
]
},
{
selector: "#handleevent",
expected: [
{
type: "click",
filename: TEST_URL + ":67",
attributes: [
"Bubbling",
"DOM2"
],
handler: "handleEvent: function(blah) {\n" +
" alert(\"handleEvent\");\n" +
"}"
}
]
}
]; ];
add_task(function* () { add_task(function* () {

Просмотреть файл

@ -0,0 +1,163 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* import-globals-from helper_events_test_runner.js */
"use strict";
// Test that markup view event bubbles show the correct event info for DOM
// events.
const TEST_URL = URL_ROOT + "doc_markup_events2.html";
loadHelperScript("helper_events_test_runner.js");
const TEST_DATA = [ // eslint-disable-line
{
selector: "#fatarrow",
expected: [
{
type: "click",
filename: TEST_URL + ":39",
attributes: [
"Bubbling",
"DOM2"
],
handler: "() => {\n" +
" alert(\"Fat arrow without params!\");\n" +
"}"
},
{
type: "click",
filename: TEST_URL + ":43",
attributes: [
"Bubbling",
"DOM2"
],
handler: "event => {\n" +
" alert(\"Fat arrow with 1 param!\");\n" +
"}"
},
{
type: "click",
filename: TEST_URL + ":47",
attributes: [
"Bubbling",
"DOM2"
],
handler: "(event, foo, bar) => {\n" +
" alert(\"Fat arrow with 3 params!\");\n" +
"}"
},
{
type: "click",
filename: TEST_URL + ":51",
attributes: [
"Bubbling",
"DOM2"
],
handler: "b => b"
}
]
},
{
selector: "#bound",
expected: [
{
type: "click",
filename: TEST_URL + ":62",
attributes: [
"Bubbling",
"DOM2"
],
handler: "function boundClickHandler(event) {\n" +
" alert(\"Bound event\");\n" +
"}"
}
]
},
{
selector: "#boundhe",
expected: [
{
type: "click",
filename: TEST_URL + ":85",
attributes: [
"Bubbling",
"DOM2"
],
handler: "handleEvent: function() {\n" +
" alert(\"boundHandleEvent\");\n" +
"}"
}
]
},
{
selector: "#comment-inline",
expected: [
{
type: "click",
filename: TEST_URL + ":91",
attributes: [
"Bubbling",
"DOM2"
],
handler: "function functionProceededByInlineComment() {\n" +
" alert(\"comment-inline\");\n" +
"}"
}
]
},
{
selector: "#comment-streaming",
expected: [
{
type: "click",
filename: TEST_URL + ":96",
attributes: [
"Bubbling",
"DOM2"
],
handler: "function functionProceededByStreamingComment() {\n" +
" alert(\"comment-streaming\");\n" +
"}"
}
]
},
{
selector: "#anon-object-method",
expected: [
{
type: "click",
filename: TEST_URL + ":71",
attributes: [
"Bubbling",
"DOM2"
],
handler: "anonObjectMethod: function() {\n" +
" alert(\"obj.anonObjectMethod\");\n" +
"}"
}
]
},
{
selector: "#object-method",
expected: [
{
type: "click",
filename: TEST_URL + ":75",
attributes: [
"Bubbling",
"DOM2"
],
handler: "objectMethod: function kay() {\n" +
" alert(\"obj.objectMethod\");\n" +
"}"
}
]
}
];
add_task(function* () {
yield runEventPopupTests(TEST_URL, TEST_DATA);
});

Просмотреть файл

@ -0,0 +1,161 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* import-globals-from helper_events_test_runner.js */
"use strict";
// Test that markup view event bubbles show the correct event info for DOM
// events.
const TEST_URL = URL_ROOT + "doc_markup_events3.html";
loadHelperScript("helper_events_test_runner.js");
const TEST_DATA = [ // eslint-disable-line
{
selector: "#es6-method",
expected: [
{
type: "click",
filename: TEST_URL + ":91",
attributes: [
"Bubbling",
"DOM2"
],
handler: "es6Method() {\n" +
" alert(\"obj.es6Method\");\n" +
"}"
}
]
},
{
selector: "#generator",
expected: [
{
type: "click",
filename: TEST_URL + ":96",
attributes: [
"Bubbling",
"DOM2"
],
handler: "function* generator() {\n" +
" alert(\"generator\");\n" +
"}"
}
]
},
{
selector: "#anon-generator",
expected: [
{
type: "click",
filename: TEST_URL + ":55",
attributes: [
"Bubbling",
"DOM2"
],
handler: "function*() {\n" +
" alert(\"anonGenerator\");\n" +
"}"
}
]
},
{
selector: "#named-function-expression",
expected: [
{
type: "click",
filename: TEST_URL + ":23",
attributes: [
"Bubbling",
"DOM2"
],
handler: "let namedFunctionExpression =\n" +
" function foo() {\n" +
" alert(\"namedFunctionExpression\");\n" +
" }"
}
]
},
{
selector: "#anon-function-expression",
expected: [
{
type: "click",
filename: TEST_URL + ":27",
attributes: [
"Bubbling",
"DOM2"
],
handler: "let anonFunctionExpression = function() {\n" +
" alert(\"anonFunctionExpression\");\n" +
"}"
}
]
},
{
selector: "#returned-function",
expected: [
{
type: "click",
filename: TEST_URL + ":32",
attributes: [
"Bubbling",
"DOM2"
],
handler: "function bar() {\n" +
" alert(\"returnedFunction\");\n" +
"}"
}
]
},
{
selector: "#constructed-function",
expected: [
{
type: "click",
filename: TEST_URL + ":1",
attributes: [
"Bubbling",
"DOM2"
],
handler: ""
}
]
},
{
selector: "#constructed-function-with-body-string",
expected: [
{
type: "click",
filename: TEST_URL + ":1",
attributes: [
"Bubbling",
"DOM2"
],
handler: "alert(\"constructedFuncWithBodyString\");"
}
]
},
{
selector: "#multiple-assignment",
expected: [
{
type: "click",
filename: TEST_URL + ":42",
attributes: [
"Bubbling",
"DOM2"
],
handler: "let multipleAssignment = foo = bar = function multi() {\n" +
" alert(\"multipleAssignment\");\n" +
"}"
}
]
},
];
add_task(function* () {
yield runEventPopupTests(TEST_URL, TEST_DATA);
});

Просмотреть файл

@ -23,8 +23,7 @@ const TEST_DATA = [
attributes: [ attributes: [
"jQuery" "jQuery"
], ],
handler: "// Handle when the DOM is ready\n" + handler: "ready: function() {\n" +
"ready: function() {\n" +
" // Make sure that the DOM is not already loaded\n" + " // Make sure that the DOM is not already loaded\n" +
" if (!jQuery.isReady) {\n" + " if (!jQuery.isReady) {\n" +
" // Remember that the DOM is ready\n" + " // Remember that the DOM is ready\n" +

Просмотреть файл

@ -23,8 +23,7 @@ const TEST_DATA = [
attributes: [ attributes: [
"jQuery" "jQuery"
], ],
handler: "// Handle when the DOM is ready\n" + handler: "ready: function() {\n" +
"ready: function() {\n" +
" // Make sure that the DOM is not already loaded\n" + " // Make sure that the DOM is not already loaded\n" +
" if (!jQuery.isReady) {\n" + " if (!jQuery.isReady) {\n" +
" // Remember that the DOM is ready\n" + " // Remember that the DOM is ready\n" +

Просмотреть файл

@ -19,15 +19,6 @@
#noevents, #noevents,
#DOM0, #DOM0,
#handleevent, #handleevent,
#fatarrow,
#bound,
#boundhe {
border: 1px solid #000;
width: 200px;
min-height: 1em;
cursor: pointer;
}
#output, #output,
#noevents { #noevents {
cursor: auto; cursor: auto;
@ -41,22 +32,14 @@
function init() { function init() {
let container = document.getElementById("container"); let container = document.getElementById("container");
let multiple = document.getElementById("multiple"); let multiple = document.getElementById("multiple");
let fatarrow = document.getElementById("fatarrow");
container.addEventListener("mouseover", mouseoverHandler, true); container.addEventListener("mouseover", mouseoverHandler, true);
multiple.addEventListener("click", clickHandler, false); multiple.addEventListener("click", clickHandler, false);
multiple.addEventListener("mouseup", mouseupHandler, false); multiple.addEventListener("mouseup", mouseupHandler, false);
new handleEventClick(); let he = new handleEventClick();
new boundHandleEventClick(); let handleevent = document.getElementById("handleevent");
handleevent.addEventListener("click", he);
let bound = document.getElementById("bound");
boundClickHandler = boundClickHandler.bind(this);
bound.addEventListener("click", boundClickHandler);
fatarrow.addEventListener("click", event => {
alert("Yay for the fat arrow!");
});
} }
function mouseoverHandler(event) { function mouseoverHandler(event) {
@ -71,54 +54,38 @@
output.textContent = "click"; output.textContent = "click";
} }
function boundClickHandler(event) {
alert("Bound event clicked");
}
function mouseupHandler(event) { function mouseupHandler(event) {
let output = document.getElementById("output"); let output = document.getElementById("output");
output.textContent = "mouseup"; output.textContent = "mouseup";
} }
function handleEventClick(hehe) { function handleEventClick(hehe) {
let handleevent = document.getElementById("handleevent");
handleevent.addEventListener("click", this);
} }
handleEventClick.prototype = { handleEventClick.prototype = {
handleEvent: function(blah) { handleEvent: function(blah) {
alert("handleEvent clicked"); alert("handleEvent");
}
};
function boundHandleEventClick() {
let boundhe = document.getElementById("boundhe");
this.handleEvent = this.handleEvent.bind(this);
boundhe.addEventListener("click", this);
}
boundHandleEventClick.prototype = {
handleEvent: function() {
alert("boundHandleEvent clicked");
} }
}; };
function noeventsClickHandler(event) { function noeventsClickHandler(event) {
alert("noevents has an event listener"); alert("noevents has an event listener");
}; }
function addNoeventsClickHandler() { function addNoeventsClickHandler() {
let noevents = document.getElementById("noevents"); let noevents = document.getElementById("noevents");
noevents.addEventListener("click", noeventsClickHandler); noevents.addEventListener("click", noeventsClickHandler);
}; }
function removeNoeventsClickHandler() { function removeNoeventsClickHandler() {
let noevents = document.getElementById("noevents"); let noevents = document.getElementById("noevents");
noevents.removeEventListener("click", noeventsClickHandler); noevents.removeEventListener("click", noeventsClickHandler);
}; }
</script> </script>
</head> </head>
<body onload="init();"> <body onload="init();">
<h1>Events test 1</h1>
<div id="container"> <div id="container">
<div>1</div> <div>1</div>
<div>2</div> <div>2</div>
@ -139,11 +106,8 @@
<div id="multiple">multiple</div> <div id="multiple">multiple</div>
</div> </div>
<div id="output"></div> <div id="output"></div>
<div id="noevents">No events here</div> <div id="noevents">noevents</div>
<div id="DOM0" onclick="alert('hi')">DOM0 event here</div> <div id="DOM0" onclick="alert('DOM0')">DOM0 event here</div>
<div id="handleevent">handleEvent event here</div> <div id="handleevent">handleEvent</div>
<div id="fatarrow">Fat arrow event</div>
<div id="boundhe">Bound handleEvent</div>
<div id="bound">Bound event</div>
</body> </body>
</html> </html>

Просмотреть файл

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
#fatarrow,
#bound,
#boundhe,
#comment-inline,
#comment-streaming,
#anon-object-method,
#object-method {
border: 1px solid #000;
width: 200px;
min-height: 1em;
cursor: pointer;
}
</style>
<script type="application/javascript;version=1.8">
function init() {
let fatarrow = document.getElementById("fatarrow");
let he = new handleEventClick();
let anonObjectMethod = document.getElementById("anon-object-method");
anonObjectMethod.addEventListener("click", he.anonObjectMethod);
let objectMethod = document.getElementById("object-method");
objectMethod.addEventListener("click", he.objectMethod);
let bhe = new boundHandleEventClick();
let boundheNode = document.getElementById("boundhe");
bhe.handleEvent = bhe.handleEvent.bind(bhe);
boundheNode.addEventListener("click", bhe);
let boundNode = document.getElementById("bound");
boundClickHandler = boundClickHandler.bind(this);
boundNode.addEventListener("click", boundClickHandler);
fatarrow.addEventListener("click", () => {
alert("Fat arrow without params!");
});
fatarrow.addEventListener("click", event => {
alert("Fat arrow with 1 param!");
});
fatarrow.addEventListener("click", (event, foo, bar) => {
alert("Fat arrow with 3 params!");
});
fatarrow.addEventListener("click", b => b);
let inlineCommentNode = document.getElementById("comment-inline");
inlineCommentNode
.addEventListener("click", functionProceededByInlineComment);
let streamingCommentNode = document.getElementById("comment-streaming");
streamingCommentNode
.addEventListener("click", functionProceededByStreamingComment);
}
function boundClickHandler(event) {
alert("Bound event");
}
function handleEventClick(hehe) {
}
handleEventClick.prototype = {
anonObjectMethod: function() {
alert("obj.anonObjectMethod");
},
objectMethod: function kay() {
alert("obj.objectMethod");
},
};
function boundHandleEventClick() {
}
boundHandleEventClick.prototype = {
handleEvent: function() {
alert("boundHandleEvent");
}
};
// A function proceeded with an inline comment
function functionProceededByInlineComment() {
alert("comment-inline");
}
/* A function proceeded with a streaming comment */
function functionProceededByStreamingComment() {
alert("comment-streaming");
}
</script>
</head>
<body onload="init();">
<h1>Events test 2</h1>
<div id="fatarrow">Fat arrows</div>
<div id="boundhe">Bound handleEvent</div>
<div id="bound">Bound event</div>
<div id="comment-inline">Event proceeded by an inline comment</div>
<div id="comment-streaming">Event proceeded by a streaming comment</div>
<div id="anon-object-method">Anonymous object method</div>
<div id="object-method">Object method</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
#es6-method,
#generator,
#anon-generator,
#named-function-expression,
#anon-function-expression,
#returned-function,
#constructed-function,
#constructed-function-with-body-string,
#multiple-assignment {
border: 1px solid #000;
width: 200px;
min-height: 1em;
cursor: pointer;
}
</style>
<script type="application/javascript;version=1.8">
let namedFunctionExpression =
function foo() {
alert("namedFunctionExpression");
}
let anonFunctionExpression = function() {
alert("anonFunctionExpression");
};
let returnedFunction = (function() {
return function bar() {
alert("returnedFunction");
}
})();
let constructedFunc = new Function();
let constructedFuncWithBodyString =
new Function('a', 'b', 'c', 'alert("constructedFuncWithBodyString");');
let multipleAssignment = foo = bar = function multi() {
alert("multipleAssignment");
}
function init() {
let he = new handleEventClick();
let es6Method = document.getElementById("es6-method");
es6Method.addEventListener("click", he.es6Method);
let generatorNode = document.getElementById("generator");
generatorNode.addEventListener("click", generator);
let anonGenerator = document.getElementById("anon-generator");
anonGenerator.addEventListener("click", function* () {
alert("anonGenerator");
});
let namedFunctionExpressionNode =
document.getElementById("named-function-expression");
namedFunctionExpressionNode.addEventListener("click",
namedFunctionExpression);
let anonFunctionExpressionNode =
document.getElementById("anon-function-expression");
anonFunctionExpressionNode.addEventListener("click",
anonFunctionExpression);
let returnedFunctionNode = document.getElementById("returned-function");
returnedFunctionNode.addEventListener("click", returnedFunction);
let constructedFunctionNode =
document.getElementById("constructed-function");
constructedFunctionNode.addEventListener("click", constructedFunc);
let constructedFunctionWithBodyStringNode =
document.getElementById("constructed-function-with-body-string");
constructedFunctionWithBodyStringNode
.addEventListener("click", constructedFuncWithBodyString);
let multipleAssignmentNode =
document.getElementById("multiple-assignment");
multipleAssignmentNode.addEventListener("click", multipleAssignment);
}
function handleEventClick(hehe) {
}
handleEventClick.prototype = {
es6Method() {
alert("obj.es6Method");
}
};
function* generator() {
alert("generator");
}
</script>
</head>
<body onload="init();">
<h1>Events test 3</h1>
<div id="es6-method">ES6 method</div>
<div id="generator">Generator</div>
<div id="anon-generator">Anonymous Generator</div>
<div id="named-function-expression">Named Function Expression</div>
<div id="anon-function-expression">Anonymous Function Expression</div>
<div id="returned-function">Returned Function</div>
<div id="constructed-function">Constructed Function</div>
<div id="constructed-function-with-body-string">
Constructed Function with body string
</div>
<div id="multiple-assignment">Multiple Assignment</div>
</body>
</html>

Просмотреть файл

@ -87,8 +87,10 @@ const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
const PSEUDO_CLASSES = [":hover", ":active", ":focus"]; const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__"; const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
const XHTML_NS = "http://www.w3.org/1999/xhtml"; const XHTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const IMAGE_FETCHING_TIMEOUT = 500; const IMAGE_FETCHING_TIMEOUT = 500;
const RX_FUNC_NAME = /((var|const|let)\s+)?([\w$.]+\s*[:=]\s*)*(function)?\s*\*?\s*([\w$]+)?\s*$/;
// The possible completions to a ':' with added score to give certain values // The possible completions to a ':' with added score to give certain values
// some preference. // some preference.
const PSEUDO_SELECTORS = [ const PSEUDO_SELECTORS = [
@ -553,28 +555,22 @@ var NodeActor = exports.NodeActor = protocol.ActorClass({
/* /*
The script returned is the whole script and The script returned is the whole script and
scriptSource.substr(script.sourceStart, script.sourceLength) returns scriptSource.substr(script.sourceStart, script.sourceLength) returns
something like: something like this:
() { doSomething(); } () { doSomething(); }
So we need to work back to the preceeding \n, ; or } so we can get the So we need to use some regex magic to get the appropriate function info
appropriate function info e.g.: e.g.:
() => { doSomething(); } () => { ... }
function doit() { doSomething(); } function doit() { ... }
doit: function() { doSomething(); } doit: function() { ... }
es6func() { ... }
var|let|const foo = function () { ... }
function generator*() { ... }
*/ */
let scriptBeforeFunc = scriptSource.substr(0, script.sourceStart); let scriptBeforeFunc = scriptSource.substr(0, script.sourceStart);
let lastEnding = Math.max( let matches = scriptBeforeFunc.match(RX_FUNC_NAME);
scriptBeforeFunc.lastIndexOf(";"), if (matches && matches.length > 0) {
scriptBeforeFunc.lastIndexOf("}"), functionSource = matches[0].trim() + functionSource;
scriptBeforeFunc.lastIndexOf("{"),
scriptBeforeFunc.lastIndexOf("("),
scriptBeforeFunc.lastIndexOf(","),
scriptBeforeFunc.lastIndexOf("!")
);
if (lastEnding !== -1) {
let functionPrefix = scriptBeforeFunc.substr(lastEnding + 1);
functionSource = functionPrefix + functionSource;
} }
let dom0 = false; let dom0 = false;