changeset 11173:1a7f16bc4f71

Merge
author kcr
date Fri, 11 Jan 2019 07:51:13 -0800
parents 6baf949064fb cf3c996ca3b9
children 356023276b17 f8b8ead4ac56
files apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/shBrushJava.js apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/shCore.js apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/shCoreDefault.css modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/check-relaxng-test-suite.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/check-relaxng-test-suite2.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/check-xinclude-test-suite.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/check-xml-test-suite.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/check-xsddata-test-suite.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/dbgen.pl modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/dbgenattr.pl modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/genUnicode.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/gentest.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/regressions.py modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/runsuite.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/runtest.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/runxmlconf.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testAutomata.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testC14N.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testHTML.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testModule.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testReader.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testRegexp.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testRelax.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testSAX.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testSchemas.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testThreads.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testThreadsWin32.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testURI.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testXPath.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testapi.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testchar.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testdict.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testdso.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testlimits.c modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/testrecurse.c
diffstat 204 files changed, 43094 insertions(+), 97108 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Dec 21 15:21:30 2018 -0800
+++ b/.hgtags	Fri Jan 11 07:51:13 2019 -0800
@@ -517,3 +517,5 @@
 0e8471a4ad564366ee0559550acb03fb53d66bcc 12+4
 32a30b0adafc71a1d3e9cee8acc476fffc230bb7 12+5
 1f990b4b789afb91f5ca1e37bbeaa7172744108e 12+6
+aea5c65b89db93c41af94bf7c67634b6e9c40f93 12+7
+1d6bec87575fb993de57e9b63d0c56a845bbf7e7 12+8
--- a/apps/samples/Ensemble8/legal/syntaxhighlighter.md	Fri Dec 21 15:21:30 2018 -0800
+++ b/apps/samples/Ensemble8/legal/syntaxhighlighter.md	Fri Jan 11 07:51:13 2019 -0800
@@ -1,8 +1,8 @@
-## SyntaxHighlighter v3.0.83
+## SyntaxHighlighter v4.0.1
 
 ### MIT License
 <pre>
-Copyright (C) 2004-2010 Alex Gorbatchev.
+Copyright (c) 2004-2013, Alex Gorbatchev
 
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
--- a/apps/samples/Ensemble8/src/app/java/ensemble/samplepage/SourceTab.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/apps/samples/Ensemble8/src/app/java/ensemble/samplepage/SourceTab.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates.
  * All rights reserved. Use is subject to license terms.
  *
  * This file is available and licensed under the following license:
@@ -93,21 +93,19 @@
 
     private static final Pattern JAVA_DOC_PATTERN = Pattern.compile("(^\\s+\\*$\\s)?^\\s+\\*\\s+@.*$\\s",Pattern.MULTILINE);
     private static String shCoreJs;
-    private static String shBrushJScript;
-    private static String shCoreDefaultCss;
+    private static String shThemeCss;
 
     private static String convertToHTML(String source) {
         // load syntax highlighter
         if (shCoreJs == null) {
-            shCoreJs = Utils.loadFile(EnsembleApp.class.getResource("syntaxhighlighter/shCore.js")) +";";
+            shCoreJs = Utils.loadFile(EnsembleApp.class.getResource("syntaxhighlighter/syntaxhighlighter.js"));
         }
-        if (shBrushJScript == null) {
-            shBrushJScript = Utils.loadFile(EnsembleApp.class.getResource("syntaxhighlighter/shBrushJava.js"));
+        if (shThemeCss == null) {
+            shThemeCss = Utils.loadFile(EnsembleApp.class.getResource("syntaxhighlighter/theme.css"))
+                    .replaceAll("!important","");
         }
-        if (shCoreDefaultCss == null) {
-            shCoreDefaultCss = Utils.loadFile(EnsembleApp.class.getResource("syntaxhighlighter/shCoreDefault.css")).replaceAll("!important","");
-        }
-        // split copy right and source
+
+        // split copyright and source
         String[] parts = source.split("\\*/",2);
         String copyRight = null;
         if (parts.length > 1) {
@@ -128,11 +126,9 @@
         html.append("    <head>\n");
         html.append("    <script type=\"text/javascript\">\n");
         html.append(shCoreJs);
-        html.append('\n');
-        html.append(shBrushJScript);
         html.append("    </script>\n");
         html.append("    <style>\n");
-        html.append(shCoreDefaultCss);
+        html.append(shThemeCss);
         html.append('\n');
         html.append("        .syntaxhighlighter {\n");
         html.append("           overflow: visible;\n");
@@ -176,7 +172,6 @@
         html.append(source);
         html.append('\n');
         html.append("    </pre>\n");
-        html.append("    <script type=\"text/javascript\"> SyntaxHighlighter.all(); </script>\n");
         html.append("</body>\n");
         html.append("</html>\n");
 
--- a/apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/shBrushJava.js	Fri Dec 21 15:21:30 2018 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
- *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
- *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
- */
-;(function()
-{
-	// CommonJS
-	typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
-
-	function Brush()
-	{
-		var keywords =	'abstract assert boolean break byte case catch char class const ' +
-						'continue default do double else enum extends ' +
-						'false final finally float for goto if implements import ' +
-						'instanceof int interface long native new null ' +
-						'package private protected public return ' +
-						'short static strictfp super switch synchronized this throw throws true ' +
-						'transient try void volatile while';
-                                            
-                this.regexList = [
-			{ regex: SyntaxHighlighter.regexLib.singleLineCComments,	css: 'comments' },		// one line comments
-                        { regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' },      // multiline comments
-			{ regex: /\/\*(?!\*\/)\*[\s\S]*?\*\//gm,					css: 'preprocessor' },	// documentation comments
-			{ regex: SyntaxHighlighter.regexLib.doubleQuotedString,		css: 'string' },		// strings
-			{ regex: SyntaxHighlighter.regexLib.singleQuotedString,		css: 'string' },		// strings
-			{ regex: /\b([\d]+(\.[\d]+)?|0x[a-f0-9]+)\b/gi,				css: 'value' },			// numbers
-			{ regex: /(?!\@interface\b)\@[\$\w]+\b/g,					css: 'color1' },		// annotation @anno
-			{ regex: /\@interface\b/g,									css: 'color2' },		// @interface keyword
-			{ regex: new RegExp(this.getKeywords(keywords), 'gm'),		css: 'keyword' }		// java keyword
-                ];
-
-		this.forHtmlScript({
-			left	: /(&lt;|<)%[@!=]?/g, 
-			right	: /%(&gt;|>)/g 
-		});
-	};
-
-	Brush.prototype	= new SyntaxHighlighter.Highlighter();
-	Brush.aliases	= ['java'];
-
-	SyntaxHighlighter.brushes.Java = Brush;
-
-	// CommonJS
-	typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
-})();
--- a/apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/shCore.js	Fri Dec 21 15:21:30 2018 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
- *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
- *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
- */
-eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('K M;I(M)1S 2U("2a\'t 4k M 4K 2g 3l 4G 4H");(6(){6 r(f,e){I(!M.1R(f))1S 3m("3s 15 4R");K a=f.1w;f=M(f.1m,t(f)+(e||""));I(a)f.1w={1m:a.1m,19:a.19?a.19.1a(0):N};H f}6 t(f){H(f.1J?"g":"")+(f.4s?"i":"")+(f.4p?"m":"")+(f.4v?"x":"")+(f.3n?"y":"")}6 B(f,e,a,b){K c=u.L,d,h,g;v=R;5K{O(;c--;){g=u[c];I(a&g.3r&&(!g.2p||g.2p.W(b))){g.2q.12=e;I((h=g.2q.X(f))&&h.P===e){d={3k:g.2b.W(b,h,a),1C:h};1N}}}}5v(i){1S i}5q{v=11}H d}6 p(f,e,a){I(3b.Z.1i)H f.1i(e,a);O(a=a||0;a<f.L;a++)I(f[a]===e)H a;H-1}M=6(f,e){K a=[],b=M.1B,c=0,d,h;I(M.1R(f)){I(e!==1d)1S 3m("2a\'t 5r 5I 5F 5B 5C 15 5E 5p");H r(f)}I(v)1S 2U("2a\'t W 3l M 59 5m 5g 5x 5i");e=e||"";O(d={2N:11,19:[],2K:6(g){H e.1i(g)>-1},3d:6(g){e+=g}};c<f.L;)I(h=B(f,c,b,d)){a.U(h.3k);c+=h.1C[0].L||1}Y I(h=n.X.W(z[b],f.1a(c))){a.U(h[0]);c+=h[0].L}Y{h=f.3a(c);I(h==="[")b=M.2I;Y I(h==="]")b=M.1B;a.U(h);c++}a=15(a.1K(""),n.Q.W(e,w,""));a.1w={1m:f,19:d.2N?d.19:N};H a};M.3v="1.5.0";M.2I=1;M.1B=2;K C=/\\$(?:(\\d\\d?|[$&`\'])|{([$\\w]+)})/g,w=/[^5h]+|([\\s\\S])(?=[\\s\\S]*\\1)/g,A=/^(?:[?*+]|{\\d+(?:,\\d*)?})\\??/,v=11,u=[],n={X:15.Z.X,1A:15.Z.1A,1C:1r.Z.1C,Q:1r.Z.Q,1e:1r.Z.1e},x=n.X.W(/()??/,"")[1]===1d,D=6(){K f=/^/g;n.1A.W(f,"");H!f.12}(),y=6(){K f=/x/g;n.Q.W("x",f,"");H!f.12}(),E=15.Z.3n!==1d,z={};z[M.2I]=/^(?:\\\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\\29-26-f]{2}|u[\\29-26-f]{4}|c[A-3o-z]|[\\s\\S]))/;z[M.1B]=/^(?:\\\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\\d*|x[\\29-26-f]{2}|u[\\29-26-f]{4}|c[A-3o-z]|[\\s\\S])|\\(\\?[:=!]|[?*+]\\?|{\\d+(?:,\\d*)?}\\??)/;M.1h=6(f,e,a,b){u.U({2q:r(f,"g"+(E?"y":"")),2b:e,3r:a||M.1B,2p:b||N})};M.2n=6(f,e){K a=f+"/"+(e||"");H M.2n[a]||(M.2n[a]=M(f,e))};M.3c=6(f){H r(f,"g")};M.5l=6(f){H f.Q(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g,"\\\\$&")};M.5e=6(f,e,a,b){e=r(e,"g"+(b&&E?"y":""));e.12=a=a||0;f=e.X(f);H b?f&&f.P===a?f:N:f};M.3q=6(){M.1h=6(){1S 2U("2a\'t 55 1h 54 3q")}};M.1R=6(f){H 53.Z.1q.W(f)==="[2m 15]"};M.3p=6(f,e,a,b){O(K c=r(e,"g"),d=-1,h;h=c.X(f);){a.W(b,h,++d,f,c);c.12===h.P&&c.12++}I(e.1J)e.12=0};M.57=6(f,e){H 6 a(b,c){K d=e[c].1I?e[c]:{1I:e[c]},h=r(d.1I,"g"),g=[],i;O(i=0;i<b.L;i++)M.3p(b[i],h,6(k){g.U(d.3j?k[d.3j]||"":k[0])});H c===e.L-1||!g.L?g:a(g,c+1)}([f],0)};15.Z.1p=6(f,e){H J.X(e[0])};15.Z.W=6(f,e){H J.X(e)};15.Z.X=6(f){K e=n.X.1p(J,14),a;I(e){I(!x&&e.L>1&&p(e,"")>-1){a=15(J.1m,n.Q.W(t(J),"g",""));n.Q.W(f.1a(e.P),a,6(){O(K c=1;c<14.L-2;c++)I(14[c]===1d)e[c]=1d})}I(J.1w&&J.1w.19)O(K b=1;b<e.L;b++)I(a=J.1w.19[b-1])e[a]=e[b];!D&&J.1J&&!e[0].L&&J.12>e.P&&J.12--}H e};I(!D)15.Z.1A=6(f){(f=n.X.W(J,f))&&J.1J&&!f[0].L&&J.12>f.P&&J.12--;H!!f};1r.Z.1C=6(f){M.1R(f)||(f=15(f));I(f.1J){K e=n.1C.1p(J,14);f.12=0;H e}H f.X(J)};1r.Z.Q=6(f,e){K a=M.1R(f),b,c;I(a&&1j e.58()==="3f"&&e.1i("${")===-1&&y)H n.Q.1p(J,14);I(a){I(f.1w)b=f.1w.19}Y f+="";I(1j e==="6")c=n.Q.W(J,f,6(){I(b){14[0]=1f 1r(14[0]);O(K d=0;d<b.L;d++)I(b[d])14[0][b[d]]=14[d+1]}I(a&&f.1J)f.12=14[14.L-2]+14[0].L;H e.1p(N,14)});Y{c=J+"";c=n.Q.W(c,f,6(){K d=14;H n.Q.W(e,C,6(h,g,i){I(g)5b(g){24"$":H"$";24"&":H d[0];24"`":H d[d.L-1].1a(0,d[d.L-2]);24"\'":H d[d.L-1].1a(d[d.L-2]+d[0].L);5a:i="";g=+g;I(!g)H h;O(;g>d.L-3;){i=1r.Z.1a.W(g,-1)+i;g=1Q.3i(g/10)}H(g?d[g]||"":"$")+i}Y{g=+i;I(g<=d.L-3)H d[g];g=b?p(b,i):-1;H g>-1?d[g+1]:h}})})}I(a&&f.1J)f.12=0;H c};1r.Z.1e=6(f,e){I(!M.1R(f))H n.1e.1p(J,14);K a=J+"",b=[],c=0,d,h;I(e===1d||+e<0)e=5D;Y{e=1Q.3i(+e);I(!e)H[]}O(f=M.3c(f);d=f.X(a);){I(f.12>c){b.U(a.1a(c,d.P));d.L>1&&d.P<a.L&&3b.Z.U.1p(b,d.1a(1));h=d[0].L;c=f.12;I(b.L>=e)1N}f.12===d.P&&f.12++}I(c===a.L){I(!n.1A.W(f,"")||h)b.U("")}Y b.U(a.1a(c));H b.L>e?b.1a(0,e):b};M.1h(/\\(\\?#[^)]*\\)/,6(f){H n.1A.W(A,f.2S.1a(f.P+f[0].L))?"":"(?:)"});M.1h(/\\((?!\\?)/,6(){J.19.U(N);H"("});M.1h(/\\(\\?<([$\\w]+)>/,6(f){J.19.U(f[1]);J.2N=R;H"("});M.1h(/\\\\k<([\\w$]+)>/,6(f){K e=p(J.19,f[1]);H e>-1?"\\\\"+(e+1)+(3R(f.2S.3a(f.P+f[0].L))?"":"(?:)"):f[0]});M.1h(/\\[\\^?]/,6(f){H f[0]==="[]"?"\\\\b\\\\B":"[\\\\s\\\\S]"});M.1h(/^\\(\\?([5A]+)\\)/,6(f){J.3d(f[1]);H""});M.1h(/(?:\\s+|#.*)+/,6(f){H n.1A.W(A,f.2S.1a(f.P+f[0].L))?"":"(?:)"},M.1B,6(){H J.2K("x")});M.1h(/\\./,6(){H"[\\\\s\\\\S]"},M.1B,6(){H J.2K("s")})})();1j 2e!="1d"&&(2e.M=M);K 1v=6(){6 r(a,b){a.1l.1i(b)!=-1||(a.1l+=" "+b)}6 t(a){H a.1i("3e")==0?a:"3e"+a}6 B(a){H e.1Y.2A[t(a)]}6 p(a,b,c){I(a==N)H N;K d=c!=R?a.3G:[a.2G],h={"#":"1c",".":"1l"}[b.1o(0,1)]||"3h",g,i;g=h!="3h"?b.1o(1):b.5u();I((a[h]||"").1i(g)!=-1)H a;O(a=0;d&&a<d.L&&i==N;a++)i=p(d[a],b,c);H i}6 C(a,b){K c={},d;O(d 2g a)c[d]=a[d];O(d 2g b)c[d]=b[d];H c}6 w(a,b,c,d){6 h(g){g=g||1P.5y;I(!g.1F){g.1F=g.52;g.3N=6(){J.5w=11}}c.W(d||1P,g)}a.3g?a.3g("4U"+b,h):a.4y(b,h,11)}6 A(a,b){K c=e.1Y.2j,d=N;I(c==N){c={};O(K h 2g e.1U){K g=e.1U[h];d=g.4x;I(d!=N){g.1V=h.4w();O(g=0;g<d.L;g++)c[d[g]]=h}}e.1Y.2j=c}d=e.1U[c[a]];d==N&&b!=11&&1P.1X(e.13.1x.1X+(e.13.1x.3E+a));H d}6 v(a,b){O(K c=a.1e("\\n"),d=0;d<c.L;d++)c[d]=b(c[d],d);H c.1K("\\n")}6 u(a,b){I(a==N||a.L==0||a=="\\n")H a;a=a.Q(/</g,"&1y;");a=a.Q(/ {2,}/g,6(c){O(K d="",h=0;h<c.L-1;h++)d+=e.13.1W;H d+" "});I(b!=N)a=v(a,6(c){I(c.L==0)H"";K d="";c=c.Q(/^(&2s;| )+/,6(h){d=h;H""});I(c.L==0)H d;H d+\'<17 1g="\'+b+\'">\'+c+"</17>"});H a}6 n(a,b){a.1e("\\n");O(K c="",d=0;d<50;d++)c+="                    ";H a=v(a,6(h){I(h.1i("\\t")==-1)H h;O(K g=0;(g=h.1i("\\t"))!=-1;)h=h.1o(0,g)+c.1o(0,b-g%b)+h.1o(g+1,h.L);H h})}6 x(a){H a.Q(/^\\s+|\\s+$/g,"")}6 D(a,b){I(a.P<b.P)H-1;Y I(a.P>b.P)H 1;Y I(a.L<b.L)H-1;Y I(a.L>b.L)H 1;H 0}6 y(a,b){6 c(k){H k[0]}O(K d=N,h=[],g=b.2D?b.2D:c;(d=b.1I.X(a))!=N;){K i=g(d,b);I(1j i=="3f")i=[1f e.2L(i,d.P,b.23)];h=h.1O(i)}H h}6 E(a){K b=/(.*)((&1G;|&1y;).*)/;H a.Q(e.3A.3M,6(c){K d="",h=N;I(h=b.X(c)){c=h[1];d=h[2]}H\'<a 2h="\'+c+\'">\'+c+"</a>"+d})}6 z(){O(K a=1E.36("1k"),b=[],c=0;c<a.L;c++)a[c].3s=="20"&&b.U(a[c]);H b}6 f(a){a=a.1F;K b=p(a,".20",R);a=p(a,".3O",R);K c=1E.4i("3t");I(!(!a||!b||p(a,"3t"))){B(b.1c);r(b,"1m");O(K d=a.3G,h=[],g=0;g<d.L;g++)h.U(d[g].4z||d[g].4A);h=h.1K("\\r");c.39(1E.4D(h));a.39(c);c.2C();c.4C();w(c,"4u",6(){c.2G.4E(c);b.1l=b.1l.Q("1m","")})}}I(1j 3F!="1d"&&1j M=="1d")M=3F("M").M;K e={2v:{"1g-27":"","2i-1s":1,"2z-1s-2t":11,1M:N,1t:N,"42-45":R,"43-22":4,1u:R,16:R,"3V-17":R,2l:11,"41-40":R,2k:11,"1z-1k":11},13:{1W:"&2s;",2M:R,46:11,44:11,34:"4n",1x:{21:"4o 1m",2P:"?",1X:"1v\\n\\n",3E:"4r\'t 4t 1D O: ",4g:"4m 4B\'t 51 O 1z-1k 4F: ",37:\'<!4T 1z 4S "-//4V//3H 4W 1.0 4Z//4Y" "1Z://2y.3L.3K/4X/3I/3H/3I-4P.4J"><1z 4I="1Z://2y.3L.3K/4L/5L"><3J><4N 1Z-4M="5G-5M" 6K="2O/1z; 6J=6I-8" /><1t>6L 1v</1t></3J><3B 1L="25-6M:6Q,6P,6O,6N-6F;6y-2f:#6x;2f:#6w;25-22:6v;2O-3D:3C;"><T 1L="2O-3D:3C;3w-32:1.6z;"><T 1L="25-22:6A-6E;">1v</T><T 1L="25-22:.6C;3w-6B:6R;"><T>3v 3.0.76 (72 73 3x)</T><T><a 2h="1Z://3u.2w/1v" 1F="38" 1L="2f:#3y">1Z://3u.2w/1v</a></T><T>70 17 6U 71.</T><T>6T 6X-3x 6Y 6D.</T></T><T>6t 61 60 J 1k, 5Z <a 2h="6u://2y.62.2w/63-66/65?64=5X-5W&5P=5O" 1L="2f:#3y">5R</a> 5V <2R/>5U 5T 5S!</T></T></3B></1z>\'}},1Y:{2j:N,2A:{}},1U:{},3A:{6n:/\\/\\*[\\s\\S]*?\\*\\//2c,6m:/\\/\\/.*$/2c,6l:/#.*$/2c,6k:/"([^\\\\"\\n]|\\\\.)*"/g,6o:/\'([^\\\\\'\\n]|\\\\.)*\'/g,6p:1f M(\'"([^\\\\\\\\"]|\\\\\\\\.)*"\',"3z"),6s:1f M("\'([^\\\\\\\\\']|\\\\\\\\.)*\'","3z"),6q:/(&1y;|<)!--[\\s\\S]*?--(&1G;|>)/2c,3M:/\\w+:\\/\\/[\\w-.\\/?%&=:@;]*/g,6a:{18:/(&1y;|<)\\?=?/g,1b:/\\?(&1G;|>)/g},69:{18:/(&1y;|<)%=?/g,1b:/%(&1G;|>)/g},6d:{18:/(&1y;|<)\\s*1k.*?(&1G;|>)/2T,1b:/(&1y;|<)\\/\\s*1k\\s*(&1G;|>)/2T}},16:{1H:6(a){6 b(i,k){H e.16.2o(i,k,e.13.1x[k])}O(K c=\'<T 1g="16">\',d=e.16.2x,h=d.2X,g=0;g<h.L;g++)c+=(d[h[g]].1H||b)(a,h[g]);c+="</T>";H c},2o:6(a,b,c){H\'<2W><a 2h="#" 1g="6e 6h\'+b+" "+b+\'">\'+c+"</a></2W>"},2b:6(a){K b=a.1F,c=b.1l||"";b=B(p(b,".20",R).1c);K d=6(h){H(h=15(h+"6f(\\\\w+)").X(c))?h[1]:N}("6g");b&&d&&e.16.2x[d].2B(b);a.3N()},2x:{2X:["21","2P"],21:{1H:6(a){I(a.V("2l")!=R)H"";K b=a.V("1t");H e.16.2o(a,"21",b?b:e.13.1x.21)},2B:6(a){a=1E.6j(t(a.1c));a.1l=a.1l.Q("47","")}},2P:{2B:6(){K a="68=0";a+=", 18="+(31.30-33)/2+", 32="+(31.2Z-2Y)/2+", 30=33, 2Z=2Y";a=a.Q(/^,/,"");a=1P.6Z("","38",a);a.2C();K b=a.1E;b.6W(e.13.1x.37);b.6V();a.2C()}}}},35:6(a,b){K c;I(b)c=[b];Y{c=1E.36(e.13.34);O(K d=[],h=0;h<c.L;h++)d.U(c[h]);c=d}c=c;d=[];I(e.13.2M)c=c.1O(z());I(c.L===0)H d;O(h=0;h<c.L;h++){O(K g=c[h],i=a,k=c[h].1l,j=3W 0,l={},m=1f M("^\\\\[(?<2V>(.*?))\\\\]$"),s=1f M("(?<27>[\\\\w-]+)\\\\s*:\\\\s*(?<1T>[\\\\w-%#]+|\\\\[.*?\\\\]|\\".*?\\"|\'.*?\')\\\\s*;?","g");(j=s.X(k))!=N;){K o=j.1T.Q(/^[\'"]|[\'"]$/g,"");I(o!=N&&m.1A(o)){o=m.X(o);o=o.2V.L>0?o.2V.1e(/\\s*,\\s*/):[]}l[j.27]=o}g={1F:g,1n:C(i,l)};g.1n.1D!=N&&d.U(g)}H d},1M:6(a,b){K c=J.35(a,b),d=N,h=e.13;I(c.L!==0)O(K g=0;g<c.L;g++){b=c[g];K i=b.1F,k=b.1n,j=k.1D,l;I(j!=N){I(k["1z-1k"]=="R"||e.2v["1z-1k"]==R){d=1f e.4l(j);j="4O"}Y I(d=A(j))d=1f d;Y 6H;l=i.3X;I(h.2M){l=l;K m=x(l),s=11;I(m.1i("<![6G[")==0){m=m.4h(9);s=R}K o=m.L;I(m.1i("]]\\>")==o-3){m=m.4h(0,o-3);s=R}l=s?m:l}I((i.1t||"")!="")k.1t=i.1t;k.1D=j;d.2Q(k);b=d.2F(l);I((i.1c||"")!="")b.1c=i.1c;i.2G.74(b,i)}}},2E:6(a){w(1P,"4k",6(){e.1M(a)})}};e.2E=e.2E;e.1M=e.1M;e.2L=6(a,b,c){J.1T=a;J.P=b;J.L=a.L;J.23=c;J.1V=N};e.2L.Z.1q=6(){H J.1T};e.4l=6(a){6 b(j,l){O(K m=0;m<j.L;m++)j[m].P+=l}K c=A(a),d,h=1f e.1U.5Y,g=J,i="2F 1H 2Q".1e(" ");I(c!=N){d=1f c;O(K k=0;k<i.L;k++)(6(){K j=i[k];g[j]=6(){H h[j].1p(h,14)}})();d.28==N?1P.1X(e.13.1x.1X+(e.13.1x.4g+a)):h.2J.U({1I:d.28.17,2D:6(j){O(K l=j.17,m=[],s=d.2J,o=j.P+j.18.L,F=d.28,q,G=0;G<s.L;G++){q=y(l,s[G]);b(q,o);m=m.1O(q)}I(F.18!=N&&j.18!=N){q=y(j.18,F.18);b(q,j.P);m=m.1O(q)}I(F.1b!=N&&j.1b!=N){q=y(j.1b,F.1b);b(q,j.P+j[0].5Q(j.1b));m=m.1O(q)}O(j=0;j<m.L;j++)m[j].1V=c.1V;H m}})}};e.4j=6(){};e.4j.Z={V:6(a,b){K c=J.1n[a];c=c==N?b:c;K d={"R":R,"11":11}[c];H d==N?c:d},3Y:6(a){H 1E.4i(a)},4c:6(a,b){K c=[];I(a!=N)O(K d=0;d<a.L;d++)I(1j a[d]=="2m")c=c.1O(y(b,a[d]));H J.4e(c.6b(D))},4e:6(a){O(K b=0;b<a.L;b++)I(a[b]!==N)O(K c=a[b],d=c.P+c.L,h=b+1;h<a.L&&a[b]!==N;h++){K g=a[h];I(g!==N)I(g.P>d)1N;Y I(g.P==c.P&&g.L>c.L)a[b]=N;Y I(g.P>=c.P&&g.P<d)a[h]=N}H a},4d:6(a){K b=[],c=2u(J.V("2i-1s"));v(a,6(d,h){b.U(h+c)});H b},3U:6(a){K b=J.V("1M",[]);I(1j b!="2m"&&b.U==N)b=[b];a:{a=a.1q();K c=3W 0;O(c=c=1Q.6c(c||0,0);c<b.L;c++)I(b[c]==a){b=c;1N a}b=-1}H b!=-1},2r:6(a,b,c){a=["1s","6i"+b,"P"+a,"6r"+(b%2==0?1:2).1q()];J.3U(b)&&a.U("67");b==0&&a.U("1N");H\'<T 1g="\'+a.1K(" ")+\'">\'+c+"</T>"},3Q:6(a,b){K c="",d=a.1e("\\n").L,h=2u(J.V("2i-1s")),g=J.V("2z-1s-2t");I(g==R)g=(h+d-1).1q().L;Y I(3R(g)==R)g=0;O(K i=0;i<d;i++){K k=b?b[i]:h+i,j;I(k==0)j=e.13.1W;Y{j=g;O(K l=k.1q();l.L<j;)l="0"+l;j=l}a=j;c+=J.2r(i,k,a)}H c},49:6(a,b){a=x(a);K c=a.1e("\\n");J.V("2z-1s-2t");K d=2u(J.V("2i-1s"));a="";O(K h=J.V("1D"),g=0;g<c.L;g++){K i=c[g],k=/^(&2s;|\\s)+/.X(i),j=N,l=b?b[g]:d+g;I(k!=N){j=k[0].1q();i=i.1o(j.L);j=j.Q(" ",e.13.1W)}i=x(i);I(i.L==0)i=e.13.1W;a+=J.2r(g,l,(j!=N?\'<17 1g="\'+h+\' 5N">\'+j+"</17>":"")+i)}H a},4f:6(a){H a?"<4a>"+a+"</4a>":""},4b:6(a,b){6 c(l){H(l=l?l.1V||g:g)?l+" ":""}O(K d=0,h="",g=J.V("1D",""),i=0;i<b.L;i++){K k=b[i],j;I(!(k===N||k.L===0)){j=c(k);h+=u(a.1o(d,k.P-d),j+"48")+u(k.1T,j+k.23);d=k.P+k.L+(k.75||0)}}h+=u(a.1o(d),c()+"48");H h},1H:6(a){K b="",c=["20"],d;I(J.V("2k")==R)J.1n.16=J.1n.1u=11;1l="20";J.V("2l")==R&&c.U("47");I((1u=J.V("1u"))==11)c.U("6S");c.U(J.V("1g-27"));c.U(J.V("1D"));a=a.Q(/^[ ]*[\\n]+|[\\n]*[ ]*$/g,"").Q(/\\r/g," ");b=J.V("43-22");I(J.V("42-45")==R)a=n(a,b);Y{O(K h="",g=0;g<b;g++)h+=" ";a=a.Q(/\\t/g,h)}a=a;a:{b=a=a;h=/<2R\\s*\\/?>|&1y;2R\\s*\\/?&1G;/2T;I(e.13.46==R)b=b.Q(h,"\\n");I(e.13.44==R)b=b.Q(h,"");b=b.1e("\\n");h=/^\\s*/;g=4Q;O(K i=0;i<b.L&&g>0;i++){K k=b[i];I(x(k).L!=0){k=h.X(k);I(k==N){a=a;1N a}g=1Q.4q(k[0].L,g)}}I(g>0)O(i=0;i<b.L;i++)b[i]=b[i].1o(g);a=b.1K("\\n")}I(1u)d=J.4d(a);b=J.4c(J.2J,a);b=J.4b(a,b);b=J.49(b,d);I(J.V("41-40"))b=E(b);1j 2H!="1d"&&2H.3S&&2H.3S.1C(/5s/)&&c.U("5t");H b=\'<T 1c="\'+t(J.1c)+\'" 1g="\'+c.1K(" ")+\'">\'+(J.V("16")?e.16.1H(J):"")+\'<3Z 5z="0" 5H="0" 5J="0">\'+J.4f(J.V("1t"))+"<3T><3P>"+(1u?\'<2d 1g="1u">\'+J.3Q(a)+"</2d>":"")+\'<2d 1g="17"><T 1g="3O">\'+b+"</T></2d></3P></3T></3Z></T>"},2F:6(a){I(a===N)a="";J.17=a;K b=J.3Y("T");b.3X=J.1H(a);J.V("16")&&w(p(b,".16"),"5c",e.16.2b);J.V("3V-17")&&w(p(b,".17"),"56",f);H b},2Q:6(a){J.1c=""+1Q.5d(1Q.5n()*5k).1q();e.1Y.2A[t(J.1c)]=J;J.1n=C(e.2v,a||{});I(J.V("2k")==R)J.1n.16=J.1n.1u=11},5j:6(a){a=a.Q(/^\\s+|\\s+$/g,"").Q(/\\s+/g,"|");H"\\\\b(?:"+a+")\\\\b"},5f:6(a){J.28={18:{1I:a.18,23:"1k"},1b:{1I:a.1b,23:"1k"},17:1f M("(?<18>"+a.18.1m+")(?<17>.*?)(?<1b>"+a.1b.1m+")","5o")}}};H e}();1j 2e!="1d"&&(2e.1v=1v);',62,441,'||||||function|||||||||||||||||||||||||||||||||||||return|if|this|var|length|XRegExp|null|for|index|replace|true||div|push|getParam|call|exec|else|prototype||false|lastIndex|config|arguments|RegExp|toolbar|code|left|captureNames|slice|right|id|undefined|split|new|class|addToken|indexOf|typeof|script|className|source|params|substr|apply|toString|String|line|title|gutter|SyntaxHighlighter|_xregexp|strings|lt|html|test|OUTSIDE_CLASS|match|brush|document|target|gt|getHtml|regex|global|join|style|highlight|break|concat|window|Math|isRegExp|throw|value|brushes|brushName|space|alert|vars|http|syntaxhighlighter|expandSource|size|css|case|font|Fa|name|htmlScript|dA|can|handler|gm|td|exports|color|in|href|first|discoveredBrushes|light|collapse|object|cache|getButtonHtml|trigger|pattern|getLineHtml|nbsp|numbers|parseInt|defaults|com|items|www|pad|highlighters|execute|focus|func|all|getDiv|parentNode|navigator|INSIDE_CLASS|regexList|hasFlag|Match|useScriptTags|hasNamedCapture|text|help|init|br|input|gi|Error|values|span|list|250|height|width|screen|top|500|tagName|findElements|getElementsByTagName|aboutDialog|_blank|appendChild|charAt|Array|copyAsGlobal|setFlag|highlighter_|string|attachEvent|nodeName|floor|backref|output|the|TypeError|sticky|Za|iterate|freezeTokens|scope|type|textarea|alexgorbatchev|version|margin|2010|005896|gs|regexLib|body|center|align|noBrush|require|childNodes|DTD|xhtml1|head|org|w3|url|preventDefault|container|tr|getLineNumbersHtml|isNaN|userAgent|tbody|isLineHighlighted|quick|void|innerHTML|create|table|links|auto|smart|tab|stripBrs|tabs|bloggerMode|collapsed|plain|getCodeLinesHtml|caption|getMatchesHtml|findMatches|figureOutLineNumbers|removeNestedMatches|getTitleHtml|brushNotHtmlScript|substring|createElement|Highlighter|load|HtmlScript|Brush|pre|expand|multiline|min|Can|ignoreCase|find|blur|extended|toLowerCase|aliases|addEventListener|innerText|textContent|wasn|select|createTextNode|removeChild|option|same|frame|xmlns|dtd|twice|1999|equiv|meta|htmlscript|transitional|1E3|expected|PUBLIC|DOCTYPE|on|W3C|XHTML|TR|EN|Transitional||configured|srcElement|Object|after|run|dblclick|matchChain|valueOf|constructor|default|switch|click|round|execAt|forHtmlScript|token|gimy|functions|getKeywords|1E6|escape|within|random|sgi|another|finally|supply|MSIE|ie|toUpperCase|catch|returnValue|definition|event|border|imsx|constructing|one|Infinity|from|when|Content|cellpadding|flags|cellspacing|try|xhtml|Type|spaces|2930402|hosted_button_id|lastIndexOf|donate|active|development|keep|to|xclick|_s|Xml|please|like|you|paypal|cgi|cmd|webscr|bin|highlighted|scrollbars|aspScriptTags|phpScriptTags|sort|max|scriptScriptTags|toolbar_item|_|command|command_|number|getElementById|doubleQuotedString|singleLinePerlComments|singleLineCComments|multiLineCComments|singleQuotedString|multiLineDoubleQuotedString|xmlComments|alt|multiLineSingleQuotedString|If|https|1em|000|fff|background|5em|xx|bottom|75em|Gorbatchev|large|serif|CDATA|continue|utf|charset|content|About|family|sans|Helvetica|Arial|Geneva|3em|nogutter|Copyright|syntax|close|write|2004|Alex|open|JavaScript|highlighter|July|02|replaceChild|offset|83'.split('|'),0,{}))
--- a/apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/shCoreDefault.css	Fri Dec 21 15:21:30 2018 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,328 +0,0 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
- *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
- *
- * @version
- * 3.0.83 (July 02 2010)
- *
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
- */
-.syntaxhighlighter a,
-.syntaxhighlighter div,
-.syntaxhighlighter code,
-.syntaxhighlighter table,
-.syntaxhighlighter table td,
-.syntaxhighlighter table tr,
-.syntaxhighlighter table tbody,
-.syntaxhighlighter table thead,
-.syntaxhighlighter table caption,
-.syntaxhighlighter textarea {
-  -moz-border-radius: 0 0 0 0 !important;
-  -webkit-border-radius: 0 0 0 0 !important;
-  background: none !important;
-  border: 0 !important;
-  bottom: auto !important;
-  float: none !important;
-  height: auto !important;
-  left: auto !important;
-  line-height: 1.1em !important;
-  margin: 0 !important;
-  outline: 0 !important;
-  overflow: visible !important;
-  padding: 0 !important;
-  position: static !important;
-  right: auto !important;
-  text-align: left !important;
-  top: auto !important;
-  vertical-align: baseline !important;
-  width: auto !important;
-  box-sizing: content-box !important;
-  font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
-  font-weight: normal !important;
-  font-style: normal !important;
-  font-size: 1em !important;
-  min-height: inherit !important;
-  min-height: auto !important;
-}
-
-.syntaxhighlighter {
-  width: 100% !important;
-  margin: 1em 0 1em 0 !important;
-  position: relative !important;
-  overflow: auto !important;
-  font-size: 1em !important;
-}
-.syntaxhighlighter.source {
-  overflow: hidden !important;
-}
-.syntaxhighlighter .bold {
-  font-weight: bold !important;
-}
-.syntaxhighlighter .italic {
-  font-style: italic !important;
-}
-.syntaxhighlighter .line {
-  white-space: pre !important;
-}
-.syntaxhighlighter table {
-  width: 100% !important;
-}
-.syntaxhighlighter table caption {
-  text-align: left !important;
-  padding: .5em 0 0.5em 1em !important;
-}
-.syntaxhighlighter table td.code {
-  width: 100% !important;
-}
-.syntaxhighlighter table td.code .container {
-  position: relative !important;
-}
-.syntaxhighlighter table td.code .container textarea {
-  box-sizing: border-box !important;
-  position: absolute !important;
-  left: 0 !important;
-  top: 0 !important;
-  width: 100% !important;
-  height: 100% !important;
-  border: none !important;
-  background: white !important;
-  padding-left: 1em !important;
-  overflow: hidden !important;
-  white-space: pre !important;
-}
-.syntaxhighlighter table td.gutter .line {
-  text-align: right !important;
-  padding: 0 0.5em 0 1em !important;
-}
-.syntaxhighlighter table td.code .line {
-  padding: 0 1em !important;
-}
-.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
-  padding-left: 0em !important;
-}
-.syntaxhighlighter.show {
-  display: block !important;
-}
-.syntaxhighlighter.collapsed table {
-  display: none !important;
-}
-.syntaxhighlighter.collapsed .toolbar {
-  padding: 0.1em 0.8em 0em 0.8em !important;
-  font-size: 1em !important;
-  position: static !important;
-  width: auto !important;
-  height: auto !important;
-}
-.syntaxhighlighter.collapsed .toolbar span {
-  display: inline !important;
-  margin-right: 1em !important;
-}
-.syntaxhighlighter.collapsed .toolbar span a {
-  padding: 0 !important;
-  display: none !important;
-}
-.syntaxhighlighter.collapsed .toolbar span a.expandSource {
-  display: inline !important;
-}
-.syntaxhighlighter .toolbar {
-  position: absolute !important;
-  right: 1px !important;
-  top: 1px !important;
-  width: 11px !important;
-  height: 11px !important;
-  font-size: 10px !important;
-  z-index: 10 !important;
-}
-.syntaxhighlighter .toolbar span.title {
-  display: inline !important;
-}
-.syntaxhighlighter .toolbar a {
-  display: block !important;
-  text-align: center !important;
-  text-decoration: none !important;
-  padding-top: 1px !important;
-}
-.syntaxhighlighter .toolbar a.expandSource {
-  display: none !important;
-}
-.syntaxhighlighter.ie {
-  font-size: .9em !important;
-  padding: 1px 0 1px 0 !important;
-}
-.syntaxhighlighter.ie .toolbar {
-  line-height: 8px !important;
-}
-.syntaxhighlighter.ie .toolbar a {
-  padding-top: 0px !important;
-}
-.syntaxhighlighter.printing .line.alt1 .content,
-.syntaxhighlighter.printing .line.alt2 .content,
-.syntaxhighlighter.printing .line.highlighted .number,
-.syntaxhighlighter.printing .line.highlighted.alt1 .content,
-.syntaxhighlighter.printing .line.highlighted.alt2 .content {
-  background: none !important;
-}
-.syntaxhighlighter.printing .line .number {
-  color: #bbbbbb !important;
-}
-.syntaxhighlighter.printing .line .content {
-  color: black !important;
-}
-.syntaxhighlighter.printing .toolbar {
-  display: none !important;
-}
-.syntaxhighlighter.printing a {
-  text-decoration: none !important;
-}
-.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
-  color: black !important;
-}
-.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
-  color: #008200 !important;
-}
-.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
-  color: blue !important;
-}
-.syntaxhighlighter.printing .keyword {
-  color: #006699 !important;
-  font-weight: bold !important;
-}
-.syntaxhighlighter.printing .preprocessor {
-  color: gray !important;
-}
-.syntaxhighlighter.printing .variable {
-  color: #aa7700 !important;
-}
-.syntaxhighlighter.printing .value {
-  color: #009900 !important;
-}
-.syntaxhighlighter.printing .functions {
-  color: #ff1493 !important;
-}
-.syntaxhighlighter.printing .constants {
-  color: #0066cc !important;
-}
-.syntaxhighlighter.printing .script {
-  font-weight: bold !important;
-}
-.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
-  color: gray !important;
-}
-.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
-  color: #ff1493 !important;
-}
-.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
-  color: red !important;
-}
-.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
-  color: black !important;
-}
-
-.syntaxhighlighter {
-  background-color: #f4f4f4 !important;
-}
-.syntaxhighlighter .line.alt1 {
-  background-color: #f4f4f4 !important;
-}
-.syntaxhighlighter .line.alt2 {
-  background-color: #f4f4f4 !important;
-}
-.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
-  background-color: #e0e0e0 !important;
-}
-.syntaxhighlighter .line.highlighted.number {
-  color: black !important;
-}
-.syntaxhighlighter table caption {
-  color: black !important;
-}
-.syntaxhighlighter .gutter {
-  color: #afafaf !important;
-}
-.syntaxhighlighter .gutter .line {
-  border-right: 3px solid #6ce26c !important;
-}
-.syntaxhighlighter .gutter .line.highlighted {
-  background-color: #6ce26c !important;
-  color: white !important;
-}
-.syntaxhighlighter.printing .line .content {
-  border: none !important;
-}
-.syntaxhighlighter.collapsed {
-  overflow: visible !important;
-}
-.syntaxhighlighter.collapsed .toolbar {
-  color: blue !important;
-  background: #f4f4f4 !important;
-  border: 1px solid #6ce26c !important;
-}
-.syntaxhighlighter.collapsed .toolbar a {
-  color: blue !important;
-}
-.syntaxhighlighter.collapsed .toolbar a:hover {
-  color: red !important;
-}
-.syntaxhighlighter .toolbar {
-  color: #f4f4f4 !important;
-  background: #6ce26c !important;
-  border: none !important;
-}
-.syntaxhighlighter .toolbar a {
-  color: #f4f4f4 !important;
-}
-.syntaxhighlighter .toolbar a:hover {
-  color: black !important;
-}
-.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
-  color: black !important;
-}
-.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
-  color: #008200 !important;
-}
-.syntaxhighlighter .string, .syntaxhighlighter .string a {
-  color: blue !important;
-}
-.syntaxhighlighter .keyword {
-  color: #006699 !important;
-}
-.syntaxhighlighter .preprocessor {
-  color: gray !important;
-}
-.syntaxhighlighter .variable {
-  color: #aa7700 !important;
-}
-.syntaxhighlighter .value {
-  color: #009900 !important;
-}
-.syntaxhighlighter .functions {
-  color: #ff1493 !important;
-}
-.syntaxhighlighter .constants {
-  color: #0066cc !important;
-}
-.syntaxhighlighter .script {
-  font-weight: bold !important;
-  color: #006699 !important;
-  background-color: none !important;
-}
-.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
-  color: gray !important;
-}
-.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
-  color: #ff1493 !important;
-}
-.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
-  color: red !important;
-}
-
-.syntaxhighlighter .keyword {
-  font-weight: bold !important;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/syntaxhighlighter.js	Fri Jan 11 07:51:13 2019 -0800
@@ -0,0 +1,3808 @@
+/*!
+ * Copyright (c) 2004-2016, Alex Gorbatchev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*!
+ * SyntaxHighlighter
+ * https://github.com/syntaxhighlighter/syntaxhighlighter
+ * 
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
+ * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
+ * 
+ * @version
+ * 4.0.1
+ * 
+ * @copyright
+ * Copyright (C) 2004-2016 Alex Gorbatchev.
+ * 
+ * @license
+ * Dual licensed under the MIT and GPL licenses.
+ */
+
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+/******/
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _core = __webpack_require__(1);
+	
+	Object.keys(_core).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return;
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _core[key];
+	    }
+	  });
+	});
+	
+	var _domready = __webpack_require__(24);
+	
+	var _domready2 = _interopRequireDefault(_domready);
+	
+	var _core2 = _interopRequireDefault(_core);
+	
+	var _dasherize = __webpack_require__(25);
+	
+	var dasherize = _interopRequireWildcard(_dasherize);
+	
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+	
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+	
+	// configured through the `--compat` parameter.
+	if (false) {
+	  require('./compatibility_layer_v3');
+	}
+	
+	(0, _domready2.default)(function () {
+	  return _core2.default.highlight(dasherize.object(window.syntaxhighlighterConfig || {}));
+	});
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	var optsParser = __webpack_require__(2),
+	    match = __webpack_require__(5),
+	    Renderer = __webpack_require__(9).default,
+	    utils = __webpack_require__(10),
+	    transformers = __webpack_require__(11),
+	    dom = __webpack_require__(17),
+	    config = __webpack_require__(18),
+	    defaults = __webpack_require__(19),
+	    HtmlScript = __webpack_require__(20);
+	
+	var sh = {
+	  Match: match.Match,
+	  Highlighter: __webpack_require__(22),
+	
+	  config: __webpack_require__(18),
+	  regexLib: __webpack_require__(3).commonRegExp,
+	
+	  /** Internal 'global' variables. */
+	  vars: {
+	    discoveredBrushes: null,
+	    highlighters: {}
+	  },
+	
+	  /** This object is populated by user included external brush files. */
+	  brushes: {},
+	
+	  /**
+	   * Finds all elements on the page which should be processes by SyntaxHighlighter.
+	   *
+	   * @param {Object} globalParams   Optional parameters which override element's
+	   *                  parameters. Only used if element is specified.
+	   *
+	   * @param {Object} element  Optional element to highlight. If none is
+	   *              provided, all elements in the current document
+	   *              are returned which qualify.
+	   *
+	   * @return {Array}  Returns list of <code>{ target: DOMElement, params: Object }</code> objects.
+	   */
+	  findElements: function findElements(globalParams, element) {
+	    var elements = element ? [element] : utils.toArray(document.getElementsByTagName(sh.config.tagName)),
+	        conf = sh.config,
+	        result = [];
+	
+	    // support for <SCRIPT TYPE="syntaxhighlighter" /> feature
+	    elements = elements.concat(dom.getSyntaxHighlighterScriptTags());
+	
+	    if (elements.length === 0) return result;
+	
+	    for (var i = 0, l = elements.length; i < l; i++) {
+	      var item = {
+	        target: elements[i],
+	        // local params take precedence over globals
+	        params: optsParser.defaults(optsParser.parse(elements[i].className), globalParams)
+	      };
+	
+	      if (item.params['brush'] == null) continue;
+	
+	      result.push(item);
+	    }
+	
+	    return result;
+	  },
+	
+	  /**
+	   * Shorthand to highlight all elements on the page that are marked as
+	   * SyntaxHighlighter source code.
+	   *
+	   * @param {Object} globalParams   Optional parameters which override element's
+	   *                  parameters. Only used if element is specified.
+	   *
+	   * @param {Object} element  Optional element to highlight. If none is
+	   *              provided, all elements in the current document
+	   *              are highlighted.
+	   */
+	  highlight: function highlight(globalParams, element) {
+	    var elements = sh.findElements(globalParams, element),
+	        propertyName = 'innerHTML',
+	        brush = null,
+	        renderer,
+	        conf = sh.config;
+	
+	    if (elements.length === 0) return;
+	
+	    for (var i = 0, l = elements.length; i < l; i++) {
+	      var element = elements[i],
+	          target = element.target,
+	          params = element.params,
+	          brushName = params.brush,
+	          brush,
+	          matches,
+	          code;
+	
+	      if (brushName == null) continue;
+	
+	      brush = findBrush(brushName);
+	
+	      if (!brush) continue;
+	
+	      // local params take precedence over defaults
+	      params = optsParser.defaults(params || {}, defaults);
+	      params = optsParser.defaults(params, config);
+	
+	      // Instantiate a brush
+	      if (params['html-script'] == true || defaults['html-script'] == true) {
+	        brush = new HtmlScript(findBrush('xml'), brush);
+	        brushName = 'htmlscript';
+	      } else {
+	        brush = new brush();
+	      }
+	
+	      code = target[propertyName];
+	
+	      // remove CDATA from <SCRIPT/> tags if it's present
+	      if (conf.useScriptTags) code = stripCData(code);
+	
+	      // Inject title if the attribute is present
+	      if ((target.title || '') != '') params.title = target.title;
+	
+	      params['brush'] = brushName;
+	
+	      code = transformers(code, params);
+	      matches = match.applyRegexList(code, brush.regexList, params);
+	      renderer = new Renderer(code, matches, params);
+	
+	      element = dom.create('div');
+	      element.innerHTML = renderer.getHtml();
+	
+	      // id = utils.guid();
+	      // element.id = highlighters.id(id);
+	      // highlighters.set(id, element);
+	
+	      if (params.quickCode) dom.attachEvent(dom.findElement(element, '.code'), 'dblclick', dom.quickCodeHandler);
+	
+	      // carry over ID
+	      if ((target.id || '') != '') element.id = target.id;
+	
+	      target.parentNode.replaceChild(element, target);
+	    }
+	  }
+	}; // end of sh
+	
+	/**
+	 * Displays an alert.
+	 * @param {String} str String to display.
+	 */
+	function alert(str) {
+	  window.alert('SyntaxHighlighter\n\n' + str);
+	};
+	
+	/**
+	 * Finds a brush by its alias.
+	 *
+	 * @param {String} alias    Brush alias.
+	 * @param {Boolean} showAlert Suppresses the alert if false.
+	 * @return {Brush}        Returns bursh constructor if found, null otherwise.
+	 */
+	function findBrush(alias, showAlert) {
+	  var brushes = sh.vars.discoveredBrushes,
+	      result = null;
+	
+	  if (brushes == null) {
+	    brushes = {};
+	
+	    // Find all brushes
+	    for (var brushName in sh.brushes) {
+	      var brush = sh.brushes[brushName],
+	          aliases = brush.aliases;
+	
+	      if (aliases == null) {
+	        continue;
+	      }
+	
+	      brush.className = brush.className || brush.aliases[0];
+	      brush.brushName = brush.className || brushName.toLowerCase();
+	
+	      for (var i = 0, l = aliases.length; i < l; i++) {
+	        brushes[aliases[i]] = brushName;
+	      }
+	    }
+	
+	    sh.vars.discoveredBrushes = brushes;
+	  }
+	
+	  result = sh.brushes[brushes[alias]];
+	
+	  if (result == null && showAlert) alert(sh.config.strings.noBrush + alias);
+	
+	  return result;
+	};
+	
+	/**
+	 * Strips <![CDATA[]]> from <SCRIPT /> content because it should be used
+	 * there in most cases for XHTML compliance.
+	 * @param {String} original Input code.
+	 * @return {String} Returns code without leading <![CDATA[]]> tags.
+	 */
+	function stripCData(original) {
+	  var left = '<![CDATA[',
+	      right = ']]>',
+	
+	  // for some reason IE inserts some leading blanks here
+	  copy = utils.trim(original),
+	      changed = false,
+	      leftLength = left.length,
+	      rightLength = right.length;
+	
+	  if (copy.indexOf(left) == 0) {
+	    copy = copy.substring(leftLength);
+	    changed = true;
+	  }
+	
+	  var copyLength = copy.length;
+	
+	  if (copy.indexOf(right) == copyLength - rightLength) {
+	    copy = copy.substring(0, copyLength - rightLength);
+	    changed = true;
+	  }
+	
+	  return changed ? copy : original;
+	};
+	
+	var brushCounter = 0;
+	
+	exports.default = sh;
+	var registerBrush = exports.registerBrush = function registerBrush(brush) {
+	  return sh.brushes['brush' + brushCounter++] = brush.default || brush;
+	};
+	var clearRegisteredBrushes = exports.clearRegisteredBrushes = function clearRegisteredBrushes() {
+	  sh.brushes = {};
+	  brushCounter = 0;
+	};
+	
+	/* an EJS hook for `gulp build --brushes` command
+	 * */
+	
+	registerBrush(__webpack_require__(23));
+	
+	/*
+	
+	 */
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var XRegExp = __webpack_require__(3).XRegExp;
+	
+	var BOOLEANS = { 'true': true, 'false': false };
+	
+	function camelize(key) {
+	  return key.replace(/-(\w+)/g, function (match, word) {
+	    return word.charAt(0).toUpperCase() + word.substr(1);
+	  });
+	}
+	
+	function process(value) {
+	  var result = BOOLEANS[value];
+	  return result == null ? value : result;
+	}
+	
+	module.exports = {
+	  defaults: function defaults(target, source) {
+	    for (var key in source || {}) {
+	      if (!target.hasOwnProperty(key)) target[key] = target[camelize(key)] = source[key];
+	    }return target;
+	  },
+	
+	  parse: function parse(str) {
+	    var match,
+	        key,
+	        result = {},
+	        arrayRegex = XRegExp("^\\[(?<values>(.*?))\\]$"),
+	        pos = 0,
+	        regex = XRegExp("(?<name>[\\w-]+)" + "\\s*:\\s*" + "(?<value>" + "[\\w%#-]+|" + // word
+	    "\\[.*?\\]|" + // [] array
+	    '".*?"|' + // "" string
+	    "'.*?'" + // '' string
+	    ")\\s*;?", "g");
+	
+	    while ((match = XRegExp.exec(str, regex, pos)) != null) {
+	      var value = match.value.replace(/^['"]|['"]$/g, '') // strip quotes from end of strings
+	      ;
+	
+	      // try to parse array value
+	      if (value != null && arrayRegex.test(value)) {
+	        var m = XRegExp.exec(value, arrayRegex);
+	        value = m.values.length > 0 ? m.values.split(/\s*,\s*/) : [];
+	      }
+	
+	      value = process(value);
+	      result[match.name] = result[camelize(match.name)] = value;
+	      pos = match.index + match[0].length;
+	    }
+	
+	    return result;
+	  }
+	};
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.commonRegExp = exports.XRegExp = undefined;
+	
+	var _xregexp = __webpack_require__(4);
+	
+	var _xregexp2 = _interopRequireDefault(_xregexp);
+	
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+	
+	exports.XRegExp = _xregexp2.default;
+	var commonRegExp = exports.commonRegExp = {
+	  multiLineCComments: (0, _xregexp2.default)('/\\*.*?\\*/', 'gs'),
+	  singleLineCComments: /\/\/.*$/gm,
+	  singleLinePerlComments: /#.*$/gm,
+	  doubleQuotedString: /"([^\\"\n]|\\.)*"/g,
+	  singleQuotedString: /'([^\\'\n]|\\.)*'/g,
+	  multiLineDoubleQuotedString: (0, _xregexp2.default)('"([^\\\\"]|\\\\.)*"', 'gs'),
+	  multiLineSingleQuotedString: (0, _xregexp2.default)("'([^\\\\']|\\\\.)*'", 'gs'),
+	  xmlComments: (0, _xregexp2.default)('(&lt;|<)!--.*?--(&gt;|>)', 'gs'),
+	  url: /\w+:\/\/[\w-.\/?%&=:@;#]*/g,
+	  phpScriptTags: { left: /(&lt;|<)\?(?:=|php)?/g, right: /\?(&gt;|>)/g, 'eof': true },
+	  aspScriptTags: { left: /(&lt;|<)%=?/g, right: /%(&gt;|>)/g },
+	  scriptScriptTags: { left: /(&lt;|<)\s*script.*?(&gt;|>)/gi, right: /(&lt;|<)\/\s*script\s*(&gt;|>)/gi }
+	};
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * XRegExp 3.1.0-dev
+	 * <xregexp.com>
+	 * Steven Levithan (c) 2007-2015 MIT License
+	 */
+	
+	/**
+	 * XRegExp provides augmented, extensible regular expressions. You get additional regex syntax and
+	 * flags, beyond what browsers support natively. XRegExp is also a regex utility belt with tools to
+	 * make your client-side grepping simpler and more powerful, while freeing you from related
+	 * cross-browser inconsistencies.
+	 */
+	
+	'use strict';
+	
+	/* ==============================
+	 * Private variables
+	 * ============================== */
+	
+	// Property name used for extended regex instance data
+	
+	var REGEX_DATA = 'xregexp';
+	// Optional features that can be installed and uninstalled
+	var features = {
+	    astral: false,
+	    natives: false
+	};
+	// Native methods to use and restore ('native' is an ES3 reserved keyword)
+	var nativ = {
+	    exec: RegExp.prototype.exec,
+	    test: RegExp.prototype.test,
+	    match: String.prototype.match,
+	    replace: String.prototype.replace,
+	    split: String.prototype.split
+	};
+	// Storage for fixed/extended native methods
+	var fixed = {};
+	// Storage for regexes cached by `XRegExp.cache`
+	var regexCache = {};
+	// Storage for pattern details cached by the `XRegExp` constructor
+	var patternCache = {};
+	// Storage for regex syntax tokens added internally or by `XRegExp.addToken`
+	var tokens = [];
+	// Token scopes
+	var defaultScope = 'default';
+	var classScope = 'class';
+	// Regexes that match native regex syntax, including octals
+	var nativeTokens = {
+	    // Any native multicharacter token in default scope, or any single character
+	    'default': /\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u(?:[\dA-Fa-f]{4}|{[\dA-Fa-f]+})|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??|[\s\S]/,
+	    // Any native multicharacter token in character class scope, or any single character
+	    'class': /\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u(?:[\dA-Fa-f]{4}|{[\dA-Fa-f]+})|c[A-Za-z]|[\s\S])|[\s\S]/
+	};
+	// Any backreference or dollar-prefixed character in replacement strings
+	var replacementToken = /\$(?:{([\w$]+)}|(\d\d?|[\s\S]))/g;
+	// Check for correct `exec` handling of nonparticipating capturing groups
+	var correctExecNpcg = nativ.exec.call(/()??/, '')[1] === undefined;
+	// Check for ES6 `u` flag support
+	var hasNativeU = function () {
+	    var isSupported = true;
+	    try {
+	        new RegExp('', 'u');
+	    } catch (exception) {
+	        isSupported = false;
+	    }
+	    return isSupported;
+	}();
+	// Check for ES6 `y` flag support
+	var hasNativeY = function () {
+	    var isSupported = true;
+	    try {
+	        new RegExp('', 'y');
+	    } catch (exception) {
+	        isSupported = false;
+	    }
+	    return isSupported;
+	}();
+	// Check for ES6 `flags` prop support
+	var hasFlagsProp = /a/.flags !== undefined;
+	// Tracker for known flags, including addon flags
+	var registeredFlags = {
+	    g: true,
+	    i: true,
+	    m: true,
+	    u: hasNativeU,
+	    y: hasNativeY
+	};
+	// Shortcut to `Object.prototype.toString`
+	var toString = {}.toString;
+	
+	/* ==============================
+	 * Private functions
+	 * ============================== */
+	
+	/**
+	 * Attaches extended data and `XRegExp.prototype` properties to a regex object.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to augment.
+	 * @param {Array} captureNames Array with capture names, or `null`.
+	 * @param {String} xSource XRegExp pattern used to generate `regex`, or `null` if N/A.
+	 * @param {String} xFlags XRegExp flags used to generate `regex`, or `null` if N/A.
+	 * @param {Boolean} [isInternalOnly=false] Whether the regex will be used only for internal
+	 *   operations, and never exposed to users. For internal-only regexes, we can improve perf by
+	 *   skipping some operations like attaching `XRegExp.prototype` properties.
+	 * @returns {RegExp} Augmented regex.
+	 */
+	function augment(regex, captureNames, xSource, xFlags, isInternalOnly) {
+	    var p;
+	
+	    regex[REGEX_DATA] = {
+	        captureNames: captureNames
+	    };
+	
+	    if (isInternalOnly) {
+	        return regex;
+	    }
+	
+	    // Can't auto-inherit these since the XRegExp constructor returns a nonprimitive value
+	    if (regex.__proto__) {
+	        regex.__proto__ = XRegExp.prototype;
+	    } else {
+	        for (p in XRegExp.prototype) {
+	            // An `XRegExp.prototype.hasOwnProperty(p)` check wouldn't be worth it here, since
+	            // this is performance sensitive, and enumerable `Object.prototype` or
+	            // `RegExp.prototype` extensions exist on `regex.prototype` anyway
+	            regex[p] = XRegExp.prototype[p];
+	        }
+	    }
+	
+	    regex[REGEX_DATA].source = xSource;
+	    // Emulate the ES6 `flags` prop by ensuring flags are in alphabetical order
+	    regex[REGEX_DATA].flags = xFlags ? xFlags.split('').sort().join('') : xFlags;
+	
+	    return regex;
+	}
+	
+	/**
+	 * Removes any duplicate characters from the provided string.
+	 *
+	 * @private
+	 * @param {String} str String to remove duplicate characters from.
+	 * @returns {String} String with any duplicate characters removed.
+	 */
+	function clipDuplicates(str) {
+	    return nativ.replace.call(str, /([\s\S])(?=[\s\S]*\1)/g, '');
+	}
+	
+	/**
+	 * Copies a regex object while preserving extended data and augmenting with `XRegExp.prototype`
+	 * properties. The copy has a fresh `lastIndex` property (set to zero). Allows adding and removing
+	 * flags g and y while copying the regex.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to copy.
+	 * @param {Object} [options] Options object with optional properties:
+	 *   <li>`addG` {Boolean} Add flag g while copying the regex.
+	 *   <li>`addY` {Boolean} Add flag y while copying the regex.
+	 *   <li>`removeG` {Boolean} Remove flag g while copying the regex.
+	 *   <li>`removeY` {Boolean} Remove flag y while copying the regex.
+	 *   <li>`isInternalOnly` {Boolean} Whether the copied regex will be used only for internal
+	 *     operations, and never exposed to users. For internal-only regexes, we can improve perf by
+	 *     skipping some operations like attaching `XRegExp.prototype` properties.
+	 * @returns {RegExp} Copy of the provided regex, possibly with modified flags.
+	 */
+	function copyRegex(regex, options) {
+	    if (!XRegExp.isRegExp(regex)) {
+	        throw new TypeError('Type RegExp expected');
+	    }
+	
+	    var xData = regex[REGEX_DATA] || {},
+	        flags = getNativeFlags(regex),
+	        flagsToAdd = '',
+	        flagsToRemove = '',
+	        xregexpSource = null,
+	        xregexpFlags = null;
+	
+	    options = options || {};
+	
+	    if (options.removeG) {
+	        flagsToRemove += 'g';
+	    }
+	    if (options.removeY) {
+	        flagsToRemove += 'y';
+	    }
+	    if (flagsToRemove) {
+	        flags = nativ.replace.call(flags, new RegExp('[' + flagsToRemove + ']+', 'g'), '');
+	    }
+	
+	    if (options.addG) {
+	        flagsToAdd += 'g';
+	    }
+	    if (options.addY) {
+	        flagsToAdd += 'y';
+	    }
+	    if (flagsToAdd) {
+	        flags = clipDuplicates(flags + flagsToAdd);
+	    }
+	
+	    if (!options.isInternalOnly) {
+	        if (xData.source !== undefined) {
+	            xregexpSource = xData.source;
+	        }
+	        // null or undefined; don't want to add to `flags` if the previous value was null, since
+	        // that indicates we're not tracking original precompilation flags
+	        if (xData.flags != null) {
+	            // Flags are only added for non-internal regexes by `XRegExp.globalize`. Flags are
+	            // never removed for non-internal regexes, so don't need to handle it
+	            xregexpFlags = flagsToAdd ? clipDuplicates(xData.flags + flagsToAdd) : xData.flags;
+	        }
+	    }
+	
+	    // Augment with `XRegExp.prototype` properties, but use the native `RegExp` constructor to
+	    // avoid searching for special tokens. That would be wrong for regexes constructed by
+	    // `RegExp`, and unnecessary for regexes constructed by `XRegExp` because the regex has
+	    // already undergone the translation to native regex syntax
+	    regex = augment(new RegExp(regex.source, flags), hasNamedCapture(regex) ? xData.captureNames.slice(0) : null, xregexpSource, xregexpFlags, options.isInternalOnly);
+	
+	    return regex;
+	}
+	
+	/**
+	 * Converts hexadecimal to decimal.
+	 *
+	 * @private
+	 * @param {String} hex
+	 * @returns {Number}
+	 */
+	function dec(hex) {
+	    return parseInt(hex, 16);
+	}
+	
+	/**
+	 * Returns native `RegExp` flags used by a regex object.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to check.
+	 * @returns {String} Native flags in use.
+	 */
+	function getNativeFlags(regex) {
+	    return hasFlagsProp ? regex.flags :
+	    // Explicitly using `RegExp.prototype.toString` (rather than e.g. `String` or
+	    // concatenation with an empty string) allows this to continue working predictably when
+	    // `XRegExp.proptotype.toString` is overriden
+	    nativ.exec.call(/\/([a-z]*)$/i, RegExp.prototype.toString.call(regex))[1];
+	}
+	
+	/**
+	 * Determines whether a regex has extended instance data used to track capture names.
+	 *
+	 * @private
+	 * @param {RegExp} regex Regex to check.
+	 * @returns {Boolean} Whether the regex uses named capture.
+	 */
+	function hasNamedCapture(regex) {
+	    return !!(regex[REGEX_DATA] && regex[REGEX_DATA].captureNames);
+	}
+	
+	/**
+	 * Converts decimal to hexadecimal.
+	 *
+	 * @private
+	 * @param {Number|String} dec
+	 * @returns {String}
+	 */
+	function hex(dec) {
+	    return parseInt(dec, 10).toString(16);
+	}
+	
+	/**
+	 * Returns the first index at which a given value can be found in an array.
+	 *
+	 * @private
+	 * @param {Array} array Array to search.
+	 * @param {*} value Value to locate in the array.
+	 * @returns {Number} Zero-based index at which the item is found, or -1.
+	 */
+	function indexOf(array, value) {
+	    var len = array.length,
+	        i;
+	
+	    for (i = 0; i < len; ++i) {
+	        if (array[i] === value) {
+	            return i;
+	        }
+	    }
+	
+	    return -1;
+	}
+	
+	/**
+	 * Determines whether a value is of the specified type, by resolving its internal [[Class]].
+	 *
+	 * @private
+	 * @param {*} value Object to check.
+	 * @param {String} type Type to check for, in TitleCase.
+	 * @returns {Boolean} Whether the object matches the type.
+	 */
+	function isType(value, type) {
+	    return toString.call(value) === '[object ' + type + ']';
+	}
+	
+	/**
+	 * Checks whether the next nonignorable token after the specified position is a quantifier.
+	 *
+	 * @private
+	 * @param {String} pattern Pattern to search within.
+	 * @param {Number} pos Index in `pattern` to search at.
+	 * @param {String} flags Flags used by the pattern.
+	 * @returns {Boolean} Whether the next token is a quantifier.
+	 */
+	function isQuantifierNext(pattern, pos, flags) {
+	    return nativ.test.call(flags.indexOf('x') > -1 ?
+	    // Ignore any leading whitespace, line comments, and inline comments
+	    /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/ :
+	    // Ignore any leading inline comments
+	    /^(?:\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/, pattern.slice(pos));
+	}
+	
+	/**
+	 * Pads the provided string with as many leading zeros as needed to get to length 4. Used to produce
+	 * fixed-length hexadecimal values.
+	 *
+	 * @private
+	 * @param {String} str
+	 * @returns {String}
+	 */
+	function pad4(str) {
+	    while (str.length < 4) {
+	        str = '0' + str;
+	    }
+	    return str;
+	}
+	
+	/**
+	 * Checks for flag-related errors, and strips/applies flags in a leading mode modifier. Offloads
+	 * the flag preparation logic from the `XRegExp` constructor.
+	 *
+	 * @private
+	 * @param {String} pattern Regex pattern, possibly with a leading mode modifier.
+	 * @param {String} flags Any combination of flags.
+	 * @returns {Object} Object with properties `pattern` and `flags`.
+	 */
+	function prepareFlags(pattern, flags) {
+	    var i;
+	
+	    // Recent browsers throw on duplicate flags, so copy this behavior for nonnative flags
+	    if (clipDuplicates(flags) !== flags) {
+	        throw new SyntaxError('Invalid duplicate regex flag ' + flags);
+	    }
+	
+	    // Strip and apply a leading mode modifier with any combination of flags except g or y
+	    pattern = nativ.replace.call(pattern, /^\(\?([\w$]+)\)/, function ($0, $1) {
+	        if (nativ.test.call(/[gy]/, $1)) {
+	            throw new SyntaxError('Cannot use flag g or y in mode modifier ' + $0);
+	        }
+	        // Allow duplicate flags within the mode modifier
+	        flags = clipDuplicates(flags + $1);
+	        return '';
+	    });
+	
+	    // Throw on unknown native or nonnative flags
+	    for (i = 0; i < flags.length; ++i) {
+	        if (!registeredFlags[flags.charAt(i)]) {
+	            throw new SyntaxError('Unknown regex flag ' + flags.charAt(i));
+	        }
+	    }
+	
+	    return {
+	        pattern: pattern,
+	        flags: flags
+	    };
+	}
+	
+	/**
+	 * Prepares an options object from the given value.
+	 *
+	 * @private
+	 * @param {String|Object} value Value to convert to an options object.
+	 * @returns {Object} Options object.
+	 */
+	function prepareOptions(value) {
+	    var options = {};
+	
+	    if (isType(value, 'String')) {
+	        XRegExp.forEach(value, /[^\s,]+/, function (match) {
+	            options[match] = true;
+	        });
+	
+	        return options;
+	    }
+	
+	    return value;
+	}
+	
+	/**
+	 * Registers a flag so it doesn't throw an 'unknown flag' error.
+	 *
+	 * @private
+	 * @param {String} flag Single-character flag to register.
+	 */
+	function registerFlag(flag) {
+	    if (!/^[\w$]$/.test(flag)) {
+	        throw new Error('Flag must be a single character A-Za-z0-9_$');
+	    }
+	
+	    registeredFlags[flag] = true;
+	}
+	
+	/**
+	 * Runs built-in and custom regex syntax tokens in reverse insertion order at the specified
+	 * position, until a match is found.
+	 *
+	 * @private
+	 * @param {String} pattern Original pattern from which an XRegExp object is being built.
+	 * @param {String} flags Flags being used to construct the regex.
+	 * @param {Number} pos Position to search for tokens within `pattern`.
+	 * @param {Number} scope Regex scope to apply: 'default' or 'class'.
+	 * @param {Object} context Context object to use for token handler functions.
+	 * @returns {Object} Object with properties `matchLength`, `output`, and `reparse`; or `null`.
+	 */
+	function runTokens(pattern, flags, pos, scope, context) {
+	    var i = tokens.length,
+	        leadChar = pattern.charAt(pos),
+	        result = null,
+	        match,
+	        t;
+	
+	    // Run in reverse insertion order
+	    while (i--) {
+	        t = tokens[i];
+	        if (t.leadChar && t.leadChar !== leadChar || t.scope !== scope && t.scope !== 'all' || t.flag && flags.indexOf(t.flag) === -1) {
+	            continue;
+	        }
+	
+	        match = XRegExp.exec(pattern, t.regex, pos, 'sticky');
+	        if (match) {
+	            result = {
+	                matchLength: match[0].length,
+	                output: t.handler.call(context, match, scope, flags),
+	                reparse: t.reparse
+	            };
+	            // Finished with token tests
+	            break;
+	        }
+	    }
+	
+	    return result;
+	}
+	
+	/**
+	 * Enables or disables implicit astral mode opt-in. When enabled, flag A is automatically added to
+	 * all new regexes created by XRegExp. This causes an error to be thrown when creating regexes if
+	 * the Unicode Base addon is not available, since flag A is registered by that addon.
+	 *
+	 * @private
+	 * @param {Boolean} on `true` to enable; `false` to disable.
+	 */
+	function setAstral(on) {
+	    features.astral = on;
+	}
+	
+	/**
+	 * Enables or disables native method overrides.
+	 *
+	 * @private
+	 * @param {Boolean} on `true` to enable; `false` to disable.
+	 */
+	function setNatives(on) {
+	    RegExp.prototype.exec = (on ? fixed : nativ).exec;
+	    RegExp.prototype.test = (on ? fixed : nativ).test;
+	    String.prototype.match = (on ? fixed : nativ).match;
+	    String.prototype.replace = (on ? fixed : nativ).replace;
+	    String.prototype.split = (on ? fixed : nativ).split;
+	
+	    features.natives = on;
+	}
+	
+	/**
+	 * Returns the object, or throws an error if it is `null` or `undefined`. This is used to follow
+	 * the ES5 abstract operation `ToObject`.
+	 *
+	 * @private
+	 * @param {*} value Object to check and return.
+	 * @returns {*} The provided object.
+	 */
+	function toObject(value) {
+	    // null or undefined
+	    if (value == null) {
+	        throw new TypeError('Cannot convert null or undefined to object');
+	    }
+	
+	    return value;
+	}
+	
+	/* ==============================
+	 * Constructor
+	 * ============================== */
+	
+	/**
+	 * Creates an extended regular expression object for matching text with a pattern. Differs from a
+	 * native regular expression in that additional syntax and flags are supported. The returned object
+	 * is in fact a native `RegExp` and works with all native methods.
+	 *
+	 * @class XRegExp
+	 * @constructor
+	 * @param {String|RegExp} pattern Regex pattern string, or an existing regex object to copy.
+	 * @param {String} [flags] Any combination of flags.
+	 *   Native flags:
+	 *     <li>`g` - global
+	 *     <li>`i` - ignore case
+	 *     <li>`m` - multiline anchors
+	 *     <li>`u` - unicode (ES6)
+	 *     <li>`y` - sticky (Firefox 3+, ES6)
+	 *   Additional XRegExp flags:
+	 *     <li>`n` - explicit capture
+	 *     <li>`s` - dot matches all (aka singleline)
+	 *     <li>`x` - free-spacing and line comments (aka extended)
+	 *     <li>`A` - astral (requires the Unicode Base addon)
+	 *   Flags cannot be provided when constructing one `RegExp` from another.
+	 * @returns {RegExp} Extended regular expression object.
+	 * @example
+	 *
+	 * // With named capture and flag x
+	 * XRegExp('(?<year>  [0-9]{4} ) -?  # year  \n\
+	 *          (?<month> [0-9]{2} ) -?  # month \n\
+	 *          (?<day>   [0-9]{2} )     # day   ', 'x');
+	 *
+	 * // Providing a regex object copies it. Native regexes are recompiled using native (not XRegExp)
+	 * // syntax. Copies maintain extended data, are augmented with `XRegExp.prototype` properties, and
+	 * // have fresh `lastIndex` properties (set to zero).
+	 * XRegExp(/regex/);
+	 */
+	function XRegExp(pattern, flags) {
+	    var context = {
+	        hasNamedCapture: false,
+	        captureNames: []
+	    },
+	        scope = defaultScope,
+	        output = '',
+	        pos = 0,
+	        result,
+	        token,
+	        generated,
+	        appliedPattern,
+	        appliedFlags;
+	
+	    if (XRegExp.isRegExp(pattern)) {
+	        if (flags !== undefined) {
+	            throw new TypeError('Cannot supply flags when copying a RegExp');
+	        }
+	        return copyRegex(pattern);
+	    }
+	
+	    // Copy the argument behavior of `RegExp`
+	    pattern = pattern === undefined ? '' : String(pattern);
+	    flags = flags === undefined ? '' : String(flags);
+	
+	    if (XRegExp.isInstalled('astral') && flags.indexOf('A') === -1) {
+	        // This causes an error to be thrown if the Unicode Base addon is not available
+	        flags += 'A';
+	    }
+	
+	    if (!patternCache[pattern]) {
+	        patternCache[pattern] = {};
+	    }
+	
+	    if (!patternCache[pattern][flags]) {
+	        // Check for flag-related errors, and strip/apply flags in a leading mode modifier
+	        result = prepareFlags(pattern, flags);
+	        appliedPattern = result.pattern;
+	        appliedFlags = result.flags;
+	
+	        // Use XRegExp's tokens to translate the pattern to a native regex pattern.
+	        // `appliedPattern.length` may change on each iteration if tokens use `reparse`
+	        while (pos < appliedPattern.length) {
+	            do {
+	                // Check for custom tokens at the current position
+	                result = runTokens(appliedPattern, appliedFlags, pos, scope, context);
+	                // If the matched token used the `reparse` option, splice its output into the
+	                // pattern before running tokens again at the same position
+	                if (result && result.reparse) {
+	                    appliedPattern = appliedPattern.slice(0, pos) + result.output + appliedPattern.slice(pos + result.matchLength);
+	                }
+	            } while (result && result.reparse);
+	
+	            if (result) {
+	                output += result.output;
+	                pos += result.matchLength || 1;
+	            } else {
+	                // Get the native token at the current position
+	                token = XRegExp.exec(appliedPattern, nativeTokens[scope], pos, 'sticky')[0];
+	                output += token;
+	                pos += token.length;
+	                if (token === '[' && scope === defaultScope) {
+	                    scope = classScope;
+	                } else if (token === ']' && scope === classScope) {
+	                    scope = defaultScope;
+	                }
+	            }
+	        }
+	
+	        patternCache[pattern][flags] = {
+	            // Cleanup token cruft: repeated `(?:)(?:)` and leading/trailing `(?:)`
+	            pattern: nativ.replace.call(output, /\(\?:\)(?:[*+?]|\{\d+(?:,\d*)?})?\??(?=\(\?:\))|^\(\?:\)(?:[*+?]|\{\d+(?:,\d*)?})?\??|\(\?:\)(?:[*+?]|\{\d+(?:,\d*)?})?\??$/g, ''),
+	            // Strip all but native flags
+	            flags: nativ.replace.call(appliedFlags, /[^gimuy]+/g, ''),
+	            // `context.captureNames` has an item for each capturing group, even if unnamed
+	            captures: context.hasNamedCapture ? context.captureNames : null
+	        };
+	    }
+	
+	    generated = patternCache[pattern][flags];
+	    return augment(new RegExp(generated.pattern, generated.flags), generated.captures, pattern, flags);
+	};
+	
+	// Add `RegExp.prototype` to the prototype chain
+	XRegExp.prototype = new RegExp();
+	
+	/* ==============================
+	 * Public properties
+	 * ============================== */
+	
+	/**
+	 * The XRegExp version number as a string containing three dot-separated parts. For example,
+	 * '2.0.0-beta-3'.
+	 *
+	 * @static
+	 * @memberOf XRegExp
+	 * @type String
+	 */
+	XRegExp.version = '3.1.0-dev';
+	
+	/* ==============================
+	 * Public methods
+	 * ============================== */
+	
+	/**
+	 * Extends XRegExp syntax and allows custom flags. This is used internally and can be used to
+	 * create XRegExp addons. If more than one token can match the same string, the last added wins.
+	 *
+	 * @memberOf XRegExp
+	 * @param {RegExp} regex Regex object that matches the new token.
+	 * @param {Function} handler Function that returns a new pattern string (using native regex syntax)
+	 *   to replace the matched token within all future XRegExp regexes. Has access to persistent
+	 *   properties of the regex being built, through `this`. Invoked with three arguments:
+	 *   <li>The match array, with named backreference properties.
+	 *   <li>The regex scope where the match was found: 'default' or 'class'.
+	 *   <li>The flags used by the regex, including any flags in a leading mode modifier.
+	 *   The handler function becomes part of the XRegExp construction process, so be careful not to
+	 *   construct XRegExps within the function or you will trigger infinite recursion.
+	 * @param {Object} [options] Options object with optional properties:
+	 *   <li>`scope` {String} Scope where the token applies: 'default', 'class', or 'all'.
+	 *   <li>`flag` {String} Single-character flag that triggers the token. This also registers the
+	 *     flag, which prevents XRegExp from throwing an 'unknown flag' error when the flag is used.
+	 *   <li>`optionalFlags` {String} Any custom flags checked for within the token `handler` that are
+	 *     not required to trigger the token. This registers the flags, to prevent XRegExp from
+	 *     throwing an 'unknown flag' error when any of the flags are used.
+	 *   <li>`reparse` {Boolean} Whether the `handler` function's output should not be treated as
+	 *     final, and instead be reparseable by other tokens (including the current token). Allows
+	 *     token chaining or deferring.
+	 *   <li>`leadChar` {String} Single character that occurs at the beginning of any successful match
+	 *     of the token (not always applicable). This doesn't change the behavior of the token unless
+	 *     you provide an erroneous value. However, providing it can increase the token's performance
+	 *     since the token can be skipped at any positions where this character doesn't appear.
+	 * @example
+	 *
+	 * // Basic usage: Add \a for the ALERT control code
+	 * XRegExp.addToken(
+	 *   /\\a/,
+	 *   function() {return '\\x07';},
+	 *   {scope: 'all'}
+	 * );
+	 * XRegExp('\\a[\\a-\\n]+').test('\x07\n\x07'); // -> true
+	 *
+	 * // Add the U (ungreedy) flag from PCRE and RE2, which reverses greedy and lazy quantifiers.
+	 * // Since `scope` is not specified, it uses 'default' (i.e., transformations apply outside of
+	 * // character classes only)
+	 * XRegExp.addToken(
+	 *   /([?*+]|{\d+(?:,\d*)?})(\??)/,
+	 *   function(match) {return match[1] + (match[2] ? '' : '?');},
+	 *   {flag: 'U'}
+	 * );
+	 * XRegExp('a+', 'U').exec('aaa')[0]; // -> 'a'
+	 * XRegExp('a+?', 'U').exec('aaa')[0]; // -> 'aaa'
+	 */
+	XRegExp.addToken = function (regex, handler, options) {
+	    options = options || {};
+	    var optionalFlags = options.optionalFlags,
+	        i;
+	
+	    if (options.flag) {
+	        registerFlag(options.flag);
+	    }
+	
+	    if (optionalFlags) {
+	        optionalFlags = nativ.split.call(optionalFlags, '');
+	        for (i = 0; i < optionalFlags.length; ++i) {
+	            registerFlag(optionalFlags[i]);
+	        }
+	    }
+	
+	    // Add to the private list of syntax tokens
+	    tokens.push({
+	        regex: copyRegex(regex, {
+	            addG: true,
+	            addY: hasNativeY,
+	            isInternalOnly: true
+	        }),
+	        handler: handler,
+	        scope: options.scope || defaultScope,
+	        flag: options.flag,
+	        reparse: options.reparse,
+	        leadChar: options.leadChar
+	    });
+	
+	    // Reset the pattern cache used by the `XRegExp` constructor, since the same pattern and
+	    // flags might now produce different results
+	    XRegExp.cache.flush('patterns');
+	};
+	
+	/**
+	 * Caches and returns the result of calling `XRegExp(pattern, flags)`. On any subsequent call with
+	 * the same pattern and flag combination, the cached copy of the regex is returned.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} pattern Regex pattern string.
+	 * @param {String} [flags] Any combination of XRegExp flags.
+	 * @returns {RegExp} Cached XRegExp object.
+	 * @example
+	 *
+	 * while (match = XRegExp.cache('.', 'gs').exec(str)) {
+	 *   // The regex is compiled once only
+	 * }
+	 */
+	XRegExp.cache = function (pattern, flags) {
+	    if (!regexCache[pattern]) {
+	        regexCache[pattern] = {};
+	    }
+	    return regexCache[pattern][flags] || (regexCache[pattern][flags] = XRegExp(pattern, flags));
+	};
+	
+	// Intentionally undocumented
+	XRegExp.cache.flush = function (cacheName) {
+	    if (cacheName === 'patterns') {
+	        // Flush the pattern cache used by the `XRegExp` constructor
+	        patternCache = {};
+	    } else {
+	        // Flush the regex cache populated by `XRegExp.cache`
+	        regexCache = {};
+	    }
+	};
+	
+	/**
+	 * Escapes any regular expression metacharacters, for use when matching literal strings. The result
+	 * can safely be used at any point within a regex that uses any flags.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to escape.
+	 * @returns {String} String with regex metacharacters escaped.
+	 * @example
+	 *
+	 * XRegExp.escape('Escaped? <.>');
+	 * // -> 'Escaped\?\ <\.>'
+	 */
+	XRegExp.escape = function (str) {
+	    return nativ.replace.call(toObject(str), /[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+	};
+	
+	/**
+	 * Executes a regex search in a specified string. Returns a match array or `null`. If the provided
+	 * regex uses named capture, named backreference properties are included on the match array.
+	 * Optional `pos` and `sticky` arguments specify the search start position, and whether the match
+	 * must start at the specified position only. The `lastIndex` property of the provided regex is not
+	 * used, but is updated for compatibility. Also fixes browser bugs compared to the native
+	 * `RegExp.prototype.exec` and can be used reliably cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {Number} [pos=0] Zero-based index at which to start the search.
+	 * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position
+	 *   only. The string `'sticky'` is accepted as an alternative to `true`.
+	 * @returns {Array} Match array with named backreference properties, or `null`.
+	 * @example
+	 *
+	 * // Basic use, with named backreference
+	 * var match = XRegExp.exec('U+2620', XRegExp('U\\+(?<hex>[0-9A-F]{4})'));
+	 * match.hex; // -> '2620'
+	 *
+	 * // With pos and sticky, in a loop
+	 * var pos = 2, result = [], match;
+	 * while (match = XRegExp.exec('<1><2><3><4>5<6>', /<(\d)>/, pos, 'sticky')) {
+	 *   result.push(match[1]);
+	 *   pos = match.index + match[0].length;
+	 * }
+	 * // result -> ['2', '3', '4']
+	 */
+	XRegExp.exec = function (str, regex, pos, sticky) {
+	    var cacheKey = 'g',
+	        addY = false,
+	        match,
+	        r2;
+	
+	    addY = hasNativeY && !!(sticky || regex.sticky && sticky !== false);
+	    if (addY) {
+	        cacheKey += 'y';
+	    }
+	
+	    regex[REGEX_DATA] = regex[REGEX_DATA] || {};
+	
+	    // Shares cached copies with `XRegExp.match`/`replace`
+	    r2 = regex[REGEX_DATA][cacheKey] || (regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
+	        addG: true,
+	        addY: addY,
+	        removeY: sticky === false,
+	        isInternalOnly: true
+	    }));
+	
+	    r2.lastIndex = pos = pos || 0;
+	
+	    // Fixed `exec` required for `lastIndex` fix, named backreferences, etc.
+	    match = fixed.exec.call(r2, str);
+	
+	    if (sticky && match && match.index !== pos) {
+	        match = null;
+	    }
+	
+	    if (regex.global) {
+	        regex.lastIndex = match ? r2.lastIndex : 0;
+	    }
+	
+	    return match;
+	};
+	
+	/**
+	 * Executes a provided function once per regex match. Searches always start at the beginning of the
+	 * string and continue until the end, regardless of the state of the regex's `global` property and
+	 * initial `lastIndex`.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {Function} callback Function to execute for each match. Invoked with four arguments:
+	 *   <li>The match array, with named backreference properties.
+	 *   <li>The zero-based match index.
+	 *   <li>The string being traversed.
+	 *   <li>The regex object being used to traverse the string.
+	 * @example
+	 *
+	 * // Extracts every other digit from a string
+	 * var evens = [];
+	 * XRegExp.forEach('1a2345', /\d/, function(match, i) {
+	 *   if (i % 2) evens.push(+match[0]);
+	 * });
+	 * // evens -> [2, 4]
+	 */
+	XRegExp.forEach = function (str, regex, callback) {
+	    var pos = 0,
+	        i = -1,
+	        match;
+	
+	    while (match = XRegExp.exec(str, regex, pos)) {
+	        // Because `regex` is provided to `callback`, the function could use the deprecated/
+	        // nonstandard `RegExp.prototype.compile` to mutate the regex. However, since
+	        // `XRegExp.exec` doesn't use `lastIndex` to set the search position, this can't lead
+	        // to an infinite loop, at least. Actually, because of the way `XRegExp.exec` caches
+	        // globalized versions of regexes, mutating the regex will not have any effect on the
+	        // iteration or matched strings, which is a nice side effect that brings extra safety
+	        callback(match, ++i, str, regex);
+	
+	        pos = match.index + (match[0].length || 1);
+	    }
+	};
+	
+	/**
+	 * Copies a regex object and adds flag `g`. The copy maintains extended data, is augmented with
+	 * `XRegExp.prototype` properties, and has a fresh `lastIndex` property (set to zero). Native
+	 * regexes are not recompiled using XRegExp syntax.
+	 *
+	 * @memberOf XRegExp
+	 * @param {RegExp} regex Regex to globalize.
+	 * @returns {RegExp} Copy of the provided regex with flag `g` added.
+	 * @example
+	 *
+	 * var globalCopy = XRegExp.globalize(/regex/);
+	 * globalCopy.global; // -> true
+	 */
+	XRegExp.globalize = function (regex) {
+	    return copyRegex(regex, { addG: true });
+	};
+	
+	/**
+	 * Installs optional features according to the specified options. Can be undone using
+	 * {@link #XRegExp.uninstall}.
+	 *
+	 * @memberOf XRegExp
+	 * @param {Object|String} options Options object or string.
+	 * @example
+	 *
+	 * // With an options object
+	 * XRegExp.install({
+	 *   // Enables support for astral code points in Unicode addons (implicitly sets flag A)
+	 *   astral: true,
+	 *
+	 *   // Overrides native regex methods with fixed/extended versions that support named
+	 *   // backreferences and fix numerous cross-browser bugs
+	 *   natives: true
+	 * });
+	 *
+	 * // With an options string
+	 * XRegExp.install('astral natives');
+	 */
+	XRegExp.install = function (options) {
+	    options = prepareOptions(options);
+	
+	    if (!features.astral && options.astral) {
+	        setAstral(true);
+	    }
+	
+	    if (!features.natives && options.natives) {
+	        setNatives(true);
+	    }
+	};
+	
+	/**
+	 * Checks whether an individual optional feature is installed.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} feature Name of the feature to check. One of:
+	 *   <li>`natives`
+	 *   <li>`astral`
+	 * @returns {Boolean} Whether the feature is installed.
+	 * @example
+	 *
+	 * XRegExp.isInstalled('natives');
+	 */
+	XRegExp.isInstalled = function (feature) {
+	    return !!features[feature];
+	};
+	
+	/**
+	 * Returns `true` if an object is a regex; `false` if it isn't. This works correctly for regexes
+	 * created in another frame, when `instanceof` and `constructor` checks would fail.
+	 *
+	 * @memberOf XRegExp
+	 * @param {*} value Object to check.
+	 * @returns {Boolean} Whether the object is a `RegExp` object.
+	 * @example
+	 *
+	 * XRegExp.isRegExp('string'); // -> false
+	 * XRegExp.isRegExp(/regex/i); // -> true
+	 * XRegExp.isRegExp(RegExp('^', 'm')); // -> true
+	 * XRegExp.isRegExp(XRegExp('(?s).')); // -> true
+	 */
+	XRegExp.isRegExp = function (value) {
+	    return toString.call(value) === '[object RegExp]';
+	    //return isType(value, 'RegExp');
+	};
+	
+	/**
+	 * Returns the first matched string, or in global mode, an array containing all matched strings.
+	 * This is essentially a more convenient re-implementation of `String.prototype.match` that gives
+	 * the result types you actually want (string instead of `exec`-style array in match-first mode,
+	 * and an empty array instead of `null` when no matches are found in match-all mode). It also lets
+	 * you override flag g and ignore `lastIndex`, and fixes browser bugs.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {String} [scope='one'] Use 'one' to return the first match as a string. Use 'all' to
+	 *   return an array of all matched strings. If not explicitly specified and `regex` uses flag g,
+	 *   `scope` is 'all'.
+	 * @returns {String|Array} In match-first mode: First match as a string, or `null`. In match-all
+	 *   mode: Array of all matched strings, or an empty array.
+	 * @example
+	 *
+	 * // Match first
+	 * XRegExp.match('abc', /\w/); // -> 'a'
+	 * XRegExp.match('abc', /\w/g, 'one'); // -> 'a'
+	 * XRegExp.match('abc', /x/g, 'one'); // -> null
+	 *
+	 * // Match all
+	 * XRegExp.match('abc', /\w/g); // -> ['a', 'b', 'c']
+	 * XRegExp.match('abc', /\w/, 'all'); // -> ['a', 'b', 'c']
+	 * XRegExp.match('abc', /x/, 'all'); // -> []
+	 */
+	XRegExp.match = function (str, regex, scope) {
+	    var global = regex.global && scope !== 'one' || scope === 'all',
+	        cacheKey = (global ? 'g' : '') + (regex.sticky ? 'y' : '') || 'noGY',
+	        result,
+	        r2;
+	
+	    regex[REGEX_DATA] = regex[REGEX_DATA] || {};
+	
+	    // Shares cached copies with `XRegExp.exec`/`replace`
+	    r2 = regex[REGEX_DATA][cacheKey] || (regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
+	        addG: !!global,
+	        addY: !!regex.sticky,
+	        removeG: scope === 'one',
+	        isInternalOnly: true
+	    }));
+	
+	    result = nativ.match.call(toObject(str), r2);
+	
+	    if (regex.global) {
+	        regex.lastIndex = scope === 'one' && result ?
+	        // Can't use `r2.lastIndex` since `r2` is nonglobal in this case
+	        result.index + result[0].length : 0;
+	    }
+	
+	    return global ? result || [] : result && result[0];
+	};
+	
+	/**
+	 * Retrieves the matches from searching a string using a chain of regexes that successively search
+	 * within previous matches. The provided `chain` array can contain regexes and or objects with
+	 * `regex` and `backref` properties. When a backreference is specified, the named or numbered
+	 * backreference is passed forward to the next regex or returned.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {Array} chain Regexes that each search for matches within preceding results.
+	 * @returns {Array} Matches by the last regex in the chain, or an empty array.
+	 * @example
+	 *
+	 * // Basic usage; matches numbers within <b> tags
+	 * XRegExp.matchChain('1 <b>2</b> 3 <b>4 a 56</b>', [
+	 *   XRegExp('(?is)<b>.*?</b>'),
+	 *   /\d+/
+	 * ]);
+	 * // -> ['2', '4', '56']
+	 *
+	 * // Passing forward and returning specific backreferences
+	 * html = '<a href="http://xregexp.com/api/">XRegExp</a>\
+	 *         <a href="http://www.google.com/">Google</a>';
+	 * XRegExp.matchChain(html, [
+	 *   {regex: /<a href="([^"]+)">/i, backref: 1},
+	 *   {regex: XRegExp('(?i)^https?://(?<domain>[^/?#]+)'), backref: 'domain'}
+	 * ]);
+	 * // -> ['xregexp.com', 'www.google.com']
+	 */
+	XRegExp.matchChain = function (str, chain) {
+	    return function recurseChain(values, level) {
+	        var item = chain[level].regex ? chain[level] : { regex: chain[level] },
+	            matches = [],
+	            addMatch = function addMatch(match) {
+	            if (item.backref) {
+	                /* Safari 4.0.5 (but not 5.0.5+) inappropriately uses sparse arrays to hold
+	                 * the `undefined`s for backreferences to nonparticipating capturing
+	                 * groups. In such cases, a `hasOwnProperty` or `in` check on its own would
+	                 * inappropriately throw the exception, so also check if the backreference
+	                 * is a number that is within the bounds of the array.
+	                 */
+	                if (!(match.hasOwnProperty(item.backref) || +item.backref < match.length)) {
+	                    throw new ReferenceError('Backreference to undefined group: ' + item.backref);
+	                }
+	
+	                matches.push(match[item.backref] || '');
+	            } else {
+	                matches.push(match[0]);
+	            }
+	        },
+	            i;
+	
+	        for (i = 0; i < values.length; ++i) {
+	            XRegExp.forEach(values[i], item.regex, addMatch);
+	        }
+	
+	        return level === chain.length - 1 || !matches.length ? matches : recurseChain(matches, level + 1);
+	    }([str], 0);
+	};
+	
+	/**
+	 * Returns a new string with one or all matches of a pattern replaced. The pattern can be a string
+	 * or regex, and the replacement can be a string or a function to be called for each match. To
+	 * perform a global search and replace, use the optional `scope` argument or include flag g if using
+	 * a regex. Replacement strings can use `${n}` for named and numbered backreferences. Replacement
+	 * functions can use named backreferences via `arguments[0].name`. Also fixes browser bugs compared
+	 * to the native `String.prototype.replace` and can be used reliably cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp|String} search Search pattern to be replaced.
+	 * @param {String|Function} replacement Replacement string or a function invoked to create it.
+	 *   Replacement strings can include special replacement syntax:
+	 *     <li>$$ - Inserts a literal $ character.
+	 *     <li>$&, $0 - Inserts the matched substring.
+	 *     <li>$` - Inserts the string that precedes the matched substring (left context).
+	 *     <li>$' - Inserts the string that follows the matched substring (right context).
+	 *     <li>$n, $nn - Where n/nn are digits referencing an existent capturing group, inserts
+	 *       backreference n/nn.
+	 *     <li>${n} - Where n is a name or any number of digits that reference an existent capturing
+	 *       group, inserts backreference n.
+	 *   Replacement functions are invoked with three or more arguments:
+	 *     <li>The matched substring (corresponds to $& above). Named backreferences are accessible as
+	 *       properties of this first argument.
+	 *     <li>0..n arguments, one for each backreference (corresponding to $1, $2, etc. above).
+	 *     <li>The zero-based index of the match within the total search string.
+	 *     <li>The total string being searched.
+	 * @param {String} [scope='one'] Use 'one' to replace the first match only, or 'all'. If not
+	 *   explicitly specified and using a regex with flag g, `scope` is 'all'.
+	 * @returns {String} New string with one or all matches replaced.
+	 * @example
+	 *
+	 * // Regex search, using named backreferences in replacement string
+	 * var name = XRegExp('(?<first>\\w+) (?<last>\\w+)');
+	 * XRegExp.replace('John Smith', name, '${last}, ${first}');
+	 * // -> 'Smith, John'
+	 *
+	 * // Regex search, using named backreferences in replacement function
+	 * XRegExp.replace('John Smith', name, function(match) {
+	 *   return match.last + ', ' + match.first;
+	 * });
+	 * // -> 'Smith, John'
+	 *
+	 * // String search, with replace-all
+	 * XRegExp.replace('RegExp builds RegExps', 'RegExp', 'XRegExp', 'all');
+	 * // -> 'XRegExp builds XRegExps'
+	 */
+	XRegExp.replace = function (str, search, replacement, scope) {
+	    var isRegex = XRegExp.isRegExp(search),
+	        global = search.global && scope !== 'one' || scope === 'all',
+	        cacheKey = (global ? 'g' : '') + (search.sticky ? 'y' : '') || 'noGY',
+	        s2 = search,
+	        result;
+	
+	    if (isRegex) {
+	        search[REGEX_DATA] = search[REGEX_DATA] || {};
+	
+	        // Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used, `search`'s
+	        // `lastIndex` isn't updated *during* replacement iterations
+	        s2 = search[REGEX_DATA][cacheKey] || (search[REGEX_DATA][cacheKey] = copyRegex(search, {
+	            addG: !!global,
+	            addY: !!search.sticky,
+	            removeG: scope === 'one',
+	            isInternalOnly: true
+	        }));
+	    } else if (global) {
+	        s2 = new RegExp(XRegExp.escape(String(search)), 'g');
+	    }
+	
+	    // Fixed `replace` required for named backreferences, etc.
+	    result = fixed.replace.call(toObject(str), s2, replacement);
+	
+	    if (isRegex && search.global) {
+	        // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)
+	        search.lastIndex = 0;
+	    }
+	
+	    return result;
+	};
+	
+	/**
+	 * Performs batch processing of string replacements. Used like {@link #XRegExp.replace}, but
+	 * accepts an array of replacement details. Later replacements operate on the output of earlier
+	 * replacements. Replacement details are accepted as an array with a regex or string to search for,
+	 * the replacement string or function, and an optional scope of 'one' or 'all'. Uses the XRegExp
+	 * replacement text syntax, which supports named backreference properties via `${name}`.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {Array} replacements Array of replacement detail arrays.
+	 * @returns {String} New string with all replacements.
+	 * @example
+	 *
+	 * str = XRegExp.replaceEach(str, [
+	 *   [XRegExp('(?<name>a)'), 'z${name}'],
+	 *   [/b/gi, 'y'],
+	 *   [/c/g, 'x', 'one'], // scope 'one' overrides /g
+	 *   [/d/, 'w', 'all'],  // scope 'all' overrides lack of /g
+	 *   ['e', 'v', 'all'],  // scope 'all' allows replace-all for strings
+	 *   [/f/g, function($0) {
+	 *     return $0.toUpperCase();
+	 *   }]
+	 * ]);
+	 */
+	XRegExp.replaceEach = function (str, replacements) {
+	    var i, r;
+	
+	    for (i = 0; i < replacements.length; ++i) {
+	        r = replacements[i];
+	        str = XRegExp.replace(str, r[0], r[1], r[2]);
+	    }
+	
+	    return str;
+	};
+	
+	/**
+	 * Splits a string into an array of strings using a regex or string separator. Matches of the
+	 * separator are not included in the result array. However, if `separator` is a regex that contains
+	 * capturing groups, backreferences are spliced into the result each time `separator` is matched.
+	 * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
+	 * cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to split.
+	 * @param {RegExp|String} separator Regex or string to use for separating the string.
+	 * @param {Number} [limit] Maximum number of items to include in the result array.
+	 * @returns {Array} Array of substrings.
+	 * @example
+	 *
+	 * // Basic use
+	 * XRegExp.split('a b c', ' ');
+	 * // -> ['a', 'b', 'c']
+	 *
+	 * // With limit
+	 * XRegExp.split('a b c', ' ', 2);
+	 * // -> ['a', 'b']
+	 *
+	 * // Backreferences in result array
+	 * XRegExp.split('..word1..', /([a-z]+)(\d+)/i);
+	 * // -> ['..', 'word', '1', '..']
+	 */
+	XRegExp.split = function (str, separator, limit) {
+	    return fixed.split.call(toObject(str), separator, limit);
+	};
+	
+	/**
+	 * Executes a regex search in a specified string. Returns `true` or `false`. Optional `pos` and
+	 * `sticky` arguments specify the search start position, and whether the match must start at the
+	 * specified position only. The `lastIndex` property of the provided regex is not used, but is
+	 * updated for compatibility. Also fixes browser bugs compared to the native
+	 * `RegExp.prototype.test` and can be used reliably cross-browser.
+	 *
+	 * @memberOf XRegExp
+	 * @param {String} str String to search.
+	 * @param {RegExp} regex Regex to search with.
+	 * @param {Number} [pos=0] Zero-based index at which to start the search.
+	 * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position
+	 *   only. The string `'sticky'` is accepted as an alternative to `true`.
+	 * @returns {Boolean} Whether the regex matched the provided value.
+	 * @example
+	 *
+	 * // Basic use
+	 * XRegExp.test('abc', /c/); // -> true
+	 *
+	 * // With pos and sticky
+	 * XRegExp.test('abc', /c/, 0, 'sticky'); // -> false
+	 * XRegExp.test('abc', /c/, 2, 'sticky'); // -> true
+	 */
+	XRegExp.test = function (str, regex, pos, sticky) {
+	    // Do this the easy way :-)
+	    return !!XRegExp.exec(str, regex, pos, sticky);
+	};
+	
+	/**
+	 * Uninstalls optional features according to the specified options. All optional features start out
+	 * uninstalled, so this is used to undo the actions of {@link #XRegExp.install}.
+	 *
+	 * @memberOf XRegExp
+	 * @param {Object|String} options Options object or string.
+	 * @example
+	 *
+	 * // With an options object
+	 * XRegExp.uninstall({
+	 *   // Disables support for astral code points in Unicode addons
+	 *   astral: true,
+	 *
+	 *   // Restores native regex methods
+	 *   natives: true
+	 * });
+	 *
+	 * // With an options string
+	 * XRegExp.uninstall('astral natives');
+	 */
+	XRegExp.uninstall = function (options) {
+	    options = prepareOptions(options);
+	
+	    if (features.astral && options.astral) {
+	        setAstral(false);
+	    }
+	
+	    if (features.natives && options.natives) {
+	        setNatives(false);
+	    }
+	};
+	
+	/**
+	 * Returns an XRegExp object that is the union of the given patterns. Patterns can be provided as
+	 * regex objects or strings. Metacharacters are escaped in patterns provided as strings.
+	 * Backreferences in provided regex objects are automatically renumbered to work correctly within
+	 * the larger combined pattern. Native flags used by provided regexes are ignored in favor of the
+	 * `flags` argument.
+	 *
+	 * @memberOf XRegExp
+	 * @param {Array} patterns Regexes and strings to combine.
+	 * @param {String} [flags] Any combination of XRegExp flags.
+	 * @returns {RegExp} Union of the provided regexes and strings.
+	 * @example
+	 *
+	 * XRegExp.union(['a+b*c', /(dogs)\1/, /(cats)\1/], 'i');
+	 * // -> /a\+b\*c|(dogs)\1|(cats)\2/i
+	 */
+	XRegExp.union = function (patterns, flags) {
+	    var parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,
+	        output = [],
+	        numCaptures = 0,
+	        numPriorCaptures,
+	        captureNames,
+	        pattern,
+	        rewrite = function rewrite(match, paren, backref) {
+	        var name = captureNames[numCaptures - numPriorCaptures];
+	
+	        // Capturing group
+	        if (paren) {
+	            ++numCaptures;
+	            // If the current capture has a name, preserve the name
+	            if (name) {
+	                return '(?<' + name + '>';
+	            }
+	            // Backreference
+	        } else if (backref) {
+	            // Rewrite the backreference
+	            return '\\' + (+backref + numPriorCaptures);
+	        }
+	
+	        return match;
+	    },
+	        i;
+	
+	    if (!(isType(patterns, 'Array') && patterns.length)) {
+	        throw new TypeError('Must provide a nonempty array of patterns to merge');
+	    }
+	
+	    for (i = 0; i < patterns.length; ++i) {
+	        pattern = patterns[i];
+	
+	        if (XRegExp.isRegExp(pattern)) {
+	            numPriorCaptures = numCaptures;
+	            captureNames = pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames || [];
+	
+	            // Rewrite backreferences. Passing to XRegExp dies on octals and ensures patterns
+	            // are independently valid; helps keep this simple. Named captures are put back
+	            output.push(nativ.replace.call(XRegExp(pattern.source).source, parts, rewrite));
+	        } else {
+	            output.push(XRegExp.escape(pattern));
+	        }
+	    }
+	
+	    return XRegExp(output.join('|'), flags);
+	};
+	
+	/* ==============================
+	 * Fixed/extended native methods
+	 * ============================== */
+	
+	/**
+	 * Adds named capture support (with backreferences returned as `result.name`), and fixes browser
+	 * bugs in the native `RegExp.prototype.exec`. Calling `XRegExp.install('natives')` uses this to
+	 * override the native method. Use via `XRegExp.exec` without overriding natives.
+	 *
+	 * @private
+	 * @param {String} str String to search.
+	 * @returns {Array} Match array with named backreference properties, or `null`.
+	 */
+	fixed.exec = function (str) {
+	    var origLastIndex = this.lastIndex,
+	        match = nativ.exec.apply(this, arguments),
+	        name,
+	        r2,
+	        i;
+	
+	    if (match) {
+	        // Fix browsers whose `exec` methods don't return `undefined` for nonparticipating
+	        // capturing groups. This fixes IE 5.5-8, but not IE 9's quirks mode or emulation of
+	        // older IEs. IE 9 in standards mode follows the spec
+	        if (!correctExecNpcg && match.length > 1 && indexOf(match, '') > -1) {
+	            r2 = copyRegex(this, {
+	                removeG: true,
+	                isInternalOnly: true
+	            });
+	            // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed
+	            // matching due to characters outside the match
+	            nativ.replace.call(String(str).slice(match.index), r2, function () {
+	                var len = arguments.length,
+	                    i;
+	                // Skip index 0 and the last 2
+	                for (i = 1; i < len - 2; ++i) {
+	                    if (arguments[i] === undefined) {
+	                        match[i] = undefined;
+	                    }
+	                }
+	            });
+	        }
+	
+	        // Attach named capture properties
+	        if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
+	            // Skip index 0
+	            for (i = 1; i < match.length; ++i) {
+	                name = this[REGEX_DATA].captureNames[i - 1];
+	                if (name) {
+	                    match[name] = match[i];
+	                }
+	            }
+	        }
+	
+	        // Fix browsers that increment `lastIndex` after zero-length matches
+	        if (this.global && !match[0].length && this.lastIndex > match.index) {
+	            this.lastIndex = match.index;
+	        }
+	    }
+	
+	    if (!this.global) {
+	        // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)
+	        this.lastIndex = origLastIndex;
+	    }
+	
+	    return match;
+	};
+	
+	/**
+	 * Fixes browser bugs in the native `RegExp.prototype.test`. Calling `XRegExp.install('natives')`
+	 * uses this to override the native method.
+	 *
+	 * @private
+	 * @param {String} str String to search.
+	 * @returns {Boolean} Whether the regex matched the provided value.
+	 */
+	fixed.test = function (str) {
+	    // Do this the easy way :-)
+	    return !!fixed.exec.call(this, str);
+	};
+	
+	/**
+	 * Adds named capture support (with backreferences returned as `result.name`), and fixes browser
+	 * bugs in the native `String.prototype.match`. Calling `XRegExp.install('natives')` uses this to
+	 * override the native method.
+	 *
+	 * @private
+	 * @param {RegExp|*} regex Regex to search with. If not a regex object, it is passed to `RegExp`.
+	 * @returns {Array} If `regex` uses flag g, an array of match strings or `null`. Without flag g,
+	 *   the result of calling `regex.exec(this)`.
+	 */
+	fixed.match = function (regex) {
+	    var result;
+	
+	    if (!XRegExp.isRegExp(regex)) {
+	        // Use the native `RegExp` rather than `XRegExp`
+	        regex = new RegExp(regex);
+	    } else if (regex.global) {
+	        result = nativ.match.apply(this, arguments);
+	        // Fixes IE bug
+	        regex.lastIndex = 0;
+	
+	        return result;
+	    }
+	
+	    return fixed.exec.call(regex, toObject(this));
+	};
+	
+	/**
+	 * Adds support for `${n}` tokens for named and numbered backreferences in replacement text, and
+	 * provides named backreferences to replacement functions as `arguments[0].name`. Also fixes browser
+	 * bugs in replacement text syntax when performing a replacement using a nonregex search value, and
+	 * the value of a replacement regex's `lastIndex` property during replacement iterations and upon
+	 * completion. Calling `XRegExp.install('natives')` uses this to override the native method. Note
+	 * that this doesn't support SpiderMonkey's proprietary third (`flags`) argument. Use via
+	 * `XRegExp.replace` without overriding natives.
+	 *
+	 * @private
+	 * @param {RegExp|String} search Search pattern to be replaced.
+	 * @param {String|Function} replacement Replacement string or a function invoked to create it.
+	 * @returns {String} New string with one or all matches replaced.
+	 */
+	fixed.replace = function (search, replacement) {
+	    var isRegex = XRegExp.isRegExp(search),
+	        origLastIndex,
+	        captureNames,
+	        result;
+	
+	    if (isRegex) {
+	        if (search[REGEX_DATA]) {
+	            captureNames = search[REGEX_DATA].captureNames;
+	        }
+	        // Only needed if `search` is nonglobal
+	        origLastIndex = search.lastIndex;
+	    } else {
+	        search += ''; // Type-convert
+	    }
+	
+	    // Don't use `typeof`; some older browsers return 'function' for regex objects
+	    if (isType(replacement, 'Function')) {
+	        // Stringifying `this` fixes a bug in IE < 9 where the last argument in replacement
+	        // functions isn't type-converted to a string
+	        result = nativ.replace.call(String(this), search, function () {
+	            var args = arguments,
+	                i;
+	            if (captureNames) {
+	                // Change the `arguments[0]` string primitive to a `String` object that can
+	                // store properties. This really does need to use `String` as a constructor
+	                args[0] = new String(args[0]);
+	                // Store named backreferences on the first argument
+	                for (i = 0; i < captureNames.length; ++i) {
+	                    if (captureNames[i]) {
+	                        args[0][captureNames[i]] = args[i + 1];
+	                    }
+	                }
+	            }
+	            // Update `lastIndex` before calling `replacement`. Fixes IE, Chrome, Firefox,
+	            // Safari bug (last tested IE 9, Chrome 17, Firefox 11, Safari 5.1)
+	            if (isRegex && search.global) {
+	                search.lastIndex = args[args.length - 2] + args[0].length;
+	            }
+	            // ES6 specs the context for replacement functions as `undefined`
+	            return replacement.apply(undefined, args);
+	        });
+	    } else {
+	        // Ensure that the last value of `args` will be a string when given nonstring `this`,
+	        // while still throwing on null or undefined context
+	        result = nativ.replace.call(this == null ? this : String(this), search, function () {
+	            // Keep this function's `arguments` available through closure
+	            var args = arguments;
+	            return nativ.replace.call(String(replacement), replacementToken, function ($0, $1, $2) {
+	                var n;
+	                // Named or numbered backreference with curly braces
+	                if ($1) {
+	                    // XRegExp behavior for `${n}`:
+	                    // 1. Backreference to numbered capture, if `n` is an integer. Use `0` for
+	                    //    for the entire match. Any number of leading zeros may be used.
+	                    // 2. Backreference to named capture `n`, if it exists and is not an
+	                    //    integer overridden by numbered capture. In practice, this does not
+	                    //    overlap with numbered capture since XRegExp does not allow named
+	                    //    capture to use a bare integer as the name.
+	                    // 3. If the name or number does not refer to an existing capturing group,
+	                    //    it's an error.
+	                    n = +$1; // Type-convert; drop leading zeros
+	                    if (n <= args.length - 3) {
+	                        return args[n] || '';
+	                    }
+	                    // Groups with the same name is an error, else would need `lastIndexOf`
+	                    n = captureNames ? indexOf(captureNames, $1) : -1;
+	                    if (n < 0) {
+	                        throw new SyntaxError('Backreference to undefined group ' + $0);
+	                    }
+	                    return args[n + 1] || '';
+	                }
+	                // Else, special variable or numbered backreference without curly braces
+	                if ($2 === '$') {
+	                    // $$
+	                    return '$';
+	                }
+	                if ($2 === '&' || +$2 === 0) {
+	                    // $&, $0 (not followed by 1-9), $00
+	                    return args[0];
+	                }
+	                if ($2 === '`') {
+	                    // $` (left context)
+	                    return args[args.length - 1].slice(0, args[args.length - 2]);
+	                }
+	                if ($2 === "'") {
+	                    // $' (right context)
+	                    return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
+	                }
+	                // Else, numbered backreference without curly braces
+	                $2 = +$2; // Type-convert; drop leading zero
+	                // XRegExp behavior for `$n` and `$nn`:
+	                // - Backrefs end after 1 or 2 digits. Use `${..}` for more digits.
+	                // - `$1` is an error if no capturing groups.
+	                // - `$10` is an error if less than 10 capturing groups. Use `${1}0` instead.
+	                // - `$01` is `$1` if at least one capturing group, else it's an error.
+	                // - `$0` (not followed by 1-9) and `$00` are the entire match.
+	                // Native behavior, for comparison:
+	                // - Backrefs end after 1 or 2 digits. Cannot reference capturing group 100+.
+	                // - `$1` is a literal `$1` if no capturing groups.
+	                // - `$10` is `$1` followed by a literal `0` if less than 10 capturing groups.
+	                // - `$01` is `$1` if at least one capturing group, else it's a literal `$01`.
+	                // - `$0` is a literal `$0`.
+	                if (!isNaN($2)) {
+	                    if ($2 > args.length - 3) {
+	                        throw new SyntaxError('Backreference to undefined group ' + $0);
+	                    }
+	                    return args[$2] || '';
+	                }
+	                // `$` followed by an unsupported char is an error, unlike native JS
+	                throw new SyntaxError('Invalid token ' + $0);
+	            });
+	        });
+	    }
+	
+	    if (isRegex) {
+	        if (search.global) {
+	            // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)
+	            search.lastIndex = 0;
+	        } else {
+	            // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)
+	            search.lastIndex = origLastIndex;
+	        }
+	    }
+	
+	    return result;
+	};
+	
+	/**
+	 * Fixes browser bugs in the native `String.prototype.split`. Calling `XRegExp.install('natives')`
+	 * uses this to override the native method. Use via `XRegExp.split` without overriding natives.
+	 *
+	 * @private
+	 * @param {RegExp|String} separator Regex or string to use for separating the string.
+	 * @param {Number} [limit] Maximum number of items to include in the result array.
+	 * @returns {Array} Array of substrings.
+	 */
+	fixed.split = function (separator, limit) {
+	    if (!XRegExp.isRegExp(separator)) {
+	        // Browsers handle nonregex split correctly, so use the faster native method
+	        return nativ.split.apply(this, arguments);
+	    }
+	
+	    var str = String(this),
+	        output = [],
+	        origLastIndex = separator.lastIndex,
+	        lastLastIndex = 0,
+	        lastLength;
+	
+	    // Values for `limit`, per the spec:
+	    // If undefined: pow(2,32) - 1
+	    // If 0, Infinity, or NaN: 0
+	    // If positive number: limit = floor(limit); if (limit >= pow(2,32)) limit -= pow(2,32);
+	    // If negative number: pow(2,32) - floor(abs(limit))
+	    // If other: Type-convert, then use the above rules
+	    // This line fails in very strange ways for some values of `limit` in Opera 10.5-10.63,
+	    // unless Opera Dragonfly is open (go figure). It works in at least Opera 9.5-10.1 and 11+
+	    limit = (limit === undefined ? -1 : limit) >>> 0;
+	
+	    XRegExp.forEach(str, separator, function (match) {
+	        // This condition is not the same as `if (match[0].length)`
+	        if (match.index + match[0].length > lastLastIndex) {
+	            output.push(str.slice(lastLastIndex, match.index));
+	            if (match.length > 1 && match.index < str.length) {
+	                Array.prototype.push.apply(output, match.slice(1));
+	            }
+	            lastLength = match[0].length;
+	            lastLastIndex = match.index + lastLength;
+	        }
+	    });
+	
+	    if (lastLastIndex === str.length) {
+	        if (!nativ.test.call(separator, '') || lastLength) {
+	            output.push('');
+	        }
+	    } else {
+	        output.push(str.slice(lastLastIndex));
+	    }
+	
+	    separator.lastIndex = origLastIndex;
+	    return output.length > limit ? output.slice(0, limit) : output;
+	};
+	
+	/* ==============================
+	 * Built-in syntax/flag tokens
+	 * ============================== */
+	
+	/*
+	 * Letter escapes that natively match literal characters: `\a`, `\A`, etc. These should be
+	 * SyntaxErrors but are allowed in web reality. XRegExp makes them errors for cross-browser
+	 * consistency and to reserve their syntax, but lets them be superseded by addons.
+	 */
+	XRegExp.addToken(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4}|{[\dA-Fa-f]+})|x(?![\dA-Fa-f]{2}))/, function (match, scope) {
+	    // \B is allowed in default scope only
+	    if (match[1] === 'B' && scope === defaultScope) {
+	        return match[0];
+	    }
+	    throw new SyntaxError('Invalid escape ' + match[0]);
+	}, {
+	    scope: 'all',
+	    leadChar: '\\'
+	});
+	
+	/*
+	 * Unicode code point escape with curly braces: `\u{N..}`. `N..` is any one or more digit
+	 * hexadecimal number from 0-10FFFF, and can include leading zeros. Requires the native ES6 `u` flag
+	 * to support code points greater than U+FFFF. Avoids converting code points above U+FFFF to
+	 * surrogate pairs (which could be done without flag `u`), since that could lead to broken behavior
+	 * if you follow a `\u{N..}` token that references a code point above U+FFFF with a quantifier, or
+	 * if you use the same in a character class.
+	 */
+	XRegExp.addToken(/\\u{([\dA-Fa-f]+)}/, function (match, scope, flags) {
+	    var code = dec(match[1]);
+	    if (code > 0x10FFFF) {
+	        throw new SyntaxError('Invalid Unicode code point ' + match[0]);
+	    }
+	    if (code <= 0xFFFF) {
+	        // Converting to \uNNNN avoids needing to escape the literal character and keep it
+	        // separate from preceding tokens
+	        return '\\u' + pad4(hex(code));
+	    }
+	    // If `code` is between 0xFFFF and 0x10FFFF, require and defer to native handling
+	    if (hasNativeU && flags.indexOf('u') > -1) {
+	        return match[0];
+	    }
+	    throw new SyntaxError('Cannot use Unicode code point above \\u{FFFF} without flag u');
+	}, {
+	    scope: 'all',
+	    leadChar: '\\'
+	});
+	
+	/*
+	 * Empty character class: `[]` or `[^]`. This fixes a critical cross-browser syntax inconsistency.
+	 * Unless this is standardized (per the ES spec), regex syntax can't be accurately parsed because
+	 * character class endings can't be determined.
+	 */
+	XRegExp.addToken(/\[(\^?)]/, function (match) {
+	    // For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S].
+	    // (?!) should work like \b\B, but is unreliable in some versions of Firefox
+	    return match[1] ? '[\\s\\S]' : '\\b\\B';
+	}, { leadChar: '[' });
+	
+	/*
+	 * Comment pattern: `(?# )`. Inline comments are an alternative to the line comments allowed in
+	 * free-spacing mode (flag x).
+	 */
+	XRegExp.addToken(/\(\?#[^)]*\)/, function (match, scope, flags) {
+	    // Keep tokens separated unless the following token is a quantifier
+	    return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
+	}, { leadChar: '(' });
+	
+	/*
+	 * Whitespace and line comments, in free-spacing mode (aka extended mode, flag x) only.
+	 */
+	XRegExp.addToken(/\s+|#.*/, function (match, scope, flags) {
+	    // Keep tokens separated unless the following token is a quantifier
+	    return isQuantifierNext(match.input, match.index + match[0].length, flags) ? '' : '(?:)';
+	}, { flag: 'x' });
+	
+	/*
+	 * Dot, in dotall mode (aka singleline mode, flag s) only.
+	 */
+	XRegExp.addToken(/\./, function () {
+	    return '[\\s\\S]';
+	}, {
+	    flag: 's',
+	    leadChar: '.'
+	});
+	
+	/*
+	 * Named backreference: `\k<name>`. Backreference names can use the characters A-Z, a-z, 0-9, _,
+	 * and $ only. Also allows numbered backreferences as `\k<n>`.
+	 */
+	XRegExp.addToken(/\\k<([\w$]+)>/, function (match) {
+	    // Groups with the same name is an error, else would need `lastIndexOf`
+	    var index = isNaN(match[1]) ? indexOf(this.captureNames, match[1]) + 1 : +match[1],
+	        endIndex = match.index + match[0].length;
+	    if (!index || index > this.captureNames.length) {
+	        throw new SyntaxError('Backreference to undefined group ' + match[0]);
+	    }
+	    // Keep backreferences separate from subsequent literal numbers
+	    return '\\' + index + (endIndex === match.input.length || isNaN(match.input.charAt(endIndex)) ? '' : '(?:)');
+	}, { leadChar: '\\' });
+	
+	/*
+	 * Numbered backreference or octal, plus any following digits: `\0`, `\11`, etc. Octals except `\0`
+	 * not followed by 0-9 and backreferences to unopened capture groups throw an error. Other matches
+	 * are returned unaltered. IE < 9 doesn't support backreferences above `\99` in regex syntax.
+	 */
+	XRegExp.addToken(/\\(\d+)/, function (match, scope) {
+	    if (!(scope === defaultScope && /^[1-9]/.test(match[1]) && +match[1] <= this.captureNames.length) && match[1] !== '0') {
+	        throw new SyntaxError('Cannot use octal escape or backreference to undefined group ' + match[0]);
+	    }
+	    return match[0];
+	}, {
+	    scope: 'all',
+	    leadChar: '\\'
+	});
+	
+	/*
+	 * Named capturing group; match the opening delimiter only: `(?<name>`. Capture names can use the
+	 * characters A-Z, a-z, 0-9, _, and $ only. Names can't be integers. Supports Python-style
+	 * `(?P<name>` as an alternate syntax to avoid issues in some older versions of Opera which natively
+	 * supported the Python-style syntax. Otherwise, XRegExp might treat numbered backreferences to
+	 * Python-style named capture as octals.
+	 */
+	XRegExp.addToken(/\(\?P?<([\w$]+)>/, function (match) {
+	    // Disallow bare integers as names because named backreferences are added to match
+	    // arrays and therefore numeric properties may lead to incorrect lookups
+	    if (!isNaN(match[1])) {
+	        throw new SyntaxError('Cannot use integer as capture name ' + match[0]);
+	    }
+	    if (match[1] === 'length' || match[1] === '__proto__') {
+	        throw new SyntaxError('Cannot use reserved word as capture name ' + match[0]);
+	    }
+	    if (indexOf(this.captureNames, match[1]) > -1) {
+	        throw new SyntaxError('Cannot use same name for multiple groups ' + match[0]);
+	    }
+	    this.captureNames.push(match[1]);
+	    this.hasNamedCapture = true;
+	    return '(';
+	}, { leadChar: '(' });
+	
+	/*
+	 * Capturing group; match the opening parenthesis only. Required for support of named capturing
+	 * groups. Also adds explicit capture mode (flag n).
+	 */
+	XRegExp.addToken(/\((?!\?)/, function (match, scope, flags) {
+	    if (flags.indexOf('n') > -1) {
+	        return '(?:';
+	    }
+	    this.captureNames.push(null);
+	    return '(';
+	}, {
+	    optionalFlags: 'n',
+	    leadChar: '('
+	});
+	
+	/* ==============================
+	 * Expose XRegExp
+	 * ============================== */
+	
+	module.exports = XRegExp;
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _match = __webpack_require__(6);
+	
+	Object.keys(_match).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return;
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _match[key];
+	    }
+	  });
+	});
+	
+	var _applyRegexList = __webpack_require__(7);
+	
+	Object.keys(_applyRegexList).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return;
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _applyRegexList[key];
+	    }
+	  });
+	});
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports) {
+
+	"use strict";
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+	
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+	
+	var Match = exports.Match = function () {
+	  function Match(value, index, css) {
+	    _classCallCheck(this, Match);
+	
+	    this.value = value;
+	    this.index = index;
+	    this.length = value.length;
+	    this.css = css;
+	    this.brushName = null;
+	  }
+	
+	  _createClass(Match, [{
+	    key: "toString",
+	    value: function toString() {
+	      return this.value;
+	    }
+	  }]);
+
+	  return Match;
+	}();
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	
+	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+	
+	exports.applyRegexList = applyRegexList;
+	
+	var _matches = __webpack_require__(8);
+	
+	/**
+	 * Applies all regular expression to the code and stores all found
+	 * matches in the `this.matches` array.
+	 */
+	function applyRegexList(code, regexList) {
+	  var result = [];
+	
+	  regexList = regexList || [];
+	
+	  for (var i = 0, l = regexList.length; i < l; i++) {
+	    // BUG: length returns len+1 for array if methods added to prototype chain (oising@gmail.com)
+	    if (_typeof(regexList[i]) === 'object') result = result.concat((0, _matches.find)(code, regexList[i]));
+	  }
+	
+	  result = (0, _matches.sort)(result);
+	  result = (0, _matches.removeNested)(result);
+	  result = (0, _matches.compact)(result);
+	
+	  return result;
+	}
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.find = find;
+	exports.sort = sort;
+	exports.compact = compact;
+	exports.removeNested = removeNested;
+	
+	var _match = __webpack_require__(6);
+	
+	var _syntaxhighlighterRegex = __webpack_require__(3);
+	
+	/**
+	 * Executes given regular expression on provided code and returns all matches that are found.
+	 *
+	 * @param {String} code    Code to execute regular expression on.
+	 * @param {Object} regex   Regular expression item info from `regexList` collection.
+	 * @return {Array}         Returns a list of Match objects.
+	 */
+	function find(code, regexInfo) {
+	  function defaultAdd(match, regexInfo) {
+	    return match[0];
+	  };
+	
+	  var index = 0,
+	      match = null,
+	      matches = [],
+	      process = regexInfo.func ? regexInfo.func : defaultAdd,
+	      pos = 0;
+	
+	  while (match = _syntaxhighlighterRegex.XRegExp.exec(code, regexInfo.regex, pos)) {
+	    var resultMatch = process(match, regexInfo);
+	
+	    if (typeof resultMatch === 'string') resultMatch = [new _match.Match(resultMatch, match.index, regexInfo.css)];
+	
+	    matches = matches.concat(resultMatch);
+	    pos = match.index + match[0].length;
+	  }
+	
+	  return matches;
+	};
+	
+	/**
+	 * Sorts matches by index position and then by length.
+	 */
+	function sort(matches) {
+	  function sortMatchesCallback(m1, m2) {
+	    // sort matches by index first
+	    if (m1.index < m2.index) return -1;else if (m1.index > m2.index) return 1;else {
+	      // if index is the same, sort by length
+	      if (m1.length < m2.length) return -1;else if (m1.length > m2.length) return 1;
+	    }
+	
+	    return 0;
+	  }
+	
+	  return matches.sort(sortMatchesCallback);
+	}
+	
+	function compact(matches) {
+	  var result = [],
+	      i,
+	      l;
+	
+	  for (i = 0, l = matches.length; i < l; i++) {
+	    if (matches[i]) result.push(matches[i]);
+	  }return result;
+	}
+	
+	/**
+	 * Checks to see if any of the matches are inside of other matches.
+	 * This process would get rid of highligted strings inside comments,
+	 * keywords inside strings and so on.
+	 */
+	function removeNested(matches) {
+	  // Optimized by Jose Prado (http://joseprado.com)
+	  for (var i = 0, l = matches.length; i < l; i++) {
+	    if (matches[i] === null) continue;
+	
+	    var itemI = matches[i],
+	        itemIEndPos = itemI.index + itemI.length;
+	
+	    for (var j = i + 1, l = matches.length; j < l && matches[i] !== null; j++) {
+	      var itemJ = matches[j];
+	
+	      if (itemJ === null) continue;else if (itemJ.index > itemIEndPos) break;else if (itemJ.index == itemI.index && itemJ.length > itemI.length) matches[i] = null;else if (itemJ.index >= itemI.index && itemJ.index < itemIEndPos) matches[j] = null;
+	    }
+	  }
+	
+	  return matches;
+	}
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	exports.default = Renderer;
+	/**
+	 * Pads number with zeros until it's length is the same as given length.
+	 *
+	 * @param {Number} number Number to pad.
+	 * @param {Number} length Max string length with.
+	 * @return {String}     Returns a string padded with proper amount of '0'.
+	 */
+	function padNumber(number, length) {
+	  var result = number.toString();
+	
+	  while (result.length < length) {
+	    result = '0' + result;
+	  }return result;
+	};
+	
+	function getLines(str) {
+	  return str.split(/\r?\n/);
+	}
+	
+	function getLinesToHighlight(opts) {
+	  var results = {},
+	      linesToHighlight,
+	      l,
+	      i;
+	
+	  linesToHighlight = opts.highlight || [];
+	
+	  if (typeof linesToHighlight.push !== 'function') linesToHighlight = [linesToHighlight];
+	
+	  for (i = 0, l = linesToHighlight.length; i < l; i++) {
+	    results[linesToHighlight[i]] = true;
+	  }return results;
+	}
+	
+	function Renderer(code, matches, opts) {
+	  var _this = this;
+	
+	  _this.opts = opts;
+	  _this.code = code;
+	  _this.matches = matches;
+	  _this.lines = getLines(code);
+	  _this.linesToHighlight = getLinesToHighlight(opts);
+	}
+	
+	Renderer.prototype = {
+	  /**
+	   * Wraps each line of the string into <code/> tag with given style applied to it.
+	   *
+	   * @param {String} str   Input string.
+	   * @param {String} css   Style name to apply to the string.
+	   * @return {String}      Returns input string with each line surrounded by <span/> tag.
+	   */
+	  wrapLinesWithCode: function wrapLinesWithCode(str, css) {
+	    if (str == null || str.length == 0 || str == '\n' || css == null) return str;
+	
+	    var _this = this,
+	        results = [],
+	        lines,
+	        line,
+	        spaces,
+	        i,
+	        l;
+	
+	    str = str.replace(/</g, '&lt;');
+	
+	    // Replace two or more sequential spaces with &nbsp; leaving last space untouched.
+	    str = str.replace(/ {2,}/g, function (m) {
+	      spaces = '';
+	
+	      for (i = 0, l = m.length; i < l - 1; i++) {
+	        spaces += _this.opts.space;
+	      }return spaces + ' ';
+	    });
+	
+	    lines = getLines(str);
+	
+	    // Split each line and apply <span class="...">...</span> to them so that leading spaces aren't included.
+	    for (i = 0, l = lines.length; i < l; i++) {
+	      line = lines[i];
+	      spaces = '';
+	
+	      if (line.length > 0) {
+	        line = line.replace(/^(&nbsp;| )+/, function (s) {
+	          spaces = s;
+	          return '';
+	        });
+	
+	        line = line.length === 0 ? spaces : spaces + '<code class="' + css + '">' + line + '</code>';
+	      }
+	
+	      results.push(line);
+	    }
+	
+	    return results.join('\n');
+	  },
+	
+	  /**
+	   * Turns all URLs in the code into <a/> tags.
+	   * @param {String} code Input code.
+	   * @return {String} Returns code with </a> tags.
+	   */
+	  processUrls: function processUrls(code) {
+	    var gt = /(.*)((&gt;|&lt;).*)/,
+	        url = /\w+:\/\/[\w-.\/?%&=:@;#]*/g;
+	
+	    return code.replace(url, function (m) {
+	      var suffix = '',
+	          match = null;
+	
+	      // We include &lt; and &gt; in the URL for the common cases like <http://google.com>
+	      // The problem is that they get transformed into &lt;http://google.com&gt;
+	      // Where as &gt; easily looks like part of the URL string.
+	
+	      if (match = gt.exec(m)) {
+	        m = match[1];
+	        suffix = match[2];
+	      }
+	
+	      return '<a href="' + m + '">' + m + '</a>' + suffix;
+	    });
+	  },
+	
+	  /**
+	   * Creates an array containing integer line numbers starting from the 'first-line' param.
+	   * @return {Array} Returns array of integers.
+	   */
+	  figureOutLineNumbers: function figureOutLineNumbers(code) {
+	    var lineNumbers = [],
+	        lines = this.lines,
+	        firstLine = parseInt(this.opts.firstLine || 1),
+	        i,
+	        l;
+	
+	    for (i = 0, l = lines.length; i < l; i++) {
+	      lineNumbers.push(i + firstLine);
+	    }return lineNumbers;
+	  },
+	
+	  /**
+	   * Generates HTML markup for a single line of code while determining alternating line style.
+	   * @param {Integer} lineNumber  Line number.
+	   * @param {String} code Line  HTML markup.
+	   * @return {String}       Returns HTML markup.
+	   */
+	  wrapLine: function wrapLine(lineIndex, lineNumber, lineHtml) {
+	    var classes = ['line', 'number' + lineNumber, 'index' + lineIndex, 'alt' + (lineNumber % 2 == 0 ? 1 : 2).toString()];
+	
+	    if (this.linesToHighlight[lineNumber]) classes.push('highlighted');
+	
+	    if (lineNumber == 0) classes.push('break');
+	
+	    return '<div class="' + classes.join(' ') + '">' + lineHtml + '</div>';
+	  },
+	
+	  /**
+	   * Generates HTML markup for line number column.
+	   * @param {String} code     Complete code HTML markup.
+	   * @param {Array} lineNumbers Calculated line numbers.
+	   * @return {String}       Returns HTML markup.
+	   */
+	  renderLineNumbers: function renderLineNumbers(code, lineNumbers) {
+	    var _this = this,
+	        opts = _this.opts,
+	        html = '',
+	        count = _this.lines.length,
+	        firstLine = parseInt(opts.firstLine || 1),
+	        pad = opts.padLineNumbers,
+	        lineNumber,
+	        i;
+	
+	    if (pad == true) pad = (firstLine + count - 1).toString().length;else if (isNaN(pad) == true) pad = 0;
+	
+	    for (i = 0; i < count; i++) {
+	      lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i;
+	      code = lineNumber == 0 ? opts.space : padNumber(lineNumber, pad);
+	      html += _this.wrapLine(i, lineNumber, code);
+	    }
+	
+	    return html;
+	  },
+	
+	  /**
+	   * Splits block of text into individual DIV lines.
+	   * @param {String} code     Code to highlight.
+	   * @param {Array} lineNumbers Calculated line numbers.
+	   * @return {String}       Returns highlighted code in HTML form.
+	   */
+	  getCodeLinesHtml: function getCodeLinesHtml(html, lineNumbers) {
+	    // html = utils.trim(html);
+	
+	    var _this = this,
+	        opts = _this.opts,
+	        lines = getLines(html),
+	        padLength = opts.padLineNumbers,
+	        firstLine = parseInt(opts.firstLine || 1),
+	        brushName = opts.brush,
+	        html = '';
+	
+	    for (var i = 0, l = lines.length; i < l; i++) {
+	      var line = lines[i],
+	          indent = /^(&nbsp;|\s)+/.exec(line),
+	          spaces = null,
+	          lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i;
+	      ;
+	
+	      if (indent != null) {
+	        spaces = indent[0].toString();
+	        line = line.substr(spaces.length);
+	        spaces = spaces.replace(' ', opts.space);
+	      }
+	
+	      // line = utils.trim(line);
+	
+	      if (line.length == 0) line = opts.space;
+	
+	      html += _this.wrapLine(i, lineNumber, (spaces != null ? '<code class="' + brushName + ' spaces">' + spaces + '</code>' : '') + line);
+	    }
+	
+	    return html;
+	  },
+	
+	  /**
+	   * Returns HTML for the table title or empty string if title is null.
+	   */
+	  getTitleHtml: function getTitleHtml(title) {
+	    return title ? '<caption>' + title + '</caption>' : '';
+	  },
+	
+	  /**
+	   * Finds all matches in the source code.
+	   * @param {String} code   Source code to process matches in.
+	   * @param {Array} matches Discovered regex matches.
+	   * @return {String} Returns formatted HTML with processed mathes.
+	   */
+	  getMatchesHtml: function getMatchesHtml(code, matches) {
+	    function getBrushNameCss(match) {
+	      var result = match ? match.brushName || brushName : brushName;
+	      return result ? result + ' ' : '';
+	    };
+	
+	    var _this = this,
+	        pos = 0,
+	        result = '',
+	        brushName = _this.opts.brush || '',
+	        match,
+	        matchBrushName,
+	        i,
+	        l;
+	
+	    // Finally, go through the final list of matches and pull the all
+	    // together adding everything in between that isn't a match.
+	    for (i = 0, l = matches.length; i < l; i++) {
+	      match = matches[i];
+	
+	      if (match === null || match.length === 0) continue;
+	
+	      matchBrushName = getBrushNameCss(match);
+	
+	      result += _this.wrapLinesWithCode(code.substr(pos, match.index - pos), matchBrushName + 'plain') + _this.wrapLinesWithCode(match.value, matchBrushName + match.css);
+	
+	      pos = match.index + match.length + (match.offset || 0);
+	    }
+	
+	    // don't forget to add whatever's remaining in the string
+	    result += _this.wrapLinesWithCode(code.substr(pos), getBrushNameCss() + 'plain');
+	
+	    return result;
+	  },
+	
+	  /**
+	   * Generates HTML markup for the whole syntax highlighter.
+	   * @param {String} code Source code.
+	   * @return {String} Returns HTML markup.
+	   */
+	  getHtml: function getHtml() {
+	    var _this = this,
+	        opts = _this.opts,
+	        code = _this.code,
+	        matches = _this.matches,
+	        classes = ['syntaxhighlighter'],
+	        lineNumbers,
+	        gutter,
+	        html;
+	
+	    if (opts.collapse === true) classes.push('collapsed');
+	
+	    gutter = opts.gutter !== false;
+	
+	    if (!gutter) classes.push('nogutter');
+	
+	    // add custom user style name
+	    classes.push(opts.className);
+	
+	    // add brush alias to the class name for custom CSS
+	    classes.push(opts.brush);
+	
+	    if (gutter) lineNumbers = _this.figureOutLineNumbers(code);
+	
+	    // processes found matches into the html
+	    html = _this.getMatchesHtml(code, matches);
+	
+	    // finally, split all lines so that they wrap well
+	    html = _this.getCodeLinesHtml(html, lineNumbers);
+	
+	    // finally, process the links
+	    if (opts.autoLinks) html = _this.processUrls(html);
+	
+	    html = '\n      <div class="' + classes.join(' ') + '">\n        <table border="0" cellpadding="0" cellspacing="0">\n          ' + _this.getTitleHtml(opts.title) + '\n          <tbody>\n            <tr>\n              ' + (gutter ? '<td class="gutter">' + _this.renderLineNumbers(code) + '</td>' : '') + '\n              <td class="code">\n                <div class="container">' + html + '</div>\n              </td>\n            </tr>\n          </tbody>\n        </table>\n      </div>\n    ';
+	
+	    return html;
+	  }
+	};
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * Splits block of text into lines.
+	 * @param {String} block Block of text.
+	 * @return {Array} Returns array of lines.
+	 */
+	function splitLines(block) {
+	  return block.split(/\r?\n/);
+	}
+	
+	/**
+	 * Executes a callback on each line and replaces each line with result from the callback.
+	 * @param {Object} str      Input string.
+	 * @param {Object} callback   Callback function taking one string argument and returning a string.
+	 */
+	function eachLine(str, callback) {
+	  var lines = splitLines(str);
+	
+	  for (var i = 0, l = lines.length; i < l; i++) {
+	    lines[i] = callback(lines[i], i);
+	  }return lines.join('\n');
+	}
+	
+	/**
+	 * Generates a unique element ID.
+	 */
+	function guid(prefix) {
+	  return (prefix || '') + Math.round(Math.random() * 1000000).toString();
+	}
+	
+	/**
+	 * Merges two objects. Values from obj2 override values in obj1.
+	 * Function is NOT recursive and works only for one dimensional objects.
+	 * @param {Object} obj1 First object.
+	 * @param {Object} obj2 Second object.
+	 * @return {Object} Returns combination of both objects.
+	 */
+	function merge(obj1, obj2) {
+	  var result = {},
+	      name;
+	
+	  for (name in obj1) {
+	    result[name] = obj1[name];
+	  }for (name in obj2) {
+	    result[name] = obj2[name];
+	  }return result;
+	}
+	
+	/**
+	 * Removes all white space at the begining and end of a string.
+	 *
+	 * @param {String} str   String to trim.
+	 * @return {String}      Returns string without leading and following white space characters.
+	 */
+	function trim(str) {
+	  return str.replace(/^\s+|\s+$/g, '');
+	}
+	
+	/**
+	 * Converts the source to array object. Mostly used for function arguments and
+	 * lists returned by getElementsByTagName() which aren't Array objects.
+	 * @param {List} source Source list.
+	 * @return {Array} Returns array.
+	 */
+	function toArray(source) {
+	  return Array.prototype.slice.apply(source);
+	}
+	
+	/**
+	 * Attempts to convert string to boolean.
+	 * @param {String} value Input string.
+	 * @return {Boolean} Returns true if input was "true", false if input was "false" and value otherwise.
+	 */
+	function toBoolean(value) {
+	  var result = { "true": true, "false": false }[value];
+	  return result == null ? value : result;
+	}
+	
+	module.exports = {
+	  splitLines: splitLines,
+	  eachLine: eachLine,
+	  guid: guid,
+	  merge: merge,
+	  trim: trim,
+	  toArray: toArray,
+	  toBoolean: toBoolean
+	};
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var trim = __webpack_require__(12),
+	    bloggerMode = __webpack_require__(13),
+	    stripBrs = __webpack_require__(14),
+	    unindenter = __webpack_require__(15),
+	    retabber = __webpack_require__(16);
+	
+	module.exports = function (code, opts) {
+	  code = trim(code, opts);
+	  code = bloggerMode(code, opts);
+	  code = stripBrs(code, opts);
+	  code = unindenter.unindent(code, opts);
+	
+	  var tabSize = opts['tab-size'];
+	  code = opts['smart-tabs'] === true ? retabber.smart(code, tabSize) : retabber.regular(code, tabSize);
+	
+	  return code;
+	};
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	module.exports = function (code, opts) {
+	   return code
+	   // This is a special trim which only removes first and last empty lines
+	   // and doesn't affect valid leading space on the first line.
+	   .replace(/^[ ]*[\n]+|[\n]*[ ]*$/g, '')
+	
+	   // IE lets these buggers through
+	   .replace(/\r/g, ' ');
+	};
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	module.exports = function (code, opts) {
+	  var br = /<br\s*\/?>|&lt;br\s*\/?&gt;/gi;
+	
+	  if (opts['bloggerMode'] === true) code = code.replace(br, '\n');
+	
+	  return code;
+	};
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	module.exports = function (code, opts) {
+	  var br = /<br\s*\/?>|&lt;br\s*\/?&gt;/gi;
+	
+	  if (opts['stripBrs'] === true) code = code.replace(br, '');
+	
+	  return code;
+	};
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	function isEmpty(str) {
+	  return (/^\s*$/.test(str)
+	  );
+	}
+	
+	module.exports = {
+	  unindent: function unindent(code) {
+	    var lines = code.split(/\r?\n/),
+	        regex = /^\s*/,
+	        min = 1000,
+	        line,
+	        matches,
+	        i,
+	        l;
+	
+	    // go through every line and check for common number of indents
+	    for (i = 0, l = lines.length; i < l && min > 0; i++) {
+	      line = lines[i];
+	
+	      if (isEmpty(line)) continue;
+	
+	      matches = regex.exec(line);
+	
+	      // In the event that just one line doesn't have leading white space
+	      // we can't unindent anything, so bail completely.
+	      if (matches == null) return code;
+	
+	      min = Math.min(matches[0].length, min);
+	    }
+	
+	    // trim minimum common number of white space from the begining of every line
+	    if (min > 0) for (i = 0, l = lines.length; i < l; i++) {
+	      if (!isEmpty(lines[i])) lines[i] = lines[i].substr(min);
+	    }return lines.join('\n');
+	  }
+	};
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	var spaces = '';
+	
+	// Create a string with 1000 spaces to copy spaces from...
+	// It's assumed that there would be no indentation longer than that.
+	for (var i = 0; i < 50; i++) {
+	  spaces += '                    ';
+	} // 20 spaces * 50
+	
+	// This function inserts specified amount of spaces in the string
+	// where a tab is while removing that given tab.
+	function insertSpaces(line, pos, count) {
+	  return line.substr(0, pos) + spaces.substr(0, count) + line.substr(pos + 1, line.length) // pos + 1 will get rid of the tab
+	  ;
+	}
+	
+	module.exports = {
+	  smart: function smart(code, tabSize) {
+	    var lines = code.split(/\r?\n/),
+	        tab = '\t',
+	        line,
+	        pos,
+	        i,
+	        l;
+	
+	    // Go through all the lines and do the 'smart tabs' magic.
+	    for (i = 0, l = lines.length; i < l; i++) {
+	      line = lines[i];
+	
+	      if (line.indexOf(tab) === -1) continue;
+	
+	      pos = 0;
+	
+	      while ((pos = line.indexOf(tab)) !== -1) {
+	        // This is pretty much all there is to the 'smart tabs' logic.
+	        // Based on the position within the line and size of a tab,
+	        // calculate the amount of spaces we need to insert.
+	        line = insertSpaces(line, pos, tabSize - pos % tabSize);
+	      }
+	
+	      lines[i] = line;
+	    }
+	
+	    return lines.join('\n');
+	  },
+	
+	  regular: function regular(code, tabSize) {
+	    return code.replace(/\t/g, spaces.substr(0, tabSize));
+	  }
+	};
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * Finds all &lt;SCRIPT TYPE="text/syntaxhighlighter" /> elementss.
+	 * Finds both "text/syntaxhighlighter" and "syntaxhighlighter"
+	 * ...in order to make W3C validator happy with subtype and backwardscompatible without subtype
+	 * @return {Array} Returns array of all found SyntaxHighlighter tags.
+	 */
+	function getSyntaxHighlighterScriptTags() {
+	  var tags = document.getElementsByTagName('script'),
+	      result = [];
+	
+	  for (var i = 0; i < tags.length; i++) {
+	    if (tags[i].type == 'text/syntaxhighlighter' || tags[i].type == 'syntaxhighlighter') result.push(tags[i]);
+	  }return result;
+	};
+	
+	/**
+	 * Checks if target DOM elements has specified CSS class.
+	 * @param {DOMElement} target Target DOM element to check.
+	 * @param {String} className Name of the CSS class to check for.
+	 * @return {Boolean} Returns true if class name is present, false otherwise.
+	 */
+	function hasClass(target, className) {
+	  return target.className.indexOf(className) != -1;
+	}
+	
+	/**
+	 * Adds CSS class name to the target DOM element.
+	 * @param {DOMElement} target Target DOM element.
+	 * @param {String} className New CSS class to add.
+	 */
+	function addClass(target, className) {
+	  if (!hasClass(target, className)) target.className += ' ' + className;
+	}
+	
+	/**
+	 * Removes CSS class name from the target DOM element.
+	 * @param {DOMElement} target Target DOM element.
+	 * @param {String} className CSS class to remove.
+	 */
+	function removeClass(target, className) {
+	  target.className = target.className.replace(className, '');
+	}
+	
+	/**
+	 * Adds event handler to the target object.
+	 * @param {Object} obj    Target object.
+	 * @param {String} type   Name of the event.
+	 * @param {Function} func Handling function.
+	 */
+	function attachEvent(obj, type, func, scope) {
+	  function handler(e) {
+	    e = e || window.event;
+	
+	    if (!e.target) {
+	      e.target = e.srcElement;
+	      e.preventDefault = function () {
+	        this.returnValue = false;
+	      };
+	    }
+	
+	    func.call(scope || window, e);
+	  };
+	
+	  if (obj.attachEvent) {
+	    obj.attachEvent('on' + type, handler);
+	  } else {
+	    obj.addEventListener(type, handler, false);
+	  }
+	}
+	
+	/**
+	 * Looks for a child or parent node which has specified classname.
+	 * Equivalent to jQuery's $(container).find(".className")
+	 * @param {Element} target Target element.
+	 * @param {String} search Class name or node name to look for.
+	 * @param {Boolean} reverse If set to true, will go up the node tree instead of down.
+	 * @return {Element} Returns found child or parent element on null.
+	 */
+	function findElement(target, search, reverse /* optional */) {
+	  if (target == null) return null;
+	
+	  var nodes = reverse != true ? target.childNodes : [target.parentNode],
+	      propertyToFind = { '#': 'id', '.': 'className' }[search.substr(0, 1)] || 'nodeName',
+	      expectedValue,
+	      found;
+	
+	  expectedValue = propertyToFind != 'nodeName' ? search.substr(1) : search.toUpperCase();
+	
+	  // main return of the found node
+	  if ((target[propertyToFind] || '').indexOf(expectedValue) != -1) return target;
+	
+	  for (var i = 0, l = nodes.length; nodes && i < l && found == null; i++) {
+	    found = findElement(nodes[i], search, reverse);
+	  }return found;
+	}
+	
+	/**
+	 * Looks for a parent node which has specified classname.
+	 * This is an alias to <code>findElement(container, className, true)</code>.
+	 * @param {Element} target Target element.
+	 * @param {String} className Class name to look for.
+	 * @return {Element} Returns found parent element on null.
+	 */
+	function findParentElement(target, className) {
+	  return findElement(target, className, true);
+	}
+	
+	/**
+	 * Opens up a centered popup window.
+	 * @param {String} url    URL to open in the window.
+	 * @param {String} name   Popup name.
+	 * @param {int} width   Popup width.
+	 * @param {int} height    Popup height.
+	 * @param {String} options  window.open() options.
+	 * @return {Window}     Returns window instance.
+	 */
+	function popup(url, name, width, height, options) {
+	  var x = (screen.width - width) / 2,
+	      y = (screen.height - height) / 2;
+	
+	  options += ', left=' + x + ', top=' + y + ', width=' + width + ', height=' + height;
+	  options = options.replace(/^,/, '');
+	
+	  var win = window.open(url, name, options);
+	  win.focus();
+	  return win;
+	}
+	
+	function getElementsByTagName(name) {
+	  return document.getElementsByTagName(name);
+	}
+	
+	/**
+	 * Finds all elements on the page which could be processes by SyntaxHighlighter.
+	 */
+	function findElementsToHighlight(opts) {
+	  var elements = getElementsByTagName(opts['tagName']),
+	      scripts,
+	      i;
+	
+	  // support for <SCRIPT TYPE="syntaxhighlighter" /> feature
+	  if (opts['useScriptTags']) {
+	    scripts = getElementsByTagName('script');
+	
+	    for (i = 0; i < scripts.length; i++) {
+	      if (scripts[i].type.match(/^(text\/)?syntaxhighlighter$/)) elements.push(scripts[i]);
+	    }
+	  }
+	
+	  return elements;
+	}
+	
+	function create(name) {
+	  return document.createElement(name);
+	}
+	
+	/**
+	 * Quick code mouse double click handler.
+	 */
+	function quickCodeHandler(e) {
+	  var target = e.target,
+	      highlighterDiv = findParentElement(target, '.syntaxhighlighter'),
+	      container = findParentElement(target, '.container'),
+	      textarea = document.createElement('textarea'),
+	      highlighter;
+	
+	  if (!container || !highlighterDiv || findElement(container, 'textarea')) return;
+	
+	  //highlighter = highlighters.get(highlighterDiv.id);
+	
+	  // add source class name
+	  addClass(highlighterDiv, 'source');
+	
+	  // Have to go over each line and grab it's text, can't just do it on the
+	  // container because Firefox loses all \n where as Webkit doesn't.
+	  var lines = container.childNodes,
+	      code = [];
+	
+	  for (var i = 0, l = lines.length; i < l; i++) {
+	    code.push(lines[i].innerText || lines[i].textContent);
+	  } // using \r instead of \r or \r\n makes this work equally well on IE, FF and Webkit
+	  code = code.join('\r');
+	
+	  // For Webkit browsers, replace nbsp with a breaking space
+	  code = code.replace(/\u00a0/g, " ");
+	
+	  // inject <textarea/> tag
+	  textarea.readOnly = true; // https://github.com/syntaxhighlighter/syntaxhighlighter/pull/329
+	  textarea.appendChild(document.createTextNode(code));
+	  container.appendChild(textarea);
+	
+	  // preselect all text
+	  textarea.focus();
+	  textarea.select();
+	
+	  // set up handler for lost focus
+	  attachEvent(textarea, 'blur', function (e) {
+	    textarea.parentNode.removeChild(textarea);
+	    removeClass(highlighterDiv, 'source');
+	  });
+	};
+	
+	module.exports = {
+	  quickCodeHandler: quickCodeHandler,
+	  create: create,
+	  popup: popup,
+	  hasClass: hasClass,
+	  addClass: addClass,
+	  removeClass: removeClass,
+	  attachEvent: attachEvent,
+	  findElement: findElement,
+	  findParentElement: findParentElement,
+	  getSyntaxHighlighterScriptTags: getSyntaxHighlighterScriptTags,
+	  findElementsToHighlight: findElementsToHighlight
+	};
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	module.exports = {
+	  space: '&nbsp;',
+	
+	  /** Enables use of <SCRIPT type="syntaxhighlighter" /> tags. */
+	  useScriptTags: true,
+	
+	  /** Blogger mode flag. */
+	  bloggerMode: false,
+	
+	  stripBrs: false,
+	
+	  /** Name of the tag that SyntaxHighlighter will automatically look for. */
+	  tagName: 'pre'
+	};
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	module.exports = {
+	  /** Additional CSS class names to be added to highlighter elements. */
+	  'class-name': '',
+	
+	  /** First line number. */
+	  'first-line': 1,
+	
+	  /**
+	   * Pads line numbers. Possible values are:
+	   *
+	   *   false - don't pad line numbers.
+	   *   true  - automaticaly pad numbers with minimum required number of leading zeroes.
+	   *   [int] - length up to which pad line numbers.
+	   */
+	  'pad-line-numbers': false,
+	
+	  /** Lines to highlight. */
+	  'highlight': null,
+	
+	  /** Title to be displayed above the code block. */
+	  'title': null,
+	
+	  /** Enables or disables smart tabs. */
+	  'smart-tabs': true,
+	
+	  /** Gets or sets tab size. */
+	  'tab-size': 4,
+	
+	  /** Enables or disables gutter. */
+	  'gutter': true,
+	
+	  /** Enables quick code copy and paste from double click. */
+	  'quick-code': true,
+	
+	  /** Forces code view to be collapsed. */
+	  'collapse': false,
+	
+	  /** Enables or disables automatic links. */
+	  'auto-links': true,
+	
+	  'unindent': true,
+	
+	  'html-script': false
+	};
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/* WEBPACK VAR INJECTION */(function(process) {'use strict';
+	
+	var applyRegexList = __webpack_require__(5).applyRegexList;
+	
+	function HtmlScript(BrushXML, brushClass) {
+	  var scriptBrush,
+	      xmlBrush = new BrushXML();
+	
+	  if (brushClass == null) return;
+	
+	  scriptBrush = new brushClass();
+	
+	  if (scriptBrush.htmlScript == null) throw new Error('Brush wasn\'t configured for html-script option: ' + brushClass.brushName);
+	
+	  xmlBrush.regexList.push({ regex: scriptBrush.htmlScript.code, func: process });
+	
+	  this.regexList = xmlBrush.regexList;
+	
+	  function offsetMatches(matches, offset) {
+	    for (var j = 0, l = matches.length; j < l; j++) {
+	      matches[j].index += offset;
+	    }
+	  }
+	
+	  function process(match, info) {
+	    var code = match.code,
+	        results = [],
+	        regexList = scriptBrush.regexList,
+	        offset = match.index + match.left.length,
+	        htmlScript = scriptBrush.htmlScript,
+	        matches;
+	
+	    function add(matches) {
+	      results = results.concat(matches);
+	    }
+	
+	    matches = applyRegexList(code, regexList);
+	    offsetMatches(matches, offset);
+	    add(matches);
+	
+	    // add left script bracket
+	    if (htmlScript.left != null && match.left != null) {
+	      matches = applyRegexList(match.left, [htmlScript.left]);
+	      offsetMatches(matches, match.index);
+	      add(matches);
+	    }
+	
+	    // add right script bracket
+	    if (htmlScript.right != null && match.right != null) {
+	      matches = applyRegexList(match.right, [htmlScript.right]);
+	      offsetMatches(matches, match.index + match[0].lastIndexOf(match.right));
+	      add(matches);
+	    }
+	
+	    for (var j = 0, l = results.length; j < l; j++) {
+	      results[j].brushName = brushClass.brushName;
+	    }return results;
+	  }
+	};
+	
+	module.exports = HtmlScript;
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(21)))
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	// shim for using process in browser
+	var process = module.exports = {};
+	
+	// cached from whatever global is present so that test runners that stub it
+	// don't break things.  But we need to wrap it in a try catch in case it is
+	// wrapped in strict mode code which doesn't define any globals.  It's inside a
+	// function because try/catches deoptimize in certain engines.
+	
+	var cachedSetTimeout;
+	var cachedClearTimeout;
+	
+	function defaultSetTimout() {
+	    throw new Error('setTimeout has not been defined');
+	}
+	function defaultClearTimeout() {
+	    throw new Error('clearTimeout has not been defined');
+	}
+	(function () {
+	    try {
+	        if (typeof setTimeout === 'function') {
+	            cachedSetTimeout = setTimeout;
+	        } else {
+	            cachedSetTimeout = defaultSetTimout;
+	        }
+	    } catch (e) {
+	        cachedSetTimeout = defaultSetTimout;
+	    }
+	    try {
+	        if (typeof clearTimeout === 'function') {
+	            cachedClearTimeout = clearTimeout;
+	        } else {
+	            cachedClearTimeout = defaultClearTimeout;
+	        }
+	    } catch (e) {
+	        cachedClearTimeout = defaultClearTimeout;
+	    }
+	})();
+	function runTimeout(fun) {
+	    if (cachedSetTimeout === setTimeout) {
+	        //normal enviroments in sane situations
+	        return setTimeout(fun, 0);
+	    }
+	    // if setTimeout wasn't available but was latter defined
+	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+	        cachedSetTimeout = setTimeout;
+	        return setTimeout(fun, 0);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedSetTimeout(fun, 0);
+	    } catch (e) {
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+	            return cachedSetTimeout.call(null, fun, 0);
+	        } catch (e) {
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+	            return cachedSetTimeout.call(this, fun, 0);
+	        }
+	    }
+	}
+	function runClearTimeout(marker) {
+	    if (cachedClearTimeout === clearTimeout) {
+	        //normal enviroments in sane situations
+	        return clearTimeout(marker);
+	    }
+	    // if clearTimeout wasn't available but was latter defined
+	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+	        cachedClearTimeout = clearTimeout;
+	        return clearTimeout(marker);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedClearTimeout(marker);
+	    } catch (e) {
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+	            return cachedClearTimeout.call(null, marker);
+	        } catch (e) {
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+	            return cachedClearTimeout.call(this, marker);
+	        }
+	    }
+	}
+	var queue = [];
+	var draining = false;
+	var currentQueue;
+	var queueIndex = -1;
+	
+	function cleanUpNextTick() {
+	    if (!draining || !currentQueue) {
+	        return;
+	    }
+	    draining = false;
+	    if (currentQueue.length) {
+	        queue = currentQueue.concat(queue);
+	    } else {
+	        queueIndex = -1;
+	    }
+	    if (queue.length) {
+	        drainQueue();
+	    }
+	}
+	
+	function drainQueue() {
+	    if (draining) {
+	        return;
+	    }
+	    var timeout = runTimeout(cleanUpNextTick);
+	    draining = true;
+	
+	    var len = queue.length;
+	    while (len) {
+	        currentQueue = queue;
+	        queue = [];
+	        while (++queueIndex < len) {
+	            if (currentQueue) {
+	                currentQueue[queueIndex].run();
+	            }
+	        }
+	        queueIndex = -1;
+	        len = queue.length;
+	    }
+	    currentQueue = null;
+	    draining = false;
+	    runClearTimeout(timeout);
+	}
+	
+	process.nextTick = function (fun) {
+	    var args = new Array(arguments.length - 1);
+	    if (arguments.length > 1) {
+	        for (var i = 1; i < arguments.length; i++) {
+	            args[i - 1] = arguments[i];
+	        }
+	    }
+	    queue.push(new Item(fun, args));
+	    if (queue.length === 1 && !draining) {
+	        runTimeout(drainQueue);
+	    }
+	};
+	
+	// v8 likes predictible objects
+	function Item(fun, array) {
+	    this.fun = fun;
+	    this.array = array;
+	}
+	Item.prototype.run = function () {
+	    this.fun.apply(null, this.array);
+	};
+	process.title = 'browser';
+	process.browser = true;
+	process.env = {};
+	process.argv = [];
+	process.version = ''; // empty string to avoid regexp issues
+	process.versions = {};
+	
+	function noop() {}
+	
+	process.on = noop;
+	process.addListener = noop;
+	process.once = noop;
+	process.off = noop;
+	process.removeListener = noop;
+	process.removeAllListeners = noop;
+	process.emit = noop;
+	process.prependListener = noop;
+	process.prependOnceListener = noop;
+	
+	process.listeners = function (name) {
+	    return [];
+	};
+	
+	process.binding = function (name) {
+	    throw new Error('process.binding is not supported');
+	};
+	
+	process.cwd = function () {
+	    return '/';
+	};
+	process.chdir = function (dir) {
+	    throw new Error('process.chdir is not supported');
+	};
+	process.umask = function () {
+	    return 0;
+	};
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+	
+	var _syntaxhighlighterHtmlRenderer = __webpack_require__(9);
+	
+	var _syntaxhighlighterHtmlRenderer2 = _interopRequireDefault(_syntaxhighlighterHtmlRenderer);
+	
+	var _syntaxhighlighterRegex = __webpack_require__(3);
+	
+	var _syntaxhighlighterMatch = __webpack_require__(5);
+	
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+	
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+	
+	module.exports = function () {
+	  function BrushBase() {
+	    _classCallCheck(this, BrushBase);
+	  }
+	
+	  _createClass(BrushBase, [{
+	    key: 'getKeywords',
+	
+	    /**
+	     * Converts space separated list of keywords into a regular expression string.
+	     * @param {String} str Space separated keywords.
+	     * @return {String} Returns regular expression string.
+	     */
+	    value: function getKeywords(str) {
+	      var results = str.replace(/^\s+|\s+$/g, '').replace(/\s+/g, '|');
+	
+	      return '\\b(?:' + results + ')\\b';
+	    }
+	
+	    /**
+	     * Makes a brush compatible with the `html-script` functionality.
+	     * @param {Object} regexGroup Object containing `left` and `right` regular expressions.
+	     */
+	
+	  }, {
+	    key: 'forHtmlScript',
+	    value: function forHtmlScript(regexGroup) {
+	      var regex = { 'end': regexGroup.right.source };
+	
+	      if (regexGroup.eof) {
+	        regex.end = '(?:(?:' + regex.end + ')|$)';
+	      }
+	
+	      this.htmlScript = {
+	        left: { regex: regexGroup.left, css: 'script' },
+	        right: { regex: regexGroup.right, css: 'script' },
+	        code: (0, _syntaxhighlighterRegex.XRegExp)("(?<left>" + regexGroup.left.source + ")" + "(?<code>.*?)" + "(?<right>" + regex.end + ")", "sgi")
+	      };
+	    }
+	  }, {
+	    key: 'getHtml',
+	    value: function getHtml(code) {
+	      var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+	
+	      var matches = (0, _syntaxhighlighterMatch.applyRegexList)(code, this.regexList);
+	      var renderer = new _syntaxhighlighterHtmlRenderer2.default(code, matches, params);
+	      return renderer.getHtml();
+	    }
+	  }]);
+	
+	  return BrushBase;
+	}();
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var BrushBase = __webpack_require__(22);
+	var regexLib = __webpack_require__(3).commonRegExp;
+	
+	function Brush() {
+	  var keywords = 'abstract assert boolean break byte case catch char class const ' + 'continue default do double else enum extends ' + 'false final finally float for goto if implements import ' + 'instanceof int interface long native new null ' + 'package private protected public return ' + 'short static strictfp super switch synchronized this throw throws true ' + 'transient try void volatile while';
+	
+	  this.regexList = [{
+	    regex: regexLib.singleLineCComments,
+	    css: 'comments'
+	  }, {
+	    regex: /\/\*([^\*][\s\S]*?)?\*\//gm,
+	    css: 'comments'
+	  }, {
+	    regex: /\/\*(?!\*\/)\*[\s\S]*?\*\//gm,
+	    css: 'preprocessor'
+	  }, {
+	    regex: regexLib.doubleQuotedString,
+	    css: 'string'
+	  }, {
+	    regex: regexLib.singleQuotedString,
+	    css: 'string'
+	  }, {
+	    regex: /\b([\d]+(\.[\d]+)?f?|[\d]+l?|0x[a-f0-9]+)\b/gi,
+	    css: 'value'
+	  }, {
+	    regex: /(?!\@interface\b)\@[\$\w]+\b/g,
+	    css: 'color1'
+	  }, {
+	    regex: /\@interface\b/g,
+	    css: 'color2'
+	  }, {
+	    regex: new RegExp(this.getKeywords(keywords), 'gm'),
+	    css: 'keyword'
+	  }];
+	
+	  this.forHtmlScript({
+	    left: /(&lt;|<)%[@!=]?/g,
+	    right: /%(&gt;|>)/g
+	  });
+	};
+	
+	Brush.prototype = new BrushBase();
+	Brush.aliases = ['java'];
+	module.exports = Brush;
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+	
+	/*!
+	  * domready (c) Dustin Diaz 2014 - License MIT
+	  */
+	!function (name, definition) {
+	
+	  if (true) module.exports = definition();else if (typeof define == 'function' && _typeof(define.amd) == 'object') define(definition);else this[name] = definition();
+	}('domready', function () {
+	
+	  var fns = [],
+	      _listener,
+	      doc = document,
+	      hack = doc.documentElement.doScroll,
+	      domContentLoaded = 'DOMContentLoaded',
+	      loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState);
+	
+	  if (!loaded) doc.addEventListener(domContentLoaded, _listener = function listener() {
+	    doc.removeEventListener(domContentLoaded, _listener);
+	    loaded = 1;
+	    while (_listener = fns.shift()) {
+	      _listener();
+	    }
+	  });
+	
+	  return function (fn) {
+	    loaded ? setTimeout(fn, 0) : fns.push(fn);
+	  };
+	});
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	});
+	var string = exports.string = function string(value) {
+	  return value.replace(/^([A-Z])/g, function (_, character) {
+	    return character.toLowerCase();
+	  }).replace(/([A-Z])/g, function (_, character) {
+	    return '-' + character.toLowerCase();
+	  });
+	};
+	
+	var object = exports.object = function object(value) {
+	  var result = {};
+	  Object.keys(value).forEach(function (key) {
+	    return result[string(key)] = value[key];
+	  });
+	  return result;
+	};
+
+/***/ })
+/******/ ]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/samples/Ensemble8/src/app/resources/ensemble/syntaxhighlighter/theme.css	Fri Jan 11 07:51:13 2019 -0800
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2004-2016, Alex Gorbatchev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+.syntaxhighlighter a,
+.syntaxhighlighter div,
+.syntaxhighlighter code,
+.syntaxhighlighter table,
+.syntaxhighlighter table td,
+.syntaxhighlighter table tr,
+.syntaxhighlighter table tbody,
+.syntaxhighlighter table thead,
+.syntaxhighlighter table caption,
+.syntaxhighlighter textarea {
+  -moz-border-radius: 0 0 0 0 !important;
+  -webkit-border-radius: 0 0 0 0 !important;
+  background: none !important;
+  border: 0 !important;
+  bottom: auto !important;
+  float: none !important;
+  height: auto !important;
+  left: auto !important;
+  line-height: 1.1em !important;
+  margin: 0 !important;
+  outline: 0 !important;
+  overflow: visible !important;
+  padding: 0 !important;
+  position: static !important;
+  right: auto !important;
+  text-align: left !important;
+  top: auto !important;
+  vertical-align: baseline !important;
+  width: auto !important;
+  box-sizing: content-box !important;
+  font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
+  font-weight: normal !important;
+  font-style: normal !important;
+  font-size: 1em !important;
+  min-height: inherit !important;
+  min-height: auto !important;
+}
+
+.syntaxhighlighter {
+  width: 100% !important;
+  margin: 1em 0 1em 0 !important;
+  position: relative !important;
+  overflow: auto !important;
+  font-size: 1em !important;
+}
+.syntaxhighlighter .container:before, .syntaxhighlighter .container:after {
+  content: none !important;
+}
+.syntaxhighlighter.source {
+  overflow: hidden !important;
+}
+.syntaxhighlighter .bold {
+  font-weight: bold !important;
+}
+.syntaxhighlighter .italic {
+  font-style: italic !important;
+}
+.syntaxhighlighter .line {
+  white-space: pre !important;
+}
+.syntaxhighlighter table {
+  width: 100% !important;
+}
+.syntaxhighlighter table caption {
+  text-align: left !important;
+  padding: .5em 0 0.5em 1em !important;
+}
+.syntaxhighlighter table td.code {
+  width: 100% !important;
+}
+.syntaxhighlighter table td.code .container {
+  position: relative !important;
+}
+.syntaxhighlighter table td.code .container textarea {
+  box-sizing: border-box !important;
+  position: absolute !important;
+  left: 0 !important;
+  top: 0 !important;
+  width: 100% !important;
+  height: 100% !important;
+  border: none !important;
+  background: white !important;
+  padding-left: 1em !important;
+  overflow: hidden !important;
+  white-space: pre !important;
+}
+.syntaxhighlighter table td.gutter .line {
+  text-align: right !important;
+  padding: 0 0.5em 0 1em !important;
+}
+.syntaxhighlighter table td.code .line {
+  padding: 0 1em !important;
+}
+.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
+  padding-left: 0em !important;
+}
+.syntaxhighlighter.show {
+  display: block !important;
+}
+.syntaxhighlighter.collapsed table {
+  display: none !important;
+}
+.syntaxhighlighter.collapsed .toolbar {
+  padding: 0.1em 0.8em 0em 0.8em !important;
+  font-size: 1em !important;
+  position: static !important;
+  width: auto !important;
+  height: auto !important;
+}
+.syntaxhighlighter.collapsed .toolbar span {
+  display: inline !important;
+  margin-right: 1em !important;
+}
+.syntaxhighlighter.collapsed .toolbar span a {
+  padding: 0 !important;
+  display: none !important;
+}
+.syntaxhighlighter.collapsed .toolbar span a.expandSource {
+  display: inline !important;
+}
+.syntaxhighlighter .toolbar {
+  position: absolute !important;
+  right: 1px !important;
+  top: 1px !important;
+  width: 11px !important;
+  height: 11px !important;
+  font-size: 10px !important;
+  z-index: 10 !important;
+}
+.syntaxhighlighter .toolbar span.title {
+  display: inline !important;
+}
+.syntaxhighlighter .toolbar a {
+  display: block !important;
+  text-align: center !important;
+  text-decoration: none !important;
+  padding-top: 1px !important;
+}
+.syntaxhighlighter .toolbar a.expandSource {
+  display: none !important;
+}
+.syntaxhighlighter.ie {
+  font-size: .9em !important;
+  padding: 1px 0 1px 0 !important;
+}
+.syntaxhighlighter.ie .toolbar {
+  line-height: 8px !important;
+}
+.syntaxhighlighter.ie .toolbar a {
+  padding-top: 0px !important;
+}
+.syntaxhighlighter.printing .line.alt1 .content,
+.syntaxhighlighter.printing .line.alt2 .content,
+.syntaxhighlighter.printing .line.highlighted .number,
+.syntaxhighlighter.printing .line.highlighted.alt1 .content,
+.syntaxhighlighter.printing .line.highlighted.alt2 .content {
+  background: none !important;
+}
+.syntaxhighlighter.printing .line .number {
+  color: #bbbbbb !important;
+}
+.syntaxhighlighter.printing .line .content {
+  color: black !important;
+}
+.syntaxhighlighter.printing .toolbar {
+  display: none !important;
+}
+.syntaxhighlighter.printing a {
+  text-decoration: none !important;
+}
+.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
+  color: black !important;
+}
+.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
+  color: #008200 !important;
+}
+.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
+  color: blue !important;
+}
+.syntaxhighlighter.printing .keyword {
+  color: #006699 !important;
+  font-weight: bold !important;
+}
+.syntaxhighlighter.printing .preprocessor {
+  color: gray !important;
+}
+.syntaxhighlighter.printing .variable {
+  color: #aa7700 !important;
+}
+.syntaxhighlighter.printing .value {
+  color: #009900 !important;
+}
+.syntaxhighlighter.printing .functions {
+  color: #ff1493 !important;
+}
+.syntaxhighlighter.printing .constants {
+  color: #0066cc !important;
+}
+.syntaxhighlighter.printing .script {
+  font-weight: bold !important;
+}
+.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
+  color: gray !important;
+}
+.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
+  color: #ff1493 !important;
+}
+.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
+  color: red !important;
+}
+.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
+  color: black !important;
+}
+
+.syntaxhighlighter {
+  background-color: #f4f4f4 !important;
+}
+.syntaxhighlighter .line.alt1 {
+  background-color: #f4f4f4 !important;
+}
+.syntaxhighlighter .line.alt2 {
+  background-color: #f4f4f4 !important;
+}
+.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
+  background-color: #e0e0e0 !important;
+}
+.syntaxhighlighter .line.highlighted.number {
+  color: black !important;
+}
+.syntaxhighlighter table caption {
+  color: black !important;
+}
+.syntaxhighlighter table td.code .container textarea {
+  background: #f4f4f4;
+  color: black
+}
+.syntaxhighlighter .gutter {
+  color: #afafaf !important;
+}
+.syntaxhighlighter .gutter .line {
+  border-right: 3px solid #6ce26c !important;
+}
+.syntaxhighlighter .gutter .line.highlighted {
+  background-color: #6ce26c !important;
+  color: white !important;
+}
+.syntaxhighlighter.printing .line .content {
+  border: none !important;
+}
+.syntaxhighlighter.collapsed {
+  overflow: visible !important;
+}
+.syntaxhighlighter.collapsed .toolbar {
+  color: #00f !important;
+  background: #f4f4f4 !important;
+  border: 1px solid #6ce26c !important;
+}
+.syntaxhighlighter.collapsed .toolbar a {
+  color: #00f !important;
+}
+.syntaxhighlighter.collapsed .toolbar a:hover {
+  color: #f00 !important;
+}
+.syntaxhighlighter .toolbar {
+  color: #f4f4f4 !important;
+  background: #6ce26c !important;
+  border: none !important;
+}
+.syntaxhighlighter .toolbar a {
+  color: #f4f4f4 !important;
+}
+.syntaxhighlighter .toolbar a:hover {
+  color: #000 !important;
+}
+.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
+  color: black !important;
+}
+.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
+  color: #008200 !important;
+}
+.syntaxhighlighter .string, .syntaxhighlighter .string a {
+  color: blue !important;
+}
+.syntaxhighlighter .keyword {
+  font-weight: bold !important;
+  color: #006699 !important;
+}
+.syntaxhighlighter .preprocessor {
+  color: gray !important;
+}
+.syntaxhighlighter .variable {
+  color: #aa7700 !important;
+}
+.syntaxhighlighter .value {
+  color: #009900 !important;
+}
+.syntaxhighlighter .functions {
+  color: #ff1493 !important;
+}
+.syntaxhighlighter .constants {
+  color: #0066cc !important;
+}
+.syntaxhighlighter .script {
+  font-weight: bold !important;
+  color: #006699 !important;
+  background-color: none !important;
+}
+.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
+  color: gray !important;
+}
+.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
+  color: #ff1493 !important;
+}
+.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
+  color: red !important;
+}
--- a/modules/javafx.base/src/main/java/com/sun/javafx/logging/PlatformLogger.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.base/src/main/java/com/sun/javafx/logging/PlatformLogger.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,22 +118,22 @@
      */
     @Override
     public String getName() {
-       throw new UnsupportedOperationException("not implemented");
+        return loggerProxy.getName();
     }
 
     @Override
     public boolean isLoggable(System.Logger.Level level) {
-        throw new UnsupportedOperationException("not implemented");
+        return loggerProxy.isLoggable(level);
     }
 
     @Override
     public void log(System.Logger.Level level, ResourceBundle bundle, String format, Object... params) {
-        throw new UnsupportedOperationException("not implemented");
+        loggerProxy.log(level, bundle, format, params);
     }
 
     @Override
     public void log(System.Logger.Level level, ResourceBundle bundle, String msg, Throwable thrown) {
-        throw new UnsupportedOperationException("not implemented");
+        loggerProxy.log(level, bundle, msg, thrown);
     }
 
     // ------------------------------------------------------------------------
--- a/modules/javafx.base/src/main/java/com/sun/javafx/logging/PrintLogger.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.base/src/main/java/com/sun/javafx/logging/PrintLogger.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -51,12 +50,6 @@
 class PrintLogger extends Logger {
 
     /**
-     * A reference to the pulse logger. This will be null if pulse logging
-     * is not enabled.
-     */
-    private static PrintLogger printLogger;
-
-    /**
      * A time in milliseconds which defines the threshold. If a pulse lasts <em>longer</em> than
      * the threshold, then it is logged, otherwise an abbreviated representation including
      * only the time of the pulse is logged.
@@ -110,7 +103,7 @@
 
     private Thread fxThread;
     private final ThreadLocal<ThreadLocalData> phaseData =
-        new ThreadLocal() {
+        new ThreadLocal<>() {
             @Override
             public ThreadLocalData initialValue() {
                 return new ThreadLocalData();
@@ -149,14 +142,12 @@
         active = new AtomicInteger(0);
     }
 
-    public static Logger getInstance() {
-        if (printLogger == null) {
-            boolean enabled = AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.pulseLogger"));
-            if (enabled) {
-                printLogger = new PrintLogger();
-            }
+    public static Logger createInstance() {
+        boolean enabled = PulseLogger.isPulseLoggingRequested();
+        if (enabled) {
+            return new PrintLogger();
         }
-        return printLogger;
+        return null;
     }
 
     /**
@@ -355,7 +346,7 @@
         int pulseCount;
         boolean pushedRender;
         StringBuffer message = new StringBuffer();
-        Map<String,Counter> counters = new ConcurrentHashMap();
+        Map<String,Counter> counters = new ConcurrentHashMap<>();
 
         void init(int n) {
             state = INCOMPLETE;
@@ -394,7 +385,7 @@
                 System.err.print(message);
                 if (!counters.isEmpty()) {
                     System.err.println("Counters:");
-                    List<Map.Entry<String,Counter>> entries = new ArrayList(counters.entrySet());
+                    List<Map.Entry<String,Counter>> entries = new ArrayList<>(counters.entrySet());
                     Collections.sort(entries, (a, b) -> a.getKey().compareTo(b.getKey()));
                     for (Map.Entry<String, Counter> entry : entries) {
                         System.err.println("\t" + entry.getKey() + ": " + entry.getValue().value);
--- a/modules/javafx.base/src/main/java/com/sun/javafx/logging/PulseLogger.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.base/src/main/java/com/sun/javafx/logging/PulseLogger.java	Fri Jan 11 07:51:13 2019 -0800
@@ -27,37 +27,25 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.List;
 
 public class PulseLogger {
-
     public static final boolean PULSE_LOGGING_ENABLED;
 
+    private static final String [] DEFAULT_LOGGERS = {"com.sun.javafx.logging.PrintLogger", "com.sun.javafx.logging.jfr.JFRPulseLogger"};
     private static final Logger[] loggers;
 
     static {
-        List<Logger> list = new ArrayList();
-        Logger logger = PrintLogger.getInstance();
-        if (logger != null) {
-            list.add(logger);
+        List<Logger> list = new ArrayList<>();
+        for (String loggerClass : DEFAULT_LOGGERS) {
+            Logger logger = loadLogger(loggerClass);
+            if (logger != null) {
+                list.add(logger);
+            }
         }
-
-//        // Another optional logger could be added as follows:
-//        try {
-//            Class klass = Class.forName("com.sun.javafx.logging.OtherLogger");
-//            if (klass != null) {
-//                Method method = klass.getDeclaredMethod("getInstance");
-//                logger = (Logger) method.invoke(null);
-//                if (logger != null) {
-//                    list.add(logger);
-//                }
-//            }
-//        }
-//        catch (NoClassDefFoundError | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-//            // Ignore
-//        }
-
         loggers = list.toArray(new Logger[list.size()]);
         PULSE_LOGGING_ENABLED = loggers.length > 0;
     }
@@ -109,4 +97,26 @@
             logger.newInput(name);
         }
     }
+
+    /**
+     * @return true if the user requested pulse logging by setting the system
+     *         property javafx.pulseLogger to true, false otherwise.
+     */
+    public static boolean isPulseLoggingRequested() {
+        return AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.pulseLogger"));
+    }
+
+    // Loading known loggers reflectively, in case an expected module isn't available
+    private static Logger loadLogger(String className) {
+        try {
+            Class<?> klass = Class.forName(className);
+            if (klass != null) {
+                Method method = klass.getDeclaredMethod("createInstance");
+                return (Logger) method.invoke(null);
+            }
+        } catch (NoClassDefFoundError | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            // Ignore
+        }
+        return null;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.base/src/main/java/com/sun/javafx/logging/jfr/JFRInputEvent.java	Fri Jan 11 07:51:13 2019 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.logging.jfr;
+
+import jdk.jfr.Category;
+import jdk.jfr.Description;
+import jdk.jfr.Enabled;
+import jdk.jfr.Event;
+import jdk.jfr.Label;
+import jdk.jfr.Name;
+import jdk.jfr.StackTrace;
+
+@Name("javafx.Input")
+@Label("JavaFX Input")
+@Category("JavaFX")
+@Description("JavaFX input event")
+@StackTrace(false)
+@Enabled(false)
+public final class JFRInputEvent extends Event {
+    @Label("Input Type")
+    @Description("Input event type")
+    private String input;
+
+    public String getInput() {
+        return input;
+    }
+
+    public void setInput(String input) {
+        this.input = input;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.base/src/main/java/com/sun/javafx/logging/jfr/JFRPulseLogger.java	Fri Jan 11 07:51:13 2019 -0800
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.javafx.logging.jfr;
+
+import com.sun.javafx.logging.Logger;
+import com.sun.javafx.logging.PulseLogger;
+
+import jdk.jfr.FlightRecorder;
+
+public final class JFRPulseLogger extends Logger {
+    private final ThreadLocal<JFRPulsePhaseEvent> currentPulsePhaseEvent;
+    private final ThreadLocal<JFRInputEvent> currentInputEvent;
+
+    private int pulseNumber;
+    private int fxPulseNumber;
+    private int renderPulseNumber;
+    private Thread fxThread;
+
+    public static Logger createInstance() {
+        if (FlightRecorder.isInitialized() || PulseLogger.isPulseLoggingRequested()) {
+            return new JFRPulseLogger();
+        }
+        return null;
+    }
+
+    private JFRPulseLogger() {
+        FlightRecorder.register(JFRInputEvent.class);
+        FlightRecorder.register(JFRPulsePhaseEvent.class);
+        currentPulsePhaseEvent = new ThreadLocal<JFRPulsePhaseEvent>() {
+            @Override
+            public JFRPulsePhaseEvent initialValue() {
+                return new JFRPulsePhaseEvent();
+            }
+        };
+        currentInputEvent = new ThreadLocal<JFRInputEvent>() {
+            @Override
+            public JFRInputEvent initialValue() {
+                return new JFRInputEvent();
+            }
+        };
+    }
+
+    @Override
+    public void pulseStart() {
+        ++pulseNumber;
+        fxPulseNumber = pulseNumber;
+        if (fxThread == null) {
+            fxThread = Thread.currentThread();
+        }
+        newPhase("Pulse start");
+    }
+
+    @Override
+    public void pulseEnd() {
+        newPhase(null);
+        fxPulseNumber = 0;
+    }
+
+    @Override
+    public void renderStart() {
+        renderPulseNumber = fxPulseNumber;
+    }
+
+    @Override
+    public void renderEnd() {
+        newPhase(null);
+        renderPulseNumber = 0;
+    }
+
+    /**
+     * Finishes the current phase and starts a new one if phaseName is not null.
+     *
+     * @param phaseName The name for the new phase.
+     */
+    @Override
+    public void newPhase(String phaseName) {
+        JFRPulsePhaseEvent event = currentPulsePhaseEvent.get();
+
+        /* Cleanup if no longer enabled */
+        if (!event.isEnabled()) {
+            event.setPhaseName(null);
+            return;
+        }
+
+        /* If there is an ongoing event, commit it */
+        if (event.getPhaseName() != null) {
+            event.commit();
+        }
+
+        /* Done if the new phase name is null */
+        if (phaseName == null) {
+            event.setPhaseName(null);
+            return;
+        }
+
+        event = new JFRPulsePhaseEvent();
+        event.begin();
+        event.setPhaseName(phaseName);
+        event.setPulseId(Thread.currentThread() == fxThread ? fxPulseNumber : renderPulseNumber);
+        currentPulsePhaseEvent.set(event);
+    }
+
+    @Override
+    public void newInput(String input) {
+        JFRInputEvent event = currentInputEvent.get();
+
+        /* Cleanup if no longer enabled */
+        if (!event.isEnabled()) {
+            event.setInput(null);
+            return;
+        }
+
+        /* If there is an ongoing event, commit it */
+        if (event.getInput() != null) {
+            event.commit();
+        }
+
+        /* Done if the new input is null */
+        if (input == null) {
+            event.setInput(null);
+            return;
+        }
+
+        event = new JFRInputEvent();
+        event.begin();
+        event.setInput(input);
+        currentInputEvent.set(event);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.base/src/main/java/com/sun/javafx/logging/jfr/JFRPulsePhaseEvent.java	Fri Jan 11 07:51:13 2019 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.logging.jfr;
+
+import jdk.jfr.Category;
+import jdk.jfr.Description;
+import jdk.jfr.Enabled;
+import jdk.jfr.Event;
+import jdk.jfr.Label;
+import jdk.jfr.Name;
+import jdk.jfr.StackTrace;
+
+@Name("javafx.PulsePhase")
+@Label("JavaFX Pulse Phase")
+@Category("JavaFX")
+@Description("Describes a phase in JavaFX pulse processing")
+@StackTrace(false)
+@Enabled(false)
+public final class JFRPulsePhaseEvent extends Event {
+    @PulseId
+    @Label("Pulse Id")
+    private int pulseId;
+
+    @Label("Phase Name")
+    private String phaseName;
+
+    public int getPulseId() {
+        return pulseId;
+    }
+
+    public void setPulseId(int pulseId) {
+        this.pulseId = pulseId;
+    }
+
+    public String getPhaseName() {
+        return phaseName;
+    }
+
+    public void setPhaseName(String phaseName) {
+        this.phaseName = phaseName;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.base/src/main/java/com/sun/javafx/logging/jfr/PulseId.java	Fri Jan 11 07:51:13 2019 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.logging.jfr;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import jdk.jfr.Description;
+import jdk.jfr.Name;
+import jdk.jfr.Relational;
+
+/**
+ * This annotation defines a relation for future events that are related to the
+ * same pulse id. It also informs a user interface consuming events where a
+ * field contains a pulse id that the value could be useful to find other,
+ * related events.
+ */
+@Relational
+@Name("javafx.PulseId")
+@Retention(RUNTIME)
+@Target(FIELD)
+@Description("Binds events with same pulse id together")
+public @interface PulseId {
+
+}
--- a/modules/javafx.base/src/main/java/module-info.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.base/src/main/java/module-info.java	Fri Jan 11 07:51:13 2019 -0800
@@ -32,6 +32,7 @@
  */
 module javafx.base {
     requires java.desktop;
+    requires static jdk.jfr;
 
     exports javafx.beans;
     exports javafx.beans.binding;
--- a/modules/javafx.base/src/test/java/test/com/sun/javafx/runtime/VersionInfoTest.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.base/src/test/java/test/com/sun/javafx/runtime/VersionInfoTest.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/ListViewSkin.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/ListViewSkin.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableHeaderRow.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableHeaderRow.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableViewSkin.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableViewSkin.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableViewSkinBase.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableViewSkinBase.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/ToolBarSkin.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/ToolBarSkin.java	Fri Jan 11 07:51:13 2019 -0800
@@ -453,12 +453,15 @@
 //        super.layoutChildren();
         final ToolBar toolbar = getSkinnable();
 
+        double toolbarLength = getToolbarLength(toolbar);
         if (toolbar.getOrientation() == Orientation.VERTICAL) {
             if (snapSizeY(toolbar.getHeight()) != previousHeight || needsUpdate) {
                 ((VBox)box).setSpacing(getSpacing());
                 ((VBox)box).setAlignment(getBoxAlignment());
                 previousHeight = snapSizeY(toolbar.getHeight());
                 addNodesToToolBar();
+            } else {
+                correctOverflow(toolbarLength);
             }
         } else {
             if (snapSizeX(toolbar.getWidth()) != previousWidth || needsUpdate) {
@@ -466,8 +469,11 @@
                 ((HBox)box).setAlignment(getBoxAlignment());
                 previousWidth = snapSizeX(toolbar.getWidth());
                 addNodesToToolBar();
+            } else {
+                correctOverflow(toolbarLength);
             }
         }
+
         needsUpdate = false;
 
         double toolbarWidth = w;
@@ -531,8 +537,6 @@
         }
     }
 
-
-
     /***************************************************************************
      *                                                                         *
      * Private implementation                                                  *
@@ -563,32 +567,14 @@
         getSkinnable().requestLayout();
     }
 
-    private void addNodesToToolBar() {
-        final ToolBar toolbar = getSkinnable();
-        double length = 0;
-        if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
-            length = snapSizeY(toolbar.getHeight()) - snappedTopInset() - snappedBottomInset() + getSpacing();
-        } else {
-            length = snapSizeX(toolbar.getWidth()) - snappedLeftInset() - snappedRightInset() + getSpacing();
+    private void correctOverflow(double length) {
+        boolean overflowed = isOverflowed(length);
+        if (overflowed != overflow) {
+            organizeOverflow(length, overflow);
         }
+    }
 
-        // Is there overflow ?
-        double x = 0;
-        boolean hasOverflow = false;
-        for (Node node : getSkinnable().getItems()) {
-            if (!node.isManaged()) continue;
-
-            if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
-                x += snapSizeY(node.prefHeight(-1)) + getSpacing();
-            } else {
-                x += snapSizeX(node.prefWidth(-1)) + getSpacing();
-            }
-            if (x > length) {
-                hasOverflow = true;
-                break;
-            }
-        }
-
+    private void organizeOverflow(double length, boolean hasOverflow) {
         if (hasOverflow) {
             if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
                 length -= snapSizeY(overflowMenu.prefHeight(-1));
@@ -599,7 +585,8 @@
         }
 
         // Determine which node goes to the toolbar and which goes to the overflow.
-        x = 0;
+
+        double x = 0;
         overflowMenuItems.clear();
         box.getChildren().clear();
         for (Node node : getSkinnable().getItems()) {
@@ -687,7 +674,43 @@
         overflowMenu.setManaged(overflow);
     }
 
+    private void addNodesToToolBar() {
+        final ToolBar toolbar = getSkinnable();
+        double toolbarLength = getToolbarLength(toolbar);
 
+        // Is there overflow ?
+        boolean hasOverflow = isOverflowed(toolbarLength);
+
+        organizeOverflow(toolbarLength, hasOverflow);
+    }
+
+    private double getToolbarLength(ToolBar toolbar) {
+        double length;
+        if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
+            length = snapSizeY(toolbar.getHeight()) - snappedTopInset() - snappedBottomInset() + getSpacing();
+        } else {
+            length = snapSizeX(toolbar.getWidth()) - snappedLeftInset() - snappedRightInset() + getSpacing();
+        }
+        return length;
+    }
+
+    private boolean isOverflowed(double length) {
+        double x = 0;
+        boolean hasOverflow = false;
+        for (Node node : getSkinnable().getItems()) {
+            if (!node.isManaged()) continue;
+            if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
+                x += snapSizeY(node.prefHeight(-1)) + getSpacing();
+            } else {
+                x += snapSizeX(node.prefWidth(-1)) + getSpacing();
+            }
+            if (x > length) {
+                hasOverflow = true;
+                break;
+            }
+        }
+        return hasOverflow;
+    }
 
     /***************************************************************************
      *                                                                         *
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TreeTableViewSkin.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TreeTableViewSkin.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TreeViewSkin.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TreeViewSkin.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/shims/java/javafx/scene/control/skin/VirtualFlowShim.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/shims/java/javafx/scene/control/skin/VirtualFlowShim.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.controls/src/test/java/test/com/sun/javafx/scene/control/infrastructure/MouseEventFirer.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/test/java/test/com/sun/javafx/scene/control/infrastructure/MouseEventFirer.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -194,6 +194,8 @@
                 button == MouseButton.PRIMARY,     // primary button
                 button == MouseButton.MIDDLE,      // middle button
                 button == MouseButton.SECONDARY,   // secondary button
+                button == MouseButton.BACK,        // back button
+                button == MouseButton.FORWARD,     // forward button
                 false,                             // synthesized
                 button == MouseButton.SECONDARY,   // is popup trigger
                 true,                              // still since pick
--- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/ToolbarTest.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/ToolbarTest.java	Fri Jan 11 07:51:13 2019 -0800
@@ -27,6 +27,10 @@
 
 import javafx.css.CssMetaData;
 import static test.com.sun.javafx.scene.control.infrastructure.ControlTestUtils.*;
+
+import javafx.scene.AccessibleAttribute;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.StackPane;
 import test.com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
 import test.com.sun.javafx.pgstub.StubToolkit;
 import javafx.scene.control.skin.ToolBarSkin;
@@ -58,10 +62,17 @@
 public class ToolbarTest {
     private ToolBar toolBar;//Empty
     private ToolBar toolBarWithItems;//Items
+
     private Toolkit tk;
+    private StackPane root;
+
     private Node node1;
     private Node node2;
 
+    private static final double TOOLBAR_SIZE = 300.0;
+    private static final double EXPANDED_CHILDREN_SIZE = 250.0;
+    private static final double ORIGINAL_CHILDREN_SIZE = 100.0;
+
     @Before public void setup() {
         tk = (StubToolkit)Toolkit.getToolkit();//This step is not needed (Just to make sure StubToolkit is loaded into VM)
         toolBar = new ToolBar();
@@ -221,4 +232,74 @@
         tk.firePulse();
         assertTrue(btn5.isFocused());
     }
+
+    @Test public void overflowShownInHorizontalAfterChildrenReziseTest() {
+        initializeToolBar();
+
+        toolBar.setOrientation(Orientation.HORIZONTAL);
+
+        testOverflowVisibility();
+    }
+
+    @Test public void overflowShownInVerticalAfterChildrenReziseTest() {
+        initializeToolBar();
+
+        toolBar.setOrientation(Orientation.VERTICAL);
+
+        testOverflowVisibility();
+    }
+
+    private void initializeToolBar() {
+        root = new StackPane(toolBar);
+        root.setPrefSize(400, 400);
+
+        Scene scene = new Scene(root);
+        Stage stage = new Stage();
+        stage.setScene(scene);
+
+        toolBar.getItems().addAll(node1, node2);
+        setFixSize(toolBar, TOOLBAR_SIZE);
+    }
+
+    private void testOverflowVisibility() {
+        setFixSize(node1, ORIGINAL_CHILDREN_SIZE);
+        setFixSize(node2, ORIGINAL_CHILDREN_SIZE);
+
+        assertOverflowNotShown();
+
+        setFixSize(node1, EXPANDED_CHILDREN_SIZE);
+
+        assertOverflowShown();
+
+        setFixSize(node1, ORIGINAL_CHILDREN_SIZE);
+
+        assertOverflowNotShown();
+    }
+
+    private void setFixSize(Node node, double size) {
+        if (node instanceof Region) {
+            ((Region) node).setMinSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);
+            ((Region) node).setMaxSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);
+            ((Region) node).setPrefSize(size, size);
+        } else if (node instanceof Rectangle) {
+            ((Rectangle) node).setHeight(size);
+            ((Rectangle) node).setWidth(size);
+        }
+
+        root.applyCss();
+        root.autosize();
+        root.layout();
+    }
+
+    private void assertOverflowNotShown() {
+        Pane pane = (Pane) toolBar.queryAccessibleAttribute(AccessibleAttribute.OVERFLOW_BUTTON);
+        assertNotNull(pane);
+        assertFalse(pane.isVisible());
+    }
+
+    private void assertOverflowShown() {
+        Pane pane = (Pane) toolBar.queryAccessibleAttribute(AccessibleAttribute.OVERFLOW_BUTTON);
+        assertNotNull(pane);
+        assertTrue(pane.isVisible());
+    }
 }
--- a/modules/javafx.graphics/src/jslc/java/com/sun/scenario/effect/compiler/backend/hw/ES2Backend.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/jslc/java/com/sun/scenario/effect/compiler/backend/hw/ES2Backend.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/jslc/java/com/sun/scenario/effect/compiler/backend/hw/GLSLBackend.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/jslc/java/com/sun/scenario/effect/compiler/backend/hw/GLSLBackend.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/jslc/java/com/sun/scenario/effect/compiler/backend/hw/SLBackend.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/jslc/java/com/sun/scenario/effect/compiler/backend/hw/SLBackend.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/events/KeyEvent.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/events/KeyEvent.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,8 @@
     @Native public final static int MODIFIER_BUTTON_PRIMARY    = 1 << 5;
     @Native public final static int MODIFIER_BUTTON_SECONDARY  = 1 << 6;
     @Native public final static int MODIFIER_BUTTON_MIDDLE     = 1 << 7;
+    @Native public final static int MODIFIER_BUTTON_BACK       = 1 << 8;
+    @Native public final static int MODIFIER_BUTTON_FORWARD    = 1 << 9;
 
     /*
      * Key event key codes.
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/events/MouseEvent.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/events/MouseEvent.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,8 @@
     @Native final static public int BUTTON_LEFT     = 212;
     @Native final static public int BUTTON_RIGHT    = 213;
     @Native final static public int BUTTON_OTHER    = 214;
+    @Native final static public int BUTTON_BACK     = 215;
+    @Native final static public int BUTTON_FORWARD  = 216;
 
     @Native final static public int DOWN            = 221;
     @Native final static public int UP              = 222;
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/GlassRobot.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/GlassRobot.java	Fri Jan 11 07:51:13 2019 -0800
@@ -44,6 +44,8 @@
     @Native public static final int MOUSE_LEFT_BTN    = 1 << 0;
     @Native public static final int MOUSE_RIGHT_BTN   = 1 << 1;
     @Native public static final int MOUSE_MIDDLE_BTN  = 1 << 2;
+    @Native public static final int MOUSE_BACK_BTN    = 1 << 3;
+    @Native public static final int MOUSE_FORWARD_BTN = 1 << 4;
 
     /**
      * Initializes any state necessary for this {@code Robot}. Called by
@@ -247,6 +249,8 @@
                 case PRIMARY: ret |= MOUSE_LEFT_BTN; break;
                 case SECONDARY: ret |= MOUSE_RIGHT_BTN; break;
                 case MIDDLE: ret |= MOUSE_MIDDLE_BTN; break;
+                case BACK: ret |= MOUSE_BACK_BTN; break;
+                case FORWARD: ret |= MOUSE_FORWARD_BTN; break;
                 default: throw new IllegalArgumentException("MouseButton: " + button + " not supported by Robot");
             }
         }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Timer.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Timer.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,8 @@
     protected abstract long _start(Runnable runnable);
     protected abstract long _start(Runnable runnable, int period);
     protected abstract void _stop(long timer);
+    protected abstract void _pause(long timer);
+    protected abstract void _resume(long timer);
 
     /**
      * Constructs a new timer.
@@ -133,6 +135,27 @@
     }
 
     /**
+     * Pauses the timer. See JDK-8189926.
+     * Timer is paused only from the timer thread.
+     */
+    public synchronized void pause() {
+        if (ptr != 0L) {
+            _pause(ptr);
+        }
+    }
+
+    /**
+     * Resumes the timer. See JDK-8189926
+     * Timer can get resumed from different threads.
+     */
+    public synchronized void resume() {
+        if (ptr != 0L) {
+            _resume(ptr);
+        }
+    }
+
+
+    /**
      * Returns true if the timer is currently running
      * (convenience API: might not need it)
      */
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkTimer.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkTimer.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,4 +42,7 @@
     @Override
     protected native void _stop(long timer);
 
+    @Override protected void _pause(long timer) {}
+    @Override protected void _resume(long timer) {}
+
 }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosTimer.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/ios/IosTimer.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,8 @@
     }
 
     @Override native protected long _start(Runnable runnable);
+    @Override protected void _pause(long timer) {}
+    @Override protected void _resume(long timer) {}
 
     native protected void _stopVsyncTimer(long timer);
 
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacTimer.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/mac/MacTimer.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,6 +60,8 @@
     @Override native protected long _start(Runnable runnable);
     @Override native protected long _start(Runnable runnable, int period);
     @Override native protected void _stop(long timer);
+    @Override native protected void _pause(long timer);
+    @Override native protected void _resume(long timer);
     native private static void _initIDs();
 }
 
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/LinuxMouseProcessor.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/LinuxMouseProcessor.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -127,6 +127,10 @@
                 return MouseEvent.BUTTON_OTHER;
             case LinuxInput.BTN_RIGHT:
                 return MouseEvent.BUTTON_RIGHT;
+            case LinuxInput.BTN_BACK:
+                return MouseEvent.BUTTON_BACK;
+            case LinuxInput.BTN_FORWARD:
+                return MouseEvent.BUTTON_FORWARD;
             default:
                 return -1;
         }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleRobot.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleRobot.java	Fri Jan 11 07:51:13 2019 -0800
@@ -100,6 +100,20 @@
                         state.releaseButton(MouseEvent.BUTTON_OTHER);
                     }
                     break;
+                case BACK:
+                    if (press) {
+                        state.pressButton(MouseEvent.BUTTON_BACK);
+                    } else {
+                        state.releaseButton(MouseEvent.BUTTON_BACK);
+                    }
+                    break;
+                case FORWARD:
+                    if (press) {
+                        state.pressButton(MouseEvent.BUTTON_FORWARD);
+                    } else {
+                        state.releaseButton(MouseEvent.BUTTON_FORWARD);
+                    }
+                    break;
                 default: throw new IllegalArgumentException("MouseButton: " + button +
                         " not supported by Monocle Robot");
             }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleTimer.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleTimer.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,5 +73,8 @@
             task = null;
         }
     }
+
+    @Override protected void _pause(long timer) {}
+    @Override protected void _resume(long timer) {}
 }
 
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleWindow.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MonocleWindow.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MouseState.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/MouseState.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -115,6 +115,12 @@
                 case MouseEvent.BUTTON_RIGHT:
                     modifiers |= KeyEvent.MODIFIER_BUTTON_SECONDARY;
                     break;
+                case MouseEvent.BUTTON_BACK:
+                    modifiers |= KeyEvent.MODIFIER_BUTTON_BACK;
+                    break;
+                case MouseEvent.BUTTON_FORWARD:
+                    modifiers |= KeyEvent.MODIFIER_BUTTON_FORWARD;
+                    break;
             }
         }
         return modifiers;
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/VNCScreen.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/VNCScreen.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -275,6 +275,7 @@
                             final MouseState state = new MouseState();
                             state.setX(x);
                             state.setY(y);
+                            // These values are from RFC 6143 Section 7.5.5.
                             if (buttons.get(0)) {
                                 state.pressButton(MouseEvent.BUTTON_LEFT);
                             }
@@ -284,6 +285,20 @@
                             if (buttons.get(2)) {
                                 state.pressButton(MouseEvent.BUTTON_RIGHT);
                             }
+                            if (buttons.get(3)) {
+                                state.setWheel(MouseState.WHEEL_UP);
+                            }
+                            if (buttons.get(4)) {
+                                state.setWheel(MouseState.WHEEL_DOWN);
+                            }
+                            // TODO: Buttons from here on are not officially mentioned in the docs, can someone confirm
+                            // on a real device?
+                            if (buttons.get(5)) {
+                                state.pressButton(MouseEvent.BUTTON_BACK);
+                            }
+                            if (buttons.get(6)) {
+                                state.pressButton(MouseEvent.BUTTON_FORWARD);
+                            }
                             Platform.runLater(() -> MouseInput.getInstance().setState(state, false));
                             break;
                         }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/X.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/X.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -85,6 +85,10 @@
     static final int Button3 = 3;
     static final int Button4 = 4;
     static final int Button5 = 5;
+    // 4th button (aka browser backward button).
+    static final int Button8 = 8;
+    // 5th button (aka browser forward button).
+    static final int Button9 = 9;
 
     static final long _NET_WM_STATE_REMOVE = 0;
     static final long _NET_WM_STATE_ADD = 1;
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/X11InputDeviceRegistry.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/X11InputDeviceRegistry.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -178,6 +178,8 @@
             case X.Button1: return MouseEvent.BUTTON_LEFT;
             case X.Button2: return MouseEvent.BUTTON_OTHER;
             case X.Button3: return MouseEvent.BUTTON_RIGHT;
+            case X.Button8: return MouseEvent.BUTTON_BACK;
+            case X.Button9: return MouseEvent.BUTTON_FORWARD;
             default: return MouseEvent.BUTTON_NONE;
         }
     }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinTimer.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinTimer.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,5 +61,7 @@
     }
     @Override native protected long _start(Runnable runnable, int period);
     @Override native protected void _stop(long timer);
+    @Override protected void _pause(long timer) {}
+    @Override protected void _resume(long timer) {}
 }
 
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/AbstractEvents.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/AbstractEvents.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,8 @@
     public final static int MOUSEEVENT_PRIMARY_BUTTON = 1;
     public final static int MOUSEEVENT_SECONDARY_BUTTON = 2;
     public final static int MOUSEEVENT_MIDDLE_BUTTON = 4;
+    public final static int MOUSEEVENT_BACK_BUTTON = 8;
+    public final static int MOUSEEVENT_FORWARD_BUTTON = 16;
 
     public final static int KEYEVENT_PRESSED = 0;
     public final static int KEYEVENT_RELEASED = 1;
@@ -118,6 +120,10 @@
                 return MouseButton.SECONDARY;
             case MOUSEEVENT_MIDDLE_BUTTON:
                 return MouseButton.MIDDLE;
+            case MOUSEEVENT_BACK_BUTTON:
+                return MouseButton.BACK;
+            case MOUSEEVENT_FORWARD_BUTTON:
+                return MouseButton.FORWARD;
         }
         // Should never reach here
         return MouseButton.NONE;
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,6 +69,7 @@
      */
     public void mouseEvent(int type, int button,
                            boolean primaryBtnDown, boolean middleBtnDown, boolean secondaryBtnDown,
+                           boolean backBtnDown, boolean forwardBtnDown,
                            int x, int y, int xAbs, int yAbs,
                            boolean shift, boolean ctrl, boolean alt, boolean meta,
                            boolean popupTrigger);
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/iio/common/ImageTools.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/iio/common/ImageTools.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/TKSceneListener.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,8 @@
     public void mouseEvent(EventType<MouseEvent> type, double x, double y, double screenX, double screenY,
                            MouseButton button, boolean popupTrigger, boolean synthesized,
                            boolean shiftDown, boolean controlDown, boolean altDown, boolean metaDown,
-                           boolean primaryDown, boolean middleDown, boolean secondaryDown);
+                           boolean primaryDown, boolean middleDown, boolean secondaryDown,
+                           boolean backDown, boolean forwardDown);
 
     /**
      * Pass a key event to the scene to handle
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -271,6 +271,7 @@
     @Override
     public void mouseEvent(final int type, final int button,
                            final boolean primaryBtnDown, final boolean middleBtnDown, final boolean secondaryBtnDown,
+                           final boolean backBtnDown, final boolean forwardBtnDown,
                            final int x, final int y, final int xAbs, final int yAbs,
                            final boolean shift, final boolean ctrl, final boolean alt, final boolean meta,
                            final boolean popupTrigger)
@@ -287,7 +288,9 @@
                             AbstractEvents.mouseButtonToFXMouseButton(button),
                             popupTrigger, false, // do we know if it's synthesized? RT-20142
                             shift, ctrl, alt, meta,
-                            primaryBtnDown, middleBtnDown, secondaryBtnDown);
+                            primaryBtnDown, middleBtnDown, secondaryBtnDown,
+                            backBtnDown, forwardBtnDown
+                        );
                 return null;
             }, getAccessControlContext());
         });
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassEventUtils.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassEventUtils.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,10 @@
                 return "BUTTON_RIGHT";
             case MouseEvent.BUTTON_OTHER:
                 return "BUTTON_OTHER";
+            case MouseEvent.BUTTON_BACK:
+                return "BUTTON_BACK";
+            case MouseEvent.BUTTON_FORWARD:
+                return "BUTTON_FORWARD";
             case MouseEvent.DOWN:
                 return "DOWN";
             case MouseEvent.UP:
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -283,6 +283,10 @@
                 return MouseButton.SECONDARY;
             case com.sun.glass.events.MouseEvent.BUTTON_OTHER:
                 return MouseButton.MIDDLE;
+            case com.sun.glass.events.MouseEvent.BUTTON_BACK:
+                return MouseButton.BACK;
+            case com.sun.glass.events.MouseEvent.BUTTON_FORWARD:
+                return MouseButton.FORWARD;
             default:
                 return MouseButton.NONE;
         }
@@ -319,6 +323,12 @@
                 case MouseEvent.BUTTON_RIGHT:
                     buttonMask = KeyEvent.MODIFIER_BUTTON_SECONDARY;
                     break;
+                case MouseEvent.BUTTON_BACK:
+                    buttonMask = KeyEvent.MODIFIER_BUTTON_BACK;
+                    break;
+                case MouseEvent.BUTTON_FORWARD:
+                    buttonMask = KeyEvent.MODIFIER_BUTTON_FORWARD;
+                    break;
                 default:
                     buttonMask = 0;
                     break;
@@ -375,6 +385,8 @@
                     boolean primaryButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_PRIMARY) != 0;
                     boolean middleButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_MIDDLE) != 0;
                     boolean secondaryButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_SECONDARY) != 0;
+                    boolean backButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_BACK) != 0;
+                    boolean forwardButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_FORWARD) != 0;
                     final Window w = view.getWindow();
                     double pScaleX, pScaleY, spx, spy, sx, sy;
                     if (w != null) {
@@ -399,7 +411,8 @@
                             sx + (xAbs - spx) / pScaleX, sy + (yAbs - spy) / pScaleY,
                             mouseEventButton(button), isPopupTrigger, isSynthesized,
                             shiftDown, controlDown, altDown, metaDown,
-                            primaryButtonDown, middleButtonDown, secondaryButtonDown);
+                            primaryButtonDown, middleButtonDown, secondaryButtonDown,
+                            backButtonDown, forwardButtonDown);
                 }
             } finally {
                 if (stage != null) {
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/PaintCollector.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/PaintCollector.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -178,6 +178,13 @@
         return hasDirty;
     }
 
+    private final void setDirty(boolean value) {
+        hasDirty = value;
+        if (hasDirty) {
+            QuantumToolkit.getToolkit().requestNextPulse();
+        }
+    }
+
     /**
      * Adds a dirty scene to the PaintCollector for subsequent processing.
      * This method simply makes the PaintCollector aware of this new
@@ -209,7 +216,7 @@
             dirtyScenes.add(scene);
             // Now that we know we have added a scene to dirtyScenes,
             // we should ensure hasDirty is true.
-            hasDirty = true;
+            setDirty(true);
         }
     }
 
@@ -241,7 +248,7 @@
         // Remove the scene
         dirtyScenes.remove(scene);
         // Update hasDirty
-        hasDirty = !dirtyScenes.isEmpty();
+        setDirty(!dirtyScenes.isEmpty());
     }
 
     /**
@@ -361,7 +368,7 @@
         Collections.sort(dirtyScenes, DIRTY_SCENE_SORTER);
 
         // Reset the fields
-        hasDirty = false;
+        setDirty(false);
         needsHint = false;
 
         // If pulse logging is enabled, then we must call renderStart
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java	Fri Jan 11 07:51:13 2019 -0800
@@ -191,9 +191,27 @@
                 return result;
             });
 
+    private class PulseTask {
+        private volatile boolean isRunning;
+        PulseTask(boolean state) {
+            isRunning = state;
+        }
+
+        synchronized void set(boolean state) {
+            isRunning = state;
+            if (isRunning) {
+                resumeTimer();
+            }
+        }
+
+        boolean get() {
+            return isRunning;
+        }
+    }
+
     private AtomicBoolean           toolkitRunning = new AtomicBoolean(false);
-    private AtomicBoolean           animationRunning = new AtomicBoolean(false);
-    private AtomicBoolean           nextPulseRequested = new AtomicBoolean(false);
+    private PulseTask               animationRunning = new PulseTask(false);
+    private PulseTask               nextPulseRequested = new PulseTask(false);
     private AtomicBoolean           pulseRunning = new AtomicBoolean(false);
     private int                     inPulse = 0;
     private CountDownLatch          launchLatch = new CountDownLatch(1);
@@ -201,6 +219,9 @@
     final int                       PULSE_INTERVAL = (int)(TimeUnit.SECONDS.toMillis(1L) / getRefreshRate());
     final int                       FULLSPEED_INTERVAL = 1;     // ms
     boolean                         nativeSystemVsync = false;
+    private long                    firstPauseRequestTime = 0;
+    private boolean                 pauseRequested = false;
+    private static final long       PAUSE_THRESHOLD_DURATION = 250;
     private float                   _maxPixelScale;
     private Runnable                pulseRunnable, userRunnable, timerRunnable;
     private Timer                   pulseTimer = null;
@@ -455,7 +476,7 @@
 
     void postPulse() {
         if (toolkitRunning.get() &&
-            (animationRunning.get() || nextPulseRequested.get() || collector.hasDirty()) &&
+            (animationRunning.get() || nextPulseRequested.get()) &&
             !setPulseRunning()) {
 
             Application.invokeLater(pulseRunnable);
@@ -463,17 +484,39 @@
             if (debug) {
                 System.err.println("QT.postPulse@(" + System.nanoTime() + "): " + pulseString());
             }
+        } else if (!animationRunning.get() && !nextPulseRequested.get() && !pulseRunning.get()) {
+            pauseTimer();
         } else if (debug) {
-            System.err.println("QT.postPulse#(" + System.nanoTime() + ") DROP: " + pulseString());
+            System.err.println("QT.postPulse#(" + System.nanoTime() + "): DROP : " + pulseString());
         }
     }
 
+    private synchronized void pauseTimer() {
+        if (!pauseRequested) {
+            pauseRequested = true;
+            firstPauseRequestTime = System.currentTimeMillis();
+        }
+
+        if (System.currentTimeMillis() - firstPauseRequestTime >= PAUSE_THRESHOLD_DURATION) {
+            pulseTimer.pause();
+            if (debug) {
+                System.err.println("QT.pauseTimer#(" + System.nanoTime() + "): Pausing Timer : " + pulseString());
+            }
+        } else if (debug) {
+            System.err.println("QT.pauseTimer#(" + System.nanoTime() + "): Pause Timer : DROP : " + pulseString());
+        }
+    }
+
+    private synchronized void resumeTimer() {
+        pauseRequested = false;
+        pulseTimer.resume();
+    }
+
     private String pulseString() {
         return ((toolkitRunning.get() ? "T" : "t") +
                 (animationRunning.get() ? "A" : "a") +
                 (pulseRunning.get() ? "P" : "p") +
-                (nextPulseRequested.get() ? "N" : "n") +
-                (collector.hasDirty() ? "D" : "d"));
+                (nextPulseRequested.get() ? "N" : "n"));
     }
 
     private boolean setPulseRunning() {
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/Graphics.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/Graphics.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DContext.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DContext.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Context.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Context.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/impl/BaseContext.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/impl/BaseContext.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/impl/BaseGraphics.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/impl/BaseGraphics.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/impl/ps/BaseShaderContext.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/impl/ps/BaseShaderContext.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/j2d/J2DPrismGraphics.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/j2d/J2DPrismGraphics.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/java/javafx/scene/Scene.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/Scene.java	Fri Jan 11 07:51:13 2019 -0800
@@ -2579,12 +2579,14 @@
         public void mouseEvent(EventType<MouseEvent> type, double x, double y, double screenX, double screenY,
                                MouseButton button, boolean popupTrigger, boolean synthesized,
                                boolean shiftDown, boolean controlDown, boolean altDown, boolean metaDown,
-                               boolean primaryDown, boolean middleDown, boolean secondaryDown)
+                               boolean primaryDown, boolean middleDown, boolean secondaryDown,
+                               boolean backDown, boolean forwardDown)
         {
             MouseEvent mouseEvent = new MouseEvent(type, x, y, screenX, screenY, button,
                     0, // click count will be adjusted by clickGenerator later anyway
                     shiftDown, controlDown, altDown, metaDown,
-                    primaryDown, middleDown, secondaryDown, synthesized, popupTrigger, false, null);
+                    primaryDown, middleDown, secondaryDown, backDown, forwardDown,
+                    synthesized, popupTrigger, false, null);
             processMouseEvent(mouseEvent);
         }
 
@@ -3518,7 +3520,8 @@
                 if (! e.isPrimaryButtonDown()) { counters.get(MouseButton.PRIMARY).clear(); }
                 if (! e.isSecondaryButtonDown()) { counters.get(MouseButton.SECONDARY).clear(); }
                 if (! e.isMiddleButtonDown()) { counters.get(MouseButton.MIDDLE).clear(); }
-
+                if (! e.isBackButtonDown()) { counters.get(MouseButton.BACK).clear(); }
+                if (! e.isForwardButtonDown()) { counters.get(MouseButton.FORWARD).clear(); }
                 cc.applyOut();
                 cc.inc();
                 cc.start(e.getSceneX(), e.getSceneY());
@@ -3530,6 +3533,7 @@
                     cc != null && e.getEventType() != MouseEvent.MOUSE_MOVED ? cc.get() : 0,
                     e.isShiftDown(), e.isControlDown(), e.isAltDown(), e.isMetaDown(),
                     e.isPrimaryButtonDown(), e.isMiddleButtonDown(), e.isSecondaryButtonDown(),
+                    e.isBackButtonDown(), e.isForwardButtonDown(),
                     e.isSynthesized(), e.isPopupTrigger(), still, e.getPickResult());
         }
 
@@ -3560,6 +3564,7 @@
                             cc.get(),
                             e.isShiftDown(), e.isControlDown(), e.isAltDown(), e.isMetaDown(),
                             e.isPrimaryButtonDown(), e.isMiddleButtonDown(), e.isSecondaryButtonDown(),
+                            e.isBackButtonDown(), e.isForwardButtonDown(),
                             e.isSynthesized(), e.isPopupTrigger(), lastPress.isStill(), e.getPickResult());
                     Event.fireEvent(clickedTarget, click);
                 }
@@ -3588,6 +3593,8 @@
         private boolean primaryButtonDown = false;
         private boolean secondaryButtonDown = false;
         private boolean middleButtonDown = false;
+        private boolean backButtonDown = false;
+        private boolean forwardButtonDown = false;
 
         private EventTarget fullPDRSource = null;
         private TargetWrapper fullPDRTmpTargetWrapper = new TargetWrapper();
@@ -3780,7 +3787,8 @@
             boolean gestureStarted = false;
             if (!onPulse) {
                 if (e.getEventType() == MouseEvent.MOUSE_PRESSED) {
-                    if (!(primaryButtonDown || secondaryButtonDown || middleButtonDown)) {
+                    if (!(primaryButtonDown || secondaryButtonDown || middleButtonDown ||
+                            backButtonDown || forwardButtonDown)) {
                         //old gesture ended and new one started
                         gestureStarted = true;
                         if (!PLATFORM_DRAG_GESTURE_INITIATION) {
@@ -3800,6 +3808,8 @@
                 primaryButtonDown = e.isPrimaryButtonDown();
                 secondaryButtonDown = e.isSecondaryButtonDown();
                 middleButtonDown = e.isMiddleButtonDown();
+                backButtonDown = e.isBackButtonDown();
+                forwardButtonDown = e.isForwardButtonDown();
             }
 
             pick(tmpTargetWrapper, e.getSceneX(), e.getSceneY());
@@ -3809,6 +3819,7 @@
                     e.getScreenX(), e.getScreenY(), e.getButton(), e.getClickCount(),
                     e.isShiftDown(), e.isControlDown(), e.isAltDown(), e.isMetaDown(),
                     e.isPrimaryButtonDown(), e.isMiddleButtonDown(), e.isSecondaryButtonDown(),
+                    e.isBackButtonDown(), e.isForwardButtonDown(),
                     e.isSynthesized(), e.isPopupTrigger(), e.isStillSincePress(), res);
             }
 
@@ -3885,7 +3896,8 @@
             }
 
             if (pdrInProgress &&
-                    !(primaryButtonDown || secondaryButtonDown || middleButtonDown)) {
+                    !(primaryButtonDown || secondaryButtonDown || middleButtonDown ||
+                            backButtonDown || forwardButtonDown)) {
                 clearPDREventTargets();
                 exitFullPDR(e);
                 // we need to do new picking in case the originally picked node
--- a/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseButton.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseButton.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,21 @@
     MIDDLE,
 
     /**
-     * Represents seconday (button 3, usually the right) mouse button.
+     * Represents secondary (button 3, usually the right) mouse button.
      */
     SECONDARY,
+
+    /**
+     * Represents back (button 4) mouse button.
+     *
+     * @since 12
+     */
+    BACK,
+
+    /**
+     * Represents forward (button 5) mouse button.
+     *
+     * @since 12
+     */
+    FORWARD;
 }
--- a/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseDragEvent.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseDragEvent.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,40 +130,104 @@
 
     /**
      * Constructs new MouseDragEvent event.
-     * @param source the source of the event. Can be null.
-     * @param target the target of the event. Can be null.
-     * @param eventType The type of the event.
-     * @param x The x with respect to the scene.
-     * @param y The y with respect to the scene.
-     * @param screenX The x coordinate relative to screen.
-     * @param screenY The y coordinate relative to screen.
+     *
+     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
+     * will return {@literal false} for this event
+     *
+     * @param source the source of the event, which can be {@code null}
+     * @param target the target of the event, which can be {@code null}
+     * @param eventType The type of the event
+     * @param x The x with respect to the scene
+     * @param y The y with respect to the scene
+     * @param screenX The x coordinate relative to screen
+     * @param screenY The y coordinate relative to screen
      * @param button the mouse button used
      * @param clickCount number of click counts
-     * @param shiftDown true if shift modifier was pressed.
-     * @param controlDown true if control modifier was pressed.
-     * @param altDown true if alt modifier was pressed.
-     * @param metaDown true if meta modifier was pressed.
-     * @param primaryButtonDown true if primary button was pressed.
-     * @param middleButtonDown true if middle button was pressed.
-     * @param secondaryButtonDown true if secondary button was pressed.
+     * @param shiftDown true if shift modifier was pressed
+     * @param controlDown true if control modifier was pressed
+     * @param altDown true if alt modifier was pressed
+     * @param metaDown true if meta modifier was pressed
+     * @param primaryButtonDown true if primary button was pressed
+     * @param middleButtonDown true if middle button was pressed
+     * @param secondaryButtonDown true if secondary button was pressed
      * @param synthesized if this event was synthesized
      * @param popupTrigger whether this event denotes a popup trigger for current platform
      * @param pickResult pick result. Can be null, in this case a 2D pick result
      *                   without any further values is constructed
      *                   based on the scene coordinates and target
-     * @param gestureSource source object of the ongoing gesture.
+     * @param gestureSource source object of the ongoing gesture
      * @since JavaFX 8.0
      */
-    public MouseDragEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target, @NamedArg("eventType") EventType<MouseDragEvent> eventType,
-            @NamedArg("x") double x, @NamedArg("y") double y, @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
-            @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
-            @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
-            @NamedArg("primaryButtonDown") boolean primaryButtonDown, @NamedArg("middleButtonDown") boolean middleButtonDown, @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
-            @NamedArg("synthesized") boolean synthesized, @NamedArg("popupTrigger") boolean popupTrigger, @NamedArg("pickResult") PickResult pickResult,
-            @NamedArg("gestureSource") Object gestureSource) {
+    public MouseDragEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target,
+                          @NamedArg("eventType") EventType<MouseDragEvent> eventType,
+                          @NamedArg("x") double x, @NamedArg("y") double y,
+                          @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
+                          @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
+                          @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
+                          @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
+                          @NamedArg("primaryButtonDown") boolean primaryButtonDown,
+                          @NamedArg("middleButtonDown") boolean middleButtonDown,
+                          @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
+                          @NamedArg("synthesized") boolean synthesized,
+                          @NamedArg("popupTrigger") boolean popupTrigger,
+                          @NamedArg("pickResult") PickResult pickResult,
+                          @NamedArg("gestureSource") Object gestureSource) {
+        this(source, target, eventType, x, y, screenX, screenY, button,
+                clickCount, shiftDown, controlDown, altDown, metaDown,
+                primaryButtonDown, middleButtonDown, secondaryButtonDown,
+                false, false,
+                synthesized, popupTrigger, pickResult, gestureSource);
+    }
+
+    /**
+     * Constructs new MouseDragEvent event.
+     *
+     * @param source the source of the event, which can be {@code null}
+     * @param target the target of the event, which can be {@code null}
+     * @param eventType The type of the event
+     * @param x The x with respect to the scene
+     * @param y The y with respect to the scene
+     * @param screenX The x coordinate relative to screen
+     * @param screenY The y coordinate relative to screen
+     * @param button the mouse button used
+     * @param clickCount number of click counts
+     * @param shiftDown true if shift modifier was pressed
+     * @param controlDown true if control modifier was pressed
+     * @param altDown true if alt modifier was pressed
+     * @param metaDown true if meta modifier was pressed
+     * @param primaryButtonDown true if primary button was pressed
+     * @param middleButtonDown true if middle button was pressed
+     * @param secondaryButtonDown true if secondary button was pressed
+     * @param backButtonDown true if back button was pressed
+     * @param forwardButtonDown true if forward button was pressed
+     * @param synthesized if this event was synthesized
+     * @param popupTrigger whether this event denotes a popup trigger for current platform
+     * @param pickResult pick result. Can be null, in this case a 2D pick result
+     *                   without any further values is constructed
+     *                   based on the scene coordinates and target
+     * @param gestureSource source object of the ongoing gesture
+     * @since 12
+     */
+    public MouseDragEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target,
+                          @NamedArg("eventType") EventType<MouseDragEvent> eventType,
+                          @NamedArg("x") double x, @NamedArg("y") double y,
+                          @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
+                          @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
+                          @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
+                          @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
+                          @NamedArg("primaryButtonDown") boolean primaryButtonDown,
+                          @NamedArg("middleButtonDown") boolean middleButtonDown,
+                          @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
+                          @NamedArg("backButtonDown") boolean backButtonDown,
+                          @NamedArg("forwardButtonDown") boolean forwardButtonDown,
+                          @NamedArg("synthesized") boolean synthesized,
+                          @NamedArg("popupTrigger") boolean popupTrigger,
+                          @NamedArg("pickResult") PickResult pickResult,
+                          @NamedArg("gestureSource") Object gestureSource) {
         super(source, target, eventType, x, y, screenX, screenY, button,
                 clickCount, shiftDown, controlDown, altDown, metaDown,
                 primaryButtonDown, middleButtonDown, secondaryButtonDown,
+                backButtonDown, forwardButtonDown,
                 synthesized, popupTrigger, false, pickResult);
         this.gestureSource = gestureSource;
     }
@@ -171,35 +235,43 @@
     /**
      * Constructs new MouseDragEvent event with null source and target.
      *
-     * @param eventType The type of the event.
-     * @param x The x with respect to the scene.
-     * @param y The y with respect to the scene.
-     * @param screenX The x coordinate relative to screen.
-     * @param screenY The y coordinate relative to screen.
+     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
+     * will return {@literal false} for this event.
+     *
+     * @param eventType The type of the event
+     * @param x The x with respect to the scene
+     * @param y The y with respect to the scene
+     * @param screenX The x coordinate relative to screen
+     * @param screenY The y coordinate relative to screen
      * @param button the mouse button used
      * @param clickCount number of click counts
-     * @param shiftDown true if shift modifier was pressed.
-     * @param controlDown true if control modifier was pressed.
-     * @param altDown true if alt modifier was pressed.
-     * @param metaDown true if meta modifier was pressed.
-     * @param primaryButtonDown true if primary button was pressed.
-     * @param middleButtonDown true if middle button was pressed.
-     * @param secondaryButtonDown true if secondary button was pressed.
+     * @param shiftDown true if shift modifier was pressed
+     * @param controlDown true if control modifier was pressed
+     * @param altDown true if alt modifier was pressed
+     * @param metaDown true if meta modifier was pressed
+     * @param primaryButtonDown true if primary button was pressed
+     * @param middleButtonDown true if middle button was pressed
+     * @param secondaryButtonDown true if secondary button was pressed
      * @param synthesized if this event was synthesized
      * @param popupTrigger whether this event denotes a popup trigger for current platform
      * @param pickResult pick result. Can be null, in this case a 2D pick result
      *                   without any further values is constructed
      *                   based on the scene coordinates
-     * @param gestureSource source object of the ongoing gesture.
+     * @param gestureSource source object of the ongoing gesture
      * @since JavaFX 8.0
      */
     public MouseDragEvent(@NamedArg("eventType") EventType<MouseDragEvent> eventType,
-            @NamedArg("x") double x, @NamedArg("y") double y, @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
-            @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
-            @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
-            @NamedArg("primaryButtonDown") boolean primaryButtonDown, @NamedArg("middleButtonDown") boolean middleButtonDown, @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
-            @NamedArg("synthesized") boolean synthesized, @NamedArg("popupTrigger") boolean popupTrigger, @NamedArg("pickResult") PickResult pickResult,
-            @NamedArg("gestureSource") Object gestureSource) {
+                          @NamedArg("x") double x, @NamedArg("y") double y,
+                          @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
+                          @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
+                          @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
+                          @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
+                          @NamedArg("primaryButtonDown") boolean primaryButtonDown,
+                          @NamedArg("middleButtonDown") boolean middleButtonDown,
+                          @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
+                          @NamedArg("synthesized") boolean synthesized, @NamedArg("popupTrigger") boolean popupTrigger,
+                          @NamedArg("pickResult") PickResult pickResult,
+                          @NamedArg("gestureSource") Object gestureSource) {
         this(null, null, eventType, x, y, screenX, screenY, button, clickCount,
                 shiftDown, controlDown, altDown, metaDown, primaryButtonDown,
                 middleButtonDown, secondaryButtonDown, synthesized, popupTrigger,
@@ -250,6 +322,12 @@
         if (isSecondaryButtonDown()) {
             sb.append(", secondaryButtonDown");
         }
+        if (isBackButtonDown()) {
+            sb.append(", backButtonDown");
+        }
+        if (isForwardButtonDown()) {
+            sb.append(", forwardButtonDown");
+        }
         if (isShiftDown()) {
             sb.append(", shiftDown");
         }
--- a/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseEvent.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseEvent.java	Fri Jan 11 07:51:13 2019 -0800
@@ -297,6 +297,10 @@
 
     /**
      * Constructs new MouseEvent event with null source and target.
+     *
+     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
+     * will return {@literal false} for this event.
+     *
      * @param eventType The type of the event.
      * @param x The x with respect to the scene.
      * @param y The y with respect to the scene.
@@ -343,7 +347,63 @@
     }
 
     /**
+     * Constructs new MouseEvent event with null source and target.
+     * @param eventType The type of the event.
+     * @param x The x with respect to the scene.
+     * @param y The y with respect to the scene.
+     * @param screenX The x coordinate relative to screen.
+     * @param screenY The y coordinate relative to screen.
+     * @param button the mouse button used
+     * @param clickCount number of click counts
+     * @param shiftDown true if shift modifier was pressed.
+     * @param controlDown true if control modifier was pressed.
+     * @param altDown true if alt modifier was pressed.
+     * @param metaDown true if meta modifier was pressed.
+     * @param primaryButtonDown true if primary button was pressed.
+     * @param middleButtonDown true if middle button was pressed.
+     * @param secondaryButtonDown true if secondary button was pressed.
+     * @param backButtonDown true if back button was pressed.
+     * @param forwardButtonDown true if forward button was pressed
+     * @param synthesized if this event was synthesized
+     * @param popupTrigger whether this event denotes a popup trigger for current platform
+     * @param stillSincePress see {@link #isStillSincePress() }
+     * @param pickResult pick result. Can be null, in this case a 2D pick result
+     *                   without any further values is constructed
+     *                   based on the scene coordinates
+     * @since 12
+     */
+    public MouseEvent(
+            @NamedArg("eventType") EventType<? extends MouseEvent> eventType,
+            @NamedArg("x") double x, @NamedArg("y") double y,
+            @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
+            @NamedArg("button") MouseButton button,
+            @NamedArg("clickCount") int clickCount,
+            @NamedArg("shiftDown") boolean shiftDown,
+            @NamedArg("controlDown") boolean controlDown,
+            @NamedArg("altDown") boolean altDown,
+            @NamedArg("metaDown") boolean metaDown,
+            @NamedArg("primaryButtonDown") boolean primaryButtonDown,
+            @NamedArg("middleButtonDown") boolean middleButtonDown,
+            @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
+            @NamedArg("backButtonDown") boolean backButtonDown,
+            @NamedArg("forwardButtonDown") boolean forwardButtonDown,
+            @NamedArg("synthesized") boolean synthesized,
+            @NamedArg("popupTrigger") boolean popupTrigger,
+            @NamedArg("stillSincePress") boolean stillSincePress,
+            @NamedArg("pickResult") PickResult pickResult) {
+        this(null, null, eventType, x, y, screenX, screenY, button, clickCount,
+                shiftDown, controlDown, altDown, metaDown,
+                primaryButtonDown, middleButtonDown, secondaryButtonDown,
+                backButtonDown, forwardButtonDown,
+                synthesized, popupTrigger, stillSincePress, pickResult);
+    }
+
+    /**
      * Constructs new MouseEvent event.
+     *
+     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
+     * will return {@literal false} for this event.
+     *
      * @param source the source of the event. Can be null.
      * @param target the target of the event. Can be null.
      * @param eventType The type of the event.
@@ -385,6 +445,59 @@
             @NamedArg("popupTrigger") boolean popupTrigger,
             @NamedArg("stillSincePress") boolean stillSincePress,
             @NamedArg("pickResult") PickResult pickResult) {
+        this(source, target, eventType, x, y, screenX, screenY, button, clickCount,
+                shiftDown, controlDown, altDown, metaDown,
+                primaryButtonDown, middleButtonDown, secondaryButtonDown, false, false,
+                synthesized, popupTrigger, stillSincePress, pickResult);
+    }
+
+    /**
+     * Constructs new MouseEvent event.
+     * @param source the source of the event. Can be null.
+     * @param target the target of the event. Can be null.
+     * @param eventType The type of the event.
+     * @param x The x with respect to the source. Should be in scene coordinates if source == null or source is not a Node.
+     * @param y The y with respect to the source. Should be in scene coordinates if source == null or source is not a Node.
+     * @param screenX The x coordinate relative to screen.
+     * @param screenY The y coordinate relative to screen.
+     * @param button the mouse button used
+     * @param clickCount number of click counts
+     * @param shiftDown true if shift modifier was pressed.
+     * @param controlDown true if control modifier was pressed.
+     * @param altDown true if alt modifier was pressed.
+     * @param metaDown true if meta modifier was pressed.
+     * @param primaryButtonDown true if primary button was pressed.
+     * @param middleButtonDown true if middle button was pressed.
+     * @param secondaryButtonDown true if secondary button was pressed.
+     * @param backButtonDown true if the back button was pressed
+     * @param forwardButtonDown true if the forward button was pressed
+     * @param synthesized if this event was synthesized
+     * @param popupTrigger whether this event denotes a popup trigger for current platform
+     * @param stillSincePress see {@link #isStillSincePress() }
+     * @param pickResult pick result. Can be null, in this case a 2D pick result
+     *                   without any further values is constructed
+     *                   based on the scene coordinates and target
+     * @since 12
+     */
+    public MouseEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target,
+                      @NamedArg("eventType") EventType<? extends MouseEvent> eventType,
+                      @NamedArg("x") double x, @NamedArg("y") double y,
+                      @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
+                      @NamedArg("button") MouseButton button,
+                      @NamedArg("clickCount") int clickCount,
+                      @NamedArg("shiftDown") boolean shiftDown,
+                      @NamedArg("controlDown") boolean controlDown,
+                      @NamedArg("altDown") boolean altDown,
+                      @NamedArg("metaDown") boolean metaDown,
+                      @NamedArg("primaryButtonDown") boolean primaryButtonDown,
+                      @NamedArg("middleButtonDown") boolean middleButtonDown,
+                      @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
+                      @NamedArg("backButtonDown") boolean backButtonDown,
+                      @NamedArg("forwardButtonDown") boolean forwardButtonDown,
+                      @NamedArg("synthesized") boolean synthesized,
+                      @NamedArg("popupTrigger") boolean popupTrigger,
+                      @NamedArg("stillSincePress") boolean stillSincePress,
+                      @NamedArg("pickResult") PickResult pickResult) {
         super(source, target, eventType);
         this.x = x;
         this.y = y;
@@ -401,6 +514,8 @@
         this.primaryButtonDown = primaryButtonDown;
         this.middleButtonDown = middleButtonDown;
         this.secondaryButtonDown = secondaryButtonDown;
+        this.backButtonDown = backButtonDown;
+        this.forwardButtonDown = forwardButtonDown;
         this.synthesized = synthesized;
         this.stillSincePress = stillSincePress;
         this.popupTrigger = popupTrigger;
@@ -434,7 +549,7 @@
                 type, e.sceneX, e.sceneY, e.screenX, e.screenY,
                 e.button, e.clickCount, e.shiftDown, e.controlDown,
                 e.altDown, e.metaDown, e.primaryButtonDown, e.middleButtonDown,
-                e.secondaryButtonDown, e.synthesized, e.popupTrigger,
+                e.secondaryButtonDown, e.backButtonDown, e.forwardButtonDown, e.synthesized, e.popupTrigger,
                 pickResult, gestureSource);
         ev.recomputeCoordinatesToSource(e, source);
         return ev;
@@ -847,6 +962,52 @@
     }
 
     /**
+     * {@code true} if back button (button 4) is currently pressed.
+     * Note that this is different from the {@link #getButton() button} variable in
+     * that the {@code button} variable indicates which button press was
+     * responsible for this event while this variable indicates whether the
+     * back button is depressed.
+     */
+    private final boolean backButtonDown;
+
+    /**
+     * Returns {@code true} if back button (button 4)
+     * is currently pressed. Note that this is different from the
+     * {@code getButton()} method that indicates which button press was
+     * responsible for this event while this method indicates whether the
+     * back button is depressed.
+     *
+     * @return {@code true} if back button (button 4) is currently pressed
+     * @since 12
+     */
+    public final boolean isBackButtonDown() {
+        return backButtonDown;
+    }
+
+    /**
+     * {@code true} if forward button (button 5) is currently pressed.
+     * Note that this is different from the {@link #getButton() button} variable in
+     * that the {@code button} variable indicates which button press was
+     * responsible for this event while this variable indicates whether the
+     * forward button is depressed.
+     */
+    private final boolean forwardButtonDown;
+
+    /**
+     * Returns {@code true} if forward button (button 5)
+     * is currently pressed. Note that this is different from the
+     * {@code getButton()} method that indicates which button press was
+     * responsible for this event while this method indicates whether the
+     * back button is depressed.
+     *
+     * @return {@code true} if forward button (button 5) is currently pressed
+     * @since 12
+     */
+    public final boolean isForwardButtonDown() {
+        return forwardButtonDown;
+    }
+
+    /**
      * Returns a string representation of this {@code MouseEvent} object.
      * @return a string representation of this {@code MouseEvent} object.
      */
@@ -876,6 +1037,12 @@
         if (isSecondaryButtonDown()) {
             sb.append(", secondaryButtonDown");
         }
+        if (isBackButtonDown()) {
+            sb.append(", backButtonDown");
+        }
+        if (isForwardButtonDown()) {
+            sb.append(", forwardButtonDown");
+        }
         if (isShiftDown()) {
             sb.append(", shiftDown");
         }
--- a/modules/javafx.graphics/src/main/native-font/freetype.c	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-font/freetype.c	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/native-glass/gtk/GlassRobot.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/gtk/GlassRobot.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -38,6 +38,8 @@
 #include "glass_key.h"
 #include "glass_screen.h"
 
+#define MOUSE_BACK_BTN 8
+#define MOUSE_FORWARD_BTN 9
 
 static void checkXTest(JNIEnv* env) {
     int32_t major_opcode, first_event, first_error;
@@ -152,6 +154,12 @@
     if (buttons & com_sun_glass_ui_GlassRobot_MOUSE_RIGHT_BTN) {
         XTestFakeButtonEvent(xdisplay, 3, press, CurrentTime);
     }
+    if (buttons & com_sun_glass_ui_GlassRobot_MOUSE_BACK_BTN) {
+        XTestFakeButtonEvent(xdisplay, MOUSE_BACK_BTN, press, CurrentTime);
+    }
+    if (buttons & com_sun_glass_ui_GlassRobot_MOUSE_FORWARD_BTN) {
+        XTestFakeButtonEvent(xdisplay, MOUSE_FORWARD_BTN, press, CurrentTime);
+    }
 
     XSync(xdisplay, False);
 }
--- a/modules/javafx.graphics/src/main/native-glass/gtk/glass_key.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/gtk/glass_key.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -293,6 +293,8 @@
     glass_mask |= (mask & GDK_BUTTON1_MASK) ? com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_PRIMARY : 0;
     glass_mask |= (mask & GDK_BUTTON2_MASK) ? com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_MIDDLE : 0;
     glass_mask |= (mask & GDK_BUTTON3_MASK) ? com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_SECONDARY : 0;
+    glass_mask |= (mask & GDK_BUTTON4_MASK) ? com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_BACK : 0;
+    glass_mask |= (mask & GDK_BUTTON5_MASK) ? com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_FORWARD : 0;
     glass_mask |= (mask & GDK_SUPER_MASK) ? com_sun_glass_events_KeyEvent_MODIFIER_WINDOWS : 0; // XXX: is this OK?
 
     return glass_mask;
--- a/modules/javafx.graphics/src/main/native-glass/gtk/glass_window.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/gtk/glass_window.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -48,6 +48,9 @@
 
 #include <algorithm>
 
+#define MOUSE_BACK_BTN 8
+#define MOUSE_FORWARD_BTN 9
+
 WindowContext * WindowContextBase::sm_grab_window = NULL;
 WindowContext * WindowContextBase::sm_mouse_drag_window = NULL;
 
@@ -241,6 +244,10 @@
             return com_sun_glass_events_MouseEvent_BUTTON_OTHER;
         case 3:
             return com_sun_glass_events_MouseEvent_BUTTON_RIGHT;
+        case MOUSE_BACK_BTN:
+            return com_sun_glass_events_MouseEvent_BUTTON_BACK;
+        case MOUSE_FORWARD_BTN:
+            return com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
         default:
             // Other buttons are not supported by quantum and are not reported by other platforms
             return com_sun_glass_events_MouseEvent_BUTTON_NONE;
@@ -265,6 +272,12 @@
         case 3:
             mask = GDK_BUTTON3_MASK;
             break;
+        case MOUSE_BACK_BTN:
+            mask = GDK_BUTTON4_MASK;
+            break;
+        case MOUSE_FORWARD_BTN:
+            mask = GDK_BUTTON5_MASK;
+            break;
     }
 
     if (press) {
@@ -290,9 +303,17 @@
     // We can grab mouse pointer for these needs.
     if (press) {
         grab_mouse_drag_focus();
-    } else if ((event->state & MOUSE_BUTTONS_MASK)
+    } else {
+        if ((event->state & MOUSE_BUTTONS_MASK)
             && !(state & MOUSE_BUTTONS_MASK)) { // all buttons released
-        ungrab_mouse_drag_focus();
+            ungrab_mouse_drag_focus();
+        } else if (event->button == 8 || event->button == 9) {
+            // GDK X backend interprets button press events for buttons 4-7 as
+            // scroll events so GDK_BUTTON4_MASK and GDK_BUTTON5_MASK will never
+            // be set on the event->state from GDK. Thus we cannot check if all
+            // buttons have been released in the usual way (as above).
+            ungrab_mouse_drag_focus();
+        }
     }
 
     jint button = gtk_button_number_to_mouse_button(event->button);
@@ -323,7 +344,9 @@
     jint isDrag = glass_modifier & (
             com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_PRIMARY |
             com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_MIDDLE |
-            com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_SECONDARY);
+            com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_SECONDARY |
+            com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_BACK |
+            com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_FORWARD);
     jint button = com_sun_glass_events_MouseEvent_BUTTON_NONE;
 
     if (glass_modifier & com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_PRIMARY) {
@@ -332,6 +355,10 @@
         button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
     } else if (glass_modifier & com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_SECONDARY) {
         button = com_sun_glass_events_MouseEvent_BUTTON_RIGHT;
+    } else if (glass_modifier & com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_BACK) {
+        button = com_sun_glass_events_MouseEvent_BUTTON_BACK;
+    } else if (glass_modifier & com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_FORWARD) {
+        button = com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
     }
 
     if (jview) {
--- a/modules/javafx.graphics/src/main/native-glass/ios/GlassViewDelegate.m	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/ios/GlassViewDelegate.m	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -501,6 +501,12 @@
             case com_sun_glass_events_MouseEvent_BUTTON_OTHER:
                 modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_MIDDLE;
                 break;
+            case com_sun_glass_events_MouseEvent_BUTTON_BACK:
+                modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_BACK;
+                break;
+            case com_sun_glass_events_MouseEvent_BUTTON_FORWARD:
+                modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_FORWARD;
+                break;
         }
     }
 
--- a/modules/javafx.graphics/src/main/native-glass/mac/GlassKey.m	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/mac/GlassKey.m	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -218,6 +218,12 @@
     if (buttons & (1 << 2)) {
         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_MIDDLE;
     }
+    if (buttons & (1 << 3)) {
+        jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_BACK;
+    }
+    if (buttons & (1 << 4)) {
+        jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_FORWARD;
+    }
     return jModifiers;
 }
 
--- a/modules/javafx.graphics/src/main/native-glass/mac/GlassTimer.h	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/mac/GlassTimer.h	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
 
     pthread_t   _thread;
     BOOL        _running;
+    BOOL        _paused;
 
     int64_t     _period;
     JNIEnv*     _env;
--- a/modules/javafx.graphics/src/main/native-glass/mac/GlassTimer.m	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/mac/GlassTimer.m	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,7 @@
             while (timer->_running == YES)
             {
                 int64_t now = getTimeMicroseconds();
+                if (timer->_paused == NO)
                 {
                     if (timer->_runnable != NULL)
                     {
@@ -108,6 +109,8 @@
     return NULL;
 }
 
+JavaVMAttachArgs attachArgs = {JNI_VERSION_1_2, "PulseTimer-CVDisplayLink thread", NULL};
+
 CVReturn CVOutputCallback(CVDisplayLinkRef displayLink,
                           const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime,
                           CVOptionFlags flagsIn, CVOptionFlags *flagsOut,
@@ -119,27 +122,33 @@
     {
         GlassTimer *timer = (GlassTimer*)displayLinkContext;
 
-        // Attach the thread every time.  Cocoa changes the thread when a new
-        // display resolution is selected so we need to make sure that we are
-        // able to call into Java.  Attaching the same thread multiple times
-        // does nothing.
-        jint error = (*MAIN_JVM)->AttachCurrentThreadAsDaemon(MAIN_JVM, (void **)&timer->_env, NULL);
-        if (error == 0)
+        // CVDisplayLinkStart() starts a new CVDisplayLink thread. This thread
+        // should be attached to JVM. Cocoa changes the thread when a new display
+        // resolution is selected so we need to make sure that we are able to
+        // call into Java. Attaching the same thread multiple times does nothing.
+        // As the thread is attached as a daemon, it will not stop Java from exiting.
+
+        jint ret = (*MAIN_JVM)->AttachCurrentThreadAsDaemon(MAIN_JVM, (void **)&timer->_env, (void*)&attachArgs);
+        if (ret == 0)
         {
             if (timer->_runnable != NULL)
             {
                 (*timer->_env)->CallVoidMethod(timer->_env, timer->_runnable, jRunnableRun);
             }
 
-              // Do not detach the thread - continuously attaching and detaching a thread
-              // kills some debuggers making it impossible to step through Prism.  Since
-              // the thread is attached as a daemon, it will not stop Java from exiting.
-//            error = (*MAIN_JVM)->DetachCurrentThread(MAIN_JVM);
-//            if (error != JNI_OK) {
-//                NSLog(@"ERROR: Glass could not detach CVDisplayLink _thread to VM, result:%d\n", (int)error);
-//            }
+            if (timer->_paused == YES)
+            {
+                // _1pause() calls CVDisplayLinkStop() on current CVDisplayLink thread, which
+                // in turn stops the thread. Hence the thread should be detached.
+
+                ret = (*MAIN_JVM)->DetachCurrentThread(MAIN_JVM);
+                if (ret != JNI_OK)
+                {
+                    NSLog(@"ERROR: CVOutputCallback(): Glass could not detach CVDisplayLink _thread to VM, result:%d\n", (int)ret);
+                }
+            }
         } else {
-            NSLog(@"ERROR: Glass could not attach CVDisplayLink _thread to VM, result:%d\n", (int)error);
+            NSLog(@"ERROR: Glass could not attach CVDisplayLink _thread to VM, result:%d\n", (int)ret);
         }
     }
 
@@ -155,6 +164,7 @@
     self = [super init];
     if (self != nil)
     {
+        self->_paused = NO;
         CVReturn err = CVDisplayLinkSetOutputCallback(GlassDisplayLink, &CVOutputCallback, self);
         if (err != kCVReturnSuccess)
         {
@@ -175,6 +185,7 @@
     {
         self->_thread = NULL;
         self->_running = NO;
+        self->_paused = NO;
         self->_runnable = NULL;
         self->_period = (1000 * period); // ms --> us
 
@@ -290,6 +301,91 @@
 
 /*
  * Class:     com_sun_glass_ui_mac_MacTimer
+ * Method:    _pause
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacTimer__1pause
+(JNIEnv *env, jclass cls, jlong jTimerPtr)
+{
+    LOG("Java_com_sun_glass_ui_mac_MacTimer__1pause");
+
+    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
+    GLASS_POOL_ENTER;
+    {
+        GlassTimer *timer = (GlassTimer*)jlong_to_ptr(jTimerPtr);
+        if (timer->_period == 0)
+        {
+            // Stop the CVDisplayLink thread. There is no API to pause the CVDisplayLink
+            // thread. CVDisplayLinkStop() stops the CVDisplayLink thread.
+            if (GlassDisplayLink != NULL && CVDisplayLinkIsRunning(GlassDisplayLink))
+            {
+                CVReturn ret = CVDisplayLinkStop(GlassDisplayLink);
+                if (ret == kCVReturnSuccess)
+                {
+                    timer->_paused = YES;
+                }
+                else
+                {
+                    NSLog(@"ERROR: MacTimer__1pause(): CVDisplayLinkStop() error: %d\n", (int)ret);
+                }
+            }
+            else
+            {
+                NSLog(@"ERROR: MacTimer__1pause(): GlassDisplayLink is NULL or GlassDisplayLink is not running.");
+            }
+        }
+        else
+        {
+            timer->_paused = YES;
+        }
+    }
+    GLASS_POOL_EXIT;
+    GLASS_CHECK_EXCEPTION(env);
+}
+
+
+/*
+ * Class:     com_sun_glass_ui_mac_MacTimer
+ * Method:    _resume
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacTimer__1resume
+(JNIEnv *env, jclass cls, jlong jTimerPtr)
+{
+    LOG("Java_com_sun_glass_ui_mac_MacTimer__1resume");
+
+    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
+    GLASS_POOL_ENTER;
+    {
+        GlassTimer *timer = (GlassTimer*)jlong_to_ptr(jTimerPtr);
+        if (timer->_period == 0)
+        {
+            // Start the CVDisplayLink thread. There is no API to resume the CVDisplayLink
+            // thread. CVDisplayLinkStart() starts a new CVDisplayLink thread.
+            if (GlassDisplayLink != NULL && !CVDisplayLinkIsRunning(GlassDisplayLink))
+            {
+                CVReturn ret = CVDisplayLinkStart(GlassDisplayLink);
+                if (ret == kCVReturnSuccess)
+                {
+                    timer->_paused = NO;
+                }
+                else
+                {
+                    NSLog(@"ERROR: MacTimer__1resume(): CVDisplayLinkStart error: %d\n", (int)ret);
+                }
+            }
+        }
+        else
+        {
+            timer->_paused = NO;
+        }
+    }
+    GLASS_POOL_EXIT;
+    GLASS_CHECK_EXCEPTION(env);
+}
+
+/*
+ * Class:     com_sun_glass_ui_mac_MacTimer
  * Method:    _getMinPeriod
  * Signature: ()I
  */
--- a/modules/javafx.graphics/src/main/native-glass/mac/GlassViewDelegate.m	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/mac/GlassViewDelegate.m	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -339,7 +339,17 @@
             break;
         case NSOtherMouseDown:
             type = com_sun_glass_events_MouseEvent_DOWN;
-            button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
+            switch ([theEvent buttonNumber]) {
+                case 2:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
+                    break;
+                case 3:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_BACK;
+                    break;
+                case 4:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
+                    break;
+            }
             break;
 
         case NSLeftMouseUp:
@@ -352,7 +362,17 @@
             break;
         case NSOtherMouseUp:
             type = com_sun_glass_events_MouseEvent_UP;
-            button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
+            switch ([theEvent buttonNumber]) {
+                case 2:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
+                    break;
+                case 3:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_BACK;
+                    break;
+                case 4:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
+                    break;
+            }
             break;
 
         case NSLeftMouseDragged:
@@ -365,7 +385,17 @@
             break;
         case NSOtherMouseDragged:
             type = com_sun_glass_events_MouseEvent_DRAG;
-            button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
+            switch ([theEvent buttonNumber]) {
+                case 2:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
+                    break;
+                case 3:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_BACK;
+                    break;
+                case 4:
+                    button = com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
+                    break;
+            }
             break;
 
         case NSMouseMoved:
@@ -491,6 +521,12 @@
                     case com_sun_glass_events_MouseEvent_BUTTON_OTHER:
                         modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_MIDDLE;
                         break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_BACK:
+                        modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_BACK;
+                        break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_FORWARD:
+                        modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_FORWARD;
+                        break;
                 }
             }
         }
@@ -515,9 +551,11 @@
             // prepare GlassDragSource for possible drag,
             case com_sun_glass_events_MouseEvent_DOWN:
                 switch (button) {
-                    case com_sun_glass_events_MouseEvent_BUTTON_LEFT:  self->mouseDownMask |= 1 << 0; break;
-                    case com_sun_glass_events_MouseEvent_BUTTON_RIGHT: self->mouseDownMask |= 1 << 1; break;
-                    case com_sun_glass_events_MouseEvent_BUTTON_OTHER: self->mouseDownMask |= 1 << 2; break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_LEFT:    self->mouseDownMask |= 1 << 0; break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_RIGHT:   self->mouseDownMask |= 1 << 1; break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_OTHER:   self->mouseDownMask |= 1 << 2; break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_BACK:    self->mouseDownMask |= 1 << 3; break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_FORWARD: self->mouseDownMask |= 1 << 4; break;
                 }
                 //fall through
             case com_sun_glass_events_MouseEvent_DRAG:
@@ -529,9 +567,11 @@
                 break;
             case com_sun_glass_events_MouseEvent_UP:
                 switch (button) {
-                    case com_sun_glass_events_MouseEvent_BUTTON_LEFT:  self->mouseDownMask &= ~(1 << 0); break;
-                    case com_sun_glass_events_MouseEvent_BUTTON_RIGHT: self->mouseDownMask &= ~(1 << 1); break;
-                    case com_sun_glass_events_MouseEvent_BUTTON_OTHER: self->mouseDownMask &= ~(1 << 2); break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_LEFT:    self->mouseDownMask &= ~(1 << 0); break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_RIGHT:   self->mouseDownMask &= ~(1 << 1); break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_OTHER:   self->mouseDownMask &= ~(1 << 2); break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_BACK:    self->mouseDownMask &= ~(1 << 3); break;
+                    case com_sun_glass_events_MouseEvent_BUTTON_FORWARD: self->mouseDownMask &= ~(1 << 4); break;
                 }
                 break;
 
@@ -988,7 +1028,7 @@
 static jstring convertNSStringToJString(id aString, int length)
 {
     GET_MAIN_JENV;
-    
+
     jstring jStr;
     if ([aString isKindOfClass:[NSAttributedString class]]) {
         NSData *data = [[aString string] dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
@@ -1001,7 +1041,7 @@
     } else {
         jStr = (*env)->NewStringUTF(env, [aString UTF8String]);
     }
-    
+
     GLASS_CHECK_EXCEPTION(env);
 
     return jStr;
--- a/modules/javafx.graphics/src/main/native-glass/win/FullScreenWindow.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/win/FullScreenWindow.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -323,6 +323,9 @@
         case WM_MBUTTONDOWN:
         case WM_MBUTTONUP:
         case WM_MBUTTONDBLCLK:
+        case WM_XBUTTONDOWN:
+        case WM_XBUTTONUP:
+        case WM_XBUTTONDBLCLK:
         case WM_MOUSEWHEEL:
         case WM_MOUSEHWHEEL:
         case WM_MOUSELEAVE: {
--- a/modules/javafx.graphics/src/main/native-glass/win/GlassClipboard.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/win/GlassClipboard.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.graphics/src/main/native-glass/win/GlassDnD.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/win/GlassDnD.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -316,6 +316,12 @@
     case com_sun_glass_events_MouseEvent_BUTTON_OTHER:
         m_button = MK_MBUTTON;
         break;
+    case com_sun_glass_events_MouseEvent_BUTTON_BACK:
+        m_button = MK_XBUTTON1;
+        break;
+    case com_sun_glass_events_MouseEvent_BUTTON_FORWARD:
+        m_button = MK_XBUTTON2;
+        break;
     default:
         m_button = 0;
         break;
--- a/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/win/GlassWindow.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -291,12 +291,15 @@
         case WM_LBUTTONDOWN: return "WM_LBUTTONDOWN";
         case WM_RBUTTONDOWN: return "WM_RBUTTONDOWN";
         case WM_MBUTTONDOWN: return "WM_MBUTTONDOWN";
+        case WM_XBUTTONDOWN: return "WM_XBUTTONDOWN";
         case WM_LBUTTONUP: return "WM_LBUTTONUP";
         case WM_LBUTTONDBLCLK: return "WM_LBUTTONDBLCLK";
         case WM_RBUTTONUP: return "WM_RBUTTONUP";
         case WM_RBUTTONDBLCLK: return "WM_RBUTTONDBLCLK";
         case WM_MBUTTONUP: return "WM_MBUTTONUP";
         case WM_MBUTTONDBLCLK: return "WM_MBUTTONDBLCLK";
+        case WM_XBUTTONUP: return "WM_XBUTTONUP";
+        case WM_XBUTTONDBLCLK: return "WM_XBUTTONDBLCLK";
         case WM_MOUSEWHEEL: return "WM_MOUSEWHEEL";
         case WM_MOUSEHWHEEL: return "WM_MOUSEHWHEEL";
         case WM_MOUSELEAVE: return "WM_MOUSELEAVE";
@@ -499,6 +502,7 @@
         case WM_LBUTTONDOWN:
         case WM_RBUTTONDOWN:
         case WM_MBUTTONDOWN:
+        case WM_XBUTTONDOWN:
             CheckUngrab(); // check if other owned windows hierarchy holds the grab
             if (IsChild() && !IsFocused() && IsFocusable()) {
                 RequestFocus(com_sun_glass_events_WindowEvent_FOCUS_GAINED);
@@ -510,6 +514,8 @@
         case WM_RBUTTONDBLCLK:
         case WM_MBUTTONUP:
         case WM_MBUTTONDBLCLK:
+        case WM_XBUTTONUP:
+        case WM_XBUTTONDBLCLK:
         case WM_MOUSEWHEEL:
         case WM_MOUSEHWHEEL:
         case WM_MOUSELEAVE:
--- a/modules/javafx.graphics/src/main/native-glass/win/Robot.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/win/Robot.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -154,6 +154,8 @@
     (JNIEnv *env, jobject jrobot, jint buttons)
 {
     DWORD dwFlags = 0L;
+    DWORD mouseFlags = 0L;
+
     // According to MSDN: Software Driving Software
     // application should consider SM_SWAPBUTTON to correctly emulate user with
     // left handed mouse setup
@@ -168,21 +170,21 @@
     if (buttons & (1 << 2)) {
         dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
     }
+    // Support for extra buttons
+    if (buttons & (1 << 3)) {
+        dwFlags |= MOUSEEVENTF_XDOWN;
+        mouseFlags |= XBUTTON1;
+    }
+    if (buttons & (1 << 4)) {
+        dwFlags |= MOUSEEVENTF_XDOWN;
+        mouseFlags |= XBUTTON2;
+    }
 
     INPUT mouseInput = {0};
     mouseInput.type = INPUT_MOUSE;
     mouseInput.mi.time = 0;
     mouseInput.mi.dwFlags = dwFlags;
-
-    // Support for extra buttons
-    if (buttons & (1 << 3)) {
-        mouseInput.mi.dwFlags |= MOUSEEVENTF_XDOWN;
-        mouseInput.mi.mouseData = XBUTTON1;
-    }
-    if (buttons & (1 << 4)) {
-        mouseInput.mi.dwFlags |= MOUSEEVENTF_XDOWN;
-        mouseInput.mi.mouseData = XBUTTON2;
-    }
+    mouseInput.mi.mouseData = mouseFlags;
 
     ::SendInput(1, &mouseInput, sizeof(mouseInput));
 }
@@ -196,6 +198,8 @@
     (JNIEnv *env, jobject jrobot, jint buttons)
 {
     DWORD dwFlags = 0L;
+    DWORD mouseFlags = 0L;
+
     // According to MSDN: Software Driving Software
     // application should consider SM_SWAPBUTTON to correctly emulate user with
     // left handed mouse setup
@@ -210,21 +214,21 @@
     if (buttons & (1 << 2)) {
         dwFlags |= MOUSEEVENTF_MIDDLEUP;
     }
+    // Support for extra buttons
+    if (buttons & (1 << 3)) {
+        dwFlags |= MOUSEEVENTF_XUP;
+        mouseFlags |= XBUTTON1;
+    }
+    if (buttons & (1 << 4)) {
+        dwFlags |= MOUSEEVENTF_XUP;
+        mouseFlags |= XBUTTON2;
+    }
 
     INPUT mouseInput = {0};
     mouseInput.type = INPUT_MOUSE;
     mouseInput.mi.time = 0;
     mouseInput.mi.dwFlags = dwFlags;
-
-    // Support for extra buttons
-    if (buttons & (1 << 3)) {
-        mouseInput.mi.dwFlags |= MOUSEEVENTF_XUP;
-        mouseInput.mi.mouseData = XBUTTON1;
-    }
-    if (buttons & (1 << 4)) {
-        mouseInput.mi.dwFlags |= MOUSEEVENTF_XUP;
-        mouseInput.mi.mouseData = XBUTTON2;
-    }
+    mouseInput.mi.mouseData = mouseFlags;
 
     ::SendInput(1, &mouseInput, sizeof(mouseInput));
 }
--- a/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/win/Utils.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,6 +97,12 @@
     if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) {
         modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_PRIMARY;
     }
+    if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) {
+        modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_BACK;
+    }
+    if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) {
+        modifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_FORWARD;
+    }
 
     return modifiers;
 }
--- a/modules/javafx.graphics/src/main/native-glass/win/ViewContainer.cpp	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/main/native-glass/win/ViewContainer.cpp	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -781,7 +781,7 @@
                     m_lastMouseMovePosition = lParam;
                 }
                 // See RT-11305 regarding the GetCapture() check
-                if ((wParam & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)) != 0 && ::GetCapture() == hwnd) {
+                if ((wParam & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) != 0 && ::GetCapture() == hwnd) {
                     type = com_sun_glass_events_MouseEvent_DRAG;
                 } else {
                     type = com_sun_glass_events_MouseEvent_MOVE;
@@ -795,6 +795,10 @@
                     button = com_sun_glass_events_MouseEvent_BUTTON_LEFT;
                 } else if (wParam & MK_MBUTTON) {
                     button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
+                } else if (wParam & MK_XBUTTON1) {
+                    button = com_sun_glass_events_MouseEvent_BUTTON_BACK;
+                } else if (wParam & MK_XBUTTON2) {
+                    button = com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
                 }
                 break;
             case WM_LBUTTONDOWN:
@@ -821,6 +825,16 @@
                 type = com_sun_glass_events_MouseEvent_UP;
                 button = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
                 break;
+            case WM_XBUTTONDOWN:
+                type = com_sun_glass_events_MouseEvent_DOWN;
+                button = GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? com_sun_glass_events_MouseEvent_BUTTON_BACK :
+                            com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
+                break;
+            case WM_XBUTTONUP:
+                type = com_sun_glass_events_MouseEvent_UP;
+                button = GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? com_sun_glass_events_MouseEvent_BUTTON_BACK :
+                            com_sun_glass_events_MouseEvent_BUTTON_FORWARD;
+                break;
             case WM_MOUSEWHEEL:
             case WM_MOUSEHWHEEL:
                 {
--- a/modules/javafx.graphics/src/test/java/test/javafx/scene/input/MouseDragEventTest.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/test/java/test/javafx/scene/input/MouseDragEventTest.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,6 +79,8 @@
         assertFalse(e.isPrimaryButtonDown());
         assertTrue(e.isMiddleButtonDown());
         assertFalse(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
         assertTrue(e.isSynthesized());
         assertFalse(e.isPopupTrigger());
         assertSame(gsrc, e.getGestureSource());
@@ -160,6 +162,8 @@
         assertFalse(e.isPrimaryButtonDown());
         assertTrue(e.isMiddleButtonDown());
         assertFalse(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
         assertTrue(e.isSynthesized());
         assertFalse(e.isPopupTrigger());
         assertSame(gsrc, e.getGestureSource());
@@ -187,7 +191,6 @@
         assertTrue(e.isPopupTrigger());
     }
 
-
     @Test public void testLongConstructorWithoutPickResult() {
         Rectangle n1 = new Rectangle(10, 10);
         Rectangle n2 = new Rectangle(10, 10);
@@ -212,6 +215,135 @@
         assertEquals(0, e.getPickResult().getIntersectedPoint().getZ(), 10e-20);
     }
 
+    @Test public void testFullConstructor() {
+        Rectangle n1 = new Rectangle(10, 10);
+        Rectangle n2 = new Rectangle(10, 10);
+        Rectangle node = new Rectangle();
+        node.setTranslateX(3);
+        node.setTranslateY(2);
+        node.setTranslateZ(50);
+        Rectangle gsrc = new Rectangle();
+
+        PickResult pickRes = new PickResult(node, new Point3D(15, 25, 100), 33);
+
+        MouseDragEvent e = new MouseDragEvent(n1, n2, MouseDragEvent.MOUSE_DRAG_OVER,
+                10, 20, 30, 40, MouseButton.MIDDLE, 3,
+                true, false, false, true,
+                false, true, false, true, true,
+                true, false, pickRes, gsrc);
+
+        assertSame(MouseDragEvent.MOUSE_DRAG_OVER, e.getEventType());
+        assertEquals(18, e.getX(), 10e-20);
+        assertEquals(27, e.getY(), 10e-20);
+        assertEquals(150, e.getZ(), 10e-20);
+        assertEquals(10, e.getSceneX(), 10e-20);
+        assertEquals(20, e.getSceneY(), 10e-20);
+        assertEquals(30, e.getScreenX(), 10e-20);
+        assertEquals(40, e.getScreenY(), 10e-20);
+        assertSame(MouseButton.MIDDLE, e.getButton());
+        assertEquals(3, e.getClickCount());
+        assertTrue(e.isShiftDown());
+        assertFalse(e.isControlDown());
+        assertFalse(e.isAltDown());
+        assertTrue(e.isMetaDown());
+        assertFalse(e.isPrimaryButtonDown());
+        assertTrue(e.isMiddleButtonDown());
+        assertFalse(e.isSecondaryButtonDown());
+        assertTrue(e.isBackButtonDown());
+        assertTrue(e.isForwardButtonDown());
+        assertTrue(e.isSynthesized());
+        assertFalse(e.isPopupTrigger());
+        assertSame(gsrc, e.getGestureSource());
+        assertFalse(e.isConsumed());
+        assertSame(pickRes, e.getPickResult());
+        assertSame(n1, e.getSource());
+        assertSame(n2, e.getTarget());
+
+        e = new MouseDragEvent(n1, n2, MouseDragEvent.MOUSE_DRAG_OVER,
+                10, 20, 30, 40, MouseButton.MIDDLE, 3,
+                false, true, true, false,
+                true, false, true, true, false,
+                false, true, pickRes, gsrc);
+
+        assertSame(n1, e.getSource());
+        assertSame(n2, e.getTarget());
+        assertFalse(e.isShiftDown());
+        assertTrue(e.isControlDown());
+        assertTrue(e.isAltDown());
+        assertFalse(e.isMetaDown());
+        assertTrue(e.isPrimaryButtonDown());
+        assertFalse(e.isMiddleButtonDown());
+        assertTrue(e.isSecondaryButtonDown());
+        assertTrue(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
+        assertFalse(e.isSynthesized());
+        assertTrue(e.isPopupTrigger());
+
+        e = new MouseDragEvent(n1, n2, MouseDragEvent.MOUSE_DRAG_OVER,
+                10, 20, 30, 40, MouseButton.MIDDLE, 3,
+                false, true, true, false,
+                true, false, true, false, true,
+                false, true, pickRes, gsrc);
+
+        assertSame(n1, e.getSource());
+        assertSame(n2, e.getTarget());
+        assertFalse(e.isShiftDown());
+        assertTrue(e.isControlDown());
+        assertTrue(e.isAltDown());
+        assertFalse(e.isMetaDown());
+        assertTrue(e.isPrimaryButtonDown());
+        assertFalse(e.isMiddleButtonDown());
+        assertTrue(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertTrue(e.isForwardButtonDown());
+        assertFalse(e.isSynthesized());
+        assertTrue(e.isPopupTrigger());
+
+        e = new MouseDragEvent(n1, n2, MouseDragEvent.MOUSE_DRAG_OVER,
+                10, 20, 30, 40, MouseButton.MIDDLE, 3,
+                false, true, true, false,
+                true, false, true, false, false,
+                false, true, pickRes, gsrc);
+
+        assertSame(n1, e.getSource());
+        assertSame(n2, e.getTarget());
+        assertFalse(e.isShiftDown());
+        assertTrue(e.isControlDown());
+        assertTrue(e.isAltDown());
+        assertFalse(e.isMetaDown());
+        assertTrue(e.isPrimaryButtonDown());
+        assertFalse(e.isMiddleButtonDown());
+        assertTrue(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
+        assertFalse(e.isSynthesized());
+        assertTrue(e.isPopupTrigger());
+    }
+
+    @Test public void testFullConstructorWithoutPickResult() {
+        Rectangle n1 = new Rectangle(10, 10);
+        Rectangle n2 = new Rectangle(10, 10);
+        MouseDragEvent e = new MouseDragEvent(n1, n2, MouseDragEvent.MOUSE_DRAG_OVER,
+                10, 20, 30, 40, MouseButton.MIDDLE, 3,
+                true, false, false, true,
+                false, true, false, true, true,
+                true, false, null, new Rectangle());
+        assertSame(n1, e.getSource());
+        assertSame(n2, e.getTarget());
+        assertEquals(10, e.getX(), 10e-20);
+        assertEquals(20, e.getY(), 10e-20);
+        assertEquals(0, e.getZ(), 10e-20);
+        assertEquals(10, e.getSceneX(), 10e-20);
+        assertEquals(20, e.getSceneY(), 10e-20);
+        assertEquals(30, e.getScreenX(), 10e-20);
+        assertEquals(40, e.getScreenY(), 10e-20);
+        assertNotNull(e.getPickResult());
+        assertNotNull(e.getPickResult().getIntersectedPoint());
+        assertEquals(10, e.getPickResult().getIntersectedPoint().getX(), 10e-20);
+        assertEquals(20, e.getPickResult().getIntersectedPoint().getY(), 10e-20);
+        assertEquals(0, e.getPickResult().getIntersectedPoint().getZ(), 10e-20);
+    }
+
     @Test
     public void fullPDRShouldNotStartAutomatically() {
         World w = new World(false, false);
--- a/modules/javafx.graphics/src/test/java/test/javafx/scene/input/MouseEventTest.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.graphics/src/test/java/test/javafx/scene/input/MouseEventTest.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,8 @@
         assertFalse(e.isPrimaryButtonDown());
         assertTrue(e.isMiddleButtonDown());
         assertFalse(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
         assertTrue(e.isSynthesized());
         assertFalse(e.isPopupTrigger());
         assertTrue(e.isStillSincePress());
@@ -102,6 +104,8 @@
         assertTrue(e.isPrimaryButtonDown());
         assertFalse(e.isMiddleButtonDown());
         assertTrue(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
         assertFalse(e.isSynthesized());
         assertTrue(e.isPopupTrigger());
         assertFalse(e.isStillSincePress());
@@ -164,6 +168,8 @@
         assertFalse(e.isPrimaryButtonDown());
         assertTrue(e.isMiddleButtonDown());
         assertFalse(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
         assertTrue(e.isSynthesized());
         assertFalse(e.isPopupTrigger());
         assertTrue(e.isStillSincePress());
@@ -185,12 +191,13 @@
         assertTrue(e.isPrimaryButtonDown());
         assertFalse(e.isMiddleButtonDown());
         assertTrue(e.isSecondaryButtonDown());
+        assertFalse(e.isBackButtonDown());
+        assertFalse(e.isForwardButtonDown());
         assertFalse(e.isSynthesized());
         assertTrue(e.isPopupTrigger());
         assertFalse(e.isStillSincePress());
     }
 
-
     @Test public void testLongConstructorWithoutPickResult() {
         Rectangle n1 = new Rectangle(10, 10);
         Rectangle n2 = new Rectangle(10, 10);
@@ -215,6 +222,31 @@
         assertEquals(0, e.getPickResult().getIntersectedPoint().getZ(), 10e-20);
     }
 
+    @Test public void testFullConstructorWithoutPickResult() {
+        Rectangle n1 = new Rectangle(10, 10);
+        Rectangle n2 = new Rectangle(10, 10);
+        MouseEvent e = new MouseEvent(n1, n2, MouseEvent.MOUSE_DRAGGED,
+                10, 20, 30, 40, MouseButton.MIDDLE, 3,
+                true, false, false, true,
+                false, true, false,
+                false, false, true,
+                false, true, null);
+        assertSame(n1, e.getSource());
+        assertSame(n2, e.getTarget());
+        assertEquals(10, e.getX(), 10e-20);
+        assertEquals(20, e.getY(), 10e-20);
+        assertEquals(0, e.getZ(), 10e-20);
+        assertEquals(10, e.getSceneX(), 10e-20);
+        assertEquals(20, e.getSceneY(), 10e-20);
+        assertEquals(30, e.getScreenX(), 10e-20);
+        assertEquals(40, e.getScreenY(), 10e-20);
+        assertNotNull(e.getPickResult());
+        assertNotNull(e.getPickResult().getIntersectedPoint());
+        assertEquals(10, e.getPickResult().getIntersectedPoint().getX(), 10e-20);
+        assertEquals(20, e.getPickResult().getIntersectedPoint().getY(), 10e-20);
+        assertEquals(0, e.getPickResult().getIntersectedPoint().getZ(), 10e-20);
+    }
+
     @Test
     public void shouldCreateDoubleClickMouseEvent() {
         /* constructor called during initialization */
@@ -234,6 +266,8 @@
         assertFalse(doubleclick.isPrimaryButtonDown());
         assertTrue(doubleclick.isMiddleButtonDown());
         assertFalse(doubleclick.isSecondaryButtonDown());
+        assertFalse(doubleclick.isBackButtonDown());
+        assertFalse(doubleclick.isForwardButtonDown());
         assertSame(MouseEvent.MOUSE_CLICKED, doubleclick.getEventType());
         assertSame(MouseEvent.NULL_SOURCE_TARGET, doubleclick.getSource());
     }
@@ -259,6 +293,8 @@
         assertEquals(doubleclick.isPrimaryButtonDown(), copy.isPrimaryButtonDown());
         assertEquals(doubleclick.isMiddleButtonDown(), copy.isMiddleButtonDown());
         assertEquals(doubleclick.isSecondaryButtonDown(), copy.isSecondaryButtonDown());
+        assertEquals(doubleclick.isBackButtonDown(), copy.isBackButtonDown());
+        assertEquals(doubleclick.isForwardButtonDown(), copy.isForwardButtonDown());
         assertSame(doubleclick.getEventType(), copy.getEventType());
         assertSame(node1, copy.getSource());
         assertSame(node2, copy.getTarget());
@@ -286,6 +322,8 @@
         assertEquals(doubleclick.isPrimaryButtonDown(), copy.isPrimaryButtonDown());
         assertEquals(doubleclick.isMiddleButtonDown(), copy.isMiddleButtonDown());
         assertEquals(doubleclick.isSecondaryButtonDown(), copy.isSecondaryButtonDown());
+        assertEquals(doubleclick.isBackButtonDown(), copy.isBackButtonDown());
+        assertEquals(doubleclick.isForwardButtonDown(), copy.isForwardButtonDown());
         assertSame(MouseEvent.MOUSE_ENTERED, copy.getEventType());
         assertSame(node1, copy.getSource());
         assertSame(node2, copy.getTarget());
@@ -313,6 +351,8 @@
         assertEquals(doubleclick.isPrimaryButtonDown(), copy.isPrimaryButtonDown());
         assertEquals(doubleclick.isMiddleButtonDown(), copy.isMiddleButtonDown());
         assertEquals(doubleclick.isSecondaryButtonDown(), copy.isSecondaryButtonDown());
+        assertEquals(doubleclick.isBackButtonDown(), copy.isBackButtonDown());
+        assertEquals(doubleclick.isForwardButtonDown(), copy.isForwardButtonDown());
         assertSame(doubleclick.getEventType(), copy.getEventType());
         assertSame(node2, copy.getSource());
         assertSame(node1, copy.getTarget());
@@ -339,6 +379,8 @@
         assertEquals(doubleclick.isPrimaryButtonDown(), copy.isPrimaryButtonDown());
         assertEquals(doubleclick.isMiddleButtonDown(), copy.isMiddleButtonDown());
         assertEquals(doubleclick.isSecondaryButtonDown(), copy.isSecondaryButtonDown());
+        assertEquals(doubleclick.isBackButtonDown(), copy.isBackButtonDown());
+        assertEquals(doubleclick.isForwardButtonDown(), copy.isForwardButtonDown());
         assertSame(doubleclick.getEventType(), copy.getEventType());
         assertSame(node1, copy.getSource());
         assertSame(node2, copy.getTarget());
--- a/modules/javafx.swing/src/main/java/com/sun/javafx/embed/swing/SwingEvents.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.swing/src/main/java/com/sun/javafx/embed/swing/SwingEvents.java	Fri Jan 11 07:51:13 2019 -0800
@@ -71,6 +71,12 @@
             case MouseEvent.BUTTON3:
                 abstractButton = AbstractEvents.MOUSEEVENT_SECONDARY_BUTTON;
                 break;
+            case 4:
+                abstractButton = AbstractEvents.MOUSEEVENT_BACK_BUTTON;
+                break;
+            case 5:
+                abstractButton = AbstractEvents.MOUSEEVENT_FORWARD_BUTTON;
+                break;
             default:
                 break;
         }
@@ -81,6 +87,10 @@
             abstractButton = AbstractEvents.MOUSEEVENT_MIDDLE_BUTTON;
         } else if ((extModifiers & MouseEvent.BUTTON3_DOWN_MASK) != 0) {
             abstractButton = AbstractEvents.MOUSEEVENT_SECONDARY_BUTTON;
+        } else if ((extModifiers & MouseEvent.getMaskForButton(4)) != 0) {
+            abstractButton = AbstractEvents.MOUSEEVENT_BACK_BUTTON;
+        } else if ((extModifiers & MouseEvent.getMaskForButton(5)) != 0) {
+            abstractButton = AbstractEvents.MOUSEEVENT_FORWARD_BUTTON;
         }
         return abstractButton;
     }
@@ -180,6 +190,12 @@
         if (event.isMiddleButtonDown()) {
             mods |= MouseEvent.BUTTON2_DOWN_MASK;
         }
+        if (event.isBackButtonDown()) {
+            mods |= MouseEvent.getMaskForButton(4);
+        }
+        if (event.isForwardButtonDown()) {
+            mods |= MouseEvent.getMaskForButton(5);
+        }
         return mods;
     }
 
@@ -191,6 +207,10 @@
                 return MouseEvent.BUTTON3;
             case MIDDLE:
                 return MouseEvent.BUTTON2;
+            case BACK:
+                return 4;
+            case FORWARD:
+                return 5;
         }
         return 0;
     }
--- a/modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java	Fri Jan 11 07:51:13 2019 -0800
@@ -363,12 +363,12 @@
             return;
         }
 
-        // FX only supports 3 buttons so don't send the event for other buttons
+        // FX only supports 5 buttons so don't send the event for other buttons
         switch (e.getID()) {
             case MouseEvent.MOUSE_DRAGGED:
             case MouseEvent.MOUSE_PRESSED:
             case MouseEvent.MOUSE_RELEASED:
-                if (e.getButton() > 3)  return;
+                if (e.getButton() > 5)  return;
                 break;
         }
 
@@ -378,6 +378,9 @@
         boolean primaryBtnDown = (extModifiers & MouseEvent.BUTTON1_DOWN_MASK) != 0;
         boolean middleBtnDown = (extModifiers & MouseEvent.BUTTON2_DOWN_MASK) != 0;
         boolean secondaryBtnDown = (extModifiers & MouseEvent.BUTTON3_DOWN_MASK) != 0;
+        boolean backBtnDown = (extModifiers & MouseEvent.getMaskForButton(4)) != 0;
+        boolean forwardBtnDown = (extModifiers & MouseEvent.getMaskForButton(5)) != 0;
+
         // Fix for RT-16558: if a PRESSED event is consumed, e.g. by a Swing Popup,
         // subsequent DRAGGED and RELEASED events should not be sent to FX as well
         if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
@@ -390,7 +393,7 @@
             if (!isCapturingMouse) {
                 return;
             }
-            isCapturingMouse = primaryBtnDown || middleBtnDown || secondaryBtnDown;
+            isCapturingMouse = primaryBtnDown || middleBtnDown || secondaryBtnDown || backBtnDown || forwardBtnDown;
         } else if (e.getID() == MouseEvent.MOUSE_CLICKED) {
             // Don't send click events to FX, as they are generated in Scene
             return;
@@ -417,6 +420,7 @@
                     SwingEvents.mouseIDToEmbedMouseType(e.getID()),
                     SwingEvents.mouseButtonToEmbedMouseButton(e.getButton(), extModifiers),
                     primaryBtnDown, middleBtnDown, secondaryBtnDown,
+                    backBtnDown, forwardBtnDown,
                     e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(),
                     (extModifiers & MouseEvent.SHIFT_DOWN_MASK) != 0,
                     (extModifiers & MouseEvent.CTRL_DOWN_MASK) != 0,
--- a/modules/javafx.swt/src/main/java/javafx/embed/swt/FXCanvas.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.swt/src/main/java/javafx/embed/swt/FXCanvas.java	Fri Jan 11 07:51:13 2019 -0800
@@ -488,22 +488,22 @@
             }
             @Override
             public void mouseDown(MouseEvent me) {
-                // FX only supports 3 buttons so don't send the event for other buttons
-                if (me.button > 3) return;
+                // FX only supports 5 buttons so don't send the event for other buttons
+                if (me.button > 5) return;
                 FXCanvas.this.sendMouseEventToFX(me, AbstractEvents.MOUSEEVENT_PRESSED);
             }
             @Override
             public void mouseUp(MouseEvent me) {
-                // FX only supports 3 buttons so don't send the event for other buttons
-                if (me.button > 3) return;
+                // FX only supports 5 buttons so don't send the event for other buttons
+                if (me.button > 5) return;
                 FXCanvas.this.sendMouseEventToFX(me, AbstractEvents.MOUSEEVENT_RELEASED);
             }
         });
 
         addMouseMoveListener(me -> {
             if ((me.stateMask & SWT.BUTTON_MASK) != 0) {
-                // FX only supports 3 buttons so don't send the event for other buttons
-                if ((me.stateMask & (SWT.BUTTON1 | SWT.BUTTON2 | SWT.BUTTON3)) != 0) {
+                // FX only supports 5 buttons so don't send the event for other buttons
+                if ((me.stateMask & (SWT.BUTTON1 | SWT.BUTTON2 | SWT.BUTTON3 | SWT.BUTTON4 | SWT.BUTTON5)) != 0) {
                     FXCanvas.this.sendMouseEventToFX(me, AbstractEvents.MOUSEEVENT_DRAGGED);
                 } else {
                     FXCanvas.this.sendMouseEventToFX(me, AbstractEvents.MOUSEEVENT_MOVED);
@@ -689,6 +689,8 @@
         boolean primaryBtnDown = (me.stateMask & SWT.BUTTON1) != 0;
         boolean middleBtnDown = (me.stateMask & SWT.BUTTON2) != 0;
         boolean secondaryBtnDown = (me.stateMask & SWT.BUTTON3) != 0;
+        boolean backBtnDown = (me.stateMask & SWT.BUTTON4) != 0;
+        boolean forwardBtnDown = (me.stateMask & SWT.BUTTON5) != 0;
         boolean shift = (me.stateMask & SWT.SHIFT) != 0;
         boolean control = (me.stateMask & SWT.CONTROL) != 0;
         boolean alt = (me.stateMask & SWT.ALT) != 0;
@@ -699,11 +701,15 @@
                 primaryBtnDown |= me.button == 1;
                 middleBtnDown |= me.button == 2;
                 secondaryBtnDown |= me.button == 3;
+                backBtnDown |= me.button == 4;
+                forwardBtnDown |= me.button == 5;
                 break;
             case AbstractEvents.MOUSEEVENT_RELEASED:
                 primaryBtnDown &= me.button != 1;
                 middleBtnDown &= me.button != 2;
                 secondaryBtnDown &= me.button != 3;
+                backBtnDown &= me.button == 4;
+                forwardBtnDown &= me.button == 5;
                 break;
             case AbstractEvents.MOUSEEVENT_CLICKED:
                 // Don't send click events to FX, as they are generated in Scene
@@ -723,6 +729,10 @@
                         button = 2;
                     } else if ((me.stateMask & SWT.BUTTON3) != 0) {
                         button = 3;
+                    } else if ((me.stateMask & SWT.BUTTON4) != 0) {
+                        button = 4;
+                    } else if ((me.stateMask & SWT.BUTTON5) != 0) {
+                        button = 5;
                     }
                 }
                 break;
@@ -735,6 +745,7 @@
                 embedMouseType,
                 SWTEvents.mouseButtonToEmbedMouseButton(button, me.stateMask),
                 primaryBtnDown, middleBtnDown, secondaryBtnDown,
+                backBtnDown, forwardBtnDown,
                 me.x, me.y,
                 los.x, los.y,
                 shift, control, alt, meta,
--- a/modules/javafx.swt/src/main/java/javafx/embed/swt/SWTEvents.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.swt/src/main/java/javafx/embed/swt/SWTEvents.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,6 +69,8 @@
             case 1: return AbstractEvents.MOUSEEVENT_PRIMARY_BUTTON;
             case 2: return AbstractEvents.MOUSEEVENT_MIDDLE_BUTTON;
             case 3: return AbstractEvents.MOUSEEVENT_SECONDARY_BUTTON;
+            case 4: return AbstractEvents.MOUSEEVENT_BACK_BUTTON;
+            case 5: return AbstractEvents.MOUSEEVENT_FORWARD_BUTTON;
         }
         return AbstractEvents.MOUSEEVENT_NONE_BUTTON;
     }
--- a/modules/javafx.web/src/main/java/com/sun/javafx/webkit/prism/WCBufferedContext.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/java/com/sun/javafx/webkit/prism/WCBufferedContext.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.web/src/main/java/com/sun/javafx/webkit/prism/WCPageBackBufferImpl.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/java/com/sun/javafx/webkit/prism/WCPageBackBufferImpl.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.web/src/main/java/com/sun/webkit/graphics/WCGraphicsContext.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/java/com/sun/webkit/graphics/WCGraphicsContext.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.web/src/main/java/com/sun/webkit/graphics/WCTransform.java	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/java/com/sun/webkit/graphics/WCTransform.java	Fri Jan 11 07:51:13 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/modules/javafx.web/src/main/legal/libxml2.md	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/legal/libxml2.md	Fri Jan 11 07:51:13 2019 -0800
@@ -1,4 +1,4 @@
-## xmlsoft.org: libxml2 v2.9.7
+## xmlsoft.org: libxml2 v2.9.9
 
 ### libxml2 License
 <pre>
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/linux/config.h	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/linux/config.h	Fri Jan 11 07:51:13 2019 -0800
@@ -4,9 +4,6 @@
 /* Type cast for the gethostbyname() argument */
 #define GETHOSTBYNAME_ARG_CAST /**/
 
-/* Define to 1 if you have the <ansidecl.h> header file. */
-#define HAVE_ANSIDECL_H 1
-
 /* Define to 1 if you have the <arpa/inet.h> header file. */
 #define HAVE_ARPA_INET_H 1
 
@@ -16,9 +13,6 @@
 /* Whether struct sockaddr::__ss_family exists */
 /* #undef HAVE_BROKEN_SS_FAMILY */
 
-/* Define to 1 if you have the `class' function. */
-/* #undef HAVE_CLASS */
-
 /* Define to 1 if you have the <ctype.h> header file. */
 #define HAVE_CTYPE_H 1
 
@@ -40,24 +34,12 @@
 /* Define to 1 if you have the <fcntl.h> header file. */
 #define HAVE_FCNTL_H 1
 
-/* Define to 1 if you have the `finite' function. */
-#define HAVE_FINITE 1
-
 /* Define to 1 if you have the <float.h> header file. */
 #define HAVE_FLOAT_H 1
 
-/* Define to 1 if you have the `fpclass' function. */
-/* #undef HAVE_FPCLASS */
-
 /* Define to 1 if you have the `fprintf' function. */
 #define HAVE_FPRINTF 1
 
-/* Define to 1 if you have the `fp_class' function. */
-/* #undef HAVE_FP_CLASS */
-
-/* Define to 1 if you have the <fp_class.h> header file. */
-/* #undef HAVE_FP_CLASS_H */
-
 /* Define to 1 if you have the `ftime' function. */
 #define HAVE_FTIME 1
 
@@ -67,9 +49,6 @@
 /* Define to 1 if you have the `gettimeofday' function. */
 #define HAVE_GETTIMEOFDAY 1
 
-/* Define to 1 if you have the <ieeefp.h> header file. */
-/* #undef HAVE_IEEEFP_H */
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
 
@@ -82,24 +61,15 @@
 /* Define if isnan is there */
 #define HAVE_ISNAN /**/
 
-/* Define to 1 if you have the `isnand' function. */
-/* #undef HAVE_ISNAND */
-
 /* Define if history library is there (-lhistory) */
 /* #undef HAVE_LIBHISTORY */
 
-/* Have compression library */
-/* #undef HAVE_LIBLZMA */
-
 /* Define if pthread library is there (-lpthread) */
 #define HAVE_LIBPTHREAD /**/
 
 /* Define if readline library is there (-lreadline) */
 /* #undef HAVE_LIBREADLINE */
 
-/* Have compression library */
-/* #undef HAVE_LIBZ */
-
 /* Define to 1 if you have the <limits.h> header file. */
 #define HAVE_LIMITS_H 1
 
@@ -129,9 +99,6 @@
 #  undef /**/ HAVE_MMAP
 #endif
 
-/* Define to 1 if you have the <nan.h> header file. */
-/* #undef HAVE_NAN_H */
-
 /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
 /* #undef HAVE_NDIR_H */
 
@@ -195,12 +162,6 @@
 /* Define to 1 if you have the <stdlib.h> header file. */
 #define HAVE_STDLIB_H 1
 
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
 /* Define to 1 if you have the `strftime' function. */
 #define HAVE_STRFTIME 1
 
@@ -210,9 +171,6 @@
 /* Define to 1 if you have the <string.h> header file. */
 #define HAVE_STRING_H 1
 
-/* Define to 1 if you have the `strndup' function. */
-#define HAVE_STRNDUP 1
-
 /* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
    */
 /* #undef HAVE_SYS_DIR_H */
@@ -266,9 +224,6 @@
 /* Define to 1 if you have the <zlib.h> header file. */
 /* #undef HAVE_ZLIB_H */
 
-/* Define to 1 if you have the `_stat' function. */
-/* #undef HAVE__STAT */
-
 /* Whether __va_copy() is available */
 /* #undef HAVE___VA_COPY */
 
@@ -313,7 +268,7 @@
 #define VA_LIST_IS_ARRAY 1
 
 /* Version number of package */
-#define VERSION "2.9.7"
+#define VERSION "2.9.9"
 
 /* Determine what socket length (socklen_t) data type is */
 #define XML_SOCKLEN_T socklen_t
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/linux/include/libxml/xmlversion.h	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/linux/include/libxml/xmlversion.h	Fri Jan 11 07:51:13 2019 -0800
@@ -29,21 +29,21 @@
  *
  * the version string like "1.2.3"
  */
-#define LIBXML_DOTTED_VERSION "2.9.7"
+#define LIBXML_DOTTED_VERSION "2.9.9"
 
 /**
  * LIBXML_VERSION:
  *
  * the version number: 1.2.3 value is 10203
  */
-#define LIBXML_VERSION 20907
+#define LIBXML_VERSION 20909
 
 /**
  * LIBXML_VERSION_STRING:
  *
  * the version number string, 1.2.3 value is "10203"
  */
-#define LIBXML_VERSION_STRING "20907"
+#define LIBXML_VERSION_STRING "20909"
 
 /**
  * LIBXML_VERSION_EXTRA:
@@ -58,7 +58,7 @@
  * Macro to check that the libxml version in use is compatible with
  * the version the software has been compiled against
  */
-#define LIBXML_TEST_VERSION xmlCheckVersion(20907);
+#define LIBXML_TEST_VERSION xmlCheckVersion(20909);
 
 #ifndef VMS
 #if 0
@@ -410,9 +410,6 @@
 #endif
 
 #ifdef __GNUC__
-#ifdef HAVE_ANSIDECL_H
-#include <ansidecl.h>
-#endif
 
 /**
  * ATTRIBUTE_UNUSED:
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/mac/config.h	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/mac/config.h	Fri Jan 11 07:51:13 2019 -0800
@@ -4,9 +4,6 @@
 /* Type cast for the gethostbyname() argument */
 #define GETHOSTBYNAME_ARG_CAST /**/
 
-/* Define to 1 if you have the <ansidecl.h> header file. */
-/* #undef HAVE_ANSIDECL_H */
-
 /* Define to 1 if you have the <arpa/inet.h> header file. */
 #define HAVE_ARPA_INET_H 1
 
@@ -16,9 +13,6 @@
 /* Whether struct sockaddr::__ss_family exists */
 /* #undef HAVE_BROKEN_SS_FAMILY */
 
-/* Define to 1 if you have the `class' function. */
-/* #undef HAVE_CLASS */
-
 /* Define to 1 if you have the <ctype.h> header file. */
 #define HAVE_CTYPE_H 1
 
@@ -40,24 +34,12 @@
 /* Define to 1 if you have the <fcntl.h> header file. */
 #define HAVE_FCNTL_H 1
 
-/* Define to 1 if you have the `finite' function. */
-#define HAVE_FINITE 1
-
 /* Define to 1 if you have the <float.h> header file. */
 #define HAVE_FLOAT_H 1
 
-/* Define to 1 if you have the `fpclass' function. */
-/* #undef HAVE_FPCLASS */
-
 /* Define to 1 if you have the `fprintf' function. */
 #define HAVE_FPRINTF 1
 
-/* Define to 1 if you have the `fp_class' function. */
-/* #undef HAVE_FP_CLASS */
-
-/* Define to 1 if you have the <fp_class.h> header file. */
-/* #undef HAVE_FP_CLASS_H */
-
 /* Define to 1 if you have the `ftime' function. */
 #define HAVE_FTIME 1
 
@@ -67,9 +49,6 @@
 /* Define to 1 if you have the `gettimeofday' function. */
 #define HAVE_GETTIMEOFDAY 1
 
-/* Define to 1 if you have the <ieeefp.h> header file. */
-/* #undef HAVE_IEEEFP_H */
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
 
@@ -82,24 +61,15 @@
 /* Define if isnan is there */
 #define HAVE_ISNAN /**/
 
-/* Define to 1 if you have the `isnand' function. */
-/* #undef HAVE_ISNAND */
-
 /* Define if history library is there (-lhistory) */
 /* #undef HAVE_LIBHISTORY */
 
-/* Have compression library */
-/* #undef HAVE_LIBLZMA */
-
 /* Define if pthread library is there (-lpthread) */
 #define HAVE_LIBPTHREAD /**/
 
 /* Define if readline library is there (-lreadline) */
 /* #undef HAVE_LIBREADLINE */
 
-/* Have compression library */
-/* #undef HAVE_LIBZ */
-
 /* Define to 1 if you have the <limits.h> header file. */
 #define HAVE_LIMITS_H 1
 
@@ -129,9 +99,6 @@
 #  undef /**/ HAVE_MMAP
 #endif
 
-/* Define to 1 if you have the <nan.h> header file. */
-/* #undef HAVE_NAN_H */
-
 /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
 /* #undef HAVE_NDIR_H */
 
@@ -195,12 +162,6 @@
 /* Define to 1 if you have the <stdlib.h> header file. */
 #define HAVE_STDLIB_H 1
 
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
 /* Define to 1 if you have the `strftime' function. */
 #define HAVE_STRFTIME 1
 
@@ -210,9 +171,6 @@
 /* Define to 1 if you have the <string.h> header file. */
 #define HAVE_STRING_H 1
 
-/* Define to 1 if you have the `strndup' function. */
-#define HAVE_STRNDUP 1
-
 /* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
    */
 /* #undef HAVE_SYS_DIR_H */
@@ -266,9 +224,6 @@
 /* Define to 1 if you have the <zlib.h> header file. */
 /* #undef HAVE_ZLIB_H */
 
-/* Define to 1 if you have the `_stat' function. */
-/* #undef HAVE__STAT */
-
 /* Whether __va_copy() is available */
 /* #undef HAVE___VA_COPY */
 
@@ -312,7 +267,7 @@
 #define VA_LIST_IS_ARRAY 1
 
 /* Version number of package */
-#define VERSION "2.9.7"
+#define VERSION "2.9.9"
 
 /* Determine what socket length (socklen_t) data type is */
 #define XML_SOCKLEN_T socklen_t
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/mac/include/libxml/xmlversion.h	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/mac/include/libxml/xmlversion.h	Fri Jan 11 07:51:13 2019 -0800
@@ -29,21 +29,21 @@
  *
  * the version string like "1.2.3"
  */
-#define LIBXML_DOTTED_VERSION "2.9.7"
+#define LIBXML_DOTTED_VERSION "2.9.9"
 
 /**
  * LIBXML_VERSION:
  *
  * the version number: 1.2.3 value is 10203
  */
-#define LIBXML_VERSION 20907
+#define LIBXML_VERSION 20909
 
 /**
  * LIBXML_VERSION_STRING:
  *
  * the version number string, 1.2.3 value is "10203"
  */
-#define LIBXML_VERSION_STRING "20907"
+#define LIBXML_VERSION_STRING "20909"
 
 /**
  * LIBXML_VERSION_EXTRA:
@@ -58,7 +58,7 @@
  * Macro to check that the libxml version in use is compatible with
  * the version the software has been compiled against
  */
-#define LIBXML_TEST_VERSION xmlCheckVersion(20907);
+#define LIBXML_TEST_VERSION xmlCheckVersion(20909);
 
 #ifndef VMS
 #if 0
@@ -282,7 +282,7 @@
  *
  * Whether icu support is available
  */
-#if 1
+#if 0
 #define LIBXML_ICU_ENABLED
 #endif
 
@@ -410,9 +410,6 @@
 #endif
 
 #ifdef __GNUC__
-#ifdef HAVE_ANSIDECL_H
-#include <ansidecl.h>
-#endif
 
 /**
  * ATTRIBUTE_UNUSED:
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/HTMLparser.c	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/HTMLparser.c	Fri Jan 11 07:51:13 2019 -0800
@@ -26,7 +26,7 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#ifdef HAVE_ZLIB_H
+#ifdef LIBXML_ZLIB_ENABLED
 #include <zlib.h>
 #endif
 
@@ -150,7 +150,7 @@
 
 /************************************************************************
  *                                  *
- *      Parser stacks related functions and macros      *
+ *  Parser stacks related functions and macros      *
  *                                  *
  ************************************************************************/
 
@@ -516,7 +516,7 @@
 
         guess = htmlFindEncoding(ctxt);
         if (guess == NULL) {
-    xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
+            xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
         } else {
             if (ctxt->input->encoding != NULL)
                 xmlFree((xmlChar *) ctxt->input->encoding);
@@ -529,7 +529,7 @@
                              "Unsupported encoding %s", guess, NULL);
             }
         }
-    ctxt->charset = XML_CHAR_ENCODING_UTF8;
+        ctxt->charset = XML_CHAR_ENCODING_UTF8;
     }
 
     return(xmlCurrentChar(ctxt, len));
@@ -597,7 +597,7 @@
 
 /************************************************************************
  *                                  *
- *      The list of HTML elements and their properties      *
+ *  The list of HTML elements and their properties      *
  *                                  *
  ************************************************************************/
 
@@ -1084,7 +1084,7 @@
 "menu",     "p", "head", "ul", NULL,
 "p",        "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", FONTSTYLE, NULL,
 "div",      "p", "head", NULL,
-"noscript", "p", NULL,
+"noscript", "script", NULL,
 "center",   "font", "b", "i", "p", "head", NULL,
 "a",        "a", "head", NULL,
 "caption",  "p", NULL,
@@ -1216,7 +1216,7 @@
 
 /************************************************************************
  *                                  *
- *      functions to handle HTML specific data          *
+ *  functions to handle HTML specific data          *
  *                                  *
  ************************************************************************/
 
@@ -1516,7 +1516,7 @@
          */
         htmlnamePush(ctxt, BAD_CAST"head");
         if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
-        ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
+            ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
     } else if ((!xmlStrEqual(newtag, BAD_CAST"noframes")) &&
            (!xmlStrEqual(newtag, BAD_CAST"frame")) &&
            (!xmlStrEqual(newtag, BAD_CAST"frameset"))) {
@@ -1594,12 +1594,12 @@
     unsigned int i;
 
     if (name == NULL)
-        return(0);
+      return(0);
     /*
      * all script attributes start with 'on'
      */
     if ((name[0] != 'o') || (name[1] != 'n'))
-        return(0);
+      return(0);
     for (i = 0;
      i < sizeof(htmlScriptAttributes)/sizeof(htmlScriptAttributes[0]);
      i++) {
@@ -1611,7 +1611,7 @@
 
 /************************************************************************
  *                                  *
- *      The list of HTML predefined entities            *
+ *  The list of HTML predefined entities            *
  *                                  *
  ************************************************************************/
 
@@ -2879,7 +2879,7 @@
 
         while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')){
             len++;
-        NEXT;
+            NEXT;
         }
 
     if (CUR != '\'') {
@@ -2975,11 +2975,11 @@
     }
 
     if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) {
-    htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+        htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
                     "Invalid char in CDATA 0x%X\n", cur);
         if (ctxt->input->cur < ctxt->input->end) {
-    NEXT;
-    }
+            NEXT;
+        }
     }
 
     if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) {
@@ -3038,8 +3038,8 @@
                 ctxt->sax->characters(ctxt->userData, buf, nbchar);
             } else {
             if (ctxt->sax->ignorableWhitespace != NULL)
-            ctxt->sax->ignorableWhitespace(ctxt->userData,
-                                           buf, nbchar);
+                ctxt->sax->ignorableWhitespace(ctxt->userData,
+                                               buf, nbchar);
             }
         } else {
             htmlCheckParagraph(ctxt);
@@ -3075,7 +3075,7 @@
             if (ctxt->sax->characters != NULL)
             ctxt->sax->characters(ctxt->userData, buf, nbchar);
         } else {
-        if (ctxt->sax->ignorableWhitespace != NULL)
+            if (ctxt->sax->ignorableWhitespace != NULL)
             ctxt->sax->ignorableWhitespace(ctxt->userData,
                                            buf, nbchar);
         }
@@ -3636,12 +3636,12 @@
         processed = ctxt->input->cur - ctxt->input->base;
         xmlBufShrink(ctxt->input->buf->buffer, processed);
         nbchars = xmlCharEncInput(ctxt->input->buf, 1);
+            xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
         if (nbchars < 0) {
         htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
                      "htmlCheckEncoding: encoder error\n",
                  NULL, NULL);
         }
-            xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
     }
     }
 }
@@ -4175,7 +4175,7 @@
              "htmlParseStartTag: invalid element name\n",
              NULL, NULL);
             /* Dump the bogus tag like browsers do */
-            while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
+        while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
                 NEXT;
 
             if (currentNode != NULL)
@@ -5103,7 +5103,7 @@
 #ifdef LIBXML_PUSH_ENABLED
 /************************************************************************
  *                                  *
- *      Progressive parsing interfaces              *
+ *  Progressive parsing interfaces              *
  *                                  *
  ************************************************************************/
 
@@ -5149,8 +5149,8 @@
         base = ctxt->checkIndex;
 
     if (in->buf == NULL) {
-    buf = in->base;
-    len = in->length;
+        buf = in->base;
+        len = in->length;
     } else {
         buf = xmlBufContent(in->buf->buffer);
         len = xmlBufUse(in->buf->buffer);
@@ -5163,13 +5163,13 @@
         len--;
     for (; base < len; base++) {
         if ((!incomment) && (base + 4 < len) && (!iscomment)) {
-        if ((buf[base] == '<') && (buf[base + 1] == '!') &&
-        (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
-        incomment = 1;
-        /* do not increment past <! - some people use <!--> */
-        base += 2;
+            if ((buf[base] == '<') && (buf[base + 1] == '!') &&
+                (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
+                incomment = 1;
+                /* do not increment past <! - some people use <!--> */
+                base += 2;
+            }
         }
-    }
         if (ignoreattrval) {
             if (buf[base] == '"' || buf[base] == '\'') {
                 if (invalue) {
@@ -5186,53 +5186,53 @@
                 continue;
             }
         }
-    if (incomment) {
-        if (base + 3 > len)
+        if (incomment) {
+            if (base + 3 > len)
                 return (-1);
-        if ((buf[base] == '-') && (buf[base + 1] == '-') &&
-        (buf[base + 2] == '>')) {
-        incomment = 0;
-        base += 2;
+            if ((buf[base] == '-') && (buf[base + 1] == '-') &&
+                (buf[base + 2] == '>')) {
+                incomment = 0;
+                base += 2;
+            }
+            continue;
         }
-        continue;
-    }
         if (buf[base] == first) {
-        if (third != 0) {
+            if (third != 0) {
                 if ((buf[base + 1] != next) || (buf[base + 2] != third))
                     continue;
-        } else if (next != 0) {
+            } else if (next != 0) {
                 if (buf[base + 1] != next)
                     continue;
-        }
-        ctxt->checkIndex = 0;
+            }
+            ctxt->checkIndex = 0;
 #ifdef DEBUG_PUSH
-        if (next == 0)
-        xmlGenericError(xmlGenericErrorContext,
-            "HPP: lookup '%c' found at %d\n",
-            first, base);
-        else if (third == 0)
-        xmlGenericError(xmlGenericErrorContext,
-            "HPP: lookup '%c%c' found at %d\n",
-            first, next, base);
-        else
-        xmlGenericError(xmlGenericErrorContext,
-            "HPP: lookup '%c%c%c' found at %d\n",
-            first, next, third, base);
+            if (next == 0)
+                xmlGenericError(xmlGenericErrorContext,
+                                "HPP: lookup '%c' found at %d\n",
+                                first, base);
+            else if (third == 0)
+                xmlGenericError(xmlGenericErrorContext,
+                                "HPP: lookup '%c%c' found at %d\n",
+                                first, next, base);
+            else
+                xmlGenericError(xmlGenericErrorContext,
+                                "HPP: lookup '%c%c%c' found at %d\n",
+                                first, next, third, base);
 #endif
             return (base - (in->cur - in->base));
-    }
+        }
     }
     if ((!incomment) && (!invalue))
-    ctxt->checkIndex = base;
+        ctxt->checkIndex = base;
 #ifdef DEBUG_PUSH
     if (next == 0)
-    xmlGenericError(xmlGenericErrorContext,
-        "HPP: lookup '%c' failed\n", first);
+        xmlGenericError(xmlGenericErrorContext,
+                        "HPP: lookup '%c' failed\n", first);
     else if (third == 0)
-    xmlGenericError(xmlGenericErrorContext,
-        "HPP: lookup '%c%c' failed\n", first, next);
+        xmlGenericError(xmlGenericErrorContext,
+                        "HPP: lookup '%c%c' failed\n", first, next);
     else
-    xmlGenericError(xmlGenericErrorContext,
+        xmlGenericError(xmlGenericErrorContext,
                         "HPP: lookup '%c%c%c' failed\n", first, next,
                         third);
 #endif
@@ -5484,7 +5484,7 @@
             else
             next = ' ';
         } else {
-        next = in->cur[1];
+            next = in->cur[1];
         }
         cur = in->cur[0];
             if ((cur == '<') && (next == '!') &&
@@ -5786,7 +5786,7 @@
                     ctxt->sax->characters(
                         ctxt->userData, &in->cur[0], 1);
                 } else {
-                if (ctxt->sax->ignorableWhitespace != NULL)
+                    if (ctxt->sax->ignorableWhitespace != NULL)
                     ctxt->sax->ignorableWhitespace(
                         ctxt->userData, &in->cur[0], 1);
                 }
@@ -6376,12 +6376,12 @@
 
     if (l < 1000) {
         content = xmlMallocAtomic (xmlStrlen(content_line) + l + 1);
-    if (content) {
+        if (content) {
         strcpy ((char *)content, (char *)content_line);
-            strcat ((char *)content, (char *)encoding);
-            htmlCheckEncoding (ctxt, content);
+        strcat ((char *)content, (char *)encoding);
+        htmlCheckEncoding (ctxt, content);
         xmlFree (content);
-    }
+        }
     }
     }
 
@@ -6674,7 +6674,7 @@
     xmlInitNodeInfoSeq(&ctxt->node_seq);
 
     if (ctxt->attsDefault != NULL) {
-        xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
+        xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
         ctxt->attsDefault = NULL;
     }
     if (ctxt->attsSpecial != NULL) {
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/HTMLtree.c	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/HTMLtree.c	Fri Jan 11 07:51:13 2019 -0800
@@ -34,7 +34,7 @@
 
 /************************************************************************
  *                                  *
- *          Getting/Setting encoding meta tags          *
+ *      Getting/Setting encoding meta tags          *
  *                                  *
  ************************************************************************/
 
@@ -211,7 +211,7 @@
         if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) {
                 head = cur->parent;
         goto found_meta;
-    }
+            }
     }
     cur = cur->next;
     }
@@ -248,8 +248,8 @@
             else
                         {
                            if ((value != NULL) &&
-                (!xmlStrcasecmp(attr->name, BAD_CAST"content")))
-                  content = value;
+                               (!xmlStrcasecmp(attr->name, BAD_CAST"content")))
+                   content = value;
                         }
                 if ((http != 0) && (content != NULL))
                 break;
@@ -389,7 +389,7 @@
 
 /************************************************************************
  *                                  *
- *          Dumping HTML tree content to a simple buffer        *
+ *      Dumping HTML tree content to a simple buffer        *
  *                                  *
  ************************************************************************/
 
@@ -502,17 +502,17 @@
         if (handler == NULL)
         htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
     }
+    } else {
+        /*
+         * Fallback to HTML or ASCII when the encoding is unspecified
+         */
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("HTML");
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("ascii");
     }
 
     /*
-     * Fallback to HTML or ASCII when the encoding is unspecified
-     */
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("HTML");
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("ascii");
-
-    /*
      * save the content to a temp buffer.
      */
     buf = xmlOutputBufferCreateFile(out, handler);
@@ -570,32 +570,21 @@
     xmlCharEncoding enc;
 
     enc = xmlParseCharEncoding(encoding);
-    if (enc != cur->charset) {
-        if (cur->charset != XML_CHAR_ENCODING_UTF8) {
-        /*
-         * Not supported yet
-         */
-        *mem = NULL;
-        *size = 0;
-        return;
-        }
-
+    if (enc != XML_CHAR_ENCODING_UTF8) {
         handler = xmlFindCharEncodingHandler(encoding);
         if (handler == NULL)
                 htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
 
+    }
     } else {
-        handler = xmlFindCharEncodingHandler(encoding);
+        /*
+         * Fallback to HTML or ASCII when the encoding is unspecified
+         */
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("HTML");
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("ascii");
     }
-    }
-
-    /*
-     * Fallback to HTML or ASCII when the encoding is unspecified
-     */
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("HTML");
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("ascii");
 
     buf = xmlAllocOutputBufferInternal(handler);
     if (buf == NULL) {
@@ -634,7 +623,7 @@
 
 /************************************************************************
  *                                  *
- *          Dumping HTML tree content to an I/O output buffer   *
+ *      Dumping HTML tree content to an I/O output buffer   *
  *                                  *
  ************************************************************************/
 
@@ -692,8 +681,8 @@
 
     /*
      * The html output method should not escape a & character
-     *       occurring in an attribute value immediately followed by
-     *       a { character (see Section B.7.1 of the HTML 4.0 Recommendation).
+     * occurring in an attribute value immediately followed by
+     * a { character (see Section B.7.1 of the HTML 4.0 Recommendation).
      * This is implemented in xmlEncodeEntitiesReentrant
      */
 
@@ -737,13 +726,13 @@
             }
 
             /* Escape the whole string, or until start (set to '\0'). */
-        escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+");
-        if (escaped != NULL) {
+            escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+");
+            if (escaped != NULL) {
                 xmlBufCat(buf->buffer, escaped);
-            xmlFree(escaped);
-        } else {
+                xmlFree(escaped);
+            } else {
                 xmlBufCat(buf->buffer, tmp);
-        }
+            }
 
             if (end == NULL) { /* Everything has been written. */
             break;
@@ -1101,29 +1090,20 @@
     xmlCharEncoding enc;
 
     enc = xmlParseCharEncoding(encoding);
-    if (enc != cur->charset) {
-        if (cur->charset != XML_CHAR_ENCODING_UTF8) {
-        /*
-         * Not supported yet
-         */
-        return(-1);
-        }
-
+    if (enc != XML_CHAR_ENCODING_UTF8) {
         handler = xmlFindCharEncodingHandler(encoding);
         if (handler == NULL)
         htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
+    }
     } else {
-        handler = xmlFindCharEncodingHandler(encoding);
+        /*
+         * Fallback to HTML or ASCII when the encoding is unspecified
+         */
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("HTML");
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("ascii");
     }
-    }
-
-    /*
-     * Fallback to HTML or ASCII when the encoding is unspecified
-     */
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("HTML");
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("ascii");
 
     buf = xmlOutputBufferCreateFile(f, handler);
     if (buf == NULL) return(-1);
@@ -1160,29 +1140,22 @@
     xmlCharEncoding enc;
 
     enc = xmlParseCharEncoding(encoding);
-    if (enc != cur->charset) {
-        if (cur->charset != XML_CHAR_ENCODING_UTF8) {
-        /*
-         * Not supported yet
-         */
-        return(-1);
-        }
-
+    if (enc != XML_CHAR_ENCODING_UTF8) {
         handler = xmlFindCharEncodingHandler(encoding);
         if (handler == NULL)
         htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
     }
+    } else {
+        /*
+         * Fallback to HTML or ASCII when the encoding is unspecified
+         */
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("HTML");
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("ascii");
     }
 
     /*
-     * Fallback to HTML or ASCII when the encoding is unspecified
-     */
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("HTML");
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("ascii");
-
-    /*
      * save the content to a temp buffer.
      */
     buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
@@ -1221,14 +1194,7 @@
     xmlCharEncoding enc;
 
     enc = xmlParseCharEncoding(encoding);
-    if (enc != cur->charset) {
-        if (cur->charset != XML_CHAR_ENCODING_UTF8) {
-        /*
-         * Not supported yet
-         */
-        return(-1);
-        }
-
+    if (enc != XML_CHAR_ENCODING_UTF8) {
         handler = xmlFindCharEncodingHandler(encoding);
         if (handler == NULL)
         htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
@@ -1236,17 +1202,17 @@
         htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
     } else {
     htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8");
+
+        /*
+         * Fallback to HTML or ASCII when the encoding is unspecified
+         */
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("HTML");
+        if (handler == NULL)
+            handler = xmlFindCharEncodingHandler("ascii");
     }
 
     /*
-     * Fallback to HTML or ASCII when the encoding is unspecified
-     */
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("HTML");
-    if (handler == NULL)
-    handler = xmlFindCharEncodingHandler("ascii");
-
-    /*
      * save the content to a temp buffer.
      */
     buf = xmlOutputBufferCreateFilename(filename, handler, 0);
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/Makefile.am	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/Makefile.am	Fri Jan 11 07:51:13 2019 -0800
@@ -8,7 +8,7 @@
 
 AM_CPPFLAGS = -I$(top_builddir)/include -I$(srcdir)/include
 
-AM_CFLAGS = $(THREAD_CFLAGS) $(Z_CFLAGS) $(LZMA_CFLAGS)
+AM_CFLAGS = $(EXTRA_CFLAGS) $(THREAD_CFLAGS) $(Z_CFLAGS) $(LZMA_CFLAGS)
 
 check_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath testURI \
                testThreads testC14N testAutomata testRegexp \
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/NEWS	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/NEWS	Fri Jan 11 07:51:13 2019 -0800
@@ -2442,7 +2442,7 @@
    - 2.1.0 also ease the upgrade from libxml v1 to the recent version. it
     also contains numerous fixes and enhancements:
     
-    added xmlStopParser() to stop parsing
+      added xmlStopParser() to stop parsing
       improved a lot parsing speed when there is large CDATA blocs
       includes XPath patches provided by Picdar Technology
       tried to fix as much as possible DTD validation and namespace
@@ -2500,7 +2500,7 @@
    - Some interfaces may changes (especially a bit about encoding).
    - the updates includes:
     
-    fix I18N support. ISO-Latin-x/UTF-8/UTF-16 (nearly) seems correctly
+      fix I18N support. ISO-Latin-x/UTF-8/UTF-16 (nearly) seems correctly
         handled now
       Better handling of entities, especially well-formedness checking
         and proper PEref extensions in external subsets
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/SAX2.c	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/SAX2.c	Fri Jan 11 07:51:13 2019 -0800
@@ -1145,22 +1145,22 @@
 #endif
     {
 #ifdef LIBXML_VALID_ENABLED
-    /*
-     * Do the last stage of the attribute normalization
-     * Needed for HTML too:
-     *   http://www.w3.org/TR/html4/types.html#h-6.2
-     */
-    ctxt->vctxt.valid = 1;
-    nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
-                                       ctxt->myDoc, ctxt->node,
-                       fullname, value);
-    if (ctxt->vctxt.valid != 1) {
-    ctxt->valid = 0;
-    }
-    if (nval != NULL)
-    value = nval;
+        /*
+         * Do the last stage of the attribute normalization
+         * Needed for HTML too:
+         *   http://www.w3.org/TR/html4/types.html#h-6.2
+         */
+        ctxt->vctxt.valid = 1;
+        nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
+                                               ctxt->myDoc, ctxt->node,
+                                               fullname, value);
+        if (ctxt->vctxt.valid != 1) {
+            ctxt->valid = 0;
+        }
+        if (nval != NULL)
+            value = nval;
 #else
-    nval = NULL;
+        nval = NULL;
 #endif /* LIBXML_VALID_ENABLED */
     }
 
@@ -1305,24 +1305,24 @@
     } else {
             xmlAttrPtr prop;
 
-    prop = ctxt->node->properties;
-    while (prop != NULL) {
-        if (prop->ns != NULL) {
-        if ((xmlStrEqual(name, prop->name)) &&
-            ((namespace == prop->ns) ||
-             (xmlStrEqual(namespace->href, prop->ns->href)))) {
-            xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
-                    "Attribute %s in %s redefined\n",
-                             name, namespace->href);
-            ctxt->wellFormed = 0;
-            if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+            prop = ctxt->node->properties;
+            while (prop != NULL) {
+                if (prop->ns != NULL) {
+                    if ((xmlStrEqual(name, prop->name)) &&
+                        ((namespace == prop->ns) ||
+                         (xmlStrEqual(namespace->href, prop->ns->href)))) {
+                            xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
+                                    "Attribute %s in %s redefined\n",
+                                             name, namespace->href);
+                        ctxt->wellFormed = 0;
+                        if (ctxt->recovery == 0) ctxt->disableSAX = 1;
                         if (name != NULL)
                             xmlFree(name);
-            goto error;
-        }
-        }
-        prop = prop->next;
-    }
+                        goto error;
+                    }
+                }
+                prop = prop->next;
+            }
         }
     } else {
     namespace = NULL;
@@ -1665,7 +1665,11 @@
 #ifdef DEBUG_SAX_TREE
     xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
 #endif
-    nodePush(ctxt, ret);
+    if (nodePush(ctxt, ret) < 0) {
+        xmlUnlinkNode(ret);
+        xmlFreeNode(ret);
+        return;
+    }
 
     /*
      * Link the child element
@@ -2257,6 +2261,7 @@
     ctxt->freeElems = ret->next;
     ctxt->freeElemsNr--;
     memset(ret, 0, sizeof(xmlNode));
+        ret->doc = ctxt->myDoc;
     ret->type = XML_ELEMENT_NODE;
 
     if (ctxt->dictNames)
@@ -2336,7 +2341,11 @@
     /*
      * We are parsing a new node.
      */
-    nodePush(ctxt, ret);
+    if (nodePush(ctxt, ret) < 0) {
+        xmlUnlinkNode(ret);
+        xmlFreeNode(ret);
+        return;
+    }
 
     /*
      * Link the child element
@@ -2373,9 +2382,9 @@
         return;
         }
             if (prefix != NULL)
-        xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
-            "Namespace prefix %s was not found\n",
-            prefix, NULL);
+                xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+                             "Namespace prefix %s was not found\n",
+                             prefix, NULL);
             else
                 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
                              "Namespace default prefix was not found\n",
@@ -2414,7 +2423,7 @@
         }
         }
         xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
-                           attributes[j+3], attributes[j+4]);
+                   attributes[j+3], attributes[j+4]);
     }
     }
 
--- a/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/aclocal.m4	Fri Dec 21 15:21:30 2018 -0800
+++ b/modules/javafx.web/src/main/native/Source/ThirdParty/libxml/src/aclocal.m4	Fri Jan 11 07:51:13 2019 -0800
@@ -1,6 +1,6 @@