author | Wes Kocher <wkocher@mozilla.com> |
Mon, 25 Sep 2017 16:45:14 -0700 | |
changeset 670386 | 41c0020723649b183fcb7baab915e4c775f6f688 |
parent 670385 | 5084608dc0bb4a5a19258827c943ae3584bd7fb5 (current diff) |
parent 670182 | e6b3498a39b94616ba36798fe0b71a3090b1b14c (diff) |
child 670387 | 82a3a8ca311e5a814537c75eaf093a38f975f420 |
push id | 81613 |
push user | bmo:nchevobbe@mozilla.com |
push date | Tue, 26 Sep 2017 10:17:11 +0000 |
reviewers | merge |
milestone | 58.0a1 |
--- a/chrome/nsChromeRegistry.cpp +++ b/chrome/nsChromeRegistry.cpp @@ -27,19 +27,17 @@ #include "nsIWindowMediator.h" #include "nsIPrefService.h" #include "mozilla/Preferences.h" #include "mozilla/Printf.h" #include "mozilla/StyleSheet.h" #include "mozilla/StyleSheetInlines.h" #include "mozilla/dom/Location.h" -#ifdef ENABLE_INTL_API #include "unicode/uloc.h" -#endif nsChromeRegistry* nsChromeRegistry::gChromeRegistry; // DO NOT use namespace mozilla; it'll break due to a naming conflict between // mozilla::TextRange and a TextRange in OSX headers. using mozilla::StyleSheet; using mozilla::dom::IsChromeURI; using mozilla::dom::Location; @@ -633,46 +631,23 @@ nsChromeRegistry::MustLoadURLRemotely(ns *aResult = !!(flags & REMOTE_REQUIRED); } return NS_OK; } bool nsChromeRegistry::GetDirectionForLocale(const nsACString& aLocale) { -#ifdef ENABLE_INTL_API int pref = mozilla::Preferences::GetInt("intl.uidirection", -1); if (pref >= 0) { return (pref > 0); } nsAutoCString locale(aLocale); SanitizeForBCP47(locale); return uloc_isRightToLeft(locale.get()); -#else - // first check the intl.uidirection.<locale> preference, and if that is not - // set, check the same preference but with just the first two characters of - // the locale. If that isn't set, default to left-to-right. - nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + aLocale; - nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (!prefBranch) { - return false; - } - - nsCString dir; - prefBranch->GetCharPref(prefString.get(), getter_Copies(dir)); - if (dir.IsEmpty()) { - int32_t hyphen = prefString.FindChar('-'); - if (hyphen >= 1) { - nsAutoCString shortPref(Substring(prefString, 0, hyphen)); - prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir)); - } - } - - return dir.EqualsLiteral("rtl"); -#endif } NS_IMETHODIMP_(bool) nsChromeRegistry::WrappersEnabled(nsIURI *aURI) { nsCOMPtr<nsIURL> chromeURL (do_QueryInterface(aURI)); if (!chromeURL) return false; @@ -710,33 +685,23 @@ nsChromeRegistry::GetSingleton() return nullptr; return cr.forget(); } void nsChromeRegistry::SanitizeForBCP47(nsACString& aLocale) { -#ifdef ENABLE_INTL_API // Currently, the only locale code we use that's not BCP47-conformant is // "ja-JP-mac" on OS X, but let's try to be more general than just // hard-coding that here. const int32_t LANG_TAG_CAPACITY = 128; char langTag[LANG_TAG_CAPACITY]; nsAutoCString locale(aLocale); UErrorCode err = U_ZERO_ERROR; // This is a fail-safe method that will set langTag to "und" if it cannot // match any part of the input locale code. int32_t len = uloc_toLanguageTag(locale.get(), langTag, LANG_TAG_CAPACITY, false, &err); if (U_SUCCESS(err) && len > 0) { aLocale.Assign(langTag, len); } -#else - // This is only really needed for Intl API purposes, AFAIK, - // so probably won't be used in a non-ENABLE_INTL_API build. - // But let's fix up the single anomalous code we actually ship, - // just in case: - if (aLocale.EqualsLiteral("ja-JP-mac")) { - aLocale.AssignLiteral("ja-JP"); - } -#endif }
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-basic-01.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-basic-01.js @@ -29,19 +29,16 @@ function test() { performTest(); }); } function performTest() { // Make sure that the search box becomes focused when pressing ctrl+f - Bug 1211038 gEditor.focus(); synthesizeKeyFromKeyTag(gDebugger.document.getElementById("tokenSearchKey")); - let focusedEl = Services.focus.focusedElement; - focusedEl = focusedEl.ownerDocument.getBindingParent(focusedEl) || focusedEl; - is(focusedEl, gDebugger.document.getElementById("searchbox"), "Searchbox is focused"); setText(gSearchBox, "#html"); EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true }, gDebugger); is(gFiltering.searchData.toSource(), '["#", ["", "html"]]', "The searchbox data wasn't parsed correctly."); ok(isCaretPos(gPanel, 35, 7), "The editor didn't jump to the correct line.");
--- a/devtools/client/sourceeditor/codemirror/README +++ b/devtools/client/sourceeditor/codemirror/README @@ -1,16 +1,16 @@ This is the CodeMirror editor packaged for the Mozilla Project. CodeMirror is a JavaScript component that provides a code editor in the browser. When a mode is available for the language you are coding in, it will color your code, and optionally help with indentation. # Upgrade -Currently used version is 5.29.0. To upgrade: download a new version of +Currently used version is 5.30.0. To upgrade: download a new version of CodeMirror from the project's page [1] and replace all JavaScript and CSS files inside the codemirror directory [2]. Then to recreate codemirror.bundle.js: > cd devtools/client/sourceeditor > npm install > webpack
--- a/devtools/client/sourceeditor/codemirror/addon/edit/closebrackets.js +++ b/devtools/client/sourceeditor/codemirror/addon/edit/closebrackets.js @@ -18,31 +18,36 @@ var Pos = CodeMirror.Pos; CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { if (old && old != CodeMirror.Init) { cm.removeKeyMap(keyMap); cm.state.closeBrackets = null; } if (val) { + ensureBound(getOption(val, "pairs")) cm.state.closeBrackets = val; cm.addKeyMap(keyMap); } }); function getOption(conf, name) { if (name == "pairs" && typeof conf == "string") return conf; if (typeof conf == "object" && conf[name] != null) return conf[name]; return defaults[name]; } - var bind = defaults.pairs + "`"; var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; - for (var i = 0; i < bind.length; i++) - keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i)); + function ensureBound(chars) { + for (var i = 0; i < chars.length; i++) { + var ch = chars.charAt(i), key = "'" + ch + "'" + if (!keyMap[key]) keyMap[key] = handler(ch) + } + } + ensureBound(defaults.pairs + "`") function handler(ch) { return function(cm) { return handleChar(cm, ch); }; } function getConfig(cm) { var deflt = cm.state.closeBrackets; if (!deflt || deflt.override) return deflt;
--- a/devtools/client/sourceeditor/codemirror/addon/hint/show-hint.js +++ b/devtools/client/sourceeditor/codemirror/addon/hint/show-hint.js @@ -297,17 +297,17 @@ if (completion.options.completeOnSingleClick) widget.pick(); } }); CodeMirror.on(hints, "mousedown", function() { setTimeout(function(){cm.focus();}, 20); }); - CodeMirror.signal(data, "select", completions[0], hints.firstChild); + CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); return true; } Widget.prototype = { close: function() { if (this.completion.widget != this) return; this.completion.widget = null; this.hints.parentNode.removeChild(this.hints);
--- a/devtools/client/sourceeditor/codemirror/addon/search/search.js +++ b/devtools/client/sourceeditor/codemirror/addon/search/search.js @@ -127,16 +127,17 @@ queryDialog = doc.createElement("div"); queryDialog.appendChild(inp); queryDialog.style.display = "flex"; } var state = getSearchState(cm); if (state.query) return findNext(cm, rev); var q = cm.getSelection() || state.lastQuery; + if (q instanceof RegExp && q.source == "x^") q = null if (persistent && cm.openDialog) { var hiding = null var searchNext = function(query, event) { CodeMirror.e_stop(event); if (!query) return; if (query != state.queryText) { startSearch(cm, state, query); state.posFrom = state.posTo = cm.getCursor();
--- a/devtools/client/sourceeditor/codemirror/addon/selection/mark-selection.js +++ b/devtools/client/sourceeditor/codemirror/addon/selection/mark-selection.js @@ -81,17 +81,17 @@ if (cm.listSelections().length > 1) return reset(cm); var from = cm.getCursor("start"), to = cm.getCursor("end"); var array = cm.state.markedSelection; if (!array.length) return coverRange(cm, from, to); var coverStart = array[0].find(), coverEnd = array[array.length - 1].find(); - if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE || + if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE || cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0) return reset(cm); while (cmp(from, coverStart.from) > 0) { array.shift().clear(); coverStart = array[0].find(); } if (cmp(from, coverStart.from) < 0) {
--- a/devtools/client/sourceeditor/codemirror/addon/tern/tern.js +++ b/devtools/client/sourceeditor/codemirror/addon/tern/tern.js @@ -566,17 +566,17 @@ var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize); if (indent <= minIndent) break; } var from = Pos(minLine, 0); return {type: "part", name: data.name, offsetLines: from.line, - text: doc.getRange(from, Pos(endLine, 0))}; + text: doc.getRange(from, Pos(endLine, end.line == endLine ? null : 0))}; } // Generic utilities var cmpPos = CodeMirror.cmpPos; function elt(tagname, cls /*, ... elts*/) { var e = document.createElement(tagname);
--- a/devtools/client/sourceeditor/codemirror/codemirror.bundle.js +++ b/devtools/client/sourceeditor/codemirror/codemirror.bundle.js @@ -515,23 +515,28 @@ var CodeMirror = // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. function skipExtendingChars(str, pos, dir) { while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir } return pos } // Returns the value from the range [`from`; `to`] that satisfies - // `pred` and is closest to `from`. Assumes that at least `to` satisfies `pred`. + // `pred` and is closest to `from`. Assumes that at least `to` + // satisfies `pred`. Supports `from` being greater than `to`. function findFirst(pred, from, to) { + // At any point we are certain `to` satisfies `pred`, don't know + // whether `from` does. + var dir = from > to ? -1 : 1 for (;;) { - if (Math.abs(from - to) <= 1) { return pred(from) ? from : to } - var mid = Math.floor((from + to) / 2) + if (from == to) { return from } + var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF) + if (mid == from) { return pred(mid) ? from : to } if (pred(mid)) { to = mid } - else { from = mid } + else { from = mid + dir } } } // The display handles the DOM integration, both for input reading // and content drawing. It holds references to DOM nodes and // display-related state. function Display(place, doc, input) { @@ -1134,22 +1139,22 @@ var CodeMirror = d.maxLine = line } }) } // BIDI HELPERS function iterateBidiSections(order, from, to, f) { - if (!order) { return f(from, to, "ltr") } + if (!order) { return f(from, to, "ltr", 0) } var found = false for (var i = 0; i < order.length; ++i) { var part = order[i] if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr") + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i) found = true } } if (!found) { f(from, to, "ltr") } } var bidiOther = null function getBidiPartAt(order, ch, sticky) { @@ -1342,122 +1347,16 @@ var CodeMirror = // false for lines that are fully left-to-right, and an array of // BidiSpan objects otherwise. function getOrder(line, direction) { var order = line.order if (order == null) { order = line.order = bidiOrdering(line.text, direction) } return order } - function moveCharLogically(line, ch, dir) { - var target = skipExtendingChars(line.text, ch + dir, dir) - return target < 0 || target > line.text.length ? null : target - } - - function moveLogically(line, start, dir) { - var ch = moveCharLogically(line, start.ch, dir) - return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") - } - - function endOfLine(visually, cm, lineObj, lineNo, dir) { - if (visually) { - var order = getOrder(lineObj, cm.doc.direction) - if (order) { - var part = dir < 0 ? lst(order) : order[0] - var moveInStorageOrder = (dir < 0) == (part.level == 1) - var sticky = moveInStorageOrder ? "after" : "before" - var ch - // With a wrapped rtl chunk (possibly spanning multiple bidi parts), - // it could be that the last bidi part is not on the last visual line, - // since visual lines contain content order-consecutive chunks. - // Thus, in rtl, we are looking for the first (content-order) character - // in the rtl chunk that is on the last line (that is, the same line - // as the last (content-order) character). - if (part.level > 0) { - var prep = prepareMeasureForLine(cm, lineObj) - ch = dir < 0 ? lineObj.text.length - 1 : 0 - var targetTop = measureCharPrepared(cm, prep, ch).top - ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch) - if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1) } - } else { ch = dir < 0 ? part.to : part.from } - return new Pos(lineNo, ch, sticky) - } - } - return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") - } - - function moveVisually(cm, line, start, dir) { - var bidi = getOrder(line, cm.doc.direction) - if (!bidi) { return moveLogically(line, start, dir) } - if (start.ch >= line.text.length) { - start.ch = line.text.length - start.sticky = "before" - } else if (start.ch <= 0) { - start.ch = 0 - start.sticky = "after" - } - var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos] - if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { - // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, - // nothing interesting happens. - return moveLogically(line, start, dir) - } - - var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); } - var prep - var getWrappedLineExtent = function (ch) { - if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } - prep = prep || prepareMeasureForLine(cm, line) - return wrappedLineExtentChar(cm, line, prep, ch) - } - var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch) - - if (cm.doc.direction == "rtl" || part.level == 1) { - var moveInStorageOrder = (part.level == 1) == (dir < 0) - var ch = mv(start, moveInStorageOrder ? 1 : -1) - if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { - // Case 2: We move within an rtl part or in an rtl editor on the same visual line - var sticky = moveInStorageOrder ? "before" : "after" - return new Pos(start.line, ch, sticky) - } - } - - // Case 3: Could not move within this bidi part in this visual line, so leave - // the current bidi part - - var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { - var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder - ? new Pos(start.line, mv(ch, 1), "before") - : new Pos(start.line, ch, "after"); } - - for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { - var part = bidi[partPos] - var moveInStorageOrder = (dir > 0) == (part.level != 1) - var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1) - if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } - ch = moveInStorageOrder ? part.from : mv(part.to, -1) - if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } - } - } - - // Case 3a: Look for other bidi parts on the same visual line - var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent) - if (res) { return res } - - // Case 3b: Look for other bidi parts on the next visual line - var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1) - if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { - res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)) - if (res) { return res } - } - - // Case 4: Nowhere to move - return null - } - // EVENT HANDLING // Lightweight event framework. on/off also work on DOM nodes, // registering native DOM handlers. var noHandlers = [] var on = function(emitter, type, f) { @@ -2956,25 +2855,32 @@ var CodeMirror = if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) } return window.pageXOffset || (document.documentElement || document.body).scrollLeft } function pageScrollY() { if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) } return window.pageYOffset || (document.documentElement || document.body).scrollTop } + function widgetTopHeight(lineObj) { + var height = 0 + if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) + { height += widgetHeight(lineObj.widgets[i]) } } } + return height + } + // Converts a {top, bottom, left, right} box from line-local // coordinates into another coordinate system. Context may be one of // "line", "div" (display.lineDiv), "local"./null (editor), "window", // or "page". function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { - if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) { - var size = widgetHeight(lineObj.widgets[i]) - rect.top += size; rect.bottom += size - } } } + if (!includeWidgets) { + var height = widgetTopHeight(lineObj) + rect.top += height; rect.bottom += height + } if (context == "line") { return rect } if (!context) { context = "local" } var yOff = heightAtLine(lineObj) if (context == "local") { yOff += paddingTop(cm.display) } else { yOff -= cm.display.viewOffset } if (context == "page" || context == "window") { var lOff = cm.display.lineSpace.getBoundingClientRect() yOff += lOff.top + (context == "window" ? 0 : pageScrollY()) @@ -3039,17 +2945,17 @@ var CodeMirror = sticky = "before" } else if (ch <= 0) { ch = 0 sticky = "after" } if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } function getBidi(ch, partPos, invert) { - var part = order[partPos], right = (part.level % 2) != 0 + var part = order[partPos], right = part.level == 1 return get(invert ? ch - 1 : ch, right != invert) } var partPos = getBidiPartAt(order, ch, sticky) var other = bidiOther var val = getBidi(ch, partPos, sticky == "before") if (other != null) { val.other = getBidi(ch, other, sticky != "before") } return val } @@ -3097,87 +3003,156 @@ var CodeMirror = if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) { lineN = lineNo(lineObj = mergedPos.to.line) } else { return found } } } function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { - var measure = function (ch) { return intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line"); } + y -= widgetTopHeight(lineObj) var end = lineObj.text.length - var begin = findFirst(function (ch) { return measure(ch - 1).bottom <= y; }, end, 0) - end = findFirst(function (ch) { return measure(ch).top > y; }, begin, end) + var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0) + end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end) return {begin: begin, end: end} } function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) } var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) } + // Returns true if the given side of a box is after the given + // coordinates, in top-to-bottom, left-to-right order. + function boxIsAfter(box, x, y, left) { + return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x + } + function coordsCharInner(cm, lineObj, lineNo, x, y) { + // Move y into line-local coordinate space y -= heightAtLine(lineObj) - var begin = 0, end = lineObj.text.length var preparedMeasure = prepareMeasureForLine(cm, lineObj) - var pos + // When directly calling `measureCharPrepared`, we have to adjust + // for the widgets at this line. + var widgetHeight = widgetTopHeight(lineObj) + var begin = 0, end = lineObj.text.length, ltr = true + var order = getOrder(lineObj, cm.doc.direction) + // If the line isn't plain left-to-right text, first figure out + // which bidi section the coordinates fall into. if (order) { - if (cm.options.lineWrapping) { - ;var assign; - ((assign = wrappedLineExtent(cm, lineObj, preparedMeasure, y), begin = assign.begin, end = assign.end, assign)) - } - pos = new Pos(lineNo, Math.floor(begin + (end - begin) / 2)) - var beginLeft = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - var dir = beginLeft < x ? 1 : -1 - var prevDiff, diff = beginLeft - x, prevPos - var steps = Math.ceil((end - begin) / 4) - outer: do { - prevDiff = diff - prevPos = pos - var i = 0 - for (; i < steps; ++i) { - var prevPos$1 = pos - pos = moveVisually(cm, lineObj, pos, dir) - if (pos == null || pos.ch < begin || end <= (pos.sticky == "before" ? pos.ch - 1 : pos.ch)) { - pos = prevPos$1 - break outer - } - } - diff = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - x - if (steps > 1) { - var diff_change_per_step = Math.abs(diff - prevDiff) / steps - steps = Math.min(steps, Math.ceil(Math.abs(diff) / diff_change_per_step)) - dir = diff < 0 ? 1 : -1 - } - } while (diff != 0 && (steps > 1 || ((dir < 0) != (diff < 0) && (Math.abs(diff) <= Math.abs(prevDiff))))) - if (Math.abs(diff) > Math.abs(prevDiff)) { - if ((diff < 0) == (prevDiff < 0)) { throw new Error("Broke out of infinite loop in coordsCharInner") } - pos = prevPos - } + var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) + (cm, lineObj, lineNo, preparedMeasure, order, x, y) + ltr = part.level != 1 + // The awkward -1 offsets are needed because findFirst (called + // on these below) will treat its first bound as inclusive, + // second as exclusive, but we want to actually address the + // characters in the part's range + begin = ltr ? part.from : part.to - 1 + end = ltr ? part.to : part.from - 1 + } + + // A binary search to find the first character whose bounding box + // starts after the coordinates. If we run across any whose box wrap + // the coordinates, store that. + var chAround = null, boxAround = null + var ch = findFirst(function (ch) { + var box = measureCharPrepared(cm, preparedMeasure, ch) + box.top += widgetHeight; box.bottom += widgetHeight + if (!boxIsAfter(box, x, y, false)) { return false } + if (box.top <= y && box.left <= x) { + chAround = ch + boxAround = box + } + return true + }, begin, end) + + var baseX, sticky, outside = false + // If a box around the coordinates was found, use that + if (boxAround) { + // Distinguish coordinates nearer to the left or right side of the box + var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr + ch = chAround + (atStart ? 0 : 1) + sticky = atStart ? "after" : "before" + baseX = atLeft ? boxAround.left : boxAround.right } else { - var ch = findFirst(function (ch) { - var box = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line") - if (box.top > y) { - // For the cursor stickiness - end = Math.min(ch, end) - return true - } - else if (box.bottom <= y) { return false } - else if (box.left > x) { return true } - else if (box.right < x) { return false } - else { return (x - box.left < box.right - x) } - }, begin, end) - ch = skipExtendingChars(lineObj.text, ch, 1) - pos = new Pos(lineNo, ch, ch == end ? "before" : "after") - } - var coords = cursorCoords(cm, pos, "line", lineObj, preparedMeasure) - if (y < coords.top || coords.bottom < y) { pos.outside = true } - pos.xRel = x < coords.left ? -1 : (x > coords.right ? 1 : 0) - return pos + // (Adjust for extended bound, if necessary.) + if (!ltr && (ch == end || ch == begin)) { ch++ } + // To determine which side to associate with, get the box to the + // left of the character and compare it's vertical position to the + // coordinates + sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : + (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? + "after" : "before" + // Now get accurate coordinates for this place, in order to get a + // base X position + var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure) + baseX = coords.left + outside = y < coords.top || y >= coords.bottom + } + + ch = skipExtendingChars(lineObj.text, ch, 1) + return PosWithInfo(lineNo, ch, sticky, outside, x - baseX) + } + + function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) { + // Bidi parts are sorted left-to-right, and in a non-line-wrapping + // situation, we can take this ordering to correspond to the visual + // ordering. This finds the first part whose end is after the given + // coordinates. + var index = findFirst(function (i) { + var part = order[i], ltr = part.level != 1 + return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"), + "line", lineObj, preparedMeasure), x, y, true) + }, 0, order.length - 1) + var part = order[index] + // If this isn't the first part, the part's start is also after + // the coordinates, and the coordinates aren't on the same line as + // that start, move one part back. + if (index > 0) { + var ltr = part.level != 1 + var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"), + "line", lineObj, preparedMeasure) + if (boxIsAfter(start, x, y, true) && start.top > y) + { part = order[index - 1] } + } + return part + } + + function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { + // In a wrapped line, rtl text on wrapping boundaries can do things + // that don't correspond to the ordering in our `order` array at + // all, so a binary search doesn't work, and we want to return a + // part that only spans one line so that the binary search in + // coordsCharInner is safe. As such, we first find the extent of the + // wrapped line, and then do a flat search in which we discard any + // spans that aren't on the line. + var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); + var begin = ref.begin; + var end = ref.end; + var part = null, closestDist = null + for (var i = 0; i < order.length; i++) { + var p = order[i] + if (p.from >= end || p.to <= begin) { continue } + var ltr = p.level != 1 + var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right + // Weigh against spans ending before this, so that they are only + // picked if nothing ends after + var dist = endX < x ? x - endX + 1e9 : endX - x + if (!part || closestDist > dist) { + part = p + closestDist = dist + } + } + if (!part) { part = order[order.length - 1] } + // Clip the part to the wrapped line. + if (part.from < begin) { part = {from: begin, to: part.to, level: part.level} } + if (part.to > end) { part = {from: part.from, to: end, level: part.level} } + return part } var measureText // Compute the default text height. function textHeight(display) { if (display.cachedTextHeight != null) { return display.cachedTextHeight } if (measureText == null) { measureText = elt("pre") @@ -3293,22 +3268,24 @@ var CodeMirror = } } function updateSelection(cm) { cm.display.input.showSelection(cm.display.input.prepareSelection()) } function prepareSelection(cm, primary) { + if ( primary === void 0 ) primary = true; + var doc = cm.doc, result = {} var curFragment = result.cursors = document.createDocumentFragment() var selFragment = result.selection = document.createDocumentFragment() for (var i = 0; i < doc.sel.ranges.length; i++) { - if (primary === false && i == doc.sel.primIndex) { continue } + if (!primary && i == doc.sel.primIndex) { continue } var range = doc.sel.ranges[i] if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } var collapsed = range.empty() if (collapsed || cm.options.showCursorWhenSelecting) { drawSelectionCursor(cm, range.head, curFragment) } if (!collapsed) { drawSelectionRange(cm, range, selFragment) } } @@ -3329,16 +3306,18 @@ var CodeMirror = var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")) otherCursor.style.display = "" otherCursor.style.left = pos.other.left + "px" otherCursor.style.top = pos.other.top + "px" otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px" } } + function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } + // Draws the given range as a highlighted selection function drawSelectionRange(cm, range, output) { var display = cm.display, doc = cm.doc var fragment = document.createDocumentFragment() var padding = paddingH(cm.display), leftSide = padding.left var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right function add(left, top, width, bottom) { @@ -3351,40 +3330,58 @@ var CodeMirror = function drawForLine(line, fromArg, toArg) { var lineObj = getLine(doc, line) var lineLen = lineObj.text.length var start, end function coords(ch, bias) { return charCoords(cm, Pos(line, ch), "div", lineObj, bias) } - iterateBidiSections(getOrder(lineObj, doc.direction), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) { - var leftPos = coords(from, "left"), rightPos, left, right - if (from == to) { - rightPos = leftPos - left = right = leftPos.left - } else { - rightPos = coords(to - 1, "right") - if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp } - left = leftPos.left - right = rightPos.right - } - if (fromArg == null && from == 0) { left = leftSide } - if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part - add(left, leftPos.top, null, leftPos.bottom) - left = leftSide - if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top) } - } - if (toArg == null && to == lineLen) { right = rightSide } - if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) - { start = leftPos } - if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) - { end = rightPos } - if (left < leftSide + 1) { left = leftSide } - add(left, rightPos.top, right - left, rightPos.bottom) + var order = getOrder(lineObj, doc.direction) + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { + var fromPos = coords(from, dir == "ltr" ? "left" : "right") + var toPos = coords(to - 1, dir == "ltr" ? "right" : "left") + if (dir == "ltr") { + var fromLeft = fromArg == null && from == 0 ? leftSide : fromPos.left + var toRight = toArg == null && to == lineLen ? rightSide : toPos.right + if (toPos.top - fromPos.top <= 3) { // Single line + add(fromLeft, toPos.top, toRight - fromLeft, toPos.bottom) + } else { // Multiple lines + add(fromLeft, fromPos.top, null, fromPos.bottom) + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top) } + add(leftSide, toPos.top, toPos.right, toPos.bottom) + } + } else if (from < to) { // RTL + var fromRight = fromArg == null && from == 0 ? rightSide : fromPos.right + var toLeft = toArg == null && to == lineLen ? leftSide : toPos.left + if (toPos.top - fromPos.top <= 3) { // Single line + add(toLeft, toPos.top, fromRight - toLeft, toPos.bottom) + } else { // Multiple lines + var topLeft = leftSide + if (i) { + var topEnd = wrappedLineExtentChar(cm, lineObj, null, from).end + // The coordinates returned for an RTL wrapped space tend to + // be complete bogus, so try to skip that here. + topLeft = coords(topEnd - (/\s/.test(lineObj.text.charAt(topEnd - 1)) ? 2 : 1), "left").left + } + add(topLeft, fromPos.top, fromRight - topLeft, fromPos.bottom) + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top) } + var botWidth = null + if (i < order.length - 1 || true) { + var botStart = wrappedLineExtentChar(cm, lineObj, null, to).begin + botWidth = coords(botStart, "right").right - toLeft + } + add(toLeft, toPos.top, botWidth, toPos.bottom) + } + } + + if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos } + if (cmpCoords(toPos, start) < 0) { start = toPos } + if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos } + if (cmpCoords(toPos, end) < 0) { end = toPos } }) return {start: start, end: end} } var sFrom = range.from(), sTo = range.to() if (sFrom.line == sTo.line) { drawForLine(sFrom.line, sFrom.ch, sTo.ch) } else { @@ -4004,30 +4001,30 @@ var CodeMirror = op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3 cm.display.sizerWidth = op.adjustWidthTo op.barMeasure.scrollWidth = Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth) op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)) } if (op.updatedDisplay || op.selectionChanged) - { op.preparedSelection = display.input.prepareSelection(op.focus) } + { op.preparedSelection = display.input.prepareSelection() } } function endOperation_W2(op) { var cm = op.cm if (op.adjustWidthTo != null) { cm.display.sizer.style.minWidth = op.adjustWidthTo + "px" if (op.maxScrollLeft < cm.doc.scrollLeft) { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) } cm.display.maxLineChanged = false } - var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()) + var takeFocus = op.focus && op.focus == activeElt() if (op.preparedSelection) { cm.display.input.showSelection(op.preparedSelection, takeFocus) } if (op.updatedDisplay || op.startHeight != cm.doc.height) { updateScrollbars(cm, op.barMeasure) } if (op.updatedDisplay) { setDocumentHeight(cm, op.barMeasure) } if (op.selectionChanged) { restartBlink(cm) } @@ -5606,17 +5603,18 @@ var CodeMirror = if (changeHandler) { signalLater(cm, "change", cm, obj) } if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) } } cm.display.selForContextMenu = null } function replaceRange(doc, code, from, to, origin) { if (!to) { to = from } - if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp } + if (cmp(to, from) < 0) { var assign; + (assign = [to, from], from = assign[0], to = assign[1], assign) } if (typeof code == "string") { code = doc.splitLines(code) } makeChange(doc, {from: from, to: to, text: code, origin: origin}) } // Rebasing/resetting history to deal with externally-sourced changes function rebaseHistSelSingle(pos, from, to, diff) { if (to < pos.line) { @@ -6968,16 +6966,122 @@ var CodeMirror = // Next, remove those actual ranges. runInOp(cm, function () { for (var i = kill.length - 1; i >= 0; i--) { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") } ensureCursorVisible(cm) }) } + function moveCharLogically(line, ch, dir) { + var target = skipExtendingChars(line.text, ch + dir, dir) + return target < 0 || target > line.text.length ? null : target + } + + function moveLogically(line, start, dir) { + var ch = moveCharLogically(line, start.ch, dir) + return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") + } + + function endOfLine(visually, cm, lineObj, lineNo, dir) { + if (visually) { + var order = getOrder(lineObj, cm.doc.direction) + if (order) { + var part = dir < 0 ? lst(order) : order[0] + var moveInStorageOrder = (dir < 0) == (part.level == 1) + var sticky = moveInStorageOrder ? "after" : "before" + var ch + // With a wrapped rtl chunk (possibly spanning multiple bidi parts), + // it could be that the last bidi part is not on the last visual line, + // since visual lines contain content order-consecutive chunks. + // Thus, in rtl, we are looking for the first (content-order) character + // in the rtl chunk that is on the last line (that is, the same line + // as the last (content-order) character). + if (part.level > 0) { + var prep = prepareMeasureForLine(cm, lineObj) + ch = dir < 0 ? lineObj.text.length - 1 : 0 + var targetTop = measureCharPrepared(cm, prep, ch).top + ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch) + if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1) } + } else { ch = dir < 0 ? part.to : part.from } + return new Pos(lineNo, ch, sticky) + } + } + return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") + } + + function moveVisually(cm, line, start, dir) { + var bidi = getOrder(line, cm.doc.direction) + if (!bidi) { return moveLogically(line, start, dir) } + if (start.ch >= line.text.length) { + start.ch = line.text.length + start.sticky = "before" + } else if (start.ch <= 0) { + start.ch = 0 + start.sticky = "after" + } + var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos] + if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { + // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, + // nothing interesting happens. + return moveLogically(line, start, dir) + } + + var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); } + var prep + var getWrappedLineExtent = function (ch) { + if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } + prep = prep || prepareMeasureForLine(cm, line) + return wrappedLineExtentChar(cm, line, prep, ch) + } + var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch) + + if (cm.doc.direction == "rtl" || part.level == 1) { + var moveInStorageOrder = (part.level == 1) == (dir < 0) + var ch = mv(start, moveInStorageOrder ? 1 : -1) + if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { + // Case 2: We move within an rtl part or in an rtl editor on the same visual line + var sticky = moveInStorageOrder ? "before" : "after" + return new Pos(start.line, ch, sticky) + } + } + + // Case 3: Could not move within this bidi part in this visual line, so leave + // the current bidi part + + var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { + var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder + ? new Pos(start.line, mv(ch, 1), "before") + : new Pos(start.line, ch, "after"); } + + for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { + var part = bidi[partPos] + var moveInStorageOrder = (dir > 0) == (part.level != 1) + var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1) + if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } + ch = moveInStorageOrder ? part.from : mv(part.to, -1) + if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } + } + } + + // Case 3a: Look for other bidi parts on the same visual line + var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent) + if (res) { return res } + + // Case 3b: Look for other bidi parts on the next visual line + var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1) + if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { + res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)) + if (res) { return res } + } + + // Case 4: Nowhere to move + return null + } + // Commands are parameter-less actions that can be performed on an // editor, mostly used for keybindings. var commands = { selectAll: selectAll, singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, killLine: function (cm) { return deleteNearSelection(cm, function (range) { if (range.empty()) { var len = getLine(cm.doc, range.head.line).text.length @@ -7529,17 +7633,17 @@ var CodeMirror = if (cmp(range.anchor, anchor) > 0) { head = range.head anchor = minPos(oldRange.from(), range.anchor) } else { head = range.anchor anchor = maxPos(oldRange.to(), range.head) } var ranges$1 = startSel.ranges.slice(0) - ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head) + ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)) setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse) } } var editorSize = display.wrapper.getBoundingClientRect() // Used to ensure timeout re-tries don't fire when another extend // happened in the meantime (clearTimeout isn't reliable -- at // least on Chrome, the timeouts still happen even when cleared, @@ -7581,23 +7685,62 @@ var CodeMirror = else { extend(e) } }) var up = operation(cm, done) cm.state.selectingText = up on(document, "mousemove", move) on(document, "mouseup", up) } + // Used when mouse-selecting to adjust the anchor to the proper side + // of a bidi jump depending on the visual position of the head. + function bidiSimplify(cm, range) { + var anchor = range.anchor; + var head = range.head; + var anchorLine = getLine(cm.doc, anchor.line) + if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range } + var order = getOrder(anchorLine) + if (!order) { return range } + var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index] + if (part.from != anchor.ch && part.to != anchor.ch) { return range } + var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1) + if (boundary == 0 || boundary == order.length) { return range } + + // Compute the relative visual position of the head compared to the + // anchor (<0 is to the left, >0 to the right) + var leftSide + if (head.line != anchor.line) { + leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0 + } else { + var headIndex = getBidiPartAt(order, head.ch, head.sticky) + var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1) + if (headIndex == boundary - 1 || headIndex == boundary) + { leftSide = dir < 0 } + else + { leftSide = dir > 0 } + } + + var usePart = order[boundary + (leftSide ? -1 : 0)] + var from = leftSide == (usePart.level == 1) + var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before" + return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) + } + // Determines whether an event happened in the gutter, and fires the // handlers for the corresponding event. function gutterEvent(cm, e, type, prevent) { var mX, mY - try { mX = e.clientX; mY = e.clientY } - catch(e) { return false } + if (e.touches) { + mX = e.touches[0].clientX + mY = e.touches[0].clientY + } else { + try { mX = e.clientX; mY = e.clientY } + catch(e) { return false } + } if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } if (prevent) { e_preventDefault(e) } var display = cm.display var lineBox = display.lineDiv.getBoundingClientRect() if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } mY -= lineBox.top - display.viewOffset @@ -7925,17 +8068,17 @@ var CodeMirror = return touch.radiusX <= 1 && touch.radiusY <= 1 } function farAway(touch, other) { if (other.left == null) { return true } var dx = other.left - touch.left, dy = other.top - touch.top return dx * dx + dy * dy > 20 * 20 } on(d.scroller, "touchstart", function (e) { - if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { d.input.ensurePolled() clearTimeout(touchFinished) var now = +new Date d.activeTouch = {start: now, moved: false, prev: now - prevTouch.end <= 300 ? prevTouch : null} if (e.touches.length == 1) { d.activeTouch.left = e.touches[0].pageX d.activeTouch.top = e.touches[0].pageY @@ -9709,17 +9852,17 @@ var CodeMirror = CodeMirror.defineDocExtension = function (name, func) { Doc.prototype[name] = func } CodeMirror.fromTextArea = fromTextArea addLegacyProps(CodeMirror) - CodeMirror.version = "5.29.0" + CodeMirror.version = "5.30.0" return CodeMirror; }))); /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { @@ -10148,16 +10291,17 @@ var CodeMirror = queryDialog = doc.createElement("div"); queryDialog.appendChild(inp); queryDialog.style.display = "flex"; } var state = getSearchState(cm); if (state.query) return findNext(cm, rev); var q = cm.getSelection() || state.lastQuery; + if (q instanceof RegExp && q.source == "x^") q = null if (persistent && cm.openDialog) { var hiding = null var searchNext = function(query, event) { CodeMirror.e_stop(event); if (!query) return; if (query != state.queryText) { startSearch(cm, state, query); state.posFrom = state.posTo = cm.getCursor(); @@ -10457,31 +10601,36 @@ var CodeMirror = var Pos = CodeMirror.Pos; CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { if (old && old != CodeMirror.Init) { cm.removeKeyMap(keyMap); cm.state.closeBrackets = null; } if (val) { + ensureBound(getOption(val, "pairs")) cm.state.closeBrackets = val; cm.addKeyMap(keyMap); } }); function getOption(conf, name) { if (name == "pairs" && typeof conf == "string") return conf; if (typeof conf == "object" && conf[name] != null) return conf[name]; return defaults[name]; } - var bind = defaults.pairs + "`"; var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; - for (var i = 0; i < bind.length; i++) - keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i)); + function ensureBound(chars) { + for (var i = 0; i < chars.length; i++) { + var ch = chars.charAt(i), key = "'" + ch + "'" + if (!keyMap[key]) keyMap[key] = handler(ch) + } + } + ensureBound(defaults.pairs + "`") function handler(ch) { return function(cm) { return handleChar(cm, ch); }; } function getConfig(cm) { var deflt = cm.state.closeBrackets; if (!deflt || deflt.override) return deflt; @@ -10889,17 +11038,17 @@ var CodeMirror = var keywords = function(){ function kw(type) {return {type: type, style: "keyword"};} var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); var operator = kw("operator"), atom = {type: "atom", style: "atom"}; var jsKeywords = { "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C, + "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "void": C, "throw": C, "debugger": C, "var": kw("var"), "const": kw("var"), "let": kw("var"), "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, "this": kw("this"), "class": kw("class"), "super": kw("atom"), "yield": C, "export": kw("export"), "import": kw("import"), "extends": C, "await": C @@ -11259,17 +11408,17 @@ var CodeMirror = } function parenExpr(type) { if (type != "(") return pass() return cont(pushlex(")"), expression, expect(")"), poplex) } function expressionInner(type, noComma) { if (cx.state.fatArrowAt == cx.stream.start) { var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext); else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); } var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (type == "function") return cont(functiondef, maybeop); if (type == "class") return cont(pushlex("form"), classExpression, poplex); if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression); @@ -11304,16 +11453,21 @@ var CodeMirror = return cont(expr); } if (type == "quasi") { return pass(quasi, me); } if (type == ";") return; if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) } + if (type == "regexp") { + cx.state.lastType = cx.marked = "operator" + cx.stream.backUp(cx.stream.pos - cx.stream.start - 1) + return cont(expr) + } } function quasi(type, value) { if (type != "quasi") return pass(); if (value.slice(value.length - 2) != "${") return cont(quasi); return cont(expression, continueQuasi); } function continueQuasi(type) { if (type == "}") { @@ -11352,16 +11506,19 @@ var CodeMirror = } function objprop(type, value) { if (type == "async") { cx.marked = "property"; return cont(objprop); } else if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; if (value == "get" || value == "set") return cont(getterSetter); + var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params + if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false))) + cx.state.fatArrowAt = cx.stream.pos + m[0].length return cont(afterprop); } else if (type == "number" || type == "string") { cx.marked = jsonldMode ? "property" : (cx.style + " property"); return cont(afterprop); } else if (type == "jsonld-keyword") { return cont(afterprop); } else if (type == "modifier") { return cont(objprop) @@ -11509,17 +11666,18 @@ var CodeMirror = if (type != ")") cont(expression); } function functiondef(type, value) { if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} if (type == "variable") {register(value); return cont(functiondef);} if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext); if (isTS && value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, functiondef) } - function funarg(type) { + function funarg(type, value) { + if (value == "@") cont(expression, funarg) if (type == "spread" || type == "modifier") return cont(funarg); return pass(pattern, maybetype, maybeAssign); } function classExpression(type, value) { // Class expressions may have an optional name. if (type == "variable") return className(type, value); return classNameAfter(type, value); } @@ -11535,17 +11693,17 @@ var CodeMirror = function classBody(type, value) { if (type == "modifier" || type == "async" || (type == "variable" && (value == "static" || value == "get" || value == "set") && cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) { cx.marked = "keyword"; return cont(classBody); } - if (type == "variable") { + if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; return cont(isTS ? classfield : functiondef, classBody); } if (type == "[") return cont(expression, expect("]"), isTS ? classfield : functiondef, classBody) if (value == "*") { cx.marked = "keyword"; return cont(classBody); @@ -11597,17 +11755,17 @@ var CodeMirror = function isContinuedStatement(state, textAfter) { return state.lastType == "operator" || state.lastType == "," || isOperatorChar.test(textAfter.charAt(0)) || /[,.]/.test(textAfter.charAt(0)); } function expressionAllowed(stream, state, backUp) { return state.tokenize == tokenBase && - /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) || + /^(?:operator|sof|keyword [bc]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) || (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) } // Interface return { startState: function(basecolumn) { var state = {
--- a/devtools/client/sourceeditor/codemirror/lib/codemirror.js +++ b/devtools/client/sourceeditor/codemirror/lib/codemirror.js @@ -273,23 +273,28 @@ function isExtendingChar(ch) { return ch // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. function skipExtendingChars(str, pos, dir) { while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir } return pos } // Returns the value from the range [`from`; `to`] that satisfies -// `pred` and is closest to `from`. Assumes that at least `to` satisfies `pred`. +// `pred` and is closest to `from`. Assumes that at least `to` +// satisfies `pred`. Supports `from` being greater than `to`. function findFirst(pred, from, to) { + // At any point we are certain `to` satisfies `pred`, don't know + // whether `from` does. + var dir = from > to ? -1 : 1 for (;;) { - if (Math.abs(from - to) <= 1) { return pred(from) ? from : to } - var mid = Math.floor((from + to) / 2) + if (from == to) { return from } + var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF) + if (mid == from) { return pred(mid) ? from : to } if (pred(mid)) { to = mid } - else { from = mid } + else { from = mid + dir } } } // The display handles the DOM integration, both for input reading // and content drawing. It holds references to DOM nodes and // display-related state. function Display(place, doc, input) { @@ -892,22 +897,22 @@ function findMaxLine(cm) { d.maxLine = line } }) } // BIDI HELPERS function iterateBidiSections(order, from, to, f) { - if (!order) { return f(from, to, "ltr") } + if (!order) { return f(from, to, "ltr", 0) } var found = false for (var i = 0; i < order.length; ++i) { var part = order[i] if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr") + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i) found = true } } if (!found) { f(from, to, "ltr") } } var bidiOther = null function getBidiPartAt(order, ch, sticky) { @@ -1100,122 +1105,16 @@ var bidiOrdering = (function() { // false for lines that are fully left-to-right, and an array of // BidiSpan objects otherwise. function getOrder(line, direction) { var order = line.order if (order == null) { order = line.order = bidiOrdering(line.text, direction) } return order } -function moveCharLogically(line, ch, dir) { - var target = skipExtendingChars(line.text, ch + dir, dir) - return target < 0 || target > line.text.length ? null : target -} - -function moveLogically(line, start, dir) { - var ch = moveCharLogically(line, start.ch, dir) - return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") -} - -function endOfLine(visually, cm, lineObj, lineNo, dir) { - if (visually) { - var order = getOrder(lineObj, cm.doc.direction) - if (order) { - var part = dir < 0 ? lst(order) : order[0] - var moveInStorageOrder = (dir < 0) == (part.level == 1) - var sticky = moveInStorageOrder ? "after" : "before" - var ch - // With a wrapped rtl chunk (possibly spanning multiple bidi parts), - // it could be that the last bidi part is not on the last visual line, - // since visual lines contain content order-consecutive chunks. - // Thus, in rtl, we are looking for the first (content-order) character - // in the rtl chunk that is on the last line (that is, the same line - // as the last (content-order) character). - if (part.level > 0) { - var prep = prepareMeasureForLine(cm, lineObj) - ch = dir < 0 ? lineObj.text.length - 1 : 0 - var targetTop = measureCharPrepared(cm, prep, ch).top - ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch) - if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1) } - } else { ch = dir < 0 ? part.to : part.from } - return new Pos(lineNo, ch, sticky) - } - } - return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") -} - -function moveVisually(cm, line, start, dir) { - var bidi = getOrder(line, cm.doc.direction) - if (!bidi) { return moveLogically(line, start, dir) } - if (start.ch >= line.text.length) { - start.ch = line.text.length - start.sticky = "before" - } else if (start.ch <= 0) { - start.ch = 0 - start.sticky = "after" - } - var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos] - if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { - // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, - // nothing interesting happens. - return moveLogically(line, start, dir) - } - - var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); } - var prep - var getWrappedLineExtent = function (ch) { - if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } - prep = prep || prepareMeasureForLine(cm, line) - return wrappedLineExtentChar(cm, line, prep, ch) - } - var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch) - - if (cm.doc.direction == "rtl" || part.level == 1) { - var moveInStorageOrder = (part.level == 1) == (dir < 0) - var ch = mv(start, moveInStorageOrder ? 1 : -1) - if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { - // Case 2: We move within an rtl part or in an rtl editor on the same visual line - var sticky = moveInStorageOrder ? "before" : "after" - return new Pos(start.line, ch, sticky) - } - } - - // Case 3: Could not move within this bidi part in this visual line, so leave - // the current bidi part - - var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { - var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder - ? new Pos(start.line, mv(ch, 1), "before") - : new Pos(start.line, ch, "after"); } - - for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { - var part = bidi[partPos] - var moveInStorageOrder = (dir > 0) == (part.level != 1) - var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1) - if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } - ch = moveInStorageOrder ? part.from : mv(part.to, -1) - if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } - } - } - - // Case 3a: Look for other bidi parts on the same visual line - var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent) - if (res) { return res } - - // Case 3b: Look for other bidi parts on the next visual line - var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1) - if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { - res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)) - if (res) { return res } - } - - // Case 4: Nowhere to move - return null -} - // EVENT HANDLING // Lightweight event framework. on/off also work on DOM nodes, // registering native DOM handlers. var noHandlers = [] var on = function(emitter, type, f) { @@ -2714,25 +2613,32 @@ function pageScrollX() { if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) } return window.pageXOffset || (document.documentElement || document.body).scrollLeft } function pageScrollY() { if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) } return window.pageYOffset || (document.documentElement || document.body).scrollTop } +function widgetTopHeight(lineObj) { + var height = 0 + if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) + { height += widgetHeight(lineObj.widgets[i]) } } } + return height +} + // Converts a {top, bottom, left, right} box from line-local // coordinates into another coordinate system. Context may be one of // "line", "div" (display.lineDiv), "local"./null (editor), "window", // or "page". function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { - if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) { - var size = widgetHeight(lineObj.widgets[i]) - rect.top += size; rect.bottom += size - } } } + if (!includeWidgets) { + var height = widgetTopHeight(lineObj) + rect.top += height; rect.bottom += height + } if (context == "line") { return rect } if (!context) { context = "local" } var yOff = heightAtLine(lineObj) if (context == "local") { yOff += paddingTop(cm.display) } else { yOff -= cm.display.viewOffset } if (context == "page" || context == "window") { var lOff = cm.display.lineSpace.getBoundingClientRect() yOff += lOff.top + (context == "window" ? 0 : pageScrollY()) @@ -2797,17 +2703,17 @@ function cursorCoords(cm, pos, context, sticky = "before" } else if (ch <= 0) { ch = 0 sticky = "after" } if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } function getBidi(ch, partPos, invert) { - var part = order[partPos], right = (part.level % 2) != 0 + var part = order[partPos], right = part.level == 1 return get(invert ? ch - 1 : ch, right != invert) } var partPos = getBidiPartAt(order, ch, sticky) var other = bidiOther var val = getBidi(ch, partPos, sticky == "before") if (other != null) { val.other = getBidi(ch, other, sticky != "before") } return val } @@ -2855,87 +2761,156 @@ function coordsChar(cm, x, y) { if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) { lineN = lineNo(lineObj = mergedPos.to.line) } else { return found } } } function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { - var measure = function (ch) { return intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line"); } + y -= widgetTopHeight(lineObj) var end = lineObj.text.length - var begin = findFirst(function (ch) { return measure(ch - 1).bottom <= y; }, end, 0) - end = findFirst(function (ch) { return measure(ch).top > y; }, begin, end) + var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0) + end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end) return {begin: begin, end: end} } function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) } var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) } +// Returns true if the given side of a box is after the given +// coordinates, in top-to-bottom, left-to-right order. +function boxIsAfter(box, x, y, left) { + return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x +} + function coordsCharInner(cm, lineObj, lineNo, x, y) { + // Move y into line-local coordinate space y -= heightAtLine(lineObj) - var begin = 0, end = lineObj.text.length var preparedMeasure = prepareMeasureForLine(cm, lineObj) - var pos + // When directly calling `measureCharPrepared`, we have to adjust + // for the widgets at this line. + var widgetHeight = widgetTopHeight(lineObj) + var begin = 0, end = lineObj.text.length, ltr = true + var order = getOrder(lineObj, cm.doc.direction) + // If the line isn't plain left-to-right text, first figure out + // which bidi section the coordinates fall into. if (order) { - if (cm.options.lineWrapping) { - ;var assign; - ((assign = wrappedLineExtent(cm, lineObj, preparedMeasure, y), begin = assign.begin, end = assign.end, assign)) - } - pos = new Pos(lineNo, Math.floor(begin + (end - begin) / 2)) - var beginLeft = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - var dir = beginLeft < x ? 1 : -1 - var prevDiff, diff = beginLeft - x, prevPos - var steps = Math.ceil((end - begin) / 4) - outer: do { - prevDiff = diff - prevPos = pos - var i = 0 - for (; i < steps; ++i) { - var prevPos$1 = pos - pos = moveVisually(cm, lineObj, pos, dir) - if (pos == null || pos.ch < begin || end <= (pos.sticky == "before" ? pos.ch - 1 : pos.ch)) { - pos = prevPos$1 - break outer - } - } - diff = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - x - if (steps > 1) { - var diff_change_per_step = Math.abs(diff - prevDiff) / steps - steps = Math.min(steps, Math.ceil(Math.abs(diff) / diff_change_per_step)) - dir = diff < 0 ? 1 : -1 - } - } while (diff != 0 && (steps > 1 || ((dir < 0) != (diff < 0) && (Math.abs(diff) <= Math.abs(prevDiff))))) - if (Math.abs(diff) > Math.abs(prevDiff)) { - if ((diff < 0) == (prevDiff < 0)) { throw new Error("Broke out of infinite loop in coordsCharInner") } - pos = prevPos - } + var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) + (cm, lineObj, lineNo, preparedMeasure, order, x, y) + ltr = part.level != 1 + // The awkward -1 offsets are needed because findFirst (called + // on these below) will treat its first bound as inclusive, + // second as exclusive, but we want to actually address the + // characters in the part's range + begin = ltr ? part.from : part.to - 1 + end = ltr ? part.to : part.from - 1 + } + + // A binary search to find the first character whose bounding box + // starts after the coordinates. If we run across any whose box wrap + // the coordinates, store that. + var chAround = null, boxAround = null + var ch = findFirst(function (ch) { + var box = measureCharPrepared(cm, preparedMeasure, ch) + box.top += widgetHeight; box.bottom += widgetHeight + if (!boxIsAfter(box, x, y, false)) { return false } + if (box.top <= y && box.left <= x) { + chAround = ch + boxAround = box + } + return true + }, begin, end) + + var baseX, sticky, outside = false + // If a box around the coordinates was found, use that + if (boxAround) { + // Distinguish coordinates nearer to the left or right side of the box + var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr + ch = chAround + (atStart ? 0 : 1) + sticky = atStart ? "after" : "before" + baseX = atLeft ? boxAround.left : boxAround.right } else { - var ch = findFirst(function (ch) { - var box = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line") - if (box.top > y) { - // For the cursor stickiness - end = Math.min(ch, end) - return true - } - else if (box.bottom <= y) { return false } - else if (box.left > x) { return true } - else if (box.right < x) { return false } - else { return (x - box.left < box.right - x) } - }, begin, end) - ch = skipExtendingChars(lineObj.text, ch, 1) - pos = new Pos(lineNo, ch, ch == end ? "before" : "after") - } - var coords = cursorCoords(cm, pos, "line", lineObj, preparedMeasure) - if (y < coords.top || coords.bottom < y) { pos.outside = true } - pos.xRel = x < coords.left ? -1 : (x > coords.right ? 1 : 0) - return pos + // (Adjust for extended bound, if necessary.) + if (!ltr && (ch == end || ch == begin)) { ch++ } + // To determine which side to associate with, get the box to the + // left of the character and compare it's vertical position to the + // coordinates + sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : + (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? + "after" : "before" + // Now get accurate coordinates for this place, in order to get a + // base X position + var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure) + baseX = coords.left + outside = y < coords.top || y >= coords.bottom + } + + ch = skipExtendingChars(lineObj.text, ch, 1) + return PosWithInfo(lineNo, ch, sticky, outside, x - baseX) +} + +function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) { + // Bidi parts are sorted left-to-right, and in a non-line-wrapping + // situation, we can take this ordering to correspond to the visual + // ordering. This finds the first part whose end is after the given + // coordinates. + var index = findFirst(function (i) { + var part = order[i], ltr = part.level != 1 + return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"), + "line", lineObj, preparedMeasure), x, y, true) + }, 0, order.length - 1) + var part = order[index] + // If this isn't the first part, the part's start is also after + // the coordinates, and the coordinates aren't on the same line as + // that start, move one part back. + if (index > 0) { + var ltr = part.level != 1 + var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"), + "line", lineObj, preparedMeasure) + if (boxIsAfter(start, x, y, true) && start.top > y) + { part = order[index - 1] } + } + return part +} + +function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { + // In a wrapped line, rtl text on wrapping boundaries can do things + // that don't correspond to the ordering in our `order` array at + // all, so a binary search doesn't work, and we want to return a + // part that only spans one line so that the binary search in + // coordsCharInner is safe. As such, we first find the extent of the + // wrapped line, and then do a flat search in which we discard any + // spans that aren't on the line. + var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); + var begin = ref.begin; + var end = ref.end; + var part = null, closestDist = null + for (var i = 0; i < order.length; i++) { + var p = order[i] + if (p.from >= end || p.to <= begin) { continue } + var ltr = p.level != 1 + var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right + // Weigh against spans ending before this, so that they are only + // picked if nothing ends after + var dist = endX < x ? x - endX + 1e9 : endX - x + if (!part || closestDist > dist) { + part = p + closestDist = dist + } + } + if (!part) { part = order[order.length - 1] } + // Clip the part to the wrapped line. + if (part.from < begin) { part = {from: begin, to: part.to, level: part.level} } + if (part.to > end) { part = {from: part.from, to: end, level: part.level} } + return part } var measureText // Compute the default text height. function textHeight(display) { if (display.cachedTextHeight != null) { return display.cachedTextHeight } if (measureText == null) { measureText = elt("pre") @@ -3051,22 +3026,24 @@ function findViewIndex(cm, n) { } } function updateSelection(cm) { cm.display.input.showSelection(cm.display.input.prepareSelection()) } function prepareSelection(cm, primary) { + if ( primary === void 0 ) primary = true; + var doc = cm.doc, result = {} var curFragment = result.cursors = document.createDocumentFragment() var selFragment = result.selection = document.createDocumentFragment() for (var i = 0; i < doc.sel.ranges.length; i++) { - if (primary === false && i == doc.sel.primIndex) { continue } + if (!primary && i == doc.sel.primIndex) { continue } var range = doc.sel.ranges[i] if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } var collapsed = range.empty() if (collapsed || cm.options.showCursorWhenSelecting) { drawSelectionCursor(cm, range.head, curFragment) } if (!collapsed) { drawSelectionRange(cm, range, selFragment) } } @@ -3087,16 +3064,18 @@ function drawSelectionCursor(cm, head, o var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")) otherCursor.style.display = "" otherCursor.style.left = pos.other.left + "px" otherCursor.style.top = pos.other.top + "px" otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px" } } +function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } + // Draws the given range as a highlighted selection function drawSelectionRange(cm, range, output) { var display = cm.display, doc = cm.doc var fragment = document.createDocumentFragment() var padding = paddingH(cm.display), leftSide = padding.left var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right function add(left, top, width, bottom) { @@ -3109,40 +3088,58 @@ function drawSelectionRange(cm, range, o function drawForLine(line, fromArg, toArg) { var lineObj = getLine(doc, line) var lineLen = lineObj.text.length var start, end function coords(ch, bias) { return charCoords(cm, Pos(line, ch), "div", lineObj, bias) } - iterateBidiSections(getOrder(lineObj, doc.direction), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) { - var leftPos = coords(from, "left"), rightPos, left, right - if (from == to) { - rightPos = leftPos - left = right = leftPos.left - } else { - rightPos = coords(to - 1, "right") - if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp } - left = leftPos.left - right = rightPos.right + var order = getOrder(lineObj, doc.direction) + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { + var fromPos = coords(from, dir == "ltr" ? "left" : "right") + var toPos = coords(to - 1, dir == "ltr" ? "right" : "left") + if (dir == "ltr") { + var fromLeft = fromArg == null && from == 0 ? leftSide : fromPos.left + var toRight = toArg == null && to == lineLen ? rightSide : toPos.right + if (toPos.top - fromPos.top <= 3) { // Single line + add(fromLeft, toPos.top, toRight - fromLeft, toPos.bottom) + } else { // Multiple lines + add(fromLeft, fromPos.top, null, fromPos.bottom) + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top) } + add(leftSide, toPos.top, toPos.right, toPos.bottom) + } + } else if (from < to) { // RTL + var fromRight = fromArg == null && from == 0 ? rightSide : fromPos.right + var toLeft = toArg == null && to == lineLen ? leftSide : toPos.left + if (toPos.top - fromPos.top <= 3) { // Single line + add(toLeft, toPos.top, fromRight - toLeft, toPos.bottom) + } else { // Multiple lines + var topLeft = leftSide + if (i) { + var topEnd = wrappedLineExtentChar(cm, lineObj, null, from).end + // The coordinates returned for an RTL wrapped space tend to + // be complete bogus, so try to skip that here. + topLeft = coords(topEnd - (/\s/.test(lineObj.text.charAt(topEnd - 1)) ? 2 : 1), "left").left + } + add(topLeft, fromPos.top, fromRight - topLeft, fromPos.bottom) + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top) } + var botWidth = null + if (i < order.length - 1 || true) { + var botStart = wrappedLineExtentChar(cm, lineObj, null, to).begin + botWidth = coords(botStart, "right").right - toLeft + } + add(toLeft, toPos.top, botWidth, toPos.bottom) + } } - if (fromArg == null && from == 0) { left = leftSide } - if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part - add(left, leftPos.top, null, leftPos.bottom) - left = leftSide - if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top) } - } - if (toArg == null && to == lineLen) { right = rightSide } - if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) - { start = leftPos } - if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) - { end = rightPos } - if (left < leftSide + 1) { left = leftSide } - add(left, rightPos.top, right - left, rightPos.bottom) + + if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos } + if (cmpCoords(toPos, start) < 0) { start = toPos } + if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos } + if (cmpCoords(toPos, end) < 0) { end = toPos } }) return {start: start, end: end} } var sFrom = range.from(), sTo = range.to() if (sFrom.line == sTo.line) { drawForLine(sFrom.line, sFrom.ch, sTo.ch) } else { @@ -3762,30 +3759,30 @@ function endOperation_R2(op) { op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3 cm.display.sizerWidth = op.adjustWidthTo op.barMeasure.scrollWidth = Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth) op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)) } if (op.updatedDisplay || op.selectionChanged) - { op.preparedSelection = display.input.prepareSelection(op.focus) } + { op.preparedSelection = display.input.prepareSelection() } } function endOperation_W2(op) { var cm = op.cm if (op.adjustWidthTo != null) { cm.display.sizer.style.minWidth = op.adjustWidthTo + "px" if (op.maxScrollLeft < cm.doc.scrollLeft) { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) } cm.display.maxLineChanged = false } - var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()) + var takeFocus = op.focus && op.focus == activeElt() if (op.preparedSelection) { cm.display.input.showSelection(op.preparedSelection, takeFocus) } if (op.updatedDisplay || op.startHeight != cm.doc.height) { updateScrollbars(cm, op.barMeasure) } if (op.updatedDisplay) { setDocumentHeight(cm, op.barMeasure) } if (op.selectionChanged) { restartBlink(cm) } @@ -5364,17 +5361,18 @@ function makeChangeSingleDocInEditor(cm, if (changeHandler) { signalLater(cm, "change", cm, obj) } if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) } } cm.display.selForContextMenu = null } function replaceRange(doc, code, from, to, origin) { if (!to) { to = from } - if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp } + if (cmp(to, from) < 0) { var assign; + (assign = [to, from], from = assign[0], to = assign[1], assign) } if (typeof code == "string") { code = doc.splitLines(code) } makeChange(doc, {from: from, to: to, text: code, origin: origin}) } // Rebasing/resetting history to deal with externally-sourced changes function rebaseHistSelSingle(pos, from, to, diff) { if (to < pos.line) { @@ -6726,16 +6724,122 @@ function deleteNearSelection(cm, compute // Next, remove those actual ranges. runInOp(cm, function () { for (var i = kill.length - 1; i >= 0; i--) { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") } ensureCursorVisible(cm) }) } +function moveCharLogically(line, ch, dir) { + var target = skipExtendingChars(line.text, ch + dir, dir) + return target < 0 || target > line.text.length ? null : target +} + +function moveLogically(line, start, dir) { + var ch = moveCharLogically(line, start.ch, dir) + return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") +} + +function endOfLine(visually, cm, lineObj, lineNo, dir) { + if (visually) { + var order = getOrder(lineObj, cm.doc.direction) + if (order) { + var part = dir < 0 ? lst(order) : order[0] + var moveInStorageOrder = (dir < 0) == (part.level == 1) + var sticky = moveInStorageOrder ? "after" : "before" + var ch + // With a wrapped rtl chunk (possibly spanning multiple bidi parts), + // it could be that the last bidi part is not on the last visual line, + // since visual lines contain content order-consecutive chunks. + // Thus, in rtl, we are looking for the first (content-order) character + // in the rtl chunk that is on the last line (that is, the same line + // as the last (content-order) character). + if (part.level > 0) { + var prep = prepareMeasureForLine(cm, lineObj) + ch = dir < 0 ? lineObj.text.length - 1 : 0 + var targetTop = measureCharPrepared(cm, prep, ch).top + ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch) + if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1) } + } else { ch = dir < 0 ? part.to : part.from } + return new Pos(lineNo, ch, sticky) + } + } + return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") +} + +function moveVisually(cm, line, start, dir) { + var bidi = getOrder(line, cm.doc.direction) + if (!bidi) { return moveLogically(line, start, dir) } + if (start.ch >= line.text.length) { + start.ch = line.text.length + start.sticky = "before" + } else if (start.ch <= 0) { + start.ch = 0 + start.sticky = "after" + } + var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos] + if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { + // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, + // nothing interesting happens. + return moveLogically(line, start, dir) + } + + var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); } + var prep + var getWrappedLineExtent = function (ch) { + if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } + prep = prep || prepareMeasureForLine(cm, line) + return wrappedLineExtentChar(cm, line, prep, ch) + } + var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch) + + if (cm.doc.direction == "rtl" || part.level == 1) { + var moveInStorageOrder = (part.level == 1) == (dir < 0) + var ch = mv(start, moveInStorageOrder ? 1 : -1) + if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { + // Case 2: We move within an rtl part or in an rtl editor on the same visual line + var sticky = moveInStorageOrder ? "before" : "after" + return new Pos(start.line, ch, sticky) + } + } + + // Case 3: Could not move within this bidi part in this visual line, so leave + // the current bidi part + + var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { + var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder + ? new Pos(start.line, mv(ch, 1), "before") + : new Pos(start.line, ch, "after"); } + + for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { + var part = bidi[partPos] + var moveInStorageOrder = (dir > 0) == (part.level != 1) + var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1) + if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } + ch = moveInStorageOrder ? part.from : mv(part.to, -1) + if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } + } + } + + // Case 3a: Look for other bidi parts on the same visual line + var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent) + if (res) { return res } + + // Case 3b: Look for other bidi parts on the next visual line + var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1) + if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { + res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)) + if (res) { return res } + } + + // Case 4: Nowhere to move + return null +} + // Commands are parameter-less actions that can be performed on an // editor, mostly used for keybindings. var commands = { selectAll: selectAll, singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, killLine: function (cm) { return deleteNearSelection(cm, function (range) { if (range.empty()) { var len = getLine(cm.doc, range.head.line).text.length @@ -7287,17 +7391,17 @@ function leftButtonSelect(cm, event, sta if (cmp(range.anchor, anchor) > 0) { head = range.head anchor = minPos(oldRange.from(), range.anchor) } else { head = range.anchor anchor = maxPos(oldRange.to(), range.head) } var ranges$1 = startSel.ranges.slice(0) - ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head) + ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)) setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse) } } var editorSize = display.wrapper.getBoundingClientRect() // Used to ensure timeout re-tries don't fire when another extend // happened in the meantime (clearTimeout isn't reliable -- at // least on Chrome, the timeouts still happen even when cleared, @@ -7339,23 +7443,62 @@ function leftButtonSelect(cm, event, sta else { extend(e) } }) var up = operation(cm, done) cm.state.selectingText = up on(document, "mousemove", move) on(document, "mouseup", up) } +// Used when mouse-selecting to adjust the anchor to the proper side +// of a bidi jump depending on the visual position of the head. +function bidiSimplify(cm, range) { + var anchor = range.anchor; + var head = range.head; + var anchorLine = getLine(cm.doc, anchor.line) + if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range } + var order = getOrder(anchorLine) + if (!order) { return range } + var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index] + if (part.from != anchor.ch && part.to != anchor.ch) { return range } + var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1) + if (boundary == 0 || boundary == order.length) { return range } + + // Compute the relative visual position of the head compared to the + // anchor (<0 is to the left, >0 to the right) + var leftSide + if (head.line != anchor.line) { + leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0 + } else { + var headIndex = getBidiPartAt(order, head.ch, head.sticky) + var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1) + if (headIndex == boundary - 1 || headIndex == boundary) + { leftSide = dir < 0 } + else + { leftSide = dir > 0 } + } + + var usePart = order[boundary + (leftSide ? -1 : 0)] + var from = leftSide == (usePart.level == 1) + var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before" + return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) +} + // Determines whether an event happened in the gutter, and fires the // handlers for the corresponding event. function gutterEvent(cm, e, type, prevent) { var mX, mY - try { mX = e.clientX; mY = e.clientY } - catch(e) { return false } + if (e.touches) { + mX = e.touches[0].clientX + mY = e.touches[0].clientY + } else { + try { mX = e.clientX; mY = e.clientY } + catch(e) { return false } + } if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } if (prevent) { e_preventDefault(e) } var display = cm.display var lineBox = display.lineDiv.getBoundingClientRect() if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } mY -= lineBox.top - display.viewOffset @@ -7683,17 +7826,17 @@ function registerEventHandlers(cm) { return touch.radiusX <= 1 && touch.radiusY <= 1 } function farAway(touch, other) { if (other.left == null) { return true } var dx = other.left - touch.left, dy = other.top - touch.top return dx * dx + dy * dy > 20 * 20 } on(d.scroller, "touchstart", function (e) { - if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { d.input.ensurePolled() clearTimeout(touchFinished) var now = +new Date d.activeTouch = {start: now, moved: false, prev: now - prevTouch.end <= 300 ? prevTouch : null} if (e.touches.length == 1) { d.activeTouch.left = e.touches[0].pageX d.activeTouch.top = e.touches[0].pageY @@ -9467,13 +9610,13 @@ CodeMirror.defineExtension = function (n CodeMirror.defineDocExtension = function (name, func) { Doc.prototype[name] = func } CodeMirror.fromTextArea = fromTextArea addLegacyProps(CodeMirror) -CodeMirror.version = "5.29.0" +CodeMirror.version = "5.30.0" return CodeMirror; }))); \ No newline at end of file
--- a/devtools/client/sourceeditor/codemirror/mode/javascript/javascript.js +++ b/devtools/client/sourceeditor/codemirror/mode/javascript/javascript.js @@ -23,17 +23,17 @@ CodeMirror.defineMode("javascript", func var keywords = function(){ function kw(type) {return {type: type, style: "keyword"};} var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); var operator = kw("operator"), atom = {type: "atom", style: "atom"}; var jsKeywords = { "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C, + "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "void": C, "throw": C, "debugger": C, "var": kw("var"), "const": kw("var"), "let": kw("var"), "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, "this": kw("this"), "class": kw("class"), "super": kw("atom"), "yield": C, "export": kw("export"), "import": kw("import"), "extends": C, "await": C @@ -393,17 +393,17 @@ CodeMirror.defineMode("javascript", func } function parenExpr(type) { if (type != "(") return pass() return cont(pushlex(")"), expression, expect(")"), poplex) } function expressionInner(type, noComma) { if (cx.state.fatArrowAt == cx.stream.start) { var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext); else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); } var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (type == "function") return cont(functiondef, maybeop); if (type == "class") return cont(pushlex("form"), classExpression, poplex); if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression); @@ -438,16 +438,21 @@ CodeMirror.defineMode("javascript", func return cont(expr); } if (type == "quasi") { return pass(quasi, me); } if (type == ";") return; if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) } + if (type == "regexp") { + cx.state.lastType = cx.marked = "operator" + cx.stream.backUp(cx.stream.pos - cx.stream.start - 1) + return cont(expr) + } } function quasi(type, value) { if (type != "quasi") return pass(); if (value.slice(value.length - 2) != "${") return cont(quasi); return cont(expression, continueQuasi); } function continueQuasi(type) { if (type == "}") { @@ -486,16 +491,19 @@ CodeMirror.defineMode("javascript", func } function objprop(type, value) { if (type == "async") { cx.marked = "property"; return cont(objprop); } else if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; if (value == "get" || value == "set") return cont(getterSetter); + var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params + if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false))) + cx.state.fatArrowAt = cx.stream.pos + m[0].length return cont(afterprop); } else if (type == "number" || type == "string") { cx.marked = jsonldMode ? "property" : (cx.style + " property"); return cont(afterprop); } else if (type == "jsonld-keyword") { return cont(afterprop); } else if (type == "modifier") { return cont(objprop) @@ -643,17 +651,18 @@ CodeMirror.defineMode("javascript", func if (type != ")") cont(expression); } function functiondef(type, value) { if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} if (type == "variable") {register(value); return cont(functiondef);} if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext); if (isTS && value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, functiondef) } - function funarg(type) { + function funarg(type, value) { + if (value == "@") cont(expression, funarg) if (type == "spread" || type == "modifier") return cont(funarg); return pass(pattern, maybetype, maybeAssign); } function classExpression(type, value) { // Class expressions may have an optional name. if (type == "variable") return className(type, value); return classNameAfter(type, value); } @@ -669,17 +678,17 @@ CodeMirror.defineMode("javascript", func function classBody(type, value) { if (type == "modifier" || type == "async" || (type == "variable" && (value == "static" || value == "get" || value == "set") && cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) { cx.marked = "keyword"; return cont(classBody); } - if (type == "variable") { + if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; return cont(isTS ? classfield : functiondef, classBody); } if (type == "[") return cont(expression, expect("]"), isTS ? classfield : functiondef, classBody) if (value == "*") { cx.marked = "keyword"; return cont(classBody); @@ -731,17 +740,17 @@ CodeMirror.defineMode("javascript", func function isContinuedStatement(state, textAfter) { return state.lastType == "operator" || state.lastType == "," || isOperatorChar.test(textAfter.charAt(0)) || /[,.]/.test(textAfter.charAt(0)); } function expressionAllowed(stream, state, backUp) { return state.tokenize == tokenBase && - /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) || + /^(?:operator|sof|keyword [bc]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) || (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) } // Interface return { startState: function(basecolumn) { var state = {
--- a/devtools/client/sourceeditor/test/codemirror/test.js +++ b/devtools/client/sourceeditor/test/codemirror/test.js @@ -249,16 +249,21 @@ testCM("coordsCharBidi", function(cm) { var coords = cm.charCoords(Pos(line, ch), sys); var pos = cm.coordsChar({left: coords.left + 1, top: coords.top + 1}, sys); eqCharPos(pos, Pos(line, ch)); } } } }, {lineNumbers: true}); +testCM("badBidiOptimization", function(cm) { + var coords = cm.charCoords(Pos(0, 34)) + eqCharPos(cm.coordsChar({left: coords.right, top: coords.top + 2}), Pos(0, 34)) +}, {value: "----------<p class=\"title\">هل يمكنك اختيار مستوى قسط التأمين الذي ترغب بدفعه؟</p>"}) + testCM("posFromIndex", function(cm) { cm.setValue( "This function should\n" + "convert a zero based index\n" + "to line and ch." ); var examples = [ @@ -1151,16 +1156,26 @@ testCM("measureWrappedEndOfLine", functi if (i == 1) { var node = document.createElement("div"); node.innerHTML = "hi"; node.style.height = "30px"; cm.addLineWidget(0, node, {above: true}); } } }, {mode: "text/html", value: "0123456789abcde0123456789", lineWrapping: true}, ie_lt8 || opera_lt10); +testCM("measureEndOfLineBidi", function(cm) { + eqCursorPos(cm.coordsChar({left: 5000, top: cm.charCoords(Pos(0, 0)).top}), Pos(0, 8, "after")) +}, {value: "إإإإuuuuإإإإ"}) + +testCM("measureWrappedBidiLevel2", function(cm) { + cm.setSize(cm.charCoords(Pos(0, 6), "editor").right + 60) + var c9 = cm.charCoords(Pos(0, 9)) + eqCharPos(cm.coordsChar({left: c9.right - 1, top: c9.top + 1}), Pos(0, 9)) +}, {value: "foobar إإ إإ إإ إإ 555 بببببب", lineWrapping: true}) + testCM("measureWrappedBeginOfLine", function(cm) { if (phantom) return; cm.setSize(null, "auto"); var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild; var lh = inner.offsetHeight; for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) { cm.setSize(w); if (inner.offsetHeight < 2.5 * lh) { @@ -2463,16 +2478,33 @@ function testCoordsWrappedBidi(str) { testCoordsWrappedBidi("Count ١ ٢ ٣ ٤"); /* for (var i = 0; i < 5; ++i) { testCoordsWrappedBidi(getString(50)); } */ +testCM("rtl_wrapped_selection", function(cm) { + cm.setSelection(Pos(0, 10), Pos(0, 190)) + is(byClassName(cm.getWrapperElement(), "CodeMirror-selected").length >= 3) +}, {value: new Array(10).join(" فتي تم تضمينها فتي تم"), lineWrapping: true}) + +testCM("bidi_wrapped_selection", function(cm) { + if (phantom) return + cm.setSize(cm.charCoords(Pos(0, 10), "editor").left) + cm.setSelection(Pos(0, 37), Pos(0, 80)) + var blocks = byClassName(cm.getWrapperElement(), "CodeMirror-selected") + is(blocks.length >= 2) + is(blocks.length <= 3) + var boxTop = blocks[0].getBoundingClientRect(), boxBot = blocks[blocks.length - 1].getBoundingClientRect() + is(boxTop.left > cm.charCoords(Pos(0, 1)).right) + is(boxBot.right < cm.charCoords(Pos(0, cm.getLine(0).length - 2)).left) +}, {value: "<p>مفتي11 تم تضمينهفتي تم تضمينها فتي تفتي تم تضمينها فتي تفتي تم تضمينها فتي تفتي تم تضمينها فتي تا فت10ي ت</p>", lineWrapping: true}) + testCM("delete_wrapped", function(cm) { makeItWrapAfter(cm, Pos(0, 2)); cm.doc.setCursor(Pos(0, 3, "after")); cm.deleteH(-1, "char"); eq(cm.getLine(0), "1245"); }, {value: "12345", lineWrapping: true}) CodeMirror.defineMode("lookahead_mode", function() {
--- a/dom/base/ChildIterator.cpp +++ b/dom/base/ChildIterator.cpp @@ -3,17 +3,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ChildIterator.h" #include "nsContentUtils.h" #include "mozilla/dom/XBLChildrenElement.h" #include "mozilla/dom/HTMLContentElement.h" -#include "mozilla/dom/HTMLShadowElement.h" #include "mozilla/dom/ShadowRoot.h" #include "nsIAnonymousContentCreator.h" #include "nsIFrame.h" #include "nsCSSAnonBoxes.h" namespace mozilla { namespace dom { @@ -73,27 +72,16 @@ ExplicitChildIterator::GetNextChild() MOZ_ASSERT(!mDefaultChild); MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild); if (mIndexInInserted < assignedChildren.Length()) { return assignedChildren[mIndexInInserted++]; } mIndexInInserted = 0; mChild = mChild->GetNextSibling(); - } else if (mShadowIterator) { - // If we're inside of a <shadow> element, look through the - // explicit children of the projected ShadowRoot via - // the mShadowIterator. - nsIContent* nextChild = mShadowIterator->GetNextChild(); - if (nextChild) { - return nextChild; - } - - mShadowIterator = nullptr; - mChild = mChild->GetNextSibling(); } else if (mDefaultChild) { // If we're already in default content, check if there are more nodes there MOZ_ASSERT(mChild); MOZ_ASSERT(nsContentUtils::IsContentInsertionPoint(mChild)); mDefaultChild = mDefaultChild->GetNextSibling(); if (mDefaultChild) { return mDefaultChild; @@ -105,33 +93,17 @@ ExplicitChildIterator::GetNextChild() mIsFirst = false; } else if (mChild) { // in the middle of the child list mChild = mChild->GetNextSibling(); } // Iterate until we find a non-insertion point, or an insertion point with // content. while (mChild) { - // If the current child being iterated is a shadow insertion point then - // the iterator needs to go into the projected ShadowRoot. - if (ShadowRoot::IsShadowInsertionPoint(mChild)) { - // Look for the next child in the projected ShadowRoot for the <shadow> - // element. - HTMLShadowElement* shadowElem = HTMLShadowElement::FromContent(mChild); - ShadowRoot* projectedShadow = shadowElem->GetOlderShadowRoot(); - if (projectedShadow) { - mShadowIterator = new ExplicitChildIterator(projectedShadow); - nsIContent* nextChild = mShadowIterator->GetNextChild(); - if (nextChild) { - return nextChild; - } - mShadowIterator = nullptr; - } - mChild = mChild->GetNextSibling(); - } else if (nsContentUtils::IsContentInsertionPoint(mChild)) { + if (nsContentUtils::IsContentInsertionPoint(mChild)) { // If the current child being iterated is a content insertion point // then the iterator needs to return the nodes distributed into // the content insertion point. MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild); if (!assignedChildren.IsEmpty()) { // Iterate through elements projected on insertion point. mIndexInInserted = 1; return assignedChildren[0]; @@ -191,21 +163,19 @@ FlattenedChildIterator::Init(bool aIgnor bool ExplicitChildIterator::Seek(nsIContent* aChildToFind) { if (aChildToFind->GetParent() == mParent && !aChildToFind->IsRootOfAnonymousSubtree()) { // Fast path: just point ourselves to aChildToFind, which is a // normal DOM child of ours. - MOZ_ASSERT(!ShadowRoot::IsShadowInsertionPoint(aChildToFind)); MOZ_ASSERT(!nsContentUtils::IsContentInsertionPoint(aChildToFind)); mChild = aChildToFind; mIndexInInserted = 0; - mShadowIterator = nullptr; mDefaultChild = nullptr; mIsFirst = false; return true; } // Can we add more fast paths here based on whether the parent of aChildToFind // is a shadow insertion point or content insertion point? @@ -216,41 +186,33 @@ ExplicitChildIterator::Seek(nsIContent* nsIContent* ExplicitChildIterator::Get() const { MOZ_ASSERT(!mIsFirst); if (mIndexInInserted) { MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild); return assignedChildren[mIndexInInserted - 1]; - } else if (mShadowIterator) { - return mShadowIterator->Get(); } + return mDefaultChild ? mDefaultChild : mChild; } nsIContent* ExplicitChildIterator::GetPreviousChild() { // If we're already in the inserted-children array, look there first if (mIndexInInserted) { // NB: mIndexInInserted points one past the last returned child so we need // to look *two* indices back in order to return the previous child. MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild); if (--mIndexInInserted) { return assignedChildren[mIndexInInserted - 1]; } mChild = mChild->GetPreviousSibling(); - } else if (mShadowIterator) { - nsIContent* previousChild = mShadowIterator->GetPreviousChild(); - if (previousChild) { - return previousChild; - } - mShadowIterator = nullptr; - mChild = mChild->GetPreviousSibling(); } else if (mDefaultChild) { // If we're already in default content, check if there are more nodes there mDefaultChild = mDefaultChild->GetPreviousSibling(); if (mDefaultChild) { return mDefaultChild; } mChild = mChild->GetPreviousSibling(); @@ -260,32 +222,17 @@ ExplicitChildIterator::GetPreviousChild( mChild = mChild->GetPreviousSibling(); } else { // at the end of the child list mChild = mParent->GetLastChild(); } // Iterate until we find a non-insertion point, or an insertion point with // content. while (mChild) { - if (ShadowRoot::IsShadowInsertionPoint(mChild)) { - // If the current child being iterated is a shadow insertion point then - // the iterator needs to go into the projected ShadowRoot. - HTMLShadowElement* shadowElem = HTMLShadowElement::FromContent(mChild); - ShadowRoot* projectedShadow = shadowElem->GetOlderShadowRoot(); - if (projectedShadow) { - // Create a ExplicitChildIterator that begins iterating from the end. - mShadowIterator = new ExplicitChildIterator(projectedShadow, false); - nsIContent* previousChild = mShadowIterator->GetPreviousChild(); - if (previousChild) { - return previousChild; - } - mShadowIterator = nullptr; - } - mChild = mChild->GetPreviousSibling(); - } else if (nsContentUtils::IsContentInsertionPoint(mChild)) { + if (nsContentUtils::IsContentInsertionPoint(mChild)) { // If the current child being iterated is a content insertion point // then the iterator needs to return the nodes distributed into // the content insertion point. MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild); if (!assignedChildren.IsEmpty()) { mIndexInInserted = assignedChildren.Length(); return assignedChildren[mIndexInInserted - 1]; }
--- a/dom/base/ChildIterator.h +++ b/dom/base/ChildIterator.h @@ -43,26 +43,22 @@ public: mIsFirst(aStartAtBeginning), mIndexInInserted(0) { } ExplicitChildIterator(const ExplicitChildIterator& aOther) : mParent(aOther.mParent), mChild(aOther.mChild), mDefaultChild(aOther.mDefaultChild), - mShadowIterator(aOther.mShadowIterator ? - new ExplicitChildIterator(*aOther.mShadowIterator) : - nullptr), mIsFirst(aOther.mIsFirst), mIndexInInserted(aOther.mIndexInInserted) {} ExplicitChildIterator(ExplicitChildIterator&& aOther) : mParent(aOther.mParent), mChild(aOther.mChild), mDefaultChild(aOther.mDefaultChild), - mShadowIterator(Move(aOther.mShadowIterator)), mIsFirst(aOther.mIsFirst), mIndexInInserted(aOther.mIndexInInserted) {} nsIContent* GetNextChild(); // Looks for aChildToFind respecting insertion points until aChildToFind is // found. This version can take shortcuts that the two-argument version // can't, so can be faster (and in fact can be O(1) instead of O(N) in many @@ -111,21 +107,16 @@ protected: nsIContent* mChild; // If non-null, this points to the current default content for the current // insertion point that we're iterating (i.e. mChild, which must be an // nsXBLChildrenElement or HTMLContentElement). Once this transitions back // to null, we continue iterating at mChild's next sibling. nsIContent* mDefaultChild; - // If non-null, this points to an iterator of the explicit children of - // the ShadowRoot projected by the current shadow element that we're - // iterating. - nsAutoPtr<ExplicitChildIterator> mShadowIterator; - // A flag to let us know that we haven't started iterating yet. bool mIsFirst; // If not zero, we're iterating inserted children for an insertion point. This // is an index into mChild's inserted children array (mChild must be an // nsXBLChildrenElement). The index is one past the "current" child (as // opposed to mChild which represents the "current" child). uint32_t mIndexInInserted;
--- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -934,17 +934,17 @@ DoUpgrade(Element* aElement, aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } } } // anonymous namespace // https://html.spec.whatwg.org/multipage/scripting.html#upgrades -void +/* static */ void CustomElementRegistry::Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv) { aElement->RemoveStates(NS_EVENT_STATE_UNRESOLVED); RefPtr<CustomElementData> data = aElement->GetCustomElementData(); MOZ_ASSERT(data, "CustomElementData should exist"); @@ -972,18 +972,20 @@ CustomElementRegistry::Upgrade(Element* namespaceURI); LifecycleCallbackArgs args = { nsDependentAtomString(attrName), VoidString(), (attrValue.IsEmpty() ? VoidString() : attrValue), (namespaceURI.IsEmpty() ? VoidString() : namespaceURI) }; - EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, aElement, - &args, aDefinition); + nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(), + nsIDocument::eAttributeChanged, + aElement, + &args, aDefinition); } } } // Step 4. // TODO: Bug 1334043 - Implement connected lifecycle callbacks for custom elements // Step 5. @@ -998,17 +1000,19 @@ CustomElementRegistry::Upgrade(Element* data->mReactionQueue.Clear(); return; } // Step 8. data->mState = CustomElementData::State::eCustom; // This is for old spec. - EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition); + nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(), + nsIDocument::eCreated, + aElement, nullptr, aDefinition); } //----------------------------------------------------- // CustomElementReactionsStack void CustomElementReactionsStack::CreateAndPushElementQueue() {
--- a/dom/base/CustomElementRegistry.h +++ b/dom/base/CustomElementRegistry.h @@ -357,32 +357,33 @@ public: void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType, Element* aCustomElement, LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition); void GetCustomPrototype(nsIAtom* aAtom, JS::MutableHandle<JSObject*> aPrototype); + void SyncInvokeReactions(nsIDocument::ElementCallbackType aType, + Element* aCustomElement, + CustomElementDefinition* aDefinition); + /** * Upgrade an element. * https://html.spec.whatwg.org/multipage/scripting.html#upgrades */ - void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv); + static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv); private: ~CustomElementRegistry(); UniquePtr<CustomElementCallback> CreateCustomElementCallback( nsIDocument::ElementCallbackType aType, Element* aCustomElement, LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition); - void SyncInvokeReactions(nsIDocument::ElementCallbackType aType, - Element* aCustomElement, - CustomElementDefinition* aDefinition); /** * Registers an unresolved custom element that is a candidate for * upgrade when the definition is registered via registerElement. * |aTypeName| is the name of the custom element type, if it is not * provided, then element name is used. |aTypeName| should be provided * when registering a custom element that extends an existing * element. e.g. <button is="x-button">. */
--- a/dom/base/DocumentFragment.cpp +++ b/dom/base/DocumentFragment.cpp @@ -106,19 +106,17 @@ DocumentFragment::Constructor(const Glob if (!window || !window->GetDoc()) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } return window->GetDoc()->CreateDocumentFragment(); } -NS_IMPL_CYCLE_COLLECTION_INHERITED(DocumentFragment, - FragmentOrElement, - mHost) +NS_IMPL_CYCLE_COLLECTION_INHERITED(DocumentFragment, FragmentOrElement, mHost) // QueryInterface implementation for DocumentFragment NS_INTERFACE_MAP_BEGIN(DocumentFragment) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(DocumentFragment) NS_INTERFACE_MAP_ENTRY(nsIContent) NS_INTERFACE_MAP_ENTRY(nsINode) NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentFragment)
--- a/dom/base/DocumentFragment.h +++ b/dom/base/DocumentFragment.h @@ -38,18 +38,17 @@ public: using FragmentOrElement::GetFirstChild; using nsINode::QuerySelector; using nsINode::QuerySelectorAll; // Make sure bindings can see our superclass' protected GetElementById method. using nsINode::GetElementById; // nsISupports NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocumentFragment, - FragmentOrElement) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocumentFragment, FragmentOrElement) // interface nsIDOMNode NS_FORWARD_NSIDOMNODE_TO_NSINODE // interface nsIDOMDocumentFragment NS_DECL_NSIDOMDOCUMENTFRAGMENT explicit DocumentFragment(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) @@ -117,25 +116,19 @@ public: NS_ASSERTION(false, "Trying to unbind a fragment from a tree"); } virtual Element* GetNameSpaceElement() override { return nullptr; } - Element* GetHost() const - { - return mHost; - } + Element* GetHost() const { return mHost; } - void SetHost(Element* aHost) - { - mHost = aHost; - } + void SetHost(Element* aHost) { mHost = aHost; } static already_AddRefed<DocumentFragment> Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); #ifdef DEBUG virtual void List(FILE* out, int32_t aIndent) const override; virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override; #endif
--- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1101,16 +1101,21 @@ Element::RemoveFromIdTable() doc->RemoveFromIdTable(this, id); } } } already_AddRefed<ShadowRoot> Element::CreateShadowRoot(ErrorResult& aError) { + if (GetShadowRoot()) { + aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return nullptr; + } + nsAutoScriptBlocker scriptBlocker; RefPtr<mozilla::dom::NodeInfo> nodeInfo; nodeInfo = mNodeInfo->NodeInfoManager()->GetNodeInfo( nsGkAtoms::documentFragmentNodeName, nullptr, kNameSpaceID_None, nsIDOMNode::DOCUMENT_FRAGMENT_NODE); RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(OwnerDoc()); @@ -1137,34 +1142,17 @@ Element::CreateShadowRoot(ErrorResult& a // Calling SetPrototypeBinding takes ownership of protoBinding. docInfo->SetPrototypeBinding(NS_LITERAL_CSTRING("shadowroot"), protoBinding); RefPtr<ShadowRoot> shadowRoot = new ShadowRoot(this, nodeInfo.forget(), protoBinding); shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc()); - // Replace the old ShadowRoot with the new one and let the old - // ShadowRoot know about the younger ShadowRoot because the old - // ShadowRoot is projected into the younger ShadowRoot's shadow - // insertion point (if it exists). - ShadowRoot* olderShadow = GetShadowRoot(); SetShadowRoot(shadowRoot); - if (olderShadow) { - olderShadow->SetYoungerShadow(shadowRoot); - - // Unbind children of older shadow root because they - // are no longer in the composed tree. - for (nsIContent* child = olderShadow->GetFirstChild(); child; - child = child->GetNextSibling()) { - child->UnbindFromTree(true, false); - } - - olderShadow->SetIsComposedDocParticipant(false); - } // xblBinding takes ownership of docInfo. RefPtr<nsXBLBinding> xblBinding = new nsXBLBinding(shadowRoot, protoBinding); shadowRoot->SetAssociatedBinding(xblBinding); xblBinding->SetBoundElement(this); SetXBLBinding(xblBinding); return shadowRoot.forget();
--- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1042,33 +1042,20 @@ nsIContent::GetEventTargetParent(EventCh } nsIContent* parent = GetParent(); // Web components have a special event chain that need to account // for destination insertion points where nodes have been distributed. nsTArray<nsIContent*>* destPoints = GetExistingDestInsertionPoints(); if (destPoints && !destPoints->IsEmpty()) { - // Push destination insertion points to aVisitor.mDestInsertionPoints - // excluding shadow insertion points. - bool didPushNonShadowInsertionPoint = false; + // Push destination insertion points to aVisitor.mDestInsertionPoints. for (uint32_t i = 0; i < destPoints->Length(); i++) { nsIContent* point = destPoints->ElementAt(i); - if (!ShadowRoot::IsShadowInsertionPoint(point)) { - aVisitor.mDestInsertionPoints.AppendElement(point); - didPushNonShadowInsertionPoint = true; - } - } - - // Next node in the event path is the final destination - // (non-shadow) insertion point that was pushed. - if (didPushNonShadowInsertionPoint) { - parent = aVisitor.mDestInsertionPoints.LastElement(); - aVisitor.mDestInsertionPoints.SetLength( - aVisitor.mDestInsertionPoints.Length() - 1); + aVisitor.mDestInsertionPoints.AppendElement(point); } } ShadowRoot* thisShadowRoot = ShadowRoot::FromNode(this); if (thisShadowRoot) { if (!aVisitor.mEvent->mFlags.mComposed) { // If we do stop propagation, we still want to propagate // the event to chrome (nsPIDOMWindow::GetParentTarget()). @@ -1082,20 +1069,17 @@ nsIContent::GetEventTargetParent(EventCh return NS_OK; } if (!aVisitor.mDestInsertionPoints.IsEmpty()) { parent = aVisitor.mDestInsertionPoints.LastElement(); aVisitor.mDestInsertionPoints.SetLength( aVisitor.mDestInsertionPoints.Length() - 1); } else { - // The pool host for the youngest shadow root is shadow DOM host, - // for older shadow roots, it is the shadow insertion point - // where the shadow root is projected, nullptr if none exists. - parent = thisShadowRoot->GetPoolHost(); + parent = thisShadowRoot->GetHost(); } } // Event may need to be retargeted if this is the root of a native // anonymous content subtree or event is dispatched somewhere inside XBL. if (isAnonForEvents) { #ifdef DEBUG // If a DOM event is explicitly dispatched using node.dispatchEvent(), then @@ -2614,13 +2598,12 @@ FragmentOrElement::SetIsElementInStyleSc } void FragmentOrElement::SetIsElementInStyleScopeFlagOnShadowTree(bool aInStyleScope) { NS_ASSERTION(IsElement(), "calling SetIsElementInStyleScopeFlagOnShadowTree " "on a non-Element is useless"); ShadowRoot* shadowRoot = GetShadowRoot(); - while (shadowRoot) { + if (shadowRoot) { shadowRoot->SetIsElementInStyleScopeFlagOnSubtree(aInStyleScope); - shadowRoot = shadowRoot->GetOlderShadowRoot(); } }
--- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -10,99 +10,90 @@ #include "mozilla/dom/DocumentFragment.h" #include "ChildIterator.h" #include "nsContentUtils.h" #include "nsDOMClassInfoID.h" #include "nsIDOMHTMLElement.h" #include "nsIStyleSheetLinkingElement.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/HTMLContentElement.h" -#include "mozilla/dom/HTMLShadowElement.h" #include "nsXBLPrototypeBinding.h" #include "mozilla/StyleSheet.h" #include "mozilla/StyleSheetInlines.h" using namespace mozilla; using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_CLASS(ShadowRoot) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot, DocumentFragment) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPoolHost) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheetList) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOlderShadow) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mYoungerShadow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAssociatedBinding) for (auto iter = tmp->mIdentifierMap.ConstIter(); !iter.Done(); iter.Next()) { iter.Get()->Traverse(&cb); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ShadowRoot, - DocumentFragment) - if (tmp->mPoolHost) { - tmp->mPoolHost->RemoveMutationObserver(tmp); +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ShadowRoot) + if (tmp->GetHost()) { + tmp->GetHost()->RemoveMutationObserver(tmp); } - NS_IMPL_CYCLE_COLLECTION_UNLINK(mPoolHost) NS_IMPL_CYCLE_COLLECTION_UNLINK(mStyleSheetList) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mOlderShadow) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mYoungerShadow) NS_IMPL_CYCLE_COLLECTION_UNLINK(mAssociatedBinding) tmp->mIdentifierMap.Clear(); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DocumentFragment) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ShadowRoot) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent) NS_INTERFACE_MAP_ENTRY(nsIMutationObserver) NS_INTERFACE_MAP_END_INHERITING(DocumentFragment) NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment) NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment) ShadowRoot::ShadowRoot(Element* aElement, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, nsXBLPrototypeBinding* aProtoBinding) - : DocumentFragment(aNodeInfo), mPoolHost(aElement), - mProtoBinding(aProtoBinding), mShadowElement(nullptr), - mInsertionPointChanged(false), mIsComposedDocParticipant(false) + : DocumentFragment(aNodeInfo) + , mProtoBinding(aProtoBinding) + , mInsertionPointChanged(false) + , mIsComposedDocParticipant(false) { SetHost(aElement); // Nodes in a shadow tree should never store a value // in the subtree root pointer, nodes in the shadow tree // track the subtree root using GetContainingShadow(). ClearSubtreeRootPointer(); SetFlags(NODE_IS_IN_SHADOW_TREE); ExtendedDOMSlots()->mBindingParent = aElement; ExtendedDOMSlots()->mContainingShadow = this; // Add the ShadowRoot as a mutation observer on the host to watch // for mutations because the insertion points in this ShadowRoot // may need to be updated when the host children are modified. - mPoolHost->AddMutationObserver(this); + GetHost()->AddMutationObserver(this); } ShadowRoot::~ShadowRoot() { - if (mPoolHost) { + if (GetHost()) { // mPoolHost may have been unlinked or a new ShadowRoot may have been // creating, making this one obsolete. - mPoolHost->RemoveMutationObserver(this); + GetHost()->RemoveMutationObserver(this); } UnsetFlags(NODE_IS_IN_SHADOW_TREE); // nsINode destructor expects mSubtreeRoot == this. SetSubtreeRootPointer(this); - - SetHost(nullptr); } JSObject* ShadowRoot::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { return mozilla::dom::ShadowRootBinding::Wrap(aCx, this, aGivenProto); } @@ -239,25 +230,16 @@ ShadowRoot::AddInsertionPoint(HTMLConten void ShadowRoot::RemoveInsertionPoint(HTMLContentElement* aInsertionPoint) { mInsertionPoints.RemoveElement(aInsertionPoint); } void -ShadowRoot::SetYoungerShadow(ShadowRoot* aYoungerShadow) -{ - mYoungerShadow = aYoungerShadow; - mYoungerShadow->mOlderShadow = this; - - ChangePoolHost(mYoungerShadow->GetShadowElement()); -} - -void ShadowRoot::RemoveDestInsertionPoint(nsIContent* aInsertionPoint, nsTArray<nsIContent*>& aDestInsertionPoints) { // Remove the insertion point from the destination insertion points. // Also remove all succeeding insertion points because it is no longer // possible for the content to be distributed into deeper node trees. int32_t index = aDestInsertionPoints.IndexOf(aInsertionPoint); @@ -295,18 +277,17 @@ ShadowRoot::DistributeSingleNode(nsICont } // Find the index into the insertion point. if (insertionPoint) { nsCOMArray<nsIContent>& matchedNodes = insertionPoint->MatchedNodes(); // Find the appropriate position in the matched node list for the // newly distributed content. bool isIndexFound = false; - MOZ_ASSERT(mPoolHost, "Where did the content come from if there is no pool host?"); - ExplicitChildIterator childIterator(mPoolHost); + ExplicitChildIterator childIterator(GetHost()); for (uint32_t i = 0; i < matchedNodes.Length(); i++) { // Seek through the host's explicit children until the inserted content // is found or when the current matched node is reached. if (childIterator.Seek(aContent, matchedNodes[i])) { // aContent was found before the current matched node. insertionPoint->InsertMatchedNode(i, aContent); isIndexFound = true; break; @@ -316,42 +297,23 @@ ShadowRoot::DistributeSingleNode(nsICont if (!isIndexFound) { // We have still not found an index in the insertion point, // thus it must be at the end. MOZ_ASSERT(childIterator.Seek(aContent, nullptr), "Trying to match a node that is not a candidate to be matched"); insertionPoint->AppendMatchedNode(aContent); } - // Handle the case where the parent of the insertion point is a ShadowRoot - // that is projected into the younger ShadowRoot's shadow insertion point. - // The node distributed into the insertion point must be reprojected - // to the shadow insertion point. - if (insertionPoint->GetParent() == this && - mYoungerShadow && mYoungerShadow->GetShadowElement()) { - mYoungerShadow->GetShadowElement()->DistributeSingleNode(aContent); - } - // Handle the case where the parent of the insertion point has a ShadowRoot. // The node distributed into the insertion point must be reprojected to the // insertion points of the parent's ShadowRoot. ShadowRoot* parentShadow = insertionPoint->GetParent()->GetShadowRoot(); if (parentShadow) { parentShadow->DistributeSingleNode(aContent); } - - // Handle the case where the parent of the insertion point is the <shadow> - // element. The node distributed into the insertion point must be reprojected - // into the older ShadowRoot's insertion points. - if (mShadowElement && mShadowElement == insertionPoint->GetParent()) { - ShadowRoot* olderShadow = mShadowElement->GetOlderShadowRoot(); - if (olderShadow) { - olderShadow->DistributeSingleNode(aContent); - } - } } } void ShadowRoot::RemoveDistributedNode(nsIContent* aContent) { // Find insertion point containing the content and remove the node. for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) { @@ -363,63 +325,38 @@ ShadowRoot::RemoveDistributedNode(nsICon // Removing the matched node will cause fallback content to be // used instead. Give up optimization and distribute all nodes. DistributeAllNodes(); return; } mInsertionPoints[i]->RemoveMatchedNode(aContent); - // Handle the case where the parent of the insertion point is a ShadowRoot - // that is projected into the younger ShadowRoot's shadow insertion point. - // The removed node needs to be removed from the shadow insertion point. - if (mInsertionPoints[i]->GetParent() == this) { - if (mYoungerShadow && mYoungerShadow->GetShadowElement()) { - mYoungerShadow->GetShadowElement()->RemoveDistributedNode(aContent); - } - } - // Handle the case where the parent of the insertion point has a ShadowRoot. // The removed node needs to be removed from the insertion points of the // parent's ShadowRoot. ShadowRoot* parentShadow = mInsertionPoints[i]->GetParent()->GetShadowRoot(); if (parentShadow) { parentShadow->RemoveDistributedNode(aContent); } - // Handle the case where the parent of the insertion point is the <shadow> - // element. The removed node must be removed from the older ShadowRoot's - // insertion points. - if (mShadowElement && mShadowElement == mInsertionPoints[i]->GetParent()) { - ShadowRoot* olderShadow = mShadowElement->GetOlderShadowRoot(); - if (olderShadow) { - olderShadow->RemoveDistributedNode(aContent); - } - } - break; } } } void ShadowRoot::DistributeAllNodes() { // Create node pool. nsTArray<nsIContent*> nodePool; - - // Make sure there is a pool host, an older shadow may not have - // one if the younger shadow does not have a <shadow> element. - if (mPoolHost) { - ExplicitChildIterator childIterator(mPoolHost); - for (nsIContent* content = childIterator.GetNextChild(); - content; - content = childIterator.GetNextChild()) { - nodePool.AppendElement(content); - } + ExplicitChildIterator childIterator(GetHost()); + for (nsIContent* content = childIterator.GetNextChild(); content; + content = childIterator.GetNextChild()) { + nodePool.AppendElement(content); } nsTArray<ShadowRoot*> shadowsToUpdate; for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) { mInsertionPoints[i]->ClearMatchedNodes(); // Assign matching nodes from node pool. for (uint32_t j = 0; j < nodePool.Length(); j++) { @@ -440,30 +377,16 @@ ShadowRoot::DistributeAllNodes() // to the insertion point must be reprojected to the insertion points of the // parent's ShadowRoot. ShadowRoot* parentShadow = insertionParent->GetShadowRoot(); if (parentShadow && !shadowsToUpdate.Contains(parentShadow)) { shadowsToUpdate.AppendElement(parentShadow); } } - // If there is a shadow insertion point in this ShadowRoot, the children - // of the shadow insertion point needs to be distributed into the insertion - // points of the older ShadowRoot. - if (mShadowElement && mOlderShadow) { - mOlderShadow->DistributeAllNodes(); - } - - // If there is a younger ShadowRoot with a shadow insertion point, - // then the children of this ShadowRoot needs to be distributed to - // the younger ShadowRoot's shadow insertion point. - if (mYoungerShadow && mYoungerShadow->GetShadowElement()) { - mYoungerShadow->GetShadowElement()->DistributeAllNodes(); - } - for (uint32_t i = 0; i < shadowsToUpdate.Length(); i++) { shadowsToUpdate[i]->DistributeAllNodes(); } } void ShadowRoot::GetInnerHTML(nsAString& aInnerHTML) { @@ -510,81 +433,27 @@ ShadowRoot::StyleSheets() { if (!mStyleSheetList) { mStyleSheetList = new ShadowRootStyleSheetList(this); } return mStyleSheetList; } -void -ShadowRoot::SetShadowElement(HTMLShadowElement* aShadowElement) -{ - // If there is already a shadow element point, remove - // the projected shadow because it is no longer an insertion - // point. - if (mShadowElement) { - mShadowElement->SetProjectedShadow(nullptr); - } - - if (mOlderShadow) { - // Nodes for distribution will come from the new shadow element. - mOlderShadow->ChangePoolHost(aShadowElement); - } - - // Set the new shadow element to project the older ShadowRoot because - // it is the current shadow insertion point. - mShadowElement = aShadowElement; - if (mShadowElement) { - mShadowElement->SetProjectedShadow(mOlderShadow); - } -} - -void -ShadowRoot::ChangePoolHost(nsIContent* aNewHost) -{ - if (mPoolHost) { - mPoolHost->RemoveMutationObserver(this); - } - - // Clear the nodes matched to content insertion points - // because it is no longer relevant. - for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) { - mInsertionPoints[i]->ClearMatchedNodes(); - } - - mPoolHost = aNewHost; - if (mPoolHost) { - mPoolHost->AddMutationObserver(this); - } -} - -bool -ShadowRoot::IsShadowInsertionPoint(nsIContent* aContent) -{ - if (!aContent) { - return false; - } - - HTMLShadowElement* shadowElem = HTMLShadowElement::FromContent(aContent); - return shadowElem && shadowElem->IsInsertionPoint(); -} - /** * Returns whether the web components pool population algorithm * on the host would contain |aContent|. This function ignores * insertion points in the pool, thus should only be used to * test nodes that have not yet been distributed. */ bool ShadowRoot::IsPooledNode(nsIContent* aContent, nsIContent* aContainer, nsIContent* aHost) { - if (nsContentUtils::IsContentInsertionPoint(aContent) || - IsShadowInsertionPoint(aContent)) { + if (nsContentUtils::IsContentInsertionPoint(aContent)) { // Insertion points never end up in the pool. return false; } if (aContainer == aHost && nsContentUtils::IsInSameAnonymousTree(aContainer, aContent)) { // Children of the host will end up in the pool. We check to ensure // that the content is in the same anonymous tree as the container @@ -607,17 +476,17 @@ ShadowRoot::IsPooledNode(nsIContent* aCo void ShadowRoot::AttributeChanged(nsIDocument* aDocument, Element* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType, const nsAttrValue* aOldValue) { - if (!IsPooledNode(aElement, aElement->GetParent(), mPoolHost)) { + if (!IsPooledNode(aElement, aElement->GetParent(), GetHost())) { return; } // Attributes may change insertion point matching, find its new distribution. RemoveDistributedNode(aElement); DistributeSingleNode(aElement); } @@ -640,17 +509,17 @@ ShadowRoot::ContentAppended(nsIDocument* // Add insertion point to destination insertion points of fallback content. if (nsContentUtils::IsContentInsertionPoint(aContainer)) { HTMLContentElement* content = HTMLContentElement::FromContent(aContainer); if (content->MatchedNodes().IsEmpty()) { currentChild->DestInsertionPoints().AppendElement(aContainer); } } - if (IsPooledNode(currentChild, aContainer, mPoolHost)) { + if (IsPooledNode(currentChild, aContainer, GetHost())) { DistributeSingleNode(currentChild); } currentChild = currentChild->GetNextSibling(); } } void @@ -662,17 +531,17 @@ ShadowRoot::ContentInserted(nsIDocument* if (mInsertionPointChanged) { DistributeAllNodes(); mInsertionPointChanged = false; return; } // Watch for new nodes added to the pool because the node // may need to be added to an insertion point. - if (IsPooledNode(aChild, aContainer, mPoolHost)) { + if (IsPooledNode(aChild, aContainer, GetHost())) { // Add insertion point to destination insertion points of fallback content. if (nsContentUtils::IsContentInsertionPoint(aContainer)) { HTMLContentElement* content = HTMLContentElement::FromContent(aContainer); if (content->MatchedNodes().IsEmpty()) { aChild->DestInsertionPoints().AppendElement(aContainer); } } @@ -699,38 +568,29 @@ ShadowRoot::ContentRemoved(nsIDocument* HTMLContentElement* content = HTMLContentElement::FromContent(aContainer); if (content->MatchedNodes().IsEmpty()) { aChild->DestInsertionPoints().Clear(); } } // Watch for node that is removed from the pool because // it may need to be removed from an insertion point. - if (IsPooledNode(aChild, aContainer, mPoolHost)) { + if (IsPooledNode(aChild, aContainer, GetHost())) { RemoveDistributedNode(aChild); } } nsresult ShadowRoot::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult, bool aPreallocateChildren) const { *aResult = nullptr; return NS_ERROR_DOM_DATA_CLONE_ERR; } -void -ShadowRoot::DestroyContent() -{ - if (mOlderShadow) { - mOlderShadow->DestroyContent(); - } - DocumentFragment::DestroyContent(); -} - NS_IMPL_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList, StyleSheetList, mShadowRoot) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ShadowRootStyleSheetList) NS_INTERFACE_MAP_END_INHERITING(StyleSheetList) NS_IMPL_ADDREF_INHERITED(ShadowRootStyleSheetList, StyleSheetList) NS_IMPL_RELEASE_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
--- a/dom/base/ShadowRoot.h +++ b/dom/base/ShadowRoot.h @@ -20,61 +20,43 @@ class nsIAtom; class nsIContent; class nsXBLPrototypeBinding; namespace mozilla { namespace dom { class Element; class HTMLContentElement; -class HTMLShadowElement; class ShadowRootStyleSheetList; class ShadowRoot final : public DocumentFragment, public nsStubMutationObserver { friend class ShadowRootStyleSheetList; public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment) NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED - ShadowRoot(Element* aElement, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + ShadowRoot(Element* aElement, + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, nsXBLPrototypeBinding* aProtoBinding); void AddToIdTable(Element* aElement, nsIAtom* aId); void RemoveFromIdTable(Element* aElement, nsIAtom* aId); void InsertSheet(StyleSheet* aSheet, nsIContent* aLinkingContent); void RemoveSheet(StyleSheet* aSheet); bool ApplyAuthorStyles(); void SetApplyAuthorStyles(bool aApplyAuthorStyles); StyleSheetList* StyleSheets(); - HTMLShadowElement* GetShadowElement() { return mShadowElement; } - - /** - * Sets the current shadow insertion point where the older - * ShadowRoot will be projected. - */ - void SetShadowElement(HTMLShadowElement* aShadowElement); - - /** - * Change the node that populates the distribution pool with - * its children. This is distinct from the ShadowRoot host described - * in the specifications. The ShadowRoot host is the element - * which created this ShadowRoot and does not change. The pool host - * is the same as the ShadowRoot host if this is the youngest - * ShadowRoot. If this is an older ShadowRoot, the pool host is - * the <shadow> element in the younger ShadowRoot (if it exists). - */ - void ChangePoolHost(nsIContent* aNewHost); /** * Distributes a single explicit child of the pool host to the content * insertion points in this ShadowRoot. */ void DistributeSingleNode(nsIContent* aContent); /** @@ -87,98 +69,69 @@ public: * Distributes all the explicit children of the pool host to the content * insertion points in this ShadowRoot. */ void DistributeAllNodes(); void AddInsertionPoint(HTMLContentElement* aInsertionPoint); void RemoveInsertionPoint(HTMLContentElement* aInsertionPoint); - void SetYoungerShadow(ShadowRoot* aYoungerShadow); - ShadowRoot* GetYoungerShadowRoot() { return mYoungerShadow; } void SetInsertionPointChanged() { mInsertionPointChanged = true; } void SetAssociatedBinding(nsXBLBinding* aBinding) { mAssociatedBinding = aBinding; } - nsISupports* GetParentObject() const { return mPoolHost; } - - nsIContent* GetPoolHost() { return mPoolHost; } - nsTArray<HTMLShadowElement*>& ShadowDescendants() { return mShadowDescendants; } - JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; static bool IsPooledNode(nsIContent* aChild, nsIContent* aContainer, nsIContent* aHost); static ShadowRoot* FromNode(nsINode* aNode); - static bool IsShadowInsertionPoint(nsIContent* aContent); static void RemoveDestInsertionPoint(nsIContent* aInsertionPoint, nsTArray<nsIContent*>& aDestInsertionPoints); // WebIDL methods. Element* GetElementById(const nsAString& aElementId); already_AddRefed<nsContentList> GetElementsByTagName(const nsAString& aNamespaceURI); already_AddRefed<nsContentList> GetElementsByTagNameNS(const nsAString& aNamespaceURI, const nsAString& aLocalName); already_AddRefed<nsContentList> GetElementsByClassName(const nsAString& aClasses); void GetInnerHTML(nsAString& aInnerHTML); void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError); Element* Host(); - ShadowRoot* GetOlderShadowRoot() { return mOlderShadow; } void StyleSheetChanged(); bool IsComposedDocParticipant() { return mIsComposedDocParticipant; } void SetIsComposedDocParticipant(bool aIsComposedDocParticipant) { mIsComposedDocParticipant = aIsComposedDocParticipant; } - virtual void DestroyContent() override; protected: virtual ~ShadowRoot(); - // The pool host is the parent of the nodes that will be distributed - // into the insertion points in this ShadowRoot. See |ChangeShadowRoot|. - nsCOMPtr<nsIContent> mPoolHost; - // An array of content insertion points that are a descendant of the ShadowRoot // sorted in tree order. Insertion points are responsible for notifying // the ShadowRoot when they are removed or added as a descendant. The insertion // points are kept alive by the parent node, thus weak references are held // by the array. nsTArray<HTMLContentElement*> mInsertionPoints; - // An array of the <shadow> elements that are descendant of the ShadowRoot - // sorted in tree order. Only the first may be a shadow insertion point. - nsTArray<HTMLShadowElement*> mShadowDescendants; - nsTHashtable<nsIdentifierMapEntry> mIdentifierMap; nsXBLPrototypeBinding* mProtoBinding; // It is necessary to hold a reference to the associated nsXBLBinding // because the binding holds a reference on the nsXBLDocumentInfo that // owns |mProtoBinding|. RefPtr<nsXBLBinding> mAssociatedBinding; RefPtr<ShadowRootStyleSheetList> mStyleSheetList; - // The current shadow insertion point of this ShadowRoot. - HTMLShadowElement* mShadowElement; - - // The ShadowRoot that was created by the host element before - // this ShadowRoot was created. - RefPtr<ShadowRoot> mOlderShadow; - - // The ShadowRoot that was created by the host element after - // this ShadowRoot was created. - RefPtr<ShadowRoot> mYoungerShadow; - // A boolean that indicates that an insertion point was added or removed // from this ShadowRoot and that the nodes need to be redistributed into // the insertion points. After this flag is set, nodes will be distributed // on the next mutation event. bool mInsertionPointChanged; // Flag to indicate whether the descendants of this shadow root are part of the // composed document. Ideally, we would use a node flag on nodes to
--- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -180,16 +180,17 @@ EXPORTS.mozilla.dom += [ 'FormData.h', 'FragmentOrElement.h', 'FromParser.h', 'GroupedSHistory.h', 'IdleDeadline.h', 'IdleRequest.h', 'ImageEncoder.h', 'ImageTracker.h', + 'IntlUtils.h', 'Link.h', 'Location.h', 'NameSpaceConstants.h', 'Navigator.h', 'NodeInfo.h', 'NodeInfoInlines.h', 'NodeIterator.h', 'PartialSHistory.h', @@ -253,16 +254,17 @@ UNIFIED_SOURCES += [ 'EventSource.cpp', 'FormData.cpp', 'FragmentOrElement.cpp', 'GroupedSHistory.cpp', 'IdleDeadline.cpp', 'IdleRequest.cpp', 'ImageEncoder.cpp', 'ImageTracker.cpp', + 'IntlUtils.cpp', 'Link.cpp', 'Location.cpp', 'Navigator.cpp', 'NodeInfo.cpp', 'NodeIterator.cpp', 'nsAtomListUtils.cpp', 'nsAttrAndChildArray.cpp', 'nsAttrValue.cpp', @@ -370,24 +372,16 @@ if CONFIG['MOZ_WEBRTC']: 'nsDOMDataChannel.cpp', ] if CONFIG['FUZZING']: UNIFIED_SOURCES += [ 'FuzzingFunctions.cpp', ] -if CONFIG['ENABLE_INTL_API']: - UNIFIED_SOURCES += [ - 'IntlUtils.cpp', - ] - EXPORTS.mozilla.dom += [ - 'IntlUtils.h', - ] - # these files couldn't be in UNIFIED_SOURCES for now for reasons given below: SOURCES += [ # Several conflicts with other bindings. 'DOMIntersectionObserver.cpp', # Because of OS X headers. 'nsContentUtils.cpp', # this file doesn't like windows.h 'nsDOMWindowUtils.cpp',
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -45,17 +45,16 @@ #include "mozilla/dom/DOMTypes.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/ElementInlines.h" #include "mozilla/dom/FileSystemSecurity.h" #include "mozilla/dom/FileBlobImpl.h" #include "mozilla/dom/HTMLInputElement.h" #include "mozilla/dom/HTMLTemplateElement.h" #include "mozilla/dom/HTMLContentElement.h" -#include "mozilla/dom/HTMLShadowElement.h" #include "mozilla/dom/IPCBlobUtils.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/TouchEvent.h" #include "mozilla/dom/ShadowRoot.h" #include "mozilla/dom/XULCommandEvent.h" #include "mozilla/dom/WorkerPrivate.h" @@ -7562,30 +7561,16 @@ nsContentUtils::HasDistributedChildren(n } if (aContent->GetShadowRoot()) { // Children of a shadow root host are distributed // to content insertion points in the shadow root. return true; } - ShadowRoot* shadow = ShadowRoot::FromNode(aContent); - if (shadow) { - // Children of a shadow root are distributed to - // the shadow insertion point of the younger shadow root. - return shadow->GetYoungerShadowRoot(); - } - - HTMLShadowElement* shadowEl = HTMLShadowElement::FromContent(aContent); - if (shadowEl && shadowEl->IsInsertionPoint()) { - // Children of a shadow insertion points are distributed - // to the insertion points in the older shadow root. - return shadowEl->GetOlderShadowRoot(); - } - HTMLContentElement* contentEl = HTMLContentElement::FromContent(aContent); if (contentEl && contentEl->IsInsertionPoint()) { // Children of a content insertion point are distributed to the // content insertion point if the content insertion point does // not match any nodes (fallback content). return contentEl->MatchedNodes().IsEmpty(); } @@ -10150,16 +10135,59 @@ nsContentUtils::GetElementDefinitionIfOb if (!definition || !definition->IsInObservedAttributeList(aAttrName)) { return nullptr; } return definition; } /* static */ void +nsContentUtils::SyncInvokeReactions(nsIDocument::ElementCallbackType aType, + Element* aElement, + CustomElementDefinition* aDefinition) +{ + MOZ_ASSERT(aElement); + + nsIDocument* doc = aElement->OwnerDoc(); + nsPIDOMWindowInner* window(doc->GetInnerWindow()); + if (!window) { + return; + } + + RefPtr<CustomElementRegistry> registry(window->CustomElements()); + if (!registry) { + return; + } + + registry->SyncInvokeReactions(aType, aElement, aDefinition); +} + +/* static */ void +nsContentUtils::EnqueueUpgradeReaction(Element* aElement, + CustomElementDefinition* aDefinition) +{ + MOZ_ASSERT(aElement); + + nsIDocument* doc = aElement->OwnerDoc(); + nsPIDOMWindowInner* window(doc->GetInnerWindow()); + if (!window) { + return; + } + + RefPtr<CustomElementRegistry> registry(window->CustomElements()); + if (!registry) { + return; + } + + CustomElementReactionsStack* stack = + doc->GetDocGroup()->CustomElementReactionsStack(); + stack->EnqueueUpgradeReaction(registry, aElement, aDefinition); +} + +/* static */ void nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc, nsIDocument::ElementCallbackType aType, Element* aCustomElement, LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition) { MOZ_ASSERT(aDoc);
--- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -2993,16 +2993,23 @@ public: static void SetupCustomElement(Element* aElement, const nsAString* aTypeExtension = nullptr); static mozilla::dom::CustomElementDefinition* GetElementDefinitionIfObservingAttr(Element* aCustomElement, nsIAtom* aExtensionType, nsIAtom* aAttrName); + static void SyncInvokeReactions(nsIDocument::ElementCallbackType aType, + Element* aCustomElement, + mozilla::dom::CustomElementDefinition* aDefinition); + + static void EnqueueUpgradeReaction(Element* aElement, + mozilla::dom::CustomElementDefinition* aDefinition); + static void EnqueueLifecycleCallback(nsIDocument* aDoc, nsIDocument::ElementCallbackType aType, Element* aCustomElement, mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr, mozilla::dom::CustomElementDefinition* aDefinition = nullptr); static void GetCustomPrototype(nsIDocument* aDoc, int32_t aNamespaceID,
--- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -274,16 +274,17 @@ #include "nsISpeculativeConnect.h" #include "mozilla/MediaManager.h" #include "nsIURIClassifier.h" #include "mozilla/DocumentStyleRootIterator.h" #include "mozilla/ServoRestyleManager.h" #include "mozilla/ClearOnShutdown.h" +#include "nsHTMLTags.h" using namespace mozilla; using namespace mozilla::dom; typedef nsTArray<Link*> LinkArray; static LazyLogModule gDocumentLeakPRLog("DocumentLeak"); static LazyLogModule gCspPRLog("CSP"); @@ -6019,16 +6020,20 @@ nsDocument::CreateElement(const nsAStrin RefPtr<Element> elem = CreateElem( needsLowercase ? lcTagName : aTagName, nullptr, mDefaultElementType, is); if (pseudoType != CSSPseudoElementType::NotPseudo) { elem->SetPseudoElementType(pseudoType); } + if (is) { + elem->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true); + } + return elem.forget(); } NS_IMETHODIMP nsDocument::CreateElementNS(const nsAString& aNamespaceURI, const nsAString& aQualifiedName, nsIDOMElement** aReturn) { @@ -6070,16 +6075,20 @@ nsDocument::CreateElementNS(const nsAStr nsCOMPtr<Element> element; rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(), NOT_FROM_PARSER, is); if (rv.Failed()) { return nullptr; } + if (is) { + element->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true); + } + return element.forget(); } NS_IMETHODIMP nsDocument::CreateTextNode(const nsAString& aData, nsIDOMText** aReturn) { *aReturn = nsIDocument::CreateTextNode(aData).take(); return NS_OK; @@ -6352,21 +6361,36 @@ nsDocument::CustomElementConstructor(JSC if (!JS_WrapObject(aCx, &reflector)) { return false; } args.rval().setObject(*reflector); return true; } } else { - nsDependentAtomString localName(definition->mLocalName); - element = - document->CreateElem(localName, nullptr, kNameSpaceID_XHTML, - (definition->mLocalName != typeAtom) ? &elemName - : nullptr); + RefPtr<mozilla::dom::NodeInfo> nodeInfo = + document->NodeInfoManager()->GetNodeInfo(definition->mLocalName, nullptr, + kNameSpaceID_XHTML, + nsIDOMNode::ELEMENT_NODE); + + int32_t tag = nsHTMLTags::CaseSensitiveAtomTagToId(definition->mLocalName); + if (tag == eHTMLTag_userdefined && + nsContentUtils::IsCustomElementName(definition->mType)) { + element = NS_NewHTMLElement(nodeInfo.forget(), NOT_FROM_PARSER); + } else { + element = ::CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER); + } + + element->SetCustomElementData( + new CustomElementData(definition->mType, + CustomElementData::State::eCustom)); + + // It'll be removed when we deprecate custom elements v0. + nsContentUtils::SyncInvokeReactions(nsIDocument::eCreated, element, + definition); NS_ENSURE_TRUE(element, false); } // The prototype setup happens in Element::WrapObject(). nsresult rv = nsContentUtils::WrapNative(aCx, element, element, args.rval()); NS_ENSURE_SUCCESS(rv, true); return true;
--- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -1655,17 +1655,16 @@ GK_ATOM(requiredExtensions, "requiredExt GK_ATOM(requiredFeatures, "requiredFeatures") GK_ATOM(rotate, "rotate") GK_ATOM(rx, "rx") GK_ATOM(ry, "ry") GK_ATOM(saturate, "saturate") GK_ATOM(saturation, "saturation") GK_ATOM(set, "set") GK_ATOM(seed, "seed") -GK_ATOM(shadow, "shadow") GK_ATOM(shape_rendering, "shape-rendering") GK_ATOM(skewX, "skewX") GK_ATOM(skewY, "skewY") GK_ATOM(slope, "slope") GK_ATOM(softLight, "soft-light") GK_ATOM(spacing, "spacing") GK_ATOM(spacingAndGlyphs, "spacingAndGlyphs") GK_ATOM(specularConstant, "specularConstant")
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -228,19 +228,17 @@ #include "TimeChangeObserver.h" #include "mozilla/dom/AudioContext.h" #include "mozilla/dom/BrowserElementDictionariesBinding.h" #include "mozilla/dom/cache/CacheStorage.h" #include "mozilla/dom/Console.h" #include "mozilla/dom/Fetch.h" #include "mozilla/dom/FunctionBinding.h" #include "mozilla/dom/HashChangeEvent.h" -#ifdef ENABLE_INTL_API #include "mozilla/dom/IntlUtils.h" -#endif #include "mozilla/dom/MozSelfSupportBinding.h" #include "mozilla/dom/PopStateEvent.h" #include "mozilla/dom/PopupBlockedEvent.h" #include "mozilla/dom/PrimitiveConversions.h" #include "mozilla/dom/WindowBinding.h" #include "nsITabChild.h" #include "mozilla/dom/MediaQueryList.h" #include "mozilla/dom/ScriptSettings.h" @@ -2060,19 +2058,17 @@ nsGlobalWindow::CleanUp() if (mIdleTimer) { mIdleTimer->Cancel(); mIdleTimer = nullptr; } mServiceWorkerRegistrationTable.Clear(); -#ifdef ENABLE_INTL_API mIntlUtils = nullptr; -#endif } void nsGlobalWindow::ClearControllers() { if (mControllers) { uint32_t count; mControllers->GetControllerCount(&count); @@ -2351,19 +2347,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mU2F) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioWorklet) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMozSelfSupport) -#ifdef ENABLE_INTL_API NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils) -#endif tmp->TraverseHostObjectURIs(cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow) nsGlobalWindow::CleanupCachedXBLHandlers(tmp); NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext) @@ -2431,19 +2425,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto) NS_IMPL_CYCLE_COLLECTION_UNLINK(mU2F) NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole) NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioWorklet) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet) NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal) NS_IMPL_CYCLE_COLLECTION_UNLINK(mMozSelfSupport) -#ifdef ENABLE_INTL_API NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils) -#endif tmp->UnlinkHostObjectURIs(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor) tmp->DisableIdleCallbackRequests(); NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -15086,25 +15078,23 @@ nsGlobalWindow::GetRegionalPrefsLocales( AutoTArray<nsCString, 10> rpLocales; mozilla::intl::LocaleService::GetInstance()->GetRegionalPrefsLocales(rpLocales); for (const auto& loc : rpLocales) { aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc)); } } -#ifdef ENABLE_INTL_API IntlUtils* nsGlobalWindow::GetIntlUtils(ErrorResult& aError) { MOZ_RELEASE_ASSERT(IsInnerWindow()); if (!mIntlUtils) { mIntlUtils = new IntlUtils(AsInner()); } return mIntlUtils; } -#endif template class nsPIDOMWindow<mozIDOMWindowProxy>; template class nsPIDOMWindow<mozIDOMWindow>; template class nsPIDOMWindow<nsISupports>;
--- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -118,19 +118,17 @@ class CustomElementRegistry; class DocGroup; class External; class Function; class Gamepad; enum class ImageBitmapFormat : uint8_t; class IdleRequest; class IdleRequestCallback; class IncrementalRunnable; -#ifdef ENABLE_INTL_API class IntlUtils; -#endif class Location; class MediaQueryList; class MozSelfSupport; class Navigator; class OwningExternalOrWindowProxy; class Promise; class PostMessageEvent; struct RequestInit; @@ -954,20 +952,18 @@ public: GetAudioWorklet(mozilla::ErrorResult& aRv); mozilla::dom::Worklet* GetPaintWorklet(mozilla::ErrorResult& aRv); void GetRegionalPrefsLocales(nsTArray<nsString>& aLocales); -#ifdef ENABLE_INTL_API mozilla::dom::IntlUtils* GetIntlUtils(mozilla::ErrorResult& aRv); -#endif protected: bool AlertOrConfirm(bool aAlert, const nsAString& aMessage, nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError); public: void Alert(nsIPrincipal& aSubjectPrincipal, @@ -2022,19 +2018,17 @@ protected: RefPtr<mozilla::dom::VREventObserver> mVREventObserver; // When non-zero, the document should receive a vrdisplayactivate event // after loading. The value is the ID of the VRDisplay that content should // begin presentation on. uint32_t mAutoActivateVRDisplayID; // Outer windows only int64_t mBeforeUnloadListenerCount; // Inner windows only -#ifdef ENABLE_INTL_API RefPtr<mozilla::dom::IntlUtils> mIntlUtils; -#endif friend class nsDOMScriptableHelper; friend class nsDOMWindowUtils; friend class mozilla::dom::PostMessageEvent; friend class DesktopNotification; friend class mozilla::dom::TimeoutManager; friend class IdleRequestExecutor;
--- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -61,17 +61,17 @@ using mozilla::AutoJSContext; /* No need to explicitly notify the first observer first \ since that'll happen anyway. */ \ NS_OBSERVER_AUTO_ARRAY_NOTIFY_OBSERVERS( \ slots->mMutationObservers, nsIMutationObserver, 1, \ func_, params_); \ } \ ShadowRoot* shadow = ShadowRoot::FromNode(node); \ if (shadow) { \ - node = shadow->GetPoolHost(); \ + node = shadow->GetHost(); \ } else { \ node = node->GetParentNode(); \ } \ } while (node); \ if (needsEnterLeave) { \ nsDOMMutationObserver::LeaveMutationHandling(); \ } \ PR_END_MACRO @@ -89,17 +89,17 @@ using mozilla::AutoJSContext; /* No need to explicitly notify the first observer first \ since that'll happen anyway. */ \ NS_OBSERVER_AUTO_ARRAY_NOTIFY_OBSERVERS_WITH_QI( \ slots->mMutationObservers, nsIMutationObserver, 1, \ nsIAnimationObserver, func_, params_); \ } \ ShadowRoot* shadow = ShadowRoot::FromNode(node); \ if (shadow) { \ - node = shadow->GetPoolHost(); \ + node = shadow->GetHost(); \ } else { \ node = node->GetParentNode(); \ } \ } while (node); \ if (needsEnterLeave) { \ nsDOMMutationObserver::LeaveMutationHandling(); \ } \ PR_END_MACRO
--- a/dom/base/test/test_mutationobservers.html +++ b/dom/base/test/test_mutationobservers.html @@ -582,58 +582,32 @@ function testOutsideShadowDOM() { "because createShadowRoot is not supported"); then(testMarquee); return; } var m = new M(function(records, observer) { is(records.length, 1); is(records[0].type, "attributes", "Should have got attributes"); observer.disconnect(); - then(testInsideShadowDOM); + then(testMarquee); }); m.observe(div, { attributes: true, childList: true, characterData: true, subtree: true }) var sr = div.createShadowRoot(); sr.innerHTML = "<div" + ">text</" + "div>"; sr.firstChild.setAttribute("foo", "bar"); sr.firstChild.firstChild.data = "text2"; sr.firstChild.appendChild(document.createElement("div")); div.setAttribute("foo", "bar"); } -function testInsideShadowDOM() { - var m = new M(function(records, observer) { - is(records.length, 4); - is(records[0].type, "childList"); - is(records[1].type, "attributes"); - is(records[2].type, "characterData"); - is(records[3].type, "childList"); - observer.disconnect(); - then(testMarquee); - }); - var sr = div.createShadowRoot(); - m.observe(sr, { - attributes: true, - childList: true, - characterData: true, - subtree: true - }); - - sr.innerHTML = "<div" + ">text</" + "div>"; - sr.firstChild.setAttribute("foo", "bar"); - sr.firstChild.firstChild.data = "text2"; - sr.firstChild.appendChild(document.createElement("div")); - div.setAttribute("foo", "bar2"); - -} - function testMarquee() { var m = new M(function(records, observer) { is(records.length, 1); is(records[0].type, "attributes"); is(records[0].attributeName, "ok"); is(records[0].oldValue, null); observer.disconnect(); then(testStyleCreate);
--- a/dom/cache/CacheStreamControlChild.cpp +++ b/dom/cache/CacheStreamControlChild.cpp @@ -110,21 +110,28 @@ CacheStreamControlChild::OpenStream(cons { NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild); if (mDestroyStarted) { aResolver(nullptr); return; } + // If we are on a worker, then we need to hold it alive until the async + // IPC operation below completes. While the IPC layer will trigger a + // rejection here in many cases, we must handle the case where the + // MozPromise resolve runnable is already in the event queue when the + // worker wants to shut down. + RefPtr<CacheWorkerHolder> holder = GetWorkerHolder(); + SendOpenStream(aId)->Then(GetCurrentThreadSerialEventTarget(), __func__, - [aResolver](const OptionalIPCStream& aOptionalStream) { + [aResolver, holder](const OptionalIPCStream& aOptionalStream) { nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aOptionalStream); aResolver(Move(stream)); - }, [aResolver](PromiseRejectReason aReason) { + }, [aResolver, holder](PromiseRejectReason aReason) { aResolver(nullptr); }); } void CacheStreamControlChild::NoteClosedAfterForget(const nsID& aId) { NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
new file mode 100644 --- /dev/null +++ b/dom/canvas/crashtests/1296410-1.html @@ -0,0 +1,9 @@ +<canvas id='canv'></canvas> +<script> +var ctx=document.getElementById('canv').getContext('2d'); +ctx.globalAlpha=0.81; +ctx.scale(22,3406781); +ctx.filter='sepia(80%)'; +ctx.font='52px serif'; +ctx.measureText('A'); +</script>
--- a/dom/canvas/crashtests/crashtests.list +++ b/dom/canvas/crashtests/crashtests.list @@ -32,15 +32,16 @@ load 1246775-1.html load 1284356-1.html load 1284578-1.html skip-if(d2d) load 1287515-1.html load 1287652-1.html load 1288872-1.html load 1290628-1.html load 1283113-1.html load 1286458-1.html +load 1296410-1.html load 1299062-1.html load 1305085-1.html load 1305312-1.html load 1298576-1.html load 1334366-1.html load 1334647-1.html load 1357092.html
--- a/dom/events/test/mochitest.ini +++ b/dom/events/test/mochitest.ini @@ -74,17 +74,17 @@ skip-if = true # Disabled due to timeout skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM [test_bug591815.html] [test_bug593959.html] [test_bug603008.html] skip-if = toolkit == 'android' [test_bug605242.html] skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM [test_bug607464.html] -skip-if = toolkit == 'android' || (e10s && os == 'win') || (e10s && os == "mac") #CRASH_DUMP, RANDOM, bug 1252273 +skip-if = toolkit == 'android' || e10s #CRASH_DUMP, RANDOM, bug 1252273, bug 1400586 [test_bug613634.html] skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM [test_bug615597.html] [test_bug624127.html] skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM [test_bug635465.html] skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM [test_bug641477.html]
deleted file mode 100644 --- a/dom/html/HTMLShadowElement.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/ShadowRoot.h" - -#include "ChildIterator.h" -#include "nsContentUtils.h" -#include "nsDocument.h" -#include "mozilla/dom/HTMLShadowElement.h" -#include "mozilla/dom/HTMLUnknownElement.h" -#include "mozilla/dom/HTMLShadowElementBinding.h" - -// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Shadow) to add check for web components -// being enabled. -nsGenericHTMLElement* -NS_NewHTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - mozilla::dom::FromParser aFromParser) -{ - // When this check is removed, remove the nsDocument.h and - // HTMLUnknownElement.h includes. Also remove nsINode::IsHTMLShadowElement. - // - // We have to jump through some hoops to be able to produce both NodeInfo* and - // already_AddRefed<NodeInfo>& for our callees. - RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); - if (!nsDocument::IsWebComponentsEnabled(nodeInfo)) { - already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); - return new mozilla::dom::HTMLUnknownElement(nodeInfoArg); - } - - already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); - return new mozilla::dom::HTMLShadowElement(nodeInfoArg); -} - -using namespace mozilla::dom; - -HTMLShadowElement::HTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) - : nsGenericHTMLElement(aNodeInfo), mIsInsertionPoint(false) -{ -} - -HTMLShadowElement::~HTMLShadowElement() -{ - if (mProjectedShadow) { - mProjectedShadow->RemoveMutationObserver(this); - } -} - -NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLShadowElement) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLShadowElement, - nsGenericHTMLElement) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProjectedShadow) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLShadowElement, - nsGenericHTMLElement) - if (tmp->mProjectedShadow) { - tmp->mProjectedShadow->RemoveMutationObserver(tmp); - tmp->mProjectedShadow = nullptr; - } -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_ADDREF_INHERITED(HTMLShadowElement, Element) -NS_IMPL_RELEASE_INHERITED(HTMLShadowElement, Element) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLShadowElement) -NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) - -NS_IMPL_ELEMENT_CLONE(HTMLShadowElement) - -JSObject* -HTMLShadowElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) -{ - return HTMLShadowElementBinding::Wrap(aCx, this, aGivenProto); -} - -void -HTMLShadowElement::SetProjectedShadow(ShadowRoot* aProjectedShadow) -{ - if (mProjectedShadow) { - mProjectedShadow->RemoveMutationObserver(this); - - // The currently projected ShadowRoot is going away, - // thus the destination insertion points need to be updated. - ExplicitChildIterator childIterator(mProjectedShadow); - for (nsIContent* content = childIterator.GetNextChild(); - content; - content = childIterator.GetNextChild()) { - ShadowRoot::RemoveDestInsertionPoint(this, content->DestInsertionPoints()); - } - } - - mProjectedShadow = aProjectedShadow; - if (mProjectedShadow) { - // A new ShadowRoot is being projected, thus its explcit - // children will be distributed to this shadow insertion point. - ExplicitChildIterator childIterator(mProjectedShadow); - for (nsIContent* content = childIterator.GetNextChild(); - content; - content = childIterator.GetNextChild()) { - content->DestInsertionPoints().AppendElement(this); - } - - // Watch for mutations on the projected shadow because - // it affects the nodes that are distributed to this shadow - // insertion point. - mProjectedShadow->AddMutationObserver(this); - } -} - -static bool -IsInFallbackContent(nsIContent* aContent) -{ - nsINode* parentNode = aContent->GetParentNode(); - while (parentNode) { - if (parentNode->IsHTMLElement(nsGkAtoms::content)) { - return true; - } - parentNode = parentNode->GetParentNode(); - } - - return false; -} - -nsresult -HTMLShadowElement::BindToTree(nsIDocument* aDocument, - nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) -{ - RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); - - nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, - aBindingParent, - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - - ShadowRoot* containingShadow = GetContainingShadow(); - if (containingShadow && !oldContainingShadow) { - // Keep track of all descendant <shadow> elements in tree order so - // that when the current shadow insertion point is removed, the next - // one can be found quickly. - TreeOrderComparator comparator; - containingShadow->ShadowDescendants().InsertElementSorted(this, comparator); - - if (containingShadow->ShadowDescendants()[0] != this) { - // Only the first <shadow> (in tree order) of a ShadowRoot can be an insertion point. - return NS_OK; - } - - if (IsInFallbackContent(this)) { - // If the first shadow element in tree order is invalid (in fallback content), - // the containing ShadowRoot will not have a shadow insertion point. - containingShadow->SetShadowElement(nullptr); - } else { - mIsInsertionPoint = true; - containingShadow->SetShadowElement(this); - } - - containingShadow->SetInsertionPointChanged(); - } - - if (mIsInsertionPoint && containingShadow) { - // Propagate BindToTree calls to projected shadow root children. - ShadowRoot* projectedShadow = containingShadow->GetOlderShadowRoot(); - if (projectedShadow) { - projectedShadow->SetIsComposedDocParticipant(IsInComposedDoc()); - - for (nsIContent* child = projectedShadow->GetFirstChild(); child; - child = child->GetNextSibling()) { - rv = child->BindToTree(nullptr, projectedShadow, - projectedShadow->GetBindingParent(), - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - } - } - } - - return NS_OK; -} - -void -HTMLShadowElement::UnbindFromTree(bool aDeep, bool aNullParent) -{ - RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); - - if (mIsInsertionPoint && oldContainingShadow) { - // Propagate UnbindFromTree call to previous projected shadow - // root children. - ShadowRoot* projectedShadow = oldContainingShadow->GetOlderShadowRoot(); - if (projectedShadow) { - for (nsIContent* child = projectedShadow->GetFirstChild(); child; - child = child->GetNextSibling()) { - child->UnbindFromTree(true, false); - } - - projectedShadow->SetIsComposedDocParticipant(false); - } - } - - nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); - - if (oldContainingShadow && !GetContainingShadow() && mIsInsertionPoint) { - nsTArray<HTMLShadowElement*>& shadowDescendants = - oldContainingShadow->ShadowDescendants(); - shadowDescendants.RemoveElement(this); - oldContainingShadow->SetShadowElement(nullptr); - - // Find the next shadow insertion point. - if (shadowDescendants.Length() > 0 && - !IsInFallbackContent(shadowDescendants[0])) { - oldContainingShadow->SetShadowElement(shadowDescendants[0]); - } - - oldContainingShadow->SetInsertionPointChanged(); - - mIsInsertionPoint = false; - } -} - -void -HTMLShadowElement::DistributeSingleNode(nsIContent* aContent) -{ - if (aContent->DestInsertionPoints().Contains(this)) { - // Node has already been distrbuted this this node, - // we are done. - return; - } - - aContent->DestInsertionPoints().AppendElement(this); - - // Handle the case where the shadow element is a child of - // a node with a ShadowRoot. The nodes that have been distributed to - // this shadow insertion point will need to be reprojected into the - // insertion points of the parent's ShadowRoot. - ShadowRoot* parentShadowRoot = GetParent()->GetShadowRoot(); - if (parentShadowRoot) { - parentShadowRoot->DistributeSingleNode(aContent); - return; - } - - // Handle the case where the parent of this shadow element is a ShadowRoot - // that is projected into a shadow insertion point in the younger ShadowRoot. - ShadowRoot* containingShadow = GetContainingShadow(); - ShadowRoot* youngerShadow = containingShadow->GetYoungerShadowRoot(); - if (youngerShadow && GetParent() == containingShadow) { - HTMLShadowElement* youngerShadowElement = youngerShadow->GetShadowElement(); - if (youngerShadowElement) { - youngerShadowElement->DistributeSingleNode(aContent); - } - } -} - -void -HTMLShadowElement::RemoveDistributedNode(nsIContent* aContent) -{ - ShadowRoot::RemoveDestInsertionPoint(this, aContent->DestInsertionPoints()); - - // Handle the case where the shadow element is a child of - // a node with a ShadowRoot. The nodes that have been distributed to - // this shadow insertion point will need to be removed from the - // insertion points of the parent's ShadowRoot. - ShadowRoot* parentShadowRoot = GetParent()->GetShadowRoot(); - if (parentShadowRoot) { - parentShadowRoot->RemoveDistributedNode(aContent); - return; - } - - // Handle the case where the parent of this shadow element is a ShadowRoot - // that is projected into a shadow insertion point in the younger ShadowRoot. - ShadowRoot* containingShadow = GetContainingShadow(); - ShadowRoot* youngerShadow = containingShadow->GetYoungerShadowRoot(); - if (youngerShadow && GetParent() == containingShadow) { - HTMLShadowElement* youngerShadowElement = youngerShadow->GetShadowElement(); - if (youngerShadowElement) { - youngerShadowElement->RemoveDistributedNode(aContent); - } - } -} - -void -HTMLShadowElement::DistributeAllNodes() -{ - // All the explicit children of the projected ShadowRoot are distributed - // into this shadow insertion point so update the destination insertion - // points. - ShadowRoot* containingShadow = GetContainingShadow(); - ShadowRoot* olderShadow = containingShadow->GetOlderShadowRoot(); - if (olderShadow) { - ExplicitChildIterator childIterator(olderShadow); - for (nsIContent* content = childIterator.GetNextChild(); - content; - content = childIterator.GetNextChild()) { - ShadowRoot::RemoveDestInsertionPoint(this, content->DestInsertionPoints()); - content->DestInsertionPoints().AppendElement(this); - } - } - - // Handle the case where the shadow element is a child of - // a node with a ShadowRoot. The nodes that have been distributed to - // this shadow insertion point will need to be reprojected into the - // insertion points of the parent's ShadowRoot. - ShadowRoot* parentShadowRoot = GetParent()->GetShadowRoot(); - if (parentShadowRoot) { - parentShadowRoot->DistributeAllNodes(); - return; - } - - // Handle the case where the parent of this shadow element is a ShadowRoot - // that is projected into a shadow insertion point in the younger ShadowRoot. - ShadowRoot* youngerShadow = containingShadow->GetYoungerShadowRoot(); - if (youngerShadow && GetParent() == containingShadow) { - HTMLShadowElement* youngerShadowElement = youngerShadow->GetShadowElement(); - if (youngerShadowElement) { - youngerShadowElement->DistributeAllNodes(); - } - } -} - -void -HTMLShadowElement::ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aFirstNewContent, - int32_t aNewIndexInContainer) -{ - // Watch for content appended to the projected shadow (the ShadowRoot that - // will be rendered in place of this shadow insertion point) because the - // nodes may need to be distributed into other insertion points. - nsIContent* currentChild = aFirstNewContent; - while (currentChild) { - if (ShadowRoot::IsPooledNode(currentChild, aContainer, mProjectedShadow)) { - DistributeSingleNode(currentChild); - } - currentChild = currentChild->GetNextSibling(); - } -} - -void -HTMLShadowElement::ContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - int32_t aIndexInContainer) -{ - // Watch for content appended to the projected shadow (the ShadowRoot that - // will be rendered in place of this shadow insertion point) because the - // nodes may need to be distributed into other insertion points. - if (!ShadowRoot::IsPooledNode(aChild, aContainer, mProjectedShadow)) { - return; - } - - DistributeSingleNode(aChild); -} - -void -HTMLShadowElement::ContentRemoved(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - int32_t aIndexInContainer, - nsIContent* aPreviousSibling) -{ - // Watch for content removed from the projected shadow (the ShadowRoot that - // will be rendered in place of this shadow insertion point) because the - // nodes may need to be removed from other insertion points. - if (!ShadowRoot::IsPooledNode(aChild, aContainer, mProjectedShadow)) { - return; - } - - RemoveDistributedNode(aChild); -} -
deleted file mode 100644 --- a/dom/html/HTMLShadowElement.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_HTMLShadowElement_h__ -#define mozilla_dom_HTMLShadowElement_h__ - -#include "nsGenericHTMLElement.h" - -namespace mozilla { -namespace dom { - -class HTMLShadowElement final : public nsGenericHTMLElement, - public nsStubMutationObserver -{ -public: - explicit HTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED - - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLShadowElement, - nsGenericHTMLElement) - - static HTMLShadowElement* FromContent(nsIContent* aContent) - { - if (aContent->IsHTMLShadowElement()) { - return static_cast<HTMLShadowElement*>(aContent); - } - - return nullptr; - } - - virtual bool IsHTMLShadowElement() const override { return true; } - - virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult, - bool aPreallocateChildren) const override; - - virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) override; - - virtual void UnbindFromTree(bool aDeep = true, - bool aNullParent = true) override; - - bool IsInsertionPoint() { return mIsInsertionPoint; } - - /** - * Sets the ShadowRoot that will be rendered in place of - * this shadow insertion point. - */ - void SetProjectedShadow(ShadowRoot* aProjectedShadow); - - /** - * Distributes a single explicit child of the projected ShadowRoot - * to relevant insertion points. - */ - void DistributeSingleNode(nsIContent* aContent); - - /** - * Removes a single explicit child of the projected ShadowRoot - * from relevant insertion points. - */ - void RemoveDistributedNode(nsIContent* aContent); - - /** - * Distributes all the explicit children of the projected ShadowRoot - * to the shadow insertion point in the younger ShadowRoot and - * the content insertion point of the parent node's ShadowRoot. - */ - void DistributeAllNodes(); - - // WebIDL methods. - ShadowRoot* GetOlderShadowRoot() { return mProjectedShadow; } - -protected: - virtual ~HTMLShadowElement(); - - virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; - - // The ShadowRoot that will be rendered in place of this shadow insertion point. - RefPtr<ShadowRoot> mProjectedShadow; - - bool mIsInsertionPoint; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_HTMLShadowElement_h__ -
--- a/dom/html/moz.build +++ b/dom/html/moz.build @@ -90,17 +90,16 @@ EXPORTS.mozilla.dom += [ 'HTMLOptionsCollection.h', 'HTMLOutputElement.h', 'HTMLParagraphElement.h', 'HTMLPictureElement.h', 'HTMLPreElement.h', 'HTMLProgressElement.h', 'HTMLScriptElement.h', 'HTMLSelectElement.h', - 'HTMLShadowElement.h', 'HTMLSharedElement.h', 'HTMLSharedListElement.h', 'HTMLSourceElement.h', 'HTMLSpanElement.h', 'HTMLStyleElement.h', 'HTMLSummaryElement.h', 'HTMLTableCaptionElement.h', 'HTMLTableCellElement.h', @@ -170,17 +169,16 @@ UNIFIED_SOURCES += [ 'HTMLOptionsCollection.cpp', 'HTMLOutputElement.cpp', 'HTMLParagraphElement.cpp', 'HTMLPictureElement.cpp', 'HTMLPreElement.cpp', 'HTMLProgressElement.cpp', 'HTMLScriptElement.cpp', 'HTMLSelectElement.cpp', - 'HTMLShadowElement.cpp', 'HTMLSharedElement.cpp', 'HTMLSharedListElement.cpp', 'HTMLSourceElement.cpp', 'HTMLSpanElement.cpp', 'HTMLStyleElement.cpp', 'HTMLSummaryElement.cpp', 'HTMLTableCaptionElement.cpp', 'HTMLTableCellElement.cpp',
--- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -1576,17 +1576,16 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup) NS_DECLARE_NS_NEW_HTML_ELEMENT(Option) NS_DECLARE_NS_NEW_HTML_ELEMENT(Output) NS_DECLARE_NS_NEW_HTML_ELEMENT(Paragraph) NS_DECLARE_NS_NEW_HTML_ELEMENT(Picture) NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre) NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress) NS_DECLARE_NS_NEW_HTML_ELEMENT(Script) NS_DECLARE_NS_NEW_HTML_ELEMENT(Select) -NS_DECLARE_NS_NEW_HTML_ELEMENT(Shadow) NS_DECLARE_NS_NEW_HTML_ELEMENT(Source) NS_DECLARE_NS_NEW_HTML_ELEMENT(Span) NS_DECLARE_NS_NEW_HTML_ELEMENT(Style) NS_DECLARE_NS_NEW_HTML_ELEMENT(Summary) NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCaption) NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCell) NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCol) NS_DECLARE_NS_NEW_HTML_ELEMENT(Table)
--- a/dom/html/nsGenericHTMLFrameElement.cpp +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -19,16 +19,17 @@ #include "nsIInterfaceRequestorUtils.h" #include "nsIPermissionManager.h" #include "nsIPresShell.h" #include "nsIScrollable.h" #include "nsPresContext.h" #include "nsServiceManagerUtils.h" #include "nsSubDocumentFrame.h" #include "nsXULElement.h" +#include "nsAttrValueOrString.h" using namespace mozilla; using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement)
--- a/dom/html/nsHTMLContentSink.cpp +++ b/dom/html/nsHTMLContentSink.cpp @@ -25,16 +25,17 @@ #include "mozilla/dom/NodeInfo.h" #include "mozilla/dom/ScriptLoader.h" #include "nsIAppShell.h" #include "nsCRT.h" #include "prtime.h" #include "mozilla/Logging.h" #include "nsNodeUtils.h" #include "nsIContent.h" +#include "mozilla/dom/CustomElementRegistry.h" #include "mozilla/dom/Element.h" #include "mozilla/Preferences.h" #include "nsGenericHTMLElement.h" #include "nsIDOMDocument.h" #include "nsIDOMDocumentType.h" #include "nsIScriptElement.h" @@ -218,31 +219,126 @@ public: nsIContent *Add(nsIContent *child); }; Node* mStack; int32_t mStackSize; int32_t mStackPos; }; +static void +DoCustomElementCreate(Element** aElement, nsIDocument* aDoc, + CustomElementConstructor* aConstructor, ErrorResult& aRv) +{ + RefPtr<Element> element = + aConstructor->Construct("Custom Element Create", aRv); + if (aRv.Failed() || !element->IsHTMLElement()) { + aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("HTMLElement")); + return; + } + + if (aDoc != element->OwnerDoc() || element->GetParentNode() || + element->HasChildren() || element->GetAttrCount()) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + + element.forget(aElement); +} + nsresult NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FromParser aFromParser, const nsAString* aIs) { *aResult = nullptr; RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo; nsIAtom *name = nodeInfo->NameAtom(); NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML), "Trying to HTML elements that don't have the XHTML namespace"); int32_t tag = nsHTMLTags::CaseSensitiveAtomTagToId(name); + // https://dom.spec.whatwg.org/#concept-create-element + // We only handle the "synchronous custom elements flag is set" now. + // For the unset case (e.g. cloning a node), see bug 1319342 for that. + // Step 4. + CustomElementDefinition* definition = nullptr; + if (CustomElementRegistry::IsCustomElementEnabled()) { + definition = + nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(), + nodeInfo->LocalName(), + nodeInfo->NamespaceID(), + aIs); + } + + // It might be a problem that parser synchronously calls constructor, so filed + // bug 1378079 to figure out what we should do for parser case. + if (definition) { + /* + * Synchronous custom elements flag is determined by 3 places in spec, + * 1) create an element for a token, the flag is determined by + * "will execute script" which is not originally created + * for the HTML fragment parsing algorithm. + * 2) createElement and createElementNS, the flag is the same as + * NOT_FROM_PARSER. + * 3) clone a node, our implementation will not go into this function. + * For the unset case which is non-synchronous only applied for + * inner/outerHTML. + */ + bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT || + aFromParser == dom::NOT_FROM_PARSER; + // Per discussion in https://github.com/w3c/webcomponents/issues/635, + // use entry global in those places that are called from JS APIs. + nsIGlobalObject* global = GetEntryGlobal(); + MOZ_ASSERT(global); + AutoEntryScript aes(global, "create custom elements"); + JSContext* cx = aes.cx(); + ErrorResult rv; + + // Step 5. + if (definition->IsCustomBuiltIn()) { + // SetupCustomElement() should be called with an element that don't have + // CustomElementData setup, if not we will hit the assertion in + // SetCustomElementData(). + nsCOMPtr<nsIAtom> tagAtom = nodeInfo->NameAtom(); + nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom; + // Built-in element + *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take(); + (*aResult)->SetCustomElementData(new CustomElementData(typeAtom)); + if (synchronousCustomElements) { + CustomElementRegistry::Upgrade(*aResult, definition, rv); + } else { + nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); + } + + if (rv.MaybeSetPendingException(cx)) { + aes.ReportException(); + } + return NS_OK; + } + + // Step 6.1. + if (synchronousCustomElements) { + DoCustomElementCreate(aResult, nodeInfo->GetDocument(), + definition->mConstructor, rv); + if (rv.MaybeSetPendingException(cx)) { + NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser)); + } + return NS_OK; + } + + // Step 6.2. + NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser)); + nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); + return NS_OK; + } + // Per the Custom Element specification, unknown tags that are valid custom // element names should be HTMLElement instead of HTMLUnknownElement. bool isCustomElementName = (tag == eHTMLTag_userdefined && nsContentUtils::IsCustomElementName(name)); if (isCustomElementName) { NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser)); } else { *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
--- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -7710,22 +7710,20 @@ private: SendBlockedNotification() override; nsresult DispatchToWorkThread() override; void SendResults() override; -#ifdef ENABLE_INTL_API static nsresult UpdateLocaleAwareIndex(mozIStorageConnection* aConnection, const IndexMetadata& aIndexMetadata, const nsCString& aLocale); -#endif }; class OpenDatabaseOp::VersionChangeOp final : public TransactionDatabaseOperationBase { friend class OpenDatabaseOp; RefPtr<OpenDatabaseOp> mOpenDatabaseOp; @@ -19909,19 +19907,16 @@ DatabaseOperationBase::BindKeyRangeToSta // static nsresult DatabaseOperationBase::BindKeyRangeToStatement( const SerializedKeyRange& aKeyRange, mozIStorageStatement* aStatement, const nsCString& aLocale) { -#ifndef ENABLE_INTL_API - return BindKeyRangeToStatement(aKeyRange, aStatement); -#else MOZ_ASSERT(!IsOnBackgroundThread()); MOZ_ASSERT(aStatement); MOZ_ASSERT(!aLocale.IsEmpty()); nsresult rv = NS_OK; if (!aKeyRange.lower().IsUnset()) { Key lower; @@ -19949,17 +19944,16 @@ DatabaseOperationBase::BindKeyRangeToSta rv = upper.BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key")); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } return NS_OK; -#endif } // static void DatabaseOperationBase::AppendConditionClause(const nsACString& aColumnName, const nsACString& aArgName, bool aLessThan, bool aEquals, @@ -22012,17 +22006,16 @@ OpenDatabaseOp::LoadDatabaseInformation( rv = stmt->GetInt32(5, &scratch); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } indexMetadata->mCommonMetadata.multiEntry() = !!scratch; -#ifdef ENABLE_INTL_API const bool localeAware = !stmt->IsNull(6); if (localeAware) { rv = stmt->GetUTF8String(6, indexMetadata->mCommonMetadata.locale()); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } rv = stmt->GetInt32(7, &scratch); @@ -22042,17 +22035,16 @@ OpenDatabaseOp::LoadDatabaseInformation( rv = UpdateLocaleAwareIndex(aConnection, indexMetadata->mCommonMetadata, systemLocale); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } } -#endif if (NS_WARN_IF(!objectStoreMetadata->mIndexes.Put(indexId, indexMetadata, fallible))) { return NS_ERROR_OUT_OF_MEMORY; } lastIndexId = std::max(lastIndexId, indexId); } @@ -22068,17 +22060,16 @@ OpenDatabaseOp::LoadDatabaseInformation( } mMetadata->mNextObjectStoreId = lastObjectStoreId + 1; mMetadata->mNextIndexId = lastIndexId + 1; return NS_OK; } -#ifdef ENABLE_INTL_API /* static */ nsresult OpenDatabaseOp::UpdateLocaleAwareIndex(mozIStorageConnection* aConnection, const IndexMetadata& aIndexMetadata, const nsCString& aLocale) { nsresult rv; @@ -22186,17 +22177,16 @@ OpenDatabaseOp::UpdateLocaleAwareIndex(m rv = metaStmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), aIndexMetadata.id()); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } rv = metaStmt->Execute(); return rv; } -#endif nsresult OpenDatabaseOp::BeginVersionChange() { AssertIsOnOwningThread(); MOZ_ASSERT(mState == State::BeginVersionChange); MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty()); MOZ_ASSERT(mMetadata->mCommonMetadata.version() <= mRequestedVersion); @@ -27961,33 +27951,29 @@ OpenOp::GetRangeKeyInfo(bool aLowerBound MOZ_ASSERT(aOpen); if (mOptionalKeyRange.type() == OptionalKeyRange::TSerializedKeyRange) { const SerializedKeyRange& range = mOptionalKeyRange.get_SerializedKeyRange(); if (range.isOnly()) { *aKey = range.lower(); *aOpen = false; -#ifdef ENABLE_INTL_API if (mCursor->IsLocaleAware()) { range.lower().ToLocaleBasedKey(*aKey, mCursor->mLocale); } -#endif } else { *aKey = aLowerBound ? range.lower() : range.upper(); *aOpen = aLowerBound ? range.lowerOpen() : range.upperOpen(); -#ifdef ENABLE_INTL_API if (mCursor->IsLocaleAware()) { if (aLowerBound) { range.lower().ToLocaleBasedKey(*aKey, mCursor->mLocale); } else { range.upper().ToLocaleBasedKey(*aKey, mCursor->mLocale); } } -#endif } } else { *aOpen = false; } } nsresult Cursor::
--- a/dom/indexedDB/IDBCursor.cpp +++ b/dom/indexedDB/IDBCursor.cpp @@ -60,23 +60,21 @@ IDBCursor::IDBCursor(Type aType, MOZ_ASSERT(mScriptOwner); if (mScriptOwner) { mozilla::HoldJSObjects(this); mRooted = true; } } -#ifdef ENABLE_INTL_API bool IDBCursor::IsLocaleAware() const { return mSourceIndex && !mSourceIndex->Locale().IsEmpty(); } -#endif IDBCursor::~IDBCursor() { AssertIsOnOwningThread(); DropJSObjects(); if (mBackgroundActor) { @@ -432,30 +430,26 @@ IDBCursor::Continue(JSContext* aCx, } Key key; aRv = key.SetFromJSVal(aCx, aKey); if (aRv.Failed()) { return; } -#ifdef ENABLE_INTL_API if (IsLocaleAware() && !key.IsUnset()) { Key tmp; aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale()); if (aRv.Failed()) { return; } key = tmp; } const Key& sortKey = IsLocaleAware() ? mSortKey : mKey; -#else - const Key& sortKey = mKey; -#endif if (!key.IsUnset()) { switch (mDirection) { case NEXT: case NEXT_UNIQUE: if (key <= sortKey) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; @@ -542,30 +536,26 @@ IDBCursor::ContinuePrimaryKey(JSContext* } Key key; aRv = key.SetFromJSVal(aCx, aKey); if (aRv.Failed()) { return; } -#ifdef ENABLE_INTL_API if (IsLocaleAware() && !key.IsUnset()) { Key tmp; aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale()); if (aRv.Failed()) { return; } key = tmp; } const Key& sortKey = IsLocaleAware() ? mSortKey : mKey; -#else - const Key& sortKey = mKey; -#endif if (key.IsUnset()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; } Key primaryKey; aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey);
--- a/dom/indexedDB/IDBCursor.h +++ b/dom/indexedDB/IDBCursor.h @@ -200,21 +200,19 @@ public: private: IDBCursor(Type aType, indexedDB::BackgroundCursorChild* aBackgroundActor, const Key& aKey); ~IDBCursor(); -#ifdef ENABLE_INTL_API // Checks if this is a locale aware cursor (ie. the index's sortKey is unset) bool IsLocaleAware() const; -#endif void DropJSObjects(); bool IsSourceDeleted() const; };
--- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -1311,19 +1311,17 @@ IDBObjectStore::AppendIndexUpdateInfo( bool aMultiEntry, const nsCString& aLocale, JSContext* aCx, JS::Handle<JS::Value> aVal, nsTArray<IndexUpdateInfo>& aUpdateInfoArray) { nsresult rv; -#ifdef ENABLE_INTL_API const bool localeAware = !aLocale.IsEmpty(); -#endif if (!aMultiEntry) { Key key; rv = aKeyPath.ExtractKey(aCx, aVal, key); // If an index's keyPath doesn't match an object, we ignore that object. if (rv == NS_ERROR_DOM_INDEXEDDB_DATA_ERR || key.IsUnset()) { return NS_OK; @@ -1331,24 +1329,22 @@ IDBObjectStore::AppendIndexUpdateInfo( if (NS_FAILED(rv)) { return rv; } IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement(); updateInfo->indexId() = aIndexID; updateInfo->value() = key; -#ifdef ENABLE_INTL_API if (localeAware) { rv = key.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } -#endif return NS_OK; } JS::Rooted<JS::Value> val(aCx); if (NS_FAILED(aKeyPath.ExtractKeyAsJSVal(aCx, aVal, val.address()))) { return NS_OK; } @@ -1378,45 +1374,41 @@ IDBObjectStore::AppendIndexUpdateInfo( value.IsUnset()) { // Not a value we can do anything with, ignore it. continue; } IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement(); updateInfo->indexId() = aIndexID; updateInfo->value() = value; -#ifdef ENABLE_INTL_API if (localeAware) { rv = value.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } -#endif } } else { Key value; if (NS_FAILED(value.SetFromJSVal(aCx, val)) || value.IsUnset()) { // Not a value we can do anything with, ignore it. return NS_OK; } IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement(); updateInfo->indexId() = aIndexID; updateInfo->value() = value; -#ifdef ENABLE_INTL_API if (localeAware) { rv = value.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } -#endif } return NS_OK; } // static void IDBObjectStore::ClearCloneReadInfo(StructuredCloneReadInfo& aReadInfo) @@ -2272,21 +2264,19 @@ IDBObjectStore::CreateIndex(const nsAStr indexes.IsEmpty() ? nullptr : indexes.Elements(); // With this setup we only validate the passed in locale name by the time we // get to encoding Keys. Maybe we should do it here right away and error out. // Valid locale names are always ASCII as per BCP-47. nsCString locale = NS_LossyConvertUTF16toASCII(aOptionalParameters.mLocale); bool autoLocale = locale.EqualsASCII("auto"); -#ifdef ENABLE_INTL_API if (autoLocale) { locale = IndexedDatabaseManager::GetLocale(); } -#endif IndexMetadata* metadata = indexes.AppendElement( IndexMetadata(transaction->NextIndexId(), nsString(aName), keyPath, locale, aOptionalParameters.mUnique, aOptionalParameters.mMultiEntry, autoLocale));
--- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -40,35 +40,32 @@ #include "IDBEvents.h" #include "IDBFactory.h" #include "IDBKeyRange.h" #include "IDBRequest.h" #include "ProfilerHelpers.h" #include "ScriptErrorHelper.h" #include "WorkerScope.h" #include "WorkerPrivate.h" +#include "nsCharSeparatedTokenizer.h" +#include "unicode/locid.h" // Bindings for ResolveConstructors #include "mozilla/dom/IDBCursorBinding.h" #include "mozilla/dom/IDBDatabaseBinding.h" #include "mozilla/dom/IDBFactoryBinding.h" #include "mozilla/dom/IDBIndexBinding.h" #include "mozilla/dom/IDBKeyRangeBinding.h" #include "mozilla/dom/IDBMutableFileBinding.h" #include "mozilla/dom/IDBObjectStoreBinding.h" #include "mozilla/dom/IDBOpenDBRequestBinding.h" #include "mozilla/dom/IDBRequestBinding.h" #include "mozilla/dom/IDBTransactionBinding.h" #include "mozilla/dom/IDBVersionChangeEventBinding.h" -#ifdef ENABLE_INTL_API -#include "nsCharSeparatedTokenizer.h" -#include "unicode/locid.h" -#endif - #define IDB_STR "indexedDB" // The two possible values for the data argument when receiving the disk space // observer notification. #define LOW_DISK_SPACE_DATA_FULL "full" #define LOW_DISK_SPACE_DATA_FREE "free" namespace mozilla { @@ -425,17 +422,16 @@ IndexedDatabaseManager::Init() kPrefLoggingEnabled); Preferences::RegisterCallbackAndCall(DataThresholdPrefChangedCallback, kDataThresholdPref); Preferences::RegisterCallbackAndCall(MaxSerializedMsgSizePrefChangeCallback, kPrefMaxSerilizedMsgSize); -#ifdef ENABLE_INTL_API nsAutoCString acceptLang; Preferences::GetLocalizedCString("intl.accept_languages", acceptLang); // Split values on commas. nsCCharSeparatedTokenizer langTokenizer(acceptLang, ','); while (langTokenizer.hasMoreTokens()) { nsAutoCString lang(langTokenizer.nextToken()); icu::Locale locale = icu::Locale::createCanonical(lang.get()); @@ -444,17 +440,16 @@ IndexedDatabaseManager::Init() mLocale.AssignASCII(locale.getBaseName()); break; } } if (mLocale.IsEmpty()) { mLocale.AssignLiteral("en_US"); } -#endif return NS_OK; } void IndexedDatabaseManager::Destroy() { // Setting the closed flag prevents the service from being recreated. @@ -1088,27 +1083,25 @@ IndexedDatabaseManager::LoggingModePrefC sLoggingMode = logDetails ? Logging_DetailedProfilerMarks : Logging_ConciseProfilerMarks; } else { sLoggingMode = logDetails ? Logging_Detailed : Logging_Concise; } } -#ifdef ENABLE_INTL_API // static const nsCString& IndexedDatabaseManager::GetLocale() { IndexedDatabaseManager* idbManager = Get(); MOZ_ASSERT(idbManager, "IDBManager is not ready!"); return idbManager->mLocale; } -#endif NS_IMPL_ADDREF(IndexedDatabaseManager) NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy()) NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager, nsIObserver, nsITimerCallback, nsINamed) NS_IMETHODIMP IndexedDatabaseManager::Observe(nsISupports* aSubject, const char* aTopic,
--- a/dom/indexedDB/IndexedDatabaseManager.h +++ b/dom/indexedDB/IndexedDatabaseManager.h @@ -184,20 +184,18 @@ public: int32_t* aRefCnt, int32_t* aDBRefCnt, int32_t* aSliceRefCnt, bool* aResult); nsresult FlushPendingFileDeletions(); -#ifdef ENABLE_INTL_API static const nsCString& GetLocale(); -#endif static mozilla::Mutex& FileMutex() { IndexedDatabaseManager* mgr = Get(); NS_ASSERTION(mgr, "Must have a manager here!"); return mgr->mFileMutex; @@ -236,19 +234,17 @@ private: nsClassHashtable<nsRefPtrHashKey<FileManager>, nsTArray<int64_t>> mPendingDeleteInfos; // Lock protecting FileManager.mFileInfos. // It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt // and FileInfo.mSliceRefCnt mozilla::Mutex mFileMutex; -#ifdef ENABLE_INTL_API nsCString mLocale; -#endif indexedDB::BackgroundUtilsChild* mBackgroundActor; static bool sIsMainProcess; static bool sFullSynchronousMode; static LazyLogModule sLoggingModule; static Atomic<LoggingMode> sLoggingMode; static mozilla::Atomic<bool> sLowDiskSpaceMode;
--- a/dom/indexedDB/Key.cpp +++ b/dom/indexedDB/Key.cpp @@ -17,22 +17,19 @@ #include "mozilla/CheckedInt.h" #include "mozilla/EndianUtils.h" #include "mozilla/FloatingPoint.h" #include "mozIStorageStatement.h" #include "mozIStorageValueArray.h" #include "nsAlgorithm.h" #include "nsJSUtils.h" #include "ReportInternalError.h" +#include "unicode/ucol.h" #include "xpcpublic.h" -#ifdef ENABLE_INTL_API -#include "unicode/ucol.h" -#endif - namespace mozilla { namespace dom { namespace indexedDB { /* Here's how we encode keys: Basic strategy is the following @@ -105,17 +102,17 @@ namespace indexedDB { end of the encoded buffer. "foo" // 0x30 s s s 1 // 0x10 bf f0 ["a", "b"] // 0x80 s 0 0x30 s [1, 2] // 0x60 bf f0 0 0 0 0 0 0 0x10 c0 [[]] // 0x80 */ -#ifdef ENABLE_INTL_API + nsresult Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const { if (IsUnset()) { aTarget.Unset(); return NS_OK; } @@ -202,17 +199,16 @@ Key::ToLocaleBasedKey(Key& aTarget, cons if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } } aTarget.TrimBuffer(); return NS_OK; } -#endif nsresult Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset, uint16_t aRecursionDepth) { static_assert(eMaxType * kMaxArrayCollapse < 256, "Unable to encode jsvals."); @@ -502,17 +498,16 @@ Key::EncodeAsString(const T* aStart, con // Write end marker *(buffer++) = eTerminator; NS_ASSERTION(buffer == mBuffer.EndReading(), "Wrote wrong number of bytes"); return NS_OK; } -#ifdef ENABLE_INTL_API nsresult Key::EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset, const nsCString& aLocale) { const int length = aString.Length(); if (length == 0) { return NS_OK; } @@ -540,17 +535,16 @@ Key::EncodeLocaleString(const nsDependen if (NS_WARN_IF(sortKeyLength == 0)) { return NS_ERROR_FAILURE; } return EncodeString(keyBuffer.Elements(), keyBuffer.Elements()+sortKeyLength, aTypeOffset); } -#endif // static nsresult Key::DecodeJSVal(const unsigned char*& aPos, const unsigned char* aEnd, JSContext* aCx, JS::MutableHandle<JS::Value> aVal) {
--- a/dom/indexedDB/Key.h +++ b/dom/indexedDB/Key.h @@ -209,20 +209,18 @@ public: ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const; nsresult ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const; nsresult AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal); -#ifdef ENABLE_INTL_API nsresult ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const; -#endif void FinishArray() { TrimBuffer(); } const nsCString& @@ -293,21 +291,19 @@ private: template <typename T> nsresult EncodeString(const T* aStart, const T* aEnd, uint8_t aTypeOffset); template <typename T> nsresult EncodeAsString(const T* aStart, const T* aEnd, uint8_t aType); -#ifdef ENABLE_INTL_API nsresult EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset, const nsCString& aLocale); -#endif void EncodeNumber(double aFloat, uint8_t aType); nsresult EncodeBinary(JSObject* aObject, bool aIsViewObject, uint8_t aTypeOffset); // Decoding functions. aPos points into mBuffer and is adjusted to point
--- a/dom/indexedDB/moz.build +++ b/dom/indexedDB/moz.build @@ -2,30 +2,30 @@ # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. with Files("**"): BUG_COMPONENT = ("Core", "DOM: IndexedDB") -MOCHITEST_MANIFESTS += ['test/mochitest.ini'] +MOCHITEST_MANIFESTS += [ + 'test/mochitest-intl-api.ini', + 'test/mochitest.ini', +] BROWSER_CHROME_MANIFESTS += ['test/browser.ini'] MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini'] XPCSHELL_TESTS_MANIFESTS += [ 'test/unit/xpcshell-child-process.ini', 'test/unit/xpcshell-parent-process.ini' ] -if CONFIG['ENABLE_INTL_API']: - MOCHITEST_MANIFESTS += ['test/mochitest-intl-api.ini'] - EXPORTS.mozilla.dom += [ 'IDBCursor.h', 'IDBDatabase.h', 'IDBEvents.h', 'IDBFactory.h', 'IDBFileHandle.h', 'IDBFileRequest.h', 'IDBIndex.h',
--- a/dom/media/CubebUtils.cpp +++ b/dom/media/CubebUtils.cpp @@ -101,19 +101,19 @@ void CubebLogCallback(const char* aFmt, // This mutex protects the variables below. StaticMutex sMutex; enum class CubebState { Uninitialized = 0, Initialized, Shutdown } sCubebState = CubebState::Uninitialized; cubeb* sCubebContext; -double sVolumeScale; -uint32_t sCubebPlaybackLatencyInMilliseconds; -uint32_t sCubebMSGLatencyInFrames; +double sVolumeScale = 1.0; +uint32_t sCubebPlaybackLatencyInMilliseconds = 100; +uint32_t sCubebMSGLatencyInFrames = 512; bool sCubebPlaybackLatencyPrefSet; bool sCubebMSGLatencyPrefSet; bool sAudioStreamInitEverSucceeded = false; #ifdef MOZ_CUBEB_REMOTING bool sCubebSandbox; #endif StaticAutoPtr<char> sBrandName; StaticAutoPtr<char> sCubebBackendName;
--- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -1,13 +1,14 @@ # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +include('/media/webrtc/webrtc.mozbuild') FILES_PER_UNIFIED_FILE = 6 with Files('*'): BUG_COMPONENT = ('Core', 'Audio/Video') with Files('test/**'): BUG_COMPONENT = ('Core', 'Audio/Video: Playback') @@ -311,21 +312,16 @@ LOCAL_INCLUDES += [ if CONFIG['MOZ_WEBRTC']: LOCAL_INCLUDES += [ '/media/webrtc/signaling/src/common', '/media/webrtc/trunk', ] DEFINES['MOZILLA_INTERNAL_API'] = True -if CONFIG['OS_TARGET'] == 'WINNT': - DEFINES['WEBRTC_WIN'] = True -else: - DEFINES['WEBRTC_POSIX'] = True - if CONFIG['ANDROID_VERSION'] > '15': DEFINES['MOZ_OMX_WEBM_DECODER'] = True if CONFIG['MOZ_ANDROID_HLS_SUPPORT']: DEFINES['MOZ_ANDROID_HLS_SUPPORT'] = True include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/media/systemservices/moz.build +++ b/dom/media/systemservices/moz.build @@ -1,13 +1,14 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +include('/media/webrtc/webrtc.mozbuild') if CONFIG['MOZ_WEBRTC']: EXPORTS += [ 'CamerasChild.h', 'CamerasParent.h', 'VideoEngine.h', 'VideoFrameUtils.h' ] @@ -17,22 +18,16 @@ if CONFIG['MOZ_WEBRTC']: 'ShmemPool.cpp', 'VideoEngine.cpp', 'VideoFrameUtils.cpp' ] LOCAL_INCLUDES += [ '/media/webrtc/signaling', '/media/webrtc/trunk', ] -if CONFIG['OS_TARGET'] == 'WINNT': - DEFINES['WEBRTC_WIN'] = True -else: - DEFINES['WEBRTC_POSIX'] = True - # Must match build/gyp.mozbuild: enable_libevent - DEFINES['WEBRTC_BUILD_LIBEVENT'] = True if CONFIG['OS_TARGET'] == 'Android': DEFINES['WEBRTC_ANDROID'] = True if CONFIG['OS_TARGET'] == 'Android': EXPORTS += [ 'OpenSLESProvider.h'
--- a/dom/media/webrtc/moz.build +++ b/dom/media/webrtc/moz.build @@ -1,13 +1,14 @@ # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +include('/media/webrtc/webrtc.mozbuild') with Files('*'): BUG_COMPONENT = ('Core', 'WebRTC: Audio/Video') with Files('PeerIdentity.*'): BUG_COMPONENT = ('Core', 'WebRTC: Signaling') XPIDL_MODULE = 'content_webrtc' @@ -15,20 +16,16 @@ XPIDL_MODULE = 'content_webrtc' EXPORTS += [ 'MediaEngine.h', 'MediaEngineCameraVideoSource.h', 'MediaEngineDefault.h', 'MediaTrackConstraints.h', ] if CONFIG['MOZ_WEBRTC']: - if CONFIG['OS_TARGET'] == 'WINNT': - DEFINES['WEBRTC_WIN'] = True - else: - DEFINES['WEBRTC_POSIX'] = True EXPORTS += ['AudioOutputObserver.h', 'MediaEngineRemoteVideoSource.h', 'MediaEngineWebRTC.h'] EXPORTS.mozilla.dom += [ 'RTCIdentityProviderRegistrar.h' ] UNIFIED_SOURCES += [ 'MediaEngineCameraVideoSource.cpp', 'MediaEngineRemoteVideoSource.cpp', 'MediaEngineTabVideoSource.cpp',
--- a/dom/payments/PaymentRequest.cpp +++ b/dom/payments/PaymentRequest.cpp @@ -1,19 +1,21 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "BasicCardPayment.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/PaymentRequest.h" #include "mozilla/dom/PaymentResponse.h" #include "nsContentUtils.h" -#include "BasicCardPayment.h" +#include "nsIURLParser.h" +#include "nsNetCID.h" #include "PaymentRequestManager.h" namespace mozilla { namespace dom { NS_IMPL_CYCLE_COLLECTION_CLASS(PaymentRequest) NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PaymentRequest, @@ -48,31 +50,217 @@ NS_IMPL_RELEASE_INHERITED(PaymentRequest bool PaymentRequest::PrefEnabled(JSContext* aCx, JSObject* aObj) { return Preferences::GetBool("dom.payments.request.enabled"); } nsresult +PaymentRequest::IsValidStandardizedPMI(const nsAString& aIdentifier, + nsAString& aErrorMsg) +{ + /* + * The syntax of a standardized payment method identifier is given by the + * following [ABNF]: + * + * stdpmi = part *( "-" part ) + * part = 1loweralpha *( DIGIT / loweralpha ) + * loweralpha = %x61-7A + */ + nsString::const_iterator start, end; + aIdentifier.BeginReading(start); + aIdentifier.EndReading(end); + while (start != end) { + // the first char must be in the range %x61-7A + if ((*start < 'a' || *start > 'z')) { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AppendLiteral("' is not valid. The character '"); + aErrorMsg.Append(*start); + aErrorMsg.AppendLiteral("' at the beginning or after the '-' must be in the range [a-z]."); + return NS_ERROR_RANGE_ERR; + } + ++start; + // the rest can be in the range %x61-7A + DIGITs + while (start != end && *start != '-' && + ((*start >= 'a' && *start <= 'z') || (*start >= '0' && *start <= '9'))) { + ++start; + } + // if the char is not in the range %x61-7A + DIGITs, it must be '-' + if (start != end && *start != '-') { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AppendLiteral("' is not valid. The character '"); + aErrorMsg.Append(*start); + aErrorMsg.AppendLiteral("' must be in the range [a-zA-z0-9-]."); + return NS_ERROR_RANGE_ERR; + } + if (*start == '-') { + ++start; + // the last char can not be '-' + if (start == end) { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AppendLiteral("' is not valid. The last character '"); + aErrorMsg.Append(*start); + aErrorMsg.AppendLiteral("' must be in the range [a-z0-9]."); + return NS_ERROR_RANGE_ERR; + } + } + } + return NS_OK; +} + +nsresult +PaymentRequest::IsValidPaymentMethodIdentifier(const nsAString& aIdentifier, + nsAString& aErrorMsg) +{ + if (aIdentifier.IsEmpty()) { + aErrorMsg.AssignLiteral("Payment method identifier is required."); + return NS_ERROR_TYPE_ERR; + } + /* + * URL-based payment method identifier + * + * 1. If url's scheme is not "https", return false. + * 2. If url's username or password is not the empty string, return false. + * 3. Otherwise, return true. + */ + nsCOMPtr<nsIURLParser> urlParser = do_GetService(NS_STDURLPARSER_CONTRACTID); + MOZ_ASSERT(urlParser); + uint32_t schemePos = 0; + int32_t schemeLen = 0; + uint32_t authorityPos = 0; + int32_t authorityLen = 0; + NS_ConvertUTF16toUTF8 url(aIdentifier); + nsresult rv = urlParser->ParseURL(url.get(), + url.Length(), + &schemePos, &schemeLen, + &authorityPos, &authorityLen, + nullptr, nullptr); + NS_ENSURE_SUCCESS(rv, NS_ERROR_RANGE_ERR); + if (schemeLen == -1) { + // The PMI is not a URL-based PMI, check if it is a standardized PMI + return IsValidStandardizedPMI(aIdentifier, aErrorMsg); + } + if (!Substring(aIdentifier, schemePos, schemeLen).EqualsASCII("https")) { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AppendLiteral("' is not valid. The scheme must be 'https'."); + return NS_ERROR_RANGE_ERR; + } + if (Substring(aIdentifier, authorityPos, authorityLen).IsEmpty()) { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AppendLiteral("' is not valid. hostname can not be empty."); + return NS_ERROR_RANGE_ERR; + } + + uint32_t usernamePos = 0; + int32_t usernameLen = 0; + uint32_t passwordPos = 0; + int32_t passwordLen = 0; + uint32_t hostnamePos = 0; + int32_t hostnameLen = 0; + int32_t port = 0; + + NS_ConvertUTF16toUTF8 authority(Substring(aIdentifier, authorityPos, authorityLen)); + rv = urlParser->ParseAuthority(authority.get(), + authority.Length(), + &usernamePos, &usernameLen, + &passwordPos, &passwordLen, + &hostnamePos, &hostnameLen, + &port); + if (NS_FAILED(rv)) { + // Handle the special cases that URLParser treats it as an invalid URL, but + // are used in web-platform-test + // For exmaple: + // https://:@example.com // should be considered as valid + // https://:password@example.com. // should be considered as invalid + int32_t atPos = authority.FindChar('@'); + if (atPos >= 0) { + // only accept the case https://:@xxx + if (atPos == 1 && authority.CharAt(0) == ':') { + usernamePos = 0; + usernameLen = 0; + passwordPos = 0; + passwordLen = 0; + } else { + // for the fail cases, don't care about what the actual length is. + usernamePos = 0; + usernameLen = INT32_MAX; + passwordPos = 0; + passwordLen = INT32_MAX; + } + } else { + usernamePos = 0; + usernameLen = -1; + passwordPos = 0; + passwordLen = -1; + } + // Parse server information when both username and password are empty or do not + // exist. + if ((usernameLen <= 0) && (passwordLen <= 0)) { + if (authority.Length() - atPos - 1 == 0) { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AppendLiteral("' is not valid. hostname can not be empty."); + return NS_ERROR_RANGE_ERR; + } + // Re-using nsIURLParser::ParseServerInfo to extract the hostname and port + // information. This can help us to handle complicated IPv6 cases. + nsAutoCString serverInfo(Substring(authority, + atPos + 1, + authority.Length() - atPos - 1)); + rv = urlParser->ParseServerInfo(serverInfo.get(), + serverInfo.Length(), + &hostnamePos, &hostnameLen, &port); + if (NS_FAILED(rv)) { + // ParseServerInfo returns NS_ERROR_MALFORMED_URI in all fail cases, we + // probably need a followup bug to figure out the fail reason. + return NS_ERROR_RANGE_ERR; + } + } + } + // PMI is valid when usernameLen/passwordLen equals to -1 or 0. + if (usernameLen > 0 || passwordLen > 0) { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AssignLiteral("' is not valid. Username and password must be empty."); + return NS_ERROR_RANGE_ERR; + } + + // PMI is valid when hostnameLen is larger than 0 + if (hostnameLen <= 0) { + aErrorMsg.AssignLiteral("'"); + aErrorMsg.Append(aIdentifier); + aErrorMsg.AppendLiteral("' is not valid. hostname can not be empty."); + return NS_ERROR_RANGE_ERR; + } + return NS_OK; +} + +nsresult PaymentRequest::IsValidMethodData(JSContext* aCx, const Sequence<PaymentMethodData>& aMethodData, nsAString& aErrorMsg) { if (!aMethodData.Length()) { aErrorMsg.AssignLiteral("At least one payment method is required."); return NS_ERROR_TYPE_ERR; } for (const PaymentMethodData& methodData : aMethodData) { - if (methodData.mSupportedMethods.IsEmpty()) { - aErrorMsg.AssignLiteral( - "Payment method identifier is required."); - return NS_ERROR_TYPE_ERR; + nsresult rv = IsValidPaymentMethodIdentifier(methodData.mSupportedMethods, + aErrorMsg); + if (NS_FAILED(rv)) { + return rv; } + RefPtr<BasicCardService> service = BasicCardService::GetService(); MOZ_ASSERT(service); if (service->IsBasicCardPayment(methodData.mSupportedMethods)) { if (!methodData.mData.WasPassed()) { continue; } MOZ_ASSERT(aCx); if (!service->IsValidBasicCardRequest(aCx, @@ -294,16 +482,20 @@ PaymentRequest::IsValidDetailsBase(const seenIDs.AppendElement(shippingOption.mId); } } // Check payment details modifiers if (aDetails.mModifiers.WasPassed()) { const Sequence<PaymentDetailsModifier>& modifiers = aDetails.mModifiers.Value(); for (const PaymentDetailsModifier& modifier : modifiers) { + rv = IsValidPaymentMethodIdentifier(modifier.mSupportedMethods, aErrorMsg); + if (NS_FAILED(rv)) { + return rv; + } rv = IsValidCurrencyAmount(NS_LITERAL_STRING("details.modifiers.total"), modifier.mTotal.mAmount, true, // isTotalItem aErrorMsg); if (NS_FAILED(rv)) { return rv; } if (modifier.mAdditionalDisplayItems.WasPassed()) { @@ -372,17 +564,21 @@ PaymentRequest::Constructor(const Global } while (node); // Check payment methods and details nsAutoString message; nsresult rv = IsValidMethodData(aGlobal.Context(), aMethodData, message); if (NS_FAILED(rv)) { - aRv.ThrowTypeError<MSG_ILLEGAL_TYPE_PR_CONSTRUCTOR>(message); + if (rv == NS_ERROR_TYPE_ERR) { + aRv.ThrowTypeError<MSG_ILLEGAL_TYPE_PR_CONSTRUCTOR>(message); + } else if (rv == NS_ERROR_RANGE_ERR) { + aRv.ThrowRangeError<MSG_ILLEGAL_RANGE_PR_CONSTRUCTOR>(message); + } return nullptr; } rv = IsValidDetailsInit(aDetails, message); if (NS_FAILED(rv)) { if (rv == NS_ERROR_TYPE_ERR) { aRv.ThrowTypeError<MSG_ILLEGAL_TYPE_PR_CONSTRUCTOR>(message); } else if (rv == NS_ERROR_RANGE_ERR) { aRv.ThrowRangeError<MSG_ILLEGAL_RANGE_PR_CONSTRUCTOR>(message);
--- a/dom/payments/PaymentRequest.h +++ b/dom/payments/PaymentRequest.h @@ -31,16 +31,22 @@ public: virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; static already_AddRefed<PaymentRequest> CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv); static bool PrefEnabled(JSContext* aCx, JSObject* aObj); + static nsresult IsValidStandardizedPMI(const nsAString& aIdentifier, + nsAString& aErrorMsg); + + static nsresult IsValidPaymentMethodIdentifier(const nsAString& aIdentifier, + nsAString& aErrorMsg); + static nsresult IsValidMethodData(JSContext* aCx, const Sequence<PaymentMethodData>& aMethodData, nsAString& aErrorMsg); static nsresult IsValidNumber(const nsAString& aItem, const nsAString& aStr, nsAString& aErrorMsg);
new file mode 100644 --- /dev/null +++ b/dom/payments/test/PMIValidationChromeScript.js @@ -0,0 +1,58 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService); + +const UIService = { + showPayment: function(requestId) { + paymentSrv.changeShippingOption(requestId, ""); + }, + abortPayment: function(requestId) { + let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"]. + createInstance(Ci.nsIPaymentAbortActionResponse); + abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED); + paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse)); + }, + completePayment: function(requestId) { + const completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]. + createInstance(Ci.nsIPaymentCompleteActionResponse); + completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED); + paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse)); + }, + updatePayment: function(requestId) { + const showResponseData = Cc["@mozilla.org/dom/payments/general-response-data;1"]. + createInstance(Ci.nsIGeneralResponseData); + showResponseData.initData({ paymentToken: "6880281f-0df3-4b8e-916f-66575e2457c1",}); + + const showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"]. + createInstance(Ci.nsIPaymentShowActionResponse); + showResponse.init(requestId, + Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED, + "https://example.com", // payment method + showResponseData, // payment method data + "Bill A. Pacheco", // payer name + "", // payer email + ""); // payer phone + paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse)); + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), +}; + +function emitTestFail(message) { + sendAsyncMessage("test-fail", message); +} + +addMessageListener("set-ui-service", function() { + paymentSrv.setTestingUIService(UIService.QueryInterface(Ci.nsIPaymentUIService)); +}); + +addMessageListener("teardown", function() { + paymentSrv.cleanup(); + sendAsyncMessage("teardown-complete"); +});
--- a/dom/payments/test/head.js +++ b/dom/payments/test/head.js @@ -2,17 +2,17 @@ const kTestRoot = getRootDirectory(gTest "https://example.com"); function checkSimplePayment(aSimplePayment) { // checking the passed PaymentMethods parameter is(aSimplePayment.paymentMethods.length, 1, "paymentMethods' length should be 1."); const methodData = aSimplePayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData); ok(methodData, "Fail to get payment methodData."); - is(methodData.supportedMethods, "MyPay", "supported method should be 'MyPay'."); + is(methodData.supportedMethods, "basic-card", "supported method should be 'basic-card'."); ok(!methodData.data, "methodData.data should not exist."); // checking the passed PaymentDetails parameter const details = aSimplePayment.paymentDetails; is(details.id, "simple details", "details.id should be 'simple details'."); is(details.totalItem.label, "Donation", "total item's label should be 'Donation'."); is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'."); is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'."); @@ -31,17 +31,17 @@ function checkSimplePayment(aSimplePayme } function checkDupShippingOptionsPayment(aPayment) { // checking the passed PaymentMethods parameter is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1."); const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData); ok(methodData, "Fail to get payment methodData."); - is(methodData.supportedMethods, "MyPay", "methodData.supportedMethod name should be 'MyPay'."); + is(methodData.supportedMethods, "basic-card", "methodData.supportedMethod name should be 'basic-card'."); ok(!methodData.data, "methodData.data should not exist."); // checking the passed PaymentDetails parameter const details = aPayment.paymentDetails; is(details.id, "duplicate shipping options details", "details.id should be 'duplicate shipping options details'."); is(details.totalItem.label, "Donation", "total item's label should be 'Donation'."); is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'."); is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
--- a/dom/payments/test/mochitest.ini +++ b/dom/payments/test/mochitest.ini @@ -3,19 +3,21 @@ skip-if = !e10s scheme = https support-files = simple_payment_request.html BasiccardChromeScript.js ConstructorChromeScript.js CurrencyAmountValidationChromeScript.js GeneralChromeScript.js + PMIValidationChromeScript.js ShowPaymentChromeScript.js [test_abortPayment.html] run-if = nightly_build # Bug 1390018: Depends on the Nightly-only UI service [test_basiccard.html] [test_canMakePayment.html] run-if = nightly_build # Bug 1390737: Depends on the Nightly-only UI service [test_constructor.html] [test_currency_amount_validation.html] [test_payment-request-in-iframe.html] +[test_pmi_validation.html] [test_showPayment.html]
--- a/dom/payments/test/simple_payment_request.html +++ b/dom/payments/test/simple_payment_request.html @@ -4,17 +4,17 @@ <title>Payment Request Testing</title> <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> <meta content="utf-8" http-equiv="encoding"> </head> <body> <script type="text/javascript"> const supportedInstruments = [{ - supportedMethods: "MyPay", + supportedMethods: "basic-card", }]; const details = { id: "simple details", total: { label: "Donation", amount: { currency: "USD", value: "55.00" } }, };
--- a/dom/payments/test/test_abortPayment.html +++ b/dom/payments/test/test_abortPayment.html @@ -83,16 +83,11 @@ https://bugzilla.mozilla.org/show_bug.cg ] }, runTests); }); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1345367">Mozilla Bug 1345367</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> </pre> </body> </html>
--- a/dom/payments/test/test_basiccard.html +++ b/dom/payments/test/test_basiccard.html @@ -283,16 +283,10 @@ https://bugzilla.mozilla.org/show_bug.cg ] }, runTests); }); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1375345">Mozilla Bug 1375345</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -</pre> </body> </html>
--- a/dom/payments/test/test_canMakePayment.html +++ b/dom/payments/test/test_canMakePayment.html @@ -154,16 +154,10 @@ https://bugzilla.mozilla.org/show_bug.cg ] }, runTests); }); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1345365">Mozilla Bug 1345365</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -</pre> </body> </html>
--- a/dom/payments/test/test_currency_amount_validation.html +++ b/dom/payments/test/test_currency_amount_validation.html @@ -371,16 +371,10 @@ https://bugzilla.mozilla.org/show_bug.cg }, runTests); }); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1367669">Mozilla Bug 1367669</a> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1388661">Mozilla Bug 1388661</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -</pre> </body> </html>
--- a/dom/payments/test/test_payment-request-in-iframe.html +++ b/dom/payments/test/test_payment-request-in-iframe.html @@ -88,15 +88,10 @@ https://bugzilla.mozilla.org/show_bug.cg ['dom.payments.request.enabled', true], ] }, runTests); }); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1318988">Mozilla Bug 1318988</a> -<p id="display"></p> -<div id="content" style="display: none"> -</div> -<pre id="test"> -</pre> </body> </html>
new file mode 100644 --- /dev/null +++ b/dom/payments/test/test_pmi_validation.html @@ -0,0 +1,241 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1389418 +--> +<head> + <meta charset="utf-8"> + <title>Test for PaymentRequest API payment method identifier validation</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript"> + + "use strict"; + SimpleTest.waitForExplicitFinish(); + + var gUrl = SimpleTest.getTestFileURL('PMIValidationChromeScript.js'); + var gScript = SpecialPowers.loadChromeScript(gUrl); + + function testFailHandler(message) { + ok(false, message); + } + gScript.addMessageListener("test-fail", testFailHandler); + + const defaultMethods = [{ + supportedMethods: "basic-card", + }]; + + const defaultDetails = { + total: { + label: "total", + amount: { + currency: "usd", + value: "1.00", + }, + }, + }; + + const validPMIs = [ + "https://wpt", + "https://wpt.fyi/", + "https://wpt.fyi/payment", + "https://wpt.fyi/payment-request", + "https://wpt.fyi/payment-request?", + "https://wpt.fyi/payment-request?this=is", + "https://wpt.fyi/payment-request?this=is&totally", + "https://wpt.fyi:443/payment-request?this=is&totally", + "https://wpt.fyi:443/payment-request?this=is&totally#fine", + "https://:@wpt.fyi:443/payment-request?this=is&totally#👍", + " \thttps://wpt\n ", + "https://xn--c1yn36f", + "https://點看", + "e", + "n6jzof05mk2g4lhxr-u-q-w1-c-i-pa-ty-bdvs9-ho-ae7-p-md8-s-wq3-h-qd-e-q-sa", + "a-b-q-n-s-pw0", + "m-u", + "s-l5", + "k9-f", + "m-l", + "u4-n-t", + "i488jh6-g18-fck-yb-v7-i", + "x-x-t-t-c34-o", + "basic-card", + ]; + + const invalidPMIs = [ + "https://:password@example.com", + "https://username@example.com", + "https://username:password@example.com/pay", + "http://username:password@example.com/pay", + "https://:@example.com:100000000/pay", + "https://foo.com:100000000/pay", + "basic-💳", + "not-https://wpt.fyi/payment-request", + "../realitive/url", + "/absolute/../path?", + "https://", + "¡basic-*-card!", + "Basic-Card", + "0", + "-", + "--", + "a--b", + "-a--b", + "a-b-", + "0-", + "0-a", + "a0--", + "A-", + "A-B", + "A-b", + "a-0", + "a-0b", + " a-b", + "\t\na-b", + "a-b ", + "a-b\n\t", + ]; + + function testWithValidPMIs() { + return new Promise((resolve, reject) => { + for (const validPMI of validPMIs) { + try { + const validMethods = [{supportedMethods: validPMI},]; + const payRequest = new PaymentRequest(validMethods, defaultDetails); + resolve(); + } catch (e) { + ok(false, "Unexpected error '" + e.name + "'."); + resolve(); + } + } + }); + } + + function testWithInvalidPMIs() { + return new Promise((resolve, reject) => { + for (const invalidPMI of invalidPMIs) { + try { + const invalidMethods = [{supportedMethods: invalidPMI},]; + const payRequest = new PaymentRequest(invalidMethods, defaultDetails); + ok(false, "Expected throw 'RangeError', but got resolved"); + resolve(); + } catch (e) { + is(e.name, "RangeError", "Expected 'RangeError'."); + resolve(); + } + } + }); + } + + function testUpdateWithValidPMI() { + gScript.sendAsyncMessage("set-ui-service"); + return new Promise((resolve, reject) => { + const payRequest = new PaymentRequest(defaultMethods, defaultDetails); + payRequest.addEventListener("shippingoptionchange", event => { + const validDetails = { + total: { + label: "total", + amount: { + currency: "USD", + value: "1.00", + }, + }, + modifiers: [{ + supportedMethods: "https://example.com", + total: { + label: "total", + amount: { + currency: "USD", + value: "1.00", + }, + } + },], + } + event.updateWith(validDetails); + }); + payRequest.show().then((response) => { + response.complete("success").then(() => { + resolve(); + }).catch((e) => { + ok(false, "Unexpected error '" + e.name + "'."); + resolve(); + }); + }).catch((e) => { + ok(false, "Unexpected error '" + e.name + "'."); + resolve(); + }); + }); + } + + function testUpdateWithInvalidPMI() { + gScript.sendAsyncMessage("set-ui-service"); + return new Promise((resolve, reject) => { + const payRequest = new PaymentRequest(defaultMethods, defaultDetails); + payRequest.addEventListener("shippingoptionchange", event => { + const invalidDetails = { + total: { + label: "total", + amount: { + currency: "USD", + value: "1.00", + }, + }, + modifiers: [{ + supportedMethods: "https://username:password@example.com", + total: { + label: "total", + amount: { + currency: "USD", + value: "1.00", + }, + }, + },], + } + event.updateWith(invalidDetails); + }); + payRequest.show().then((result) => { + ok(false, "Expected throw 'RangeError', but got resolved."); + resolve(); + }).catch((e) => { + is(e.name, "RangeError", "Expected 'RangeError'."); + resolve(); + }); + }); + } + + function teardown() { + gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() { + gScript.removeMessageListener("teardown-complete", teardownCompleteHandler); + gScript.removeMessageListener("test-fail", testFailHandler) + gScript.destroy(); + SimpleTest.finish(); + }); + gScript.sendAsyncMessage("teardown"); + } + + function runTests() { + testWithValidPMIs() + .then(testWithInvalidPMIs) + .then(testUpdateWithValidPMI) + .then(testUpdateWithInvalidPMI) + .then(teardown) + .catch( e => { + ok(false, "Unexpected error: " + e.name); + SimpleTest.finish(); + }); + } + + window.addEventListener('load', function() { + SpecialPowers.pushPrefEnv({ + 'set': [ + ['dom.payments.request.enabled', true], + ] + }, runTests); + }); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1389418">Mozilla Bug 1389418</a> +</body> +</html>
--- a/dom/payments/test/test_showPayment.html +++ b/dom/payments/test/test_showPayment.html @@ -295,16 +295,10 @@ https://bugzilla.mozilla.org/show_bug.cg ] }, runTests); }); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1345366">Mozilla Bug 1345366</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -</pre> </body> </html>
--- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -509,18 +509,16 @@ var interfaceNamesInGlobalScope = "HTMLProgressElement", // IMPORTANT: Do not change this list without review from a DOM peer! "HTMLQuoteElement", // IMPORTANT: Do not change this list without review from a DOM peer! "HTMLScriptElement", // IMPORTANT: Do not change this list without review from a DOM peer! "HTMLSelectElement", // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "HTMLShadowElement", stylo: false}, -// IMPORTANT: Do not change this list without review from a DOM peer! "HTMLSourceElement", // IMPORTANT: Do not change this list without review from a DOM peer! "HTMLSpanElement", // IMPORTANT: Do not change this list without review from a DOM peer! "HTMLStyleElement", // IMPORTANT: Do not change this list without review from a DOM peer! "HTMLTableCaptionElement", // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/tests/mochitest/webcomponents/mochitest.ini +++ b/dom/tests/mochitest/webcomponents/mochitest.ini @@ -28,18 +28,16 @@ skip-if = true || stylo # disabled - See [test_custom_element_upgrade.html] support-files = test_upgrade_page.html upgrade_tests.js [test_nested_content_element.html] skip-if = stylo # bug 1293844 [test_dest_insertion_points.html] skip-if = stylo # bug 1293844 -[test_dest_insertion_points_shadow.html] -skip-if = stylo # bug 1293844 [test_fallback_dest_insertion_points.html] skip-if = stylo # bug 1293844 [test_detached_style.html] skip-if = stylo # bug 1293844 [test_dynamic_content_element_matching.html] skip-if = stylo # bug 1293844 [test_document_adoptnode.html] skip-if = stylo # bug 1293844 @@ -48,37 +46,29 @@ skip-if = stylo # bug 1293844 [test_document_register.html] [test_document_register_base_queue.html] [test_document_register_lifecycle.html] skip-if = true # disabled - See bug 1390396 [test_document_register_parser.html] [test_document_register_stack.html] skip-if = true # disabled - See bug 1390396 [test_document_shared_registry.html] -[test_event_dispatch.html] -skip-if = stylo # bug 1293844 [test_event_retarget.html] skip-if = stylo # bug 1293844 [test_event_stopping.html] skip-if = stylo # bug 1293844 [test_template.html] [test_template_xhtml.html] [test_template_custom_elements.html] [test_shadowroot.html] skip-if = stylo # bug 1293844 [test_shadowroot_inert_element.html] skip-if = stylo # bug 1293844 -[test_shadowroot_host.html] -skip-if = stylo # bug 1293844 [test_shadowroot_style.html] skip-if = stylo # bug 1293844 -[test_shadowroot_style_multiple_shadow.html] -skip-if = stylo # bug 1293844 [test_shadowroot_style_order.html] skip-if = stylo # bug 1293844 -[test_shadowroot_youngershadowroot.html] -skip-if = stylo # bug 1293844 [test_style_fallback_content.html] skip-if = stylo # bug 1293844 [test_unresolved_pseudo_class.html] [test_link_prefetch.html] [test_bug1269155.html] skip-if = stylo # bug 1293844
deleted file mode 100644 --- a/dom/tests/mochitest/webcomponents/test_dest_insertion_points_shadow.html +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=999999 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 999999</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=999999">Mozilla Bug 999999</a> -<p id="display"></p> -<div id="content"> -<div id="shadowhost"></div> -</div> -<pre id="test"> -</pre> -<script type="application/javascript"> - -/** Test for Bug 999999 **/ -var host = document.getElementById("shadowhost"); - -// Test destination insertion points of node distributed to shadow element. -var olderShadowRoot = host.createShadowRoot(); -var youngerShadowRoot = host.createShadowRoot(); - -var shadowElem = document.createElement("shadow"); -youngerShadowRoot.appendChild(shadowElem); - -var span = document.createElement("span"); -olderShadowRoot.appendChild(span); - -is(span.getDestinationInsertionPoints().length, 1, "Child of ShadowRoot should be distributed to shadow insertion point."); -is(span.getDestinationInsertionPoints()[0], shadowElem, "Shadow element should be in destination insertion point list."); - -// Test destination insertion points of node removed from tree. -olderShadowRoot.removeChild(span); -is(span.getDestinationInsertionPoints().length, 0, "Node removed from tree should no longer be distributed."); - -// Test destination insertion points of fallback content being reprojected into a shadow element. -var content = document.createElement("content"); -var fallback = document.createElement("span"); - -content.appendChild(fallback); -olderShadowRoot.appendChild(content); - -is(fallback.getDestinationInsertionPoints().length, 2, "The fallback content should have 2 destination insertion points, the parent content and the shadow element to which it is reprojected."); -is(fallback.getDestinationInsertionPoints()[0], content, "First destination of the fallback content should be the parent content element."); -is(fallback.getDestinationInsertionPoints()[1], shadowElem, "Second destination of the fallback content should be the shadow element to which the element is reprojected."); - -// Test destination insertion points of fallback content being removed from tree. -content.removeChild(fallback); -is(fallback.getDestinationInsertionPoints().length, 0, "The content should no longer be distributed to any nodes because it is no longer fallback content."); - -// Test destination insertion points of distributed content after removing shadow insertion point. -var div = document.createElement("div"); -olderShadowRoot.appendChild(div); -is(div.getDestinationInsertionPoints().length, 1, "Children in older shadow root should be distributed to shadow insertion point."); -is(div.getDestinationInsertionPoints()[0], shadowElem, "Destination insertion point should include shadow element."); - -youngerShadowRoot.removeChild(shadowElem); -is(div.getDestinationInsertionPoints().length, 0, "Destination insertion points should be empty after removing shadow element."); - -</script> -</body> -</html>
--- a/dom/tests/mochitest/webcomponents/test_document_register.html +++ b/dom/tests/mochitest/webcomponents/test_document_register.html @@ -102,17 +102,16 @@ function startTest() { is(extendedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type."); is(extendedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type."); is(extendedButton.type, "submit", "Created element should be a button with type of \"submit\""); // Custom element constructor. var constructedButton = new buttonConstructor(); is(constructedButton.tagName, "BUTTON", "Created element should have local name of BUTTON"); is(constructedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type."); - is(constructedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type."); // Try creating an element with a custom element name, but not in the html namespace. var htmlNamespaceProto = Object.create(HTMLElement.prototype); document.registerElement("x-in-html-namespace", { prototype: htmlNamespaceProto }); var wrongNamespaceElem = document.createElementNS("http://www.w3.org/2000/svg", "x-in-html-namespace"); isnot(wrongNamespaceElem.__proto__, htmlNamespaceProto, "Definition for element in html namespace should not apply to SVG elements."); }
--- a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html +++ b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html @@ -286,21 +286,24 @@ function testAttributeChanged() { createdElement.setAttribute("changeme", "newvalue"); createdElement.setAttribute("changeme", "nextvalue"); createdElement.setAttribute("changeme", ""); createdElement.removeAttribute("changeme"); } function testAttributeChangedExtended() { var p = Object.create(HTMLButtonElement.prototype); - var callbackCalled = false; + var callbackCalled = 0; p.attributeChangedCallback = function(name, oldValue, newValue) { - is(callbackCalled, false, "Callback should only be called once in this test."); - callbackCalled = true; - runNextTest(); + callbackCalled++; + if (callbackCalled > 2) { + is(false, "Got unexpected attribute changed callback."); + } else if (callbackCalled === 2) { + runNextTest(); + } }; document.registerElement("x-extended-attribute-change", { prototype: p, extends: "button" }); var elem = document.createElement("button", {is: "x-extended-attribute-change"}); elem.setAttribute("foo", "bar"); }
deleted file mode 100644 --- a/dom/tests/mochitest/webcomponents/test_event_dispatch.html +++ /dev/null @@ -1,458 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=887541 ---> -<head> - <title>Test for event model in web components</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=887541">Bug 887541</a> -<script> - -var els = SpecialPowers.Cc["@mozilla.org/eventlistenerservice;1"] - .getService(SpecialPowers.Ci.nsIEventListenerService); - -function eventListener(e) { - eventChain.push(this); -} - -function isEventChain(actual, expected, msg) { - is(actual.length, expected.length, msg); - for (var i = 0; i < expected.length; i++) { - is(actual[i], expected[i], msg + " at " + i); - } - - // Check to make sure the event chain matches what we get back from nsIEventListenerService.getEventTargetChainFor - if (0 < actual.length) { - var chain = els.getEventTargetChainFor(actual[0], true); // Events should be dispatched on actual[0]. - for (var i = 0; i < expected.length; i++) { - ok(SpecialPowers.compare(chain[i], expected[i]), msg + " at " + i + " for nsIEventListenerService"); - } - } -} - -/* - * Test 1: Test of event dispatch through a basic ShadowRoot with content a insertion point. - * - * <div elemOne> ------ <shadow-root shadowOne> - * | | - * <div elemTwo> <span elemThree> - * | - * <content elemFour> - */ - -var elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -var elemTwo = document.createElement("div"); -elemTwo.addEventListener("custom", eventListener); - -var elemThree = document.createElement("span"); -elemThree.addEventListener("custom", eventListener); - -var elemFour = document.createElement("content"); -elemFour.addEventListener("custom", eventListener); - -var shadowOne = elemOne.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -elemThree.appendChild(elemFour); -shadowOne.appendChild(elemThree); -elemOne.appendChild(elemTwo); - -var eventChain = []; -var customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemTwo.dispatchEvent(customEvent); -isEventChain(eventChain, [elemTwo, elemFour, elemThree, shadowOne, elemOne], "Event path for test 1 for event dispatched on elemTwo."); - -/* - * Test 2: Test of event dispatch through a nested ShadowRoots with content insertion points. - * - * <div elemFive> --- <shadow-root shadowTwo> - * | | - * <div elemOne> <div elemFour> ----- <shadow-root shadowOne> - * | | - * <content elemTwo> <p elemSix> - * | - * <content elemThree> - */ - -elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -elemTwo = document.createElement("content"); -elemTwo.addEventListener("custom", eventListener); - -elemThree = document.createElement("content"); -elemThree.addEventListener("custom", eventListener); - -var elemFour = document.createElement("div"); -elemFour.addEventListener("custom", eventListener); - -var elemFive = document.createElement("div"); -elemFive.addEventListener("custom", eventListener); - -var elemSix = document.createElement("p"); -elemSix.addEventListener("custom", eventListener); - -var shadowOne = elemFour.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -var shadowTwo = elemFive.createShadowRoot(); -shadowTwo.addEventListener("custom", eventListener); - -elemFive.appendChild(elemOne); -shadowTwo.appendChild(elemFour); -elemFour.appendChild(elemTwo); -shadowOne.appendChild(elemSix); -elemSix.appendChild(elemThree); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemOne.dispatchEvent(customEvent); -is(elemOne.getDestinationInsertionPoints().length, 2, "yes"); -isEventChain(eventChain, [elemOne, elemThree, elemSix, shadowOne, elemTwo, elemFour, shadowTwo, elemFive], "Event path for test 2 for event dispatched on elemOne."); - -/* - * Test 3: Test of event dispatch through nested ShadowRoot with content insertion points. - * - * <div elemOne> ------- <shadow-root shadowOne> - * | | - * <span elemTwo> <span elemThree> ------------ <shadow-root shadowTwo> - * | | - * <span elemFour> <content elemSix> - * | - * <content elemFive> - */ - -elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -elemTwo = document.createElement("span"); -elemTwo.addEventListener("custom", eventListener); - -elemThree = document.createElement("span"); -elemThree.addEventListener("custom", eventListener); - -elemFour = document.createElement("span"); -elemFour.addEventListener("custom", eventListener); - -elemFive = document.createElement("content"); -elemFive.addEventListener("custom", eventListener); - -elemSix = document.createElement("content"); -elemSix.addEventListener("custom", eventListener); - -shadowOne = elemOne.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -shadowTwo = elemThree.createShadowRoot(); -shadowTwo.addEventListener("custom", eventListener); - -elemOne.appendChild(elemTwo); -shadowOne.appendChild(elemThree); -elemThree.appendChild(elemFour); -elemFour.appendChild(elemFive); -shadowTwo.appendChild(elemSix); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemTwo.dispatchEvent(customEvent); -isEventChain(eventChain, [elemTwo, elemFive, elemFour, elemSix, shadowTwo, elemThree, shadowOne, elemOne], "Event path for test 3 for event dispatched on elemTwo."); - -/* - * Test 4: Test of event dispatch through host with multiple ShadowRoots with shadow insertion point. - * - * <div elemSeven> --- <shadow-root shadowTwo> (younger ShadowRoot) - * | | | - * <div elemOne> | <div elemSix> -------- <shadow-root shadowOne> - * | | | - * | <shadow elemFour> <content elemFive> - * | | - * | <content elemTwo> - * | - * --- <shadow-root shadowThree> (older ShadowRoot) - * | | - * | <content elemThree> - * | - * <div elemEight> - */ - -elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -elemTwo = document.createElement("content"); -elemTwo.addEventListener("custom", eventListener); - -elemThree = document.createElement("content"); -elemThree.addEventListener("custom", eventListener); - -elemFour = document.createElement("shadow"); -elemFour.addEventListener("custom", eventListener); - -elemFive = document.createElement("content"); -elemFive.addEventListener("custom", eventListener); - -elemSix = document.createElement("div"); -elemSix.addEventListener("custom", eventListener); - -var elemSeven = document.createElement("div"); -elemSeven.addEventListener("custom", eventListener); - -var elemEight = document.createElement("div"); -elemEight.addEventListener("custom", eventListener); - -var shadowThree = elemSeven.createShadowRoot(); -shadowThree.addEventListener("custom", eventListener); - -shadowTwo = elemSeven.createShadowRoot(); -shadowTwo.addEventListener("custom", eventListener); - -shadowOne = elemSix.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -elemSeven.appendChild(elemOne); -shadowTwo.appendChild(elemSix); -elemSix.appendChild(elemFour); -elemFour.appendChild(elemTwo); -shadowThree.appendChild(elemEight); -shadowThree.appendChild(elemThree); -shadowOne.appendChild(elemFive); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemOne.dispatchEvent(customEvent); -isEventChain(eventChain, [elemOne, elemFive, shadowOne, elemThree, shadowThree, elemTwo, elemFour, elemSix, shadowTwo, elemSeven], "Event path for test 4 for event dispatched on elemOne."); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemEight.dispatchEvent(customEvent); -isEventChain(eventChain, [elemEight, elemFive, shadowOne, elemSix, shadowTwo, elemSeven], "Event path for test 4 for event dispatched on elemEight."); - -/* - * Test 5: Test of event dispatch through nested shadowroot with insertion points that match specific tags. - * - * <div elemOne> --------- <shadow-root shadowOne> - * | | | - * | <p elemThree> <span elemFour> ------------------------ <shadow-root shadowTwo> - * | | | | - * <span elemTwo> | <content select="p" elemFive> <content elemSeven> - * | - * <content select="span" elemSix> - */ - -elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -elemTwo = document.createElement("span"); -elemTwo.addEventListener("custom", eventListener); - -elemThree = document.createElement("p"); -elemThree.addEventListener("custom", eventListener); - -elemFour = document.createElement("span"); -elemFour.addEventListener("custom", eventListener); - -elemFive = document.createElement("content"); -elemFive.select = "p"; -elemFive.addEventListener("custom", eventListener); - -elemSix = document.createElement("content"); -elemSix.select = "span"; -elemSix.addEventListener("custom", eventListener); - -elemSeven = document.createElement("content"); -elemSeven.addEventListener("custom", eventListener); - -shadowTwo = elemFour.createShadowRoot(); -shadowTwo.addEventListener("custom", eventListener); - -shadowOne = elemOne.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -elemOne.appendChild(elemTwo); -elemOne.appendChild(elemThree); -shadowOne.appendChild(elemFour); -elemFour.appendChild(elemSix); -elemFour.appendChild(elemFive); -shadowTwo.appendChild(elemSeven); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemTwo.dispatchEvent(customEvent); -isEventChain(eventChain, [elemTwo, elemSeven, shadowTwo, elemSix, elemFour, shadowOne, elemOne], "Event path for test 5 for event dispatched on elemTwo."); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemThree.dispatchEvent(customEvent); -isEventChain(eventChain, [elemThree, elemSeven, shadowTwo, elemFive, elemFour, shadowOne, elemOne], "Event path for test 5 for event dispatched on elemThree."); - -/* - * Test 6: Test of event dispatch through nested shadowroot with insertion points that match specific tags. - * - * <div elemOne> --------- <shadow-root shadowOne>; - * | | | - * | <p elemThree> <span elemFour> ------ <shadow-root shadowTwo> - * | | | | - * <span elemTwo> <content elemFive> | <content select="p" elemSeven> - * | - * <content select="span" elemSix> - */ - -elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -elemTwo = document.createElement("span"); -elemTwo.addEventListener("custom", eventListener); - -elemThree = document.createElement("p"); -elemThree.addEventListener("custom", eventListener); - -elemFour = document.createElement("span"); -elemFour.addEventListener("custom", eventListener); - -elemFive = document.createElement("content"); -elemFive.addEventListener("custom", eventListener); - -elemSix = document.createElement("content"); -elemSix.select = "span"; -elemSix.addEventListener("custom", eventListener); - -elemSeven = document.createElement("content"); -elemSeven.select = "p"; -elemSeven.addEventListener("custom", eventListener); - -shadowTwo = elemFour.createShadowRoot(); -shadowTwo.addEventListener("custom", eventListener); - -shadowOne = elemOne.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -elemOne.appendChild(elemTwo); -elemOne.appendChild(elemThree); -shadowOne.appendChild(elemFour); -elemFour.appendChild(elemFive); -shadowTwo.appendChild(elemSix); -shadowTwo.appendChild(elemSeven); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemTwo.dispatchEvent(customEvent); -isEventChain(eventChain, [elemTwo, elemSix, shadowTwo, elemFive, elemFour, shadowOne, elemOne], "Event path for test 6 for event dispatched on elemTwo."); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemThree.dispatchEvent(customEvent); -isEventChain(eventChain, [elemThree, elemSeven, shadowTwo, elemFive, elemFour, shadowOne, elemOne], "Event path for test 6 for event dispatched on elemThree."); - -/* - * Test 7: Test of event dispatch through nested shadowroot with insertion points that match specific tags. - * - * <div elemOne> --------- <shadow-root shadowOne> - * | | | - * | <p elemThree> <span elemFour> ------ <shadow-root shadowTwo> - * | | | - * <span elemTwo> <content elemFive> <span elemEight> - * | | - * | <content select="p" elemSeven> - * | - * <content select="span" elemSix> - */ - -elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -elemTwo = document.createElement("span"); -elemTwo.addEventListener("custom", eventListener); - -elemThree = document.createElement("p"); -elemThree.addEventListener("custom", eventListener); - -elemFour = document.createElement("span"); -elemFour.addEventListener("custom", eventListener); - -elemFive = document.createElement("content"); -elemFive.addEventListener("custom", eventListener); - -elemSix = document.createElement("content"); -elemSix.select = "span"; -elemSix.addEventListener("custom", eventListener); - -elemSeven = document.createElement("content"); -elemSeven.select = "p"; -elemSeven.addEventListener("custom", eventListener); - -elemEight = document.createElement("span"); -elemEight.addEventListener("custom", eventListener); - -shadowTwo = elemFour.createShadowRoot(); -shadowTwo.addEventListener("custom", eventListener); - -shadowOne = elemOne.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -elemOne.appendChild(elemTwo); -elemOne.appendChild(elemThree); -shadowOne.appendChild(elemFour); -elemFour.appendChild(elemFive); -shadowTwo.appendChild(elemEight); -elemEight.appendChild(elemSix); -elemEight.appendChild(elemSeven); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemTwo.dispatchEvent(customEvent); -isEventChain(eventChain, [elemTwo, elemSix, elemEight, shadowTwo, elemFive, elemFour, shadowOne, elemOne], "Event path for test 7 for event dispatched on elemTwo."); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemThree.dispatchEvent(customEvent); -isEventChain(eventChain, [elemThree, elemSeven, elemEight, shadowTwo, elemFive, elemFour, shadowOne, elemOne], "Event path for test 7 for event dispatched on elemThree."); - -/* - * Test 8: Test of event dispatch through host with multiple ShadowRoots with shadow insertion point. - * - * <div elemOne> --- <shadow-root shadowOne> (younger ShadowRoot) - * | | - * | <div elemFour> - * | | - * | <shadow elemTwo> - * | - * --- <shadow-root shadowTwo> (older ShadowRoot) - * | - * <div elemThree> - */ - -elemOne = document.createElement("div"); -elemOne.addEventListener("custom", eventListener); - -elemTwo = document.createElement("shadow"); -elemTwo.addEventListener("custom", eventListener); - -elemThree = document.createElement("div"); -elemThree.addEventListener("custom", eventListener); - -elemFour = document.createElement("div"); -elemFour.addEventListener("custom", eventListener); - -shadowTwo = elemOne.createShadowRoot(); -shadowTwo.addEventListener("custom", eventListener); - -shadowOne = elemOne.createShadowRoot(); -shadowOne.addEventListener("custom", eventListener); - -shadowOne.appendChild(elemFour); -elemFour.appendChild(elemTwo); -shadowTwo.appendChild(elemThree); - -eventChain = []; -customEvent = new CustomEvent("custom", { "bubbles" : true, "composed" : true }); -elemThree.dispatchEvent(customEvent); -isEventChain(eventChain, [elemThree, shadowTwo, elemTwo, elemFour, shadowOne, elemOne], "Event path for test 8 for event dispatched on elemThree."); - -</script> -</body> -</html>
deleted file mode 100644 --- a/dom/tests/mochitest/webcomponents/test_shadowroot_host.html +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=1083587 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 1083587</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1083587">Mozilla Bug 1083587</a> -<p id="display"></p> -<div id="content" style="display: none"> -<div id="host"></div> -</div> -<pre id="test"> -</pre> -<script type="application/javascript"> - -/** Test for Bug 1083587 **/ -var hostInDoc = document.getElementById("host"); -var shadowOne = hostInDoc.createShadowRoot(); -is(shadowOne.host, hostInDoc); - -var shadowTwo = hostInDoc.createShadowRoot(); -is(shadowOne.host, hostInDoc); -is(shadowTwo.host, hostInDoc); - -var hostNotInDoc = document.createElement("div"); -var shadowThree = hostNotInDoc.createShadowRoot(); -is(shadowThree.host, hostNotInDoc); - -var shadowFour = hostNotInDoc.createShadowRoot(); -is(shadowThree.host, hostNotInDoc); -is(shadowFour.host, hostNotInDoc); - -</script> -</body> -</html>
deleted file mode 100644 --- a/dom/tests/mochitest/webcomponents/test_shadowroot_style_multiple_shadow.html +++ /dev/null @@ -1,57 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=806506 ---> -<head> - <title>Test for ShadowRoot styles with multiple ShadowRoot on host.</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> -</head> -<body> -<div class="tall" id="bodydiv"></div> -<div id="container"></div> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a> -<script> -// Create ShadowRoot. -var container = document.getElementById("container"); -var elem = document.createElement("div"); -container.appendChild(elem); // Put ShadowRoot host in document. -var firstRoot = elem.createShadowRoot(); -var secondRoot = elem.createShadowRoot(); -var thirdRoot = elem.createShadowRoot(); - -// A style element that will be appended into the ShadowRoot. -var firstStyle = document.createElement("style"); -firstRoot.appendChild(firstStyle); -is(firstRoot.styleSheets.length, 1, "firstStyle should be the only style in firstRoot."); -is(firstRoot.styleSheets[0].ownerNode, firstStyle, "firstStyle should in the ShadowRoot styleSheets."); - -var secondStyle = document.createElement("style"); -secondRoot.appendChild(secondStyle); -is(secondRoot.styleSheets.length, 1, "secondStyle should be the only style in secondRoot."); -is(secondRoot.styleSheets[0].ownerNode, secondStyle, "secondStyle should in the ShadowRoot styleSheets."); - -var thirdStyle = document.createElement("style"); -thirdRoot.appendChild(thirdStyle); -is(thirdRoot.styleSheets.length, 1, "thirdStyle should be the only style in thirdRoot."); -is(thirdRoot.styleSheets[0].ownerNode, thirdStyle, "thirdStyle should in the ShadowRoot styleSheets."); - -// Check the stylesheet counts again to make sure that none of the style sheets leaked into the older ShadowRoots. -is(firstRoot.styleSheets.length, 1, "Adding a stylesheet to a younger ShadowRoot should not affect stylesheets in the older ShadowRoot."); -is(secondRoot.styleSheets.length, 1, "Adding a stylesheet to a younger ShadowRoot should not affect stylesheets in the older ShadowRoot."); - -// Remove styles and make sure they are removed from the correct ShadowRoot. -firstRoot.removeChild(firstStyle); -is(firstRoot.styleSheets.length, 0, "firstRoot should no longer have any styles."); - -thirdRoot.removeChild(thirdStyle); -is(thirdRoot.styleSheets.length, 0, "thirdRoot should no longer have any styles."); - -secondRoot.removeChild(secondStyle); -is(secondRoot.styleSheets.length, 0, "secondRoot should no longer have any styles."); - -</script> -</body> -</html> -
deleted file mode 100644 --- a/dom/tests/mochitest/webcomponents/test_shadowroot_youngershadowroot.html +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=1083587 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 1083587</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1083587">Mozilla Bug 1083587</a> -<p id="display"></p> -<div id="content" style="display: none"> -<div id="host"></div> -</div> -<pre id="test"> -</pre> -<script type="application/javascript"> - -/** Test for Bug 1083587 **/ -var hostInDoc = document.getElementById("host"); -var shadowOne = hostInDoc.createShadowRoot(); -is(shadowOne.olderShadowRoot, null); - -var shadowTwo = hostInDoc.createShadowRoot(); -is(shadowOne.olderShadowRoot, null); -is(shadowTwo.olderShadowRoot, shadowOne); - -var hostNotInDoc = document.createElement("div"); -var shadowThree = hostNotInDoc.createShadowRoot(); -is(shadowThree.olderShadowRoot, null); - -var shadowFour = hostNotInDoc.createShadowRoot(); -is(shadowThree.olderShadowRoot, null); -is(shadowFour.olderShadowRoot, shadowThree); - -</script> -</body> -</html>
deleted file mode 100644 --- a/dom/webidl/HTMLShadowElement.webidl +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html - * - * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and - * Opera Software ASA. You are granted a license to use, reproduce - * and create derivative works of this document. - */ - -[Func="nsDocument::IsWebComponentsEnabled"] -interface HTMLShadowElement : HTMLElement -{ - readonly attribute ShadowRoot? olderShadowRoot; -}; -
--- a/dom/webidl/ShadowRoot.webidl +++ b/dom/webidl/ShadowRoot.webidl @@ -15,13 +15,12 @@ interface ShadowRoot : DocumentFragment { Element? getElementById(DOMString elementId); HTMLCollection getElementsByTagName(DOMString localName); HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); HTMLCollection getElementsByClassName(DOMString classNames); [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString innerHTML; readonly attribute Element host; - readonly attribute ShadowRoot? olderShadowRoot; attribute boolean applyAuthorStyles; readonly attribute StyleSheetList styleSheets; };
--- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -515,17 +515,15 @@ partial interface Window { * * This API always returns at least one locale. * * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"] */ [Func="IsChromeOrXBL"] sequence<DOMString> getRegionalPrefsLocales(); -#ifdef ENABLE_INTL_API /** * Getter funcion for IntlUtils, which provides helper functions for * localization. */ [Throws, Func="IsChromeOrXBL"] readonly attribute IntlUtils intlUtils; -#endif };
--- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -611,17 +611,16 @@ WEBIDL_FILES = [ 'HTMLParagraphElement.webidl', 'HTMLParamElement.webidl', 'HTMLPictureElement.webidl', 'HTMLPreElement.webidl', 'HTMLProgressElement.webidl', 'HTMLQuoteElement.webidl', 'HTMLScriptElement.webidl', 'HTMLSelectElement.webidl', - 'HTMLShadowElement.webidl', 'HTMLSourceElement.webidl', 'HTMLSpanElement.webidl', 'HTMLStyleElement.webidl', 'HTMLTableCaptionElement.webidl', 'HTMLTableCellElement.webidl', 'HTMLTableColElement.webidl', 'HTMLTableElement.webidl', 'HTMLTableRowElement.webidl', @@ -651,16 +650,17 @@ WEBIDL_FILES = [ 'ImageBitmap.webidl', 'ImageBitmapRenderingContext.webidl', 'ImageCapture.webidl', 'ImageData.webidl', 'ImageDocument.webidl', 'InputEvent.webidl', 'InspectorUtils.webidl', 'IntersectionObserver.webidl', + 'IntlUtils.webidl', 'IterableIterator.webidl', 'KeyAlgorithm.webidl', 'KeyboardEvent.webidl', 'KeyEvent.webidl', 'KeyframeAnimationOptions.webidl', 'KeyframeEffect.webidl', 'KeyIdsInitData.webidl', 'LegacyQueryInterface.webidl', @@ -1139,13 +1139,8 @@ if CONFIG['MOZ_BUILD_APP'] in ['browser' WEBIDL_FILES += [ 'External.webidl', ] if CONFIG['ACCESSIBILITY']: WEBIDL_FILES += [ 'AccessibleNode.webidl', ] - -if CONFIG['ENABLE_INTL_API']: - WEBIDL_FILES += [ - 'IntlUtils.webidl', - ]
--- a/editor/libeditor/HTMLEditUtils.cpp +++ b/editor/libeditor/HTMLEditUtils.cpp @@ -715,17 +715,16 @@ static const ElementInfo kElements[eHTML ELEM(rtc, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT), ELEM(ruby, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT), ELEM(s, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), ELEM(samp, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT), ELEM(script, true, false, GROUP_HEAD_CONTENT | GROUP_SPECIAL, GROUP_LEAF), ELEM(section, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT), ELEM(select, true, false, GROUP_FORMCONTROL, GROUP_SELECT_CONTENT), - ELEM(shadow, true, false, GROUP_NONE, GROUP_INLINE_ELEMENT), ELEM(small, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), ELEM(source, false, false, GROUP_PICTURE_CONTENT, GROUP_NONE), ELEM(span, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), ELEM(strike, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), ELEM(strong, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT), ELEM(style, true, false, GROUP_HEAD_CONTENT, GROUP_LEAF), ELEM(sub, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), ELEM(summary, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
--- a/gfx/moz.build +++ b/gfx/moz.build @@ -26,17 +26,17 @@ DIRS += [ 'vr', 'config', 'webrender_bindings', ] if CONFIG['MOZ_ENABLE_SKIA']: DIRS += ['skia'] -if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY'] and CONFIG['ENABLE_INTL_API']: +if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY']: DIRS += ['sfntly/cpp/src'] if CONFIG['ENABLE_TESTS']: DIRS += ['tests/gtest'] TEST_DIRS += ['tests'] SPHINX_TREES['gfx'] = 'docs'
--- a/gfx/skia/generate_mozbuild.py +++ b/gfx/skia/generate_mozbuild.py @@ -96,17 +96,17 @@ elif CONFIG['_MSC_VER']: SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=52'] elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']: CXXFLAGS += CONFIG['NEON_FLAGS'] elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['GNU_CC']: SOURCES['skia/src/opts/SkOpts_crc32.cpp'].flags += ['-march=armv8-a+crc'] DEFINES['SKIA_IMPLEMENTATION'] = 1 -if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY'] and CONFIG['ENABLE_INTL_API']: +if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY']: DEFINES['SK_PDF_USE_SFNTLY'] = 1 if not CONFIG['MOZ_ENABLE_SKIA_GPU']: DEFINES['SK_SUPPORT_GPU'] = 0 if CONFIG['MOZ_TREE_FREETYPE']: DEFINES['SK_CAN_USE_DLOPEN'] = 0
--- a/gfx/skia/moz.build +++ b/gfx/skia/moz.build @@ -738,17 +738,17 @@ elif CONFIG['_MSC_VER']: SOURCES['skia/src/opts/SkOpts_hsw.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=52'] elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']: CXXFLAGS += CONFIG['NEON_FLAGS'] elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['GNU_CC']: SOURCES['skia/src/opts/SkOpts_crc32.cpp'].flags += ['-march=armv8-a+crc'] DEFINES['SKIA_IMPLEMENTATION'] = 1 -if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY'] and CONFIG['ENABLE_INTL_API']: +if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY']: DEFINES['SK_PDF_USE_SFNTLY'] = 1 if not CONFIG['MOZ_ENABLE_SKIA_GPU']: DEFINES['SK_SUPPORT_GPU'] = 0 if CONFIG['MOZ_TREE_FREETYPE']: DEFINES['SK_CAN_USE_DLOPEN'] = 0
--- a/image/ImageFactory.cpp +++ b/image/ImageFactory.cpp @@ -81,40 +81,60 @@ ComputeImageFlags(ImageURL* uri, const n rv = uri->SchemeIs("data", &isDataURI); if (NS_SUCCEEDED(rv) && isDataURI) { imageFlags |= Image::INIT_FLAG_SYNC_LOAD; } return imageFlags; } +#ifdef DEBUG +static void +NotifyImageLoading(ImageURL* aURI) +{ + if (!NS_IsMainThread()) { + RefPtr<ImageURL> uri(aURI); + nsCOMPtr<nsIRunnable> ev = + NS_NewRunnableFunction("NotifyImageLoading", [uri] () -> void { + NotifyImageLoading(uri); + }); + SystemGroup::Dispatch(TaskCategory::Other, ev.forget()); + return; + } + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + NS_WARNING_ASSERTION(obs, "Can't get an observer service handle"); + if (obs) { + nsAutoCString spec; + aURI->GetSpec(spec); + obs->NotifyObservers(nullptr, "image-loading", NS_ConvertUTF8toUTF16(spec).get()); + } +} +#endif + /* static */ already_AddRefed<Image> ImageFactory::CreateImage(nsIRequest* aRequest, ProgressTracker* aProgressTracker, const nsCString& aMimeType, ImageURL* aURI, bool aIsMultiPart, uint32_t aInnerWindowId) { MOZ_ASSERT(gfxPrefs::SingletonExists(), "Pref observers should have been initialized already"); // Compute the image's initialization flags. uint32_t imageFlags = ComputeImageFlags(aURI, aMimeType, aIsMultiPart); #ifdef DEBUG // Record the image load for startup performance testing. - if (NS_IsMainThread()) { - nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); - NS_WARNING_ASSERTION(obs, "Can't get an observer service handle"); - if (obs) { - nsAutoCString spec; - aURI->GetSpec(spec); - obs->NotifyObservers(nullptr, "image-loading", NS_ConvertUTF8toUTF16(spec).get()); - } + bool match = false; + if ((NS_SUCCEEDED(aURI->SchemeIs("resource", &match)) && match) || + (NS_SUCCEEDED(aURI->SchemeIs("chrome", &match)) && match)) { + NotifyImageLoading(aURI); } #endif // Select the type of image to create based on MIME type. if (aMimeType.EqualsLiteral(IMAGE_SVG_XML)) { return CreateVectorImage(aRequest, aProgressTracker, aMimeType, aURI, imageFlags, aInnerWindowId); } else {
--- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -1695,16 +1695,22 @@ RasterImage::GetFramesNotified(uint32_t* #ifdef DEBUG void RasterImage::NotifyDrawingObservers() { if (!mURI || !NS_IsMainThread()) { return; } + bool match = false; + if ((NS_FAILED(mURI->SchemeIs("resource", &match)) || !match) && + (NS_FAILED(mURI->SchemeIs("chrome", &match)) || !match)) { + return; + } + // Record the image drawing for startup performance testing. nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); NS_WARNING_ASSERTION(obs, "Can't get an observer service handle"); if (obs) { nsCOMPtr<nsIURI> imageURI = mURI->ToIURI(); nsAutoCString spec; imageURI->GetSpec(spec); obs->NotifyObservers(nullptr, "image-drawing", NS_ConvertUTF8toUTF16(spec).get());
--- a/image/imgRequest.cpp +++ b/image/imgRequest.cpp @@ -454,23 +454,36 @@ imgRequest::GetCurrentURI(nsIURI** aURI) NS_ADDREF(*aURI); return NS_OK; } return NS_ERROR_FAILURE; } bool +imgRequest::IsScheme(const char* aScheme) const +{ + MOZ_ASSERT(aScheme); + bool isScheme = false; + if (NS_WARN_IF(NS_FAILED(mURI->SchemeIs(aScheme, &isScheme)))) { + return false; + } + return isScheme; +} + +bool imgRequest::IsChrome() const { - bool isChrome = false; - if (NS_WARN_IF(NS_FAILED(mURI->SchemeIs("chrome", &isChrome)))) { - return false; - } - return isChrome; + return IsScheme("chrome"); +} + +bool +imgRequest::IsData() const +{ + return IsScheme("data"); } nsresult imgRequest::GetImageErrorCode() { return mImageErrorCode; } @@ -814,23 +827,27 @@ imgRequest::OnStartRequest(nsIRequest* a // Shouldn't we be dead already if this gets hit? // Probably multipart/x-mixed-replace... RefPtr<ProgressTracker> progressTracker = GetProgressTracker(); if (progressTracker->ObserverCount() == 0) { this->Cancel(NS_IMAGELIB_ERROR_FAILURE); } - // Try to retarget OnDataAvailable to a decode thread. - nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest); + // Try to retarget OnDataAvailable to a decode thread. We must process data + // URIs synchronously as per the spec however. + if (!channel || IsData()) { + return NS_OK; + } + nsCOMPtr<nsIThreadRetargetableRequest> retargetable = do_QueryInterface(aRequest); - if (httpChannel && retargetable) { + if (retargetable) { nsAutoCString mimeType; - nsresult rv = httpChannel->GetContentType(mimeType); + nsresult rv = channel->GetContentType(mimeType); if (NS_SUCCEEDED(rv) && !mimeType.EqualsLiteral(IMAGE_SVG_XML)) { // Retarget OnDataAvailable to the DecodePool's IO thread. nsCOMPtr<nsIEventTarget> target = DecodePool::Singleton()->GetIOEventTarget(); rv = retargetable->RetargetDeliveryTo(target); } MOZ_LOG(gImgLog, LogLevel::Warning, ("[this=%p] imgRequest::OnStartRequest -- "
--- a/image/imgRequest.h +++ b/image/imgRequest.h @@ -148,17 +148,19 @@ public: const ImageCacheKey& CacheKey() const { return mCacheKey; } // Resize the cache entry to 0 if it exists void ResetCacheEntry(); // OK to use on any thread. nsresult GetURI(ImageURL** aURI); nsresult GetCurrentURI(nsIURI** aURI); + bool IsScheme(const char* aScheme) const; bool IsChrome() const; + bool IsData() const; nsresult GetImageErrorCode(void); /// Returns true if we've received any data. bool HasTransferredData() const; /// Returns a non-owning pointer to this imgRequest's MIME type. const char* GetMimeType() const { return mContentType.get(); }
--- a/intl/lwbrk/nsJISx4051LineBreaker.cpp +++ b/intl/lwbrk/nsJISx4051LineBreaker.cpp @@ -551,20 +551,18 @@ GetClass(uint32_t u) /* CONDITIONAL_JAPANESE_STARTER = 37, [CJ] */ CLASS_CLOSE, /* HEBREW_LETTER = 38, [HL] */ CLASS_CHARACTER, /* REGIONAL_INDICATOR = 39, [RI] */ CLASS_CHARACTER, /* E_BASE = 40, [EB] */ CLASS_BREAKABLE, /* E_MODIFIER = 41, [EM] */ CLASS_CHARACTER, /* ZWJ = 42, [ZWJ]*/ CLASS_CHARACTER }; -#if ENABLE_INTL_API static_assert(U_LB_COUNT == mozilla::ArrayLength(sUnicodeLineBreakToClass), "Gecko vs ICU LineBreak class mismatch"); -#endif auto cls = mozilla::unicode::GetLineBreakClass(u); MOZ_ASSERT(cls < mozilla::ArrayLength(sUnicodeLineBreakToClass)); return sUnicodeLineBreakToClass[cls]; } static bool GetPair(int8_t c1, int8_t c2)
--- a/intl/unicharutil/tools/genUnicodePropertyData.pl +++ b/intl/unicharutil/tools/genUnicodePropertyData.pl @@ -4,31 +4,28 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # This tool is used to prepare lookup tables of Unicode character properties # needed by gfx code to support text shaping operations. The properties are # read from the Unicode Character Database and compiled into multi-level arrays # for efficient lookup. # +# Note that for most properties, we now rely on ICU; this tool and the tables +# it generates are used only for a couple of properties not readily exposed +# via ICU APIs. +# # To regenerate the tables in nsUnicodePropertyData.cpp: # # (1) Download the current Unicode data files from # # http://www.unicode.org/Public/UNIDATA/ # # NB: not all the files are actually needed; currently, we require # - UnicodeData.txt -# - Scripts.txt -# - BidiMirroring.txt -# - BidiBrackets.txt -# - HangulSyllableType.txt -# - LineBreak.txt -# - EastAsianWidth.txt -# - DerivedCoreProperties.txt # - ReadMe.txt (to record version/date of the UCD) # - Unihan_Variants.txt (from Unihan.zip) # though this may change if we find a need for additional properties. # # The Unicode data files listed above should be together in one directory. # # We also require the file # http://www.unicode.org/Public/security/latest/IdentifierStatus.txt @@ -39,103 +36,74 @@ # http://www.unicode.org/Public/vertical/revision-17/VerticalOrientation-17.txt # This file should be in a sub-directory "vertical" immediately below the # directory containing the other Unicode data files. # # # (2) Run this tool using a command line of the form # # perl genUnicodePropertyData.pl \ -# /path/to/harfbuzz/src \ # /path/to/icu/common/unicode \ # /path/to/UCD-directory # # This will generate (or overwrite!) the files # # nsUnicodePropertyData.cpp # nsUnicodeScriptCodes.h # # in the current directory. use strict; use List::Util qw(first); -if ($#ARGV != 2) { +if ($#ARGV != 1) { print <<__EOT; # Run this tool using a command line of the form # # perl genUnicodePropertyData.pl \\ -# /path/to/harfbuzz/src \\ # /path/to/icu/common/unicode \\ # /path/to/UCD-directory # -# where harfbuzz/src is the directory containing harfbuzz .cc and .hh files, -# icu/common/unicode is the directory containing ICU 'common' public headers, +# where icu/common/unicode is the directory containing ICU 'common' headers, # and UCD-directory is a directory containing the current Unicode Character # Database files (UnicodeData.txt, etc), available from # http://www.unicode.org/Public/UNIDATA/, with additional resources as # detailed in the source comments. # # This will generate (or overwrite!) the files # # nsUnicodePropertyData.cpp # nsUnicodeScriptCodes.h # # in the current directory. __EOT exit 0; } -my $HARFBUZZ = $ARGV[0]; -my $ICU = $ARGV[1]; -my $UNICODE = $ARGV[2]; - -# load HB_Category constants - -my $cc = -1; -my %catCode; +my $ICU = $ARGV[0]; +my $UNICODE = $ARGV[1]; -sub readHarfBuzzHeader -{ - my $file = shift; - open FH, "< $HARFBUZZ/$file" or die "can't open harfbuzz header $HARFBUZZ/$file\n"; - while (<FH>) { - if (m/HB_UNICODE_GENERAL_CATEGORY_([A-Z_]+)/) { - $cc++; - $catCode{$1} = $cc; - } - } - close FH; -} - -&readHarfBuzzHeader("hb-unicode.h"); - -die "didn't find HarfBuzz category codes\n" if $cc == -1; - -my %scriptCode; -my @scriptCodeToTag; my @scriptCodeToName; +my @idtype; my $sc = -1; sub readIcuHeader { my $file = shift; open FH, "< $ICU/$file" or die "can't open ICU header $ICU/$file\n"; while (<FH>) { # adjust for ICU vs UCD naming discrepancies s/LANNA/TAI_THAM/; s/MEITEI_MAYEK/MEETEI_MAYEK/; s/ORKHON/OLD_TURKIC/; s/MENDE/MENDE_KIKAKUI/; s/SIGN_WRITING/SIGNWRITING/; if (m|USCRIPT_([A-Z_]+)\s*=\s*([0-9]+),\s*/\*\s*([A-Z][a-z]{3})\s*\*/|) { $sc = $2; - $scriptCode{$1} = $sc; - $scriptCodeToTag[$sc] = $3; $scriptCodeToName[$sc] = $1; } } close FH; } &readIcuHeader("uscript.h"); @@ -165,254 +133,66 @@ my %idType = ( ); # These match the IdentifierType enum in nsUnicodeProperties.h. my %mappedIdType = ( "Restricted" => 0, "Allowed" => 1 ); -my %bidicategoryCode = ( - "L" => 0, # Left-to-Right - "R" => 1, # Right-to-Left - "EN" => 2, # European Number - "ES" => 3, # European Number Separator - "ET" => 4, # European Number Terminator - "AN" => 5, # Arabic Number - "CS" => 6, # Common Number Separator - "B" => 7, # Paragraph Separator - "S" => 8, # Segment Separator - "WS" => 9, # Whitespace - "ON" => 10, # Other Neutrals - "LRE" => 11, # Left-to-Right Embedding - "LRO" => 12, # Left-to-Right Override - "AL" => 13, # Right-to-Left Arabic - "RLE" => 14, # Right-to-Left Embedding - "RLO" => 15, # Right-to-Left Override - "PDF" => 16, # Pop Directional Format - "NSM" => 17, # Non-Spacing Mark - "BN" => 18, # Boundary Neutral - "FSI" => 19, # First Strong Isolate - "LRI" => 20, # Left-to-Right Isolate - "RLI" => 21, # Right-to-left Isolate - "PDI" => 22 # Pop Direcitonal Isolate -); - my %verticalOrientationCode = ( 'U' => 0, # U - Upright, the same orientation as in the code charts 'R' => 1, # R - Rotated 90 degrees clockwise compared to the code charts 'Tu' => 2, # Tu - Transformed typographically, with fallback to Upright 'Tr' => 3 # Tr - Transformed typographically, with fallback to Rotated ); -my %lineBreakCode = ( # ordering matches ICU's ULineBreak enum - "XX" => 0, - "AI" => 1, - "AL" => 2, - "B2" => 3, - "BA" => 4, - "BB" => 5, - "BK" => 6, - "CB" => 7, - "CL" => 8, - "CM" => 9, - "CR" => 10, - "EX" => 11, - "GL" => 12, - "HY" => 13, - "ID" => 14, - "IN" => 15, - "IS" => 16, - "LF" => 17, - "NS" => 18, - "NU" => 19, - "OP" => 20, - "PO" => 21, - "PR" => 22, - "QU" => 23, - "SA" => 24, - "SG" => 25, - "SP" => 26, - "SY" => 27, - "ZW" => 28, - "NL" => 29, - "WJ" => 30, - "H2" => 31, - "H3" => 32, - "JL" => 33, - "JT" => 34, - "JV" => 35, - "CP" => 36, - "CJ" => 37, - "HL" => 38, - "RI" => 39, - "EB" => 40, - "EM" => 41, - "ZWJ" => 42 -); - -my %eastAsianWidthCode = ( - "N" => 0, - "A" => 1, - "H" => 2, - "W" => 3, - "F" => 4, - "Na" => 5 -); - # initialize default properties -my @script; -my @category; -my @combining; -my @mirror; -my @pairedBracketType; -my @hangul; -my @casemap; -my @idtype; -my @numericvalue; my @hanVariant; -my @bidicategory; my @fullWidth; my @fullWidthInverse; my @verticalOrientation; -my @lineBreak; -my @eastAsianWidthFWH; -my @defaultIgnorable; for (my $i = 0; $i < 0x110000; ++$i) { - $script[$i] = $scriptCode{"UNKNOWN"}; - $category[$i] = $catCode{"UNASSIGNED"}; - $combining[$i] = 0; - $pairedBracketType[$i] = 0; - $casemap[$i] = 0; - $idtype[$i] = $mappedIdType{'Restricted'}; - $numericvalue[$i] = -1; $hanVariant[$i] = 0; - $bidicategory[$i] = $bidicategoryCode{"L"}; $fullWidth[$i] = 0; $fullWidthInverse[$i] = 0; $verticalOrientation[$i] = 1; # default for unlisted codepoints is 'R' - $lineBreak[$i] = $lineBreakCode{"XX"}; - $eastAsianWidthFWH[$i] = 0; - $defaultIgnorable[$i] = 0; } -# blocks where the default for bidi category is not L -for my $i (0x0600..0x07BF, 0x08A0..0x08FF, 0xFB50..0xFDCF, 0xFDF0..0xFDFF, 0xFE70..0xFEFF, 0x1EE00..0x0001EEFF) { - $bidicategory[$i] = $bidicategoryCode{"AL"}; -} -for my $i (0x0590..0x05FF, 0x07C0..0x089F, 0xFB1D..0xFB4F, 0x00010800..0x00010FFF, 0x0001E800..0x0001EDFF, 0x0001EF00..0x0001EFFF) { - $bidicategory[$i] = $bidicategoryCode{"R"}; -} -for my $i (0x20A0..0x20CF) { - $bidicategory[$i] = $bidicategoryCode{"ET"}; -} - -my %ucd2hb = ( -'Cc' => 'CONTROL', -'Cf' => 'FORMAT', -'Cn' => 'UNASSIGNED', -'Co' => 'PRIVATE_USE', -'Cs' => 'SURROGATE', -'Ll' => 'LOWERCASE_LETTER', -'Lm' => 'MODIFIER_LETTER', -'Lo' => 'OTHER_LETTER', -'Lt' => 'TITLECASE_LETTER', -'Lu' => 'UPPERCASE_LETTER', -'Mc' => 'SPACING_MARK', -'Me' => 'ENCLOSING_MARK', -'Mn' => 'NON_SPACING_MARK', -'Nd' => 'DECIMAL_NUMBER', -'Nl' => 'LETTER_NUMBER', -'No' => 'OTHER_NUMBER', -'Pc' => 'CONNECT_PUNCTUATION', -'Pd' => 'DASH_PUNCTUATION', -'Pe' => 'CLOSE_PUNCTUATION', -'Pf' => 'FINAL_PUNCTUATION', -'Pi' => 'INITIAL_PUNCTUATION', -'Po' => 'OTHER_PUNCTUATION', -'Ps' => 'OPEN_PUNCTUATION', -'Sc' => 'CURRENCY_SYMBOL', -'Sk' => 'MODIFIER_SYMBOL', -'Sm' => 'MATH_SYMBOL', -'So' => 'OTHER_SYMBOL', -'Zl' => 'LINE_SEPARATOR', -'Zp' => 'PARAGRAPH_SEPARATOR', -'Zs' => 'SPACE_SEPARATOR' -); - # read ReadMe.txt my @versionInfo; open FH, "< $UNICODE/ReadMe.txt" or die "can't open Unicode ReadMe.txt file\n"; while (<FH>) { chomp; push @versionInfo, $_; } close FH; -my $kTitleToUpper = 0x80000000; -my $kUpperToLower = 0x40000000; -my $kLowerToTitle = 0x20000000; -my $kLowerToUpper = 0x10000000; -my $kCaseMapCharMask = 0x001fffff; - # read UnicodeData.txt open FH, "< $UNICODE/UnicodeData.txt" or die "can't open UCD file UnicodeData.txt\n"; while (<FH>) { chomp; my @fields = split /;/; if ($fields[1] =~ /First/) { my $first = hex "0x$fields[0]"; $_ = <FH>; @fields = split /;/; if ($fields[1] =~ /Last/) { my $last = hex "0x$fields[0]"; do { - $category[$first] = $catCode{$ucd2hb{$fields[2]}}; - $combining[$first] = $fields[3]; - $bidicategory[$first] = $bidicategoryCode{$fields[4]}; - unless (length($fields[7]) == 0) { - $numericvalue[$first] = $fields[7]; - } if ($fields[1] =~ /CJK/) { @hanVariant[$first] = 3; } $first++; } while ($first <= $last); } else { die "didn't find Last code for range!\n"; } } else { my $usv = hex "0x$fields[0]"; - $category[$usv] = $catCode{$ucd2hb{$fields[2]}}; - $combining[$usv] = $fields[3]; - my $upper = hex $fields[12]; - my $lower = hex $fields[13]; - my $title = hex $fields[14]; - # we only store one mapping for each character, - # but also record what kind of mapping it is - if ($upper && $lower) { - $casemap[$usv] |= $kTitleToUpper; - $casemap[$usv] |= ($usv ^ $upper); - } - elsif ($lower) { - $casemap[$usv] |= $kUpperToLower; - $casemap[$usv] |= ($usv ^ $lower); - } - elsif ($title && ($title != $upper)) { - $casemap[$usv] |= $kLowerToTitle; - $casemap[$usv] |= ($usv ^ $title); - } - elsif ($upper) { - $casemap[$usv] |= $kLowerToUpper; - $casemap[$usv] |= ($usv ^ $upper); - } - $bidicategory[$usv] = $bidicategoryCode{$fields[4]}; - unless (length($fields[7]) == 0) { - $numericvalue[$usv] = $fields[7]; - } if ($fields[1] =~ /CJK/) { @hanVariant[$usv] = 3; } if ($fields[5] =~ /^<narrow>/) { my $wideChar = hex(substr($fields[5], 9)); die "didn't expect supplementary-plane values here" if $usv > 0xffff || $wideChar > 0xffff; $fullWidth[$usv] = $wideChar; $fullWidthInverse[$wideChar] = $usv; @@ -422,188 +202,16 @@ while (<FH>) { die "didn't expect supplementary-plane values here" if $usv > 0xffff || $narrowChar > 0xffff; $fullWidth[$narrowChar] = $usv; $fullWidthInverse[$usv] = $narrowChar; } } } close FH; -# read Scripts.txt -open FH, "< $UNICODE/Scripts.txt" or die "can't open UCD file Scripts.txt\n"; -push @versionInfo, ""; -while (<FH>) { - chomp; - push @versionInfo, $_; - last if /Date:/; -} -while (<FH>) { - if (m/([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))*\s+;\s+([^ ]+)/) { - my $script = uc($3); - unless (exists $scriptCode{$script}) { - warn "unknown ICU script $script"; - $scriptCode{$script} = $scriptCode{"UNKNOWN"}; - } - $script = $scriptCode{$script}; - my $start = hex "0x$1"; - my $end = (defined $2) ? hex "0x$2" : $start; - for (my $i = $start; $i <= $end; ++$i) { - $script[$i] = $script; - } - } -} -close FH; - -# read BidiMirroring.txt -my @offsets = (); -push @offsets, 0; - -open FH, "< $UNICODE/BidiMirroring.txt" or die "can't open UCD file BidiMirroring.txt\n"; -push @versionInfo, ""; -while (<FH>) { - chomp; - push @versionInfo, $_; - last if /Date:/; -} -while (<FH>) { - s/#.*//; - if (m/([0-9A-F]{4,6});\s*([0-9A-F]{4,6})/) { - my $mirrorOffset = hex("0x$2") - hex("0x$1"); - my $offsetIndex = first { $offsets[$_] eq $mirrorOffset } 0..$#offsets; - if ($offsetIndex == undef) { - die "too many offset codes\n" if scalar @offsets == 31; - push @offsets, $mirrorOffset; - $offsetIndex = $#offsets; - } - $mirror[hex "0x$1"] = $offsetIndex; - } -} -close FH; - -# read BidiBrackets.txt -my %pairedBracketTypeCode = ( - 'N' => 0, - 'O' => 1, - 'C' => 2 -); -open FH, "< $UNICODE/BidiBrackets.txt" or die "can't open UCD file BidiBrackets.txt\n"; -push @versionInfo, ""; -while (<FH>) { - chomp; - push @versionInfo, $_; - last if /Date:/; -} -while (<FH>) { - s/#.*//; - if (m/([0-9A-F]{4,6});\s*([0-9A-F]{4,6});\s*(.)/) { - my $mirroredChar = $offsets[$mirror[hex "0x$1"]] + hex "0x$1"; - die "bidi bracket does not match mirrored char\n" unless $mirroredChar == hex "0x$2"; - my $pbt = uc($3); - warn "unknown Bidi Bracket type" unless exists $pairedBracketTypeCode{$pbt}; - $pairedBracketType[hex "0x$1"] = $pairedBracketTypeCode{$pbt}; - } -} -close FH; - -# read HangulSyllableType.txt -my %hangulType = ( - 'L' => 0x01, - 'V' => 0x02, - 'T' => 0x04, - 'LV' => 0x03, - 'LVT' => 0x07 -); -open FH, "< $UNICODE/HangulSyllableType.txt" or die "can't open UCD file HangulSyllableType.txt\n"; -push @versionInfo, ""; -while (<FH>) { - chomp; - push @versionInfo, $_; - last if /Date:/; -} -while (<FH>) { - s/#.*//; - if (m/([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))*\s*;\s*([^ ]+)/) { - my $hangul = uc($3); - warn "unknown Hangul syllable type" unless exists $hangulType{$hangul}; - $hangul = $hangulType{$hangul}; - my $start = hex "0x$1"; - my $end = (defined $2) ? hex "0x$2" : $start; - for (my $i = $start; $i <= $end; ++$i) { - $hangul[$i] = $hangul; - } - } -} -close FH; - -# read LineBreak.txt -open FH, "< $UNICODE/LineBreak.txt" or die "can't open UCD file LineBreak.txt\n"; -push @versionInfo, ""; -while (<FH>) { - chomp; - push @versionInfo, $_; - last if /Date:/; -} -while (<FH>) { - s/#.*//; - if (m/([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))*\s*;\s*([^ ]+)/) { - my $lb = uc($3); - warn "unknown LineBreak class" unless exists $lineBreakCode{$lb}; - $lb = $lineBreakCode{$lb}; - my $start = hex "0x$1"; - my $end = (defined $2) ? hex "0x$2" : $start; - for (my $i = $start; $i <= $end; ++$i) { - $lineBreak[$i] = $lb; - } - } -} -close FH; - -# read EastAsianWidth.txt -open FH, "< $UNICODE/EastAsianWidth.txt" or die "can't open UCD file EastAsianWidth.txt\n"; -push @versionInfo, ""; -while (<FH>) { - chomp; - push @versionInfo, $_; - last if /Date:/; -} -while (<FH>) { - s/#.*//; - if (m/([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))*\s*;\s*([^ ]+)/) { - my $start = hex "0x$1"; - my $end = (defined $2) ? hex "0x$2" : $start; - my $eaw = $3; - warn "unknown EastAsianWidth class" unless exists $eastAsianWidthCode{$eaw}; - my $isFWH = ($eaw =~ m/^[FWH]$/) ? 1 : 0; - for (my $i = $start; $i <= $end; ++$i) { - $eastAsianWidthFWH[$i] = $isFWH; - } - } -} -close FH; - -# read DerivedCoreProperties.txt (for Default-Ignorables) -open FH, "< $UNICODE/DerivedCoreProperties.txt" or die "can't open UCD file DerivedCoreProperties.txt\n"; -push @versionInfo, ""; -while (<FH>) { - chomp; - push @versionInfo, $_; - last if /Date:/; -} -while (<FH>) { - s/#.*//; - if (m/([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))*\s*;\s*Default_Ignorable_Code_Point/) { - my $start = hex "0x$1"; - my $end = (defined $2) ? hex "0x$2" : $start; - for (my $i = $start; $i <= $end; ++$i) { - $defaultIgnorable[$i] = 1; - } - } -} -close FH; - # read IdentifierStatus.txt open FH, "< $UNICODE/security/IdentifierStatus.txt" or die "can't open UCD file IdentifierStatus.txt\n"; push @versionInfo, ""; while (<FH>) { chomp; s/\xef\xbb\xbf//; push @versionInfo, $_; last if /Date:/; @@ -730,162 +338,77 @@ print HEADER <<__END; * * * * * This file contains MACHINE-GENERATED DATA, do not edit! * * * * * */ #ifndef NS_UNICODE_SCRIPT_CODES #define NS_UNICODE_SCRIPT_CODES __END -print DATA_TABLES "#if !ENABLE_INTL_API\n"; -print DATA_TABLES "static const uint32_t sScriptCodeToTag[] = {\n"; -for (my $i = 0; $i < scalar @scriptCodeToTag; ++$i) { - printf DATA_TABLES " HB_TAG('%c','%c','%c','%c')", unpack('cccc', $scriptCodeToTag[$i]); - print DATA_TABLES $i < $#scriptCodeToTag ? ",\n" : "\n"; -} -print DATA_TABLES "};\n"; -print DATA_TABLES "#endif\n\n"; - our $totalData = 0; -print DATA_TABLES "#if !ENABLE_INTL_API\n"; -print DATA_TABLES "static const int16_t sMirrorOffsets[] = {\n"; -for (my $i = 0; $i < scalar @offsets; ++$i) { - printf DATA_TABLES " $offsets[$i]"; - print DATA_TABLES $i < $#offsets ? ",\n" : "\n"; -} -print DATA_TABLES "};\n"; -print DATA_TABLES "#endif\n\n"; - print HEADER "#pragma pack(1)\n\n"; -sub sprintCharProps1 -{ - my $usv = shift; - return sprintf("{%d,%d,%d}, ", $mirror[$usv], $hangul[$usv], $combining[$usv]); -} -my $type = q/ -struct nsCharProps1 { - unsigned char mMirrorOffsetIndex:5; - unsigned char mHangulType:3; - unsigned char mCombiningClass:8; -}; -/; -&genTables("#if !ENABLE_INTL_API", "#endif", - "CharProp1", $type, "nsCharProps1", 11, 5, \&sprintCharProps1, 1, 2, 1); - sub sprintCharProps2_short { my $usv = shift; return sprintf("{%d,%d},", $verticalOrientation[$usv], $idtype[$usv]); } -$type = q| +my $type = q| struct nsCharProps2 { // Currently only 4 bits are defined here, so 4 more could be added without // affecting the storage requirements for this struct. Or we could pack two // records per byte, at the cost of a slightly more complex accessor. unsigned char mVertOrient:2; unsigned char mIdType:2; }; |; -&genTables("#if ENABLE_INTL_API", "#endif", - "CharProp2", $type, "nsCharProps2", 9, 7, \&sprintCharProps2_short, 16, 1, 1); - -sub sprintCharProps2_full -{ - my $usv = shift; - return sprintf("{%d,%d,%d,%d,%d,%d,%d,%d,%d,%d},", - $script[$usv], $pairedBracketType[$usv], - $eastAsianWidthFWH[$usv], $category[$usv], - $idtype[$usv], $defaultIgnorable[$usv], $bidicategory[$usv], - $verticalOrientation[$usv], $lineBreak[$usv], - $numericvalue[$usv]); -} -$type = q| -// This struct currently requires 5 bytes. We try to ensure that whole-byte -// fields will not straddle byte boundaries, to optimize access to them. -struct nsCharProps2 { - unsigned char mScriptCode:8; - // -- byte boundary -- - unsigned char mPairedBracketType:2; - unsigned char mEastAsianWidthFWH:1; - unsigned char mCategory:5; - // -- byte boundary -- - unsigned char mIdType:2; - unsigned char mDefaultIgnorable:1; - unsigned char mBidiCategory:5; - // -- byte boundary -- - unsigned char mVertOrient:2; - unsigned char mLineBreak:6; - // -- byte boundary -- - signed char mNumericValue; // only 5 bits are actually needed here -}; -|; -&genTables("#if !ENABLE_INTL_API", "#endif", - "CharProp2", $type, "nsCharProps2", 12, 4, \&sprintCharProps2_full, 16, 5, 1); +&genTables("CharProp2", $type, "nsCharProps2", 9, 7, \&sprintCharProps2_short, 16, 1, 1); print HEADER "#pragma pack()\n\n"; sub sprintHanVariants { my $baseUsv = shift; my $varShift = 0; my $val = 0; while ($varShift < 8) { $val |= $hanVariant[$baseUsv++] << $varShift; $varShift += 2; } return sprintf("0x%02x,", $val); } ## Han Variant data currently unused but may be needed in future, see bug 857481 -## &genTables("", "", "HanVariant", "", "uint8_t", 9, 7, \&sprintHanVariants, 2, 1, 4); +## &genTables("HanVariant", "", "uint8_t", 9, 7, \&sprintHanVariants, 2, 1, 4); sub sprintFullWidth { my $usv = shift; return sprintf("0x%04x,", $fullWidth[$usv]); } -&genTables("", "", "FullWidth", "", "uint16_t", 10, 6, \&sprintFullWidth, 0, 2, 1); +&genTables("FullWidth", "", "uint16_t", 10, 6, \&sprintFullWidth, 0, 2, 1); sub sprintFullWidthInverse { my $usv = shift; return sprintf("0x%04x,", $fullWidthInverse[$usv]); } -&genTables("", "", "FullWidthInverse", "", "uint16_t", 10, 6, \&sprintFullWidthInverse, 0, 2, 1); - -sub sprintCasemap -{ - my $usv = shift; - return sprintf("0x%08x,", $casemap[$usv]); -} -&genTables("#if !ENABLE_INTL_API", "#endif", - "CaseMap", "", "uint32_t", 11, 5, \&sprintCasemap, 1, 4, 1); +&genTables("FullWidthInverse", "", "uint16_t", 10, 6, \&sprintFullWidthInverse, 0, 2, 1); print STDERR "Total data = $totalData\n"; -printf DATA_TABLES "const uint32_t kTitleToUpper = 0x%08x;\n", $kTitleToUpper; -printf DATA_TABLES "const uint32_t kUpperToLower = 0x%08x;\n", $kUpperToLower; -printf DATA_TABLES "const uint32_t kLowerToTitle = 0x%08x;\n", $kLowerToTitle; -printf DATA_TABLES "const uint32_t kLowerToUpper = 0x%08x;\n", $kLowerToUpper; -printf DATA_TABLES "const uint32_t kCaseMapCharMask = 0x%08x;\n\n", $kCaseMapCharMask; - sub genTables { - my ($guardBegin, $guardEnd, - $prefix, $typedef, $type, $indexBits, $charBits, $func, $maxPlane, $bytesPerEntry, $charsPerEntry) = @_; + my ($prefix, $typedef, $type, $indexBits, $charBits, $func, $maxPlane, $bytesPerEntry, $charsPerEntry) = @_; if ($typedef ne '') { - print HEADER "$guardBegin\n"; print HEADER "$typedef\n"; - print HEADER "$guardEnd\n\n"; } - print DATA_TABLES "\n$guardBegin\n"; print DATA_TABLES "#define k${prefix}MaxPlane $maxPlane\n"; print DATA_TABLES "#define k${prefix}IndexBits $indexBits\n"; print DATA_TABLES "#define k${prefix}CharBits $charBits\n"; my $indexLen = 1 << $indexBits; my $charsPerPage = 1 << $charBits; my %charIndex = (); my %pageMapIndex = (); @@ -944,17 +467,16 @@ sub genTables my $pageLen = $charsPerPage / $charsPerEntry; print DATA_TABLES "static const $type s${prefix}Values[$chCount][$pageLen] = {\n"; for (my $i = 0; $i < scalar @char; ++$i) { print DATA_TABLES " {"; print DATA_TABLES $char[$i]; print DATA_TABLES $i < $#char ? "},\n" : "}\n"; } print DATA_TABLES "};\n"; - print DATA_TABLES "$guardEnd\n"; my $dataSize = $pmCount * $indexLen * $pmBits/8 + $chCount * $pageLen * $bytesPerEntry + $maxPlane; $totalData += $dataSize; print STDERR "Data for $prefix = $dataSize\n"; }
--- a/intl/unicharutil/util/nsUnicodeProperties.cpp +++ b/intl/unicharutil/util/nsUnicodeProperties.cpp @@ -8,40 +8,16 @@ #include "nsUnicodePropertyData.cpp" #include "mozilla/ArrayUtils.h" #include "nsCharTraits.h" #define UNICODE_BMP_LIMIT 0x10000 #define UNICODE_LIMIT 0x110000 -#ifndef ENABLE_INTL_API -static const nsCharProps1& -GetCharProps1(uint32_t aCh) -{ - if (aCh < UNICODE_BMP_LIMIT) { - return sCharProp1Values[sCharProp1Pages[0][aCh >> kCharProp1CharBits]] - [aCh & ((1 << kCharProp1CharBits) - 1)]; - } - if (aCh < (kCharProp1MaxPlane + 1) * 0x10000) { - return sCharProp1Values[sCharProp1Pages[sCharProp1Planes[(aCh >> 16) - 1]] - [(aCh & 0xffff) >> kCharProp1CharBits]] - [aCh & ((1 << kCharProp1CharBits) - 1)]; - } - - // Default values for unassigned - static const nsCharProps1 undefined = { - 0, // Index to mirrored char offsets - 0, // Hangul Syllable type - 0 // Combining class - }; - return undefined; -} -#endif - const nsCharProps2& GetCharProps2(uint32_t aCh) { if (aCh < UNICODE_BMP_LIMIT) { return sCharProp2Values[sCharProp2Pages[0][aCh >> kCharProp2CharBits]] [aCh & ((1 << kCharProp2CharBits) - 1)]; } if (aCh < (kCharProp2MaxPlane + 1) * 0x10000) { @@ -49,31 +25,18 @@ GetCharProps2(uint32_t aCh) [(aCh & 0xffff) >> kCharProp2CharBits]] [aCh & ((1 << kCharProp2CharBits) - 1)]; } NS_NOTREACHED("Getting CharProps for codepoint outside Unicode range"); // Default values for unassigned using namespace mozilla::unicode; static const nsCharProps2 undefined = { -#if ENABLE_INTL_API VERTICAL_ORIENTATION_R, 0 // IdentifierType -#else - uint8_t(Script::UNKNOWN), - PAIRED_BRACKET_TYPE_NONE, - 0, // EastAsianWidthFWH - HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, - 0, // IdentifierType - 0, // DefaultIgnorable - eCharType_LeftToRight, - VERTICAL_ORIENTATION_R, - 0, // LineBreak - -1 // Numeric Value -#endif }; return undefined; } namespace mozilla { namespace unicode { @@ -130,17 +93,16 @@ const nsUGenCategory sDetailedToGeneralC /* MODIFIER_SYMBOL */ nsUGenCategory::kSymbol, /* MATH_SYMBOL */ nsUGenCategory::kSymbol, /* OTHER_SYMBOL */ nsUGenCategory::kSymbol, /* LINE_SEPARATOR */ nsUGenCategory::kSeparator, /* PARAGRAPH_SEPARATOR */ nsUGenCategory::kSeparator, /* SPACE_SEPARATOR */ nsUGenCategory::kSeparator }; -#ifdef ENABLE_INTL_API const hb_unicode_general_category_t sICUtoHBcategory[U_CHAR_CATEGORY_COUNT] = { HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, // U_GENERAL_OTHER_TYPES = 0, HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, // U_UPPERCASE_LETTER = 1, HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, // U_LOWERCASE_LETTER = 2, HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, // U_TITLECASE_LETTER = 3, HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, // U_MODIFIER_LETTER = 4, HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, // U_OTHER_LETTER = 5, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, // U_NON_SPACING_MARK = 6, @@ -163,152 +125,16 @@ const hb_unicode_general_category_t sICU HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, // U_OTHER_PUNCTUATION = 23, HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, // U_MATH_SYMBOL = 24, HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, // U_CURRENCY_SYMBOL = 25, HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, // U_MODIFIER_SYMBOL = 26, HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL, // U_OTHER_SYMBOL = 27, HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, // U_INITIAL_PUNCTUATION = 28, HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, // U_FINAL_PUNCTUATION = 29, }; -#endif - -#if !ENABLE_INTL_API -uint8_t GetGeneralCategory(uint32_t aCh) { - return GetCharProps2(aCh).mCategory; -} - -nsCharType GetBidiCat(uint32_t aCh) { - return nsCharType(GetCharProps2(aCh).mBidiCategory); -} - -int8_t GetNumericValue(uint32_t aCh) { - return GetCharProps2(aCh).mNumericValue; -} - -uint32_t -GetMirroredChar(uint32_t aCh) -{ - return aCh + sMirrorOffsets[GetCharProps1(aCh).mMirrorOffsetIndex]; -} - -bool -HasMirroredChar(uint32_t aCh) -{ - return GetCharProps1(aCh).mMirrorOffsetIndex != 0; -} - -uint8_t -GetCombiningClass(uint32_t aCh) -{ - return GetCharProps1(aCh).mCombiningClass; -} - -uint8_t -GetLineBreakClass(uint32_t aCh) -{ - return GetCharProps2(aCh).mLineBreak; -} - -Script -GetScriptCode(uint32_t aCh) -{ - return Script(GetCharProps2(aCh).mScriptCode); -} - -uint32_t -GetScriptTagForCode(Script aScriptCode) -{ - // this will safely return 0 for negative script codes, too :) - if (static_cast<uint32_t>(aScriptCode) > ArrayLength(sScriptCodeToTag)) { - return 0; - } - return sScriptCodeToTag[static_cast<uint32_t>(aScriptCode)]; -} - -PairedBracketType GetPairedBracketType(uint32_t aCh) -{ - return PairedBracketType(GetCharProps2(aCh).mPairedBracketType); -} - -uint32_t GetPairedBracket(uint32_t aCh) -{ - return GetPairedBracketType(aCh) != PAIRED_BRACKET_TYPE_NONE - ? GetMirroredChar(aCh) : aCh; -} - -static inline uint32_t -GetCaseMapValue(uint32_t aCh) -{ - if (aCh < UNICODE_BMP_LIMIT) { - return sCaseMapValues[sCaseMapPages[0][aCh >> kCaseMapCharBits]] - [aCh & ((1 << kCaseMapCharBits) - 1)]; - } - if (aCh < (kCaseMapMaxPlane + 1) * 0x10000) { - return sCaseMapValues[sCaseMapPages[sCaseMapPlanes[(aCh >> 16) - 1]] - [(aCh & 0xffff) >> kCaseMapCharBits]] - [aCh & ((1 << kCaseMapCharBits) - 1)]; - } - return 0; -} - -uint32_t -GetUppercase(uint32_t aCh) -{ - uint32_t mapValue = GetCaseMapValue(aCh); - if (mapValue & (kLowerToUpper | kTitleToUpper)) { - return aCh ^ (mapValue & kCaseMapCharMask); - } - if (mapValue & kLowerToTitle) { - return GetUppercase(aCh ^ (mapValue & kCaseMapCharMask)); - } - return aCh; -} - -uint32_t -GetLowercase(uint32_t aCh) -{ - uint32_t mapValue = GetCaseMapValue(aCh); - if (mapValue & kUpperToLower) { - return aCh ^ (mapValue & kCaseMapCharMask); - } - if (mapValue & kTitleToUpper) { - return GetLowercase(aCh ^ (mapValue & kCaseMapCharMask)); - } - return aCh; -} - -uint32_t -GetTitlecaseForLower(uint32_t aCh) -{ - uint32_t mapValue = GetCaseMapValue(aCh); - if (mapValue & (kLowerToTitle | kLowerToUpper)) { - return aCh ^ (mapValue & kCaseMapCharMask); - } - return aCh; -} - -uint32_t -GetTitlecaseForAll(uint32_t aCh) -{ - uint32_t mapValue = GetCaseMapValue(aCh); - if (mapValue & (kLowerToTitle | kLowerToUpper)) { - return aCh ^ (mapValue & kCaseMapCharMask); - } - if (mapValue & kUpperToLower) { - return GetTitlecaseForLower(aCh ^ (mapValue & kCaseMapCharMask)); - } - return aCh; -} - -bool IsEastAsianWidthFWH(uint32_t aCh) -{ - return GetCharProps2(aCh).mEastAsianWidthFWH; -} - -#endif #define DEFINE_BMP_1PLANE_MAPPING_GET_FUNC(prefix_) \ uint32_t Get##prefix_(uint32_t aCh) \ { \ if (aCh >= UNICODE_BMP_LIMIT) { \ return aCh; \ } \ auto page = s##prefix_##Pages[aCh >> k##prefix_##CharBits]; \ @@ -327,41 +153,28 @@ IsClusterExtender(uint32_t aCh, uint8_t { return ((aCategory >= HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK && aCategory <= HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) || (aCh >= 0x200c && aCh <= 0x200d) || // ZWJ, ZWNJ (aCh >= 0xff9e && aCh <= 0xff9f)); // katakana sound marks } enum HSType { -#if ENABLE_INTL_API HST_NONE = U_HST_NOT_APPLICABLE, HST_L = U_HST_LEADING_JAMO, HST_V = U_HST_VOWEL_JAMO, HST_T = U_HST_TRAILING_JAMO, HST_LV = U_HST_LV_SYLLABLE, HST_LVT = U_HST_LVT_SYLLABLE -#else - HST_NONE = 0x00, - HST_L = 0x01, - HST_V = 0x02, - HST_T = 0x04, - HST_LV = 0x03, - HST_LVT = 0x07 -#endif }; static HSType GetHangulSyllableType(uint32_t aCh) { -#if ENABLE_INTL_API return HSType(u_getIntPropertyValue(aCh, UCHAR_HANGUL_SYLLABLE_TYPE)); -#else - return HSType(GetCharProps1(aCh).mHangulType); -#endif } void ClusterIterator::Next() { if (AtEnd()) { NS_WARNING("ClusterIterator has already reached the end"); return;
--- a/intl/unicharutil/util/nsUnicodeProperties.h +++ b/intl/unicharutil/util/nsUnicodeProperties.h @@ -7,20 +7,18 @@ #ifndef NS_UNICODEPROPERTIES_H #define NS_UNICODEPROPERTIES_H #include "nsBidiUtils.h" #include "nsUGenCategory.h" #include "nsUnicodeScriptCodes.h" #include "harfbuzz/hb.h" -#if ENABLE_INTL_API #include "unicode/uchar.h" #include "unicode/uscript.h" -#endif const nsCharProps2& GetCharProps2(uint32_t aCh); namespace mozilla { namespace unicode { extern const nsUGenCategory sDetailedToGeneralCategory[]; @@ -43,18 +41,16 @@ enum PairedBracketType { /* Flags for Unicode security IdentifierType.txt attributes. Only a subset of these are currently checked by Gecko, so we only define flags for the ones we need. */ enum IdentifierType { IDTYPE_RESTRICTED = 0, IDTYPE_ALLOWED = 1, }; -#if ENABLE_INTL_API // ICU is available, so simply forward to its API - extern const hb_unicode_general_category_t sICUtoHBcategory[]; inline uint32_t GetMirroredChar(uint32_t aCh) { return u_charMirror(aCh); } @@ -171,73 +167,16 @@ IsEastAsianWidthFWH(uint32_t aCh) } inline bool IsDefaultIgnorable(uint32_t aCh) { return u_hasBinaryProperty(aCh, UCHAR_DEFAULT_IGNORABLE_CODE_POINT); } -#else // not ENABLE_INTL_API - -// Return whether the char has a mirrored-pair counterpart. -uint32_t GetMirroredChar(uint32_t aCh); - -bool HasMirroredChar(uint32_t aChr); - -uint8_t GetCombiningClass(uint32_t aCh); - -// returns the detailed General Category in terms of HB_UNICODE_* values -uint8_t GetGeneralCategory(uint32_t aCh); - -nsCharType GetBidiCat(uint32_t aCh); - -uint8_t GetLineBreakClass(uint32_t aCh); - -Script GetScriptCode(uint32_t aCh); - -// We don't support ScriptExtensions.txt data when building without ICU. -// The most important cases will still be handled in gfxScriptItemizer -// by checking IsClusterExtender to avoid breaking script runs within -// a cluster. -inline bool -HasScript(uint32_t aCh, Script aScript) -{ - return false; -} - -uint32_t GetScriptTagForCode(Script aScriptCode); - -PairedBracketType GetPairedBracketType(uint32_t aCh); -uint32_t GetPairedBracket(uint32_t aCh); - -/** - * Return the numeric value of the character. The value returned is the value - * of the Numeric_Value in field 7 of the UCD, or -1 if field 7 is empty. - * To restrict to decimal digits, the caller should also check whether - * GetGeneralCategory returns HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER - */ -int8_t GetNumericValue(uint32_t aCh); - -uint32_t GetUppercase(uint32_t aCh); -uint32_t GetLowercase(uint32_t aCh); -uint32_t GetTitlecaseForLower(uint32_t aCh); // maps LC to titlecase, UC unchanged -uint32_t GetTitlecaseForAll(uint32_t aCh); // maps both UC and LC to titlecase - -// Return whether the char has EastAsianWidth class F or W or H. -bool IsEastAsianWidthFWH(uint32_t aCh); - -// Return whether the char is default-ignorable. -inline bool IsDefaultIgnorable(uint32_t aCh) -{ - return GetCharProps2(aCh).mDefaultIgnorable; -} - -#endif // !ENABLE_INTL_API - // returns the simplified Gen Category as defined in nsUGenCategory inline nsUGenCategory GetGenCategory(uint32_t aCh) { return sDetailedToGeneralCategory[GetGeneralCategory(aCh)]; } inline VerticalOrientation GetVerticalOrientation(uint32_t aCh) { return VerticalOrientation(GetCharProps2(aCh).mVertOrient); }
--- a/intl/unicharutil/util/nsUnicodePropertyData.cpp +++ b/intl/unicharutil/util/nsUnicodePropertyData.cpp @@ -6,17 +6,17 @@ /* * Derived from the Unicode Character Database by genUnicodePropertyData.pl * * For Unicode terms of use, see http://www.unicode.org/terms_of_use.html */ /* - * Created on Wed Jun 28 17:08:23 2017 from UCD data files with version info: + * Created on Thu Sep 21 20:35:51 2017 from UCD data files with version info: * # Unicode Character Database # Date: 2017-06-18, 23:32:00 GMT [KW] # © 2017 Unicode®, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # # For documentation, see the following: @@ -24,37 +24,16 @@ # UAX #38, "Unicode Han Database (Unihan)" # UAX #44, "Unicode Character Database." # # The UAXes can be accessed at http://www.unicode.org/versions/Unicode10.0.0/ This directory contains the final data files for the Unicode Character Database, for Version 10.0.0 of the Unicode Standard. -# Scripts-10.0.0.txt -# Date: 2017-03-11, 06:40:37 GMT - -# BidiMirroring-10.0.0.txt -# Date: 2017-04-12, 17:30:00 GMT [KW, LI] - -# BidiBrackets-10.0.0.txt -# Date: 2017-04-12, 17:30:00 GMT [AG, LI, KW] - -# HangulSyllableType-10.0.0.txt -# Date: 2017-02-14, 04:26:11 GMT - -# LineBreak-10.0.0.txt -# Date: 2017-03-08, 02:00:00 GMT [KW, LI] - -# EastAsianWidth-10.0.0.txt -# Date: 2017-03-08, 02:00:00 GMT [KW, LI] - -# DerivedCoreProperties-10.0.0.txt -# Date: 2017-03-19, 00:05:15 GMT - # IdentifierStatus.txt # Date: 2017-04-08, 16:13:41 GMT # # Unihan_Variants.txt # Date: 2017-05-14 07:01:48 GMT [JHJ] # VerticalOrientation-17.txt @@ -62,407 +41,16 @@ for the Unicode Character Database, for * * * * * * This file contains MACHINE-GENERATED DATA, do not edit! * * * * * */ #include <stdint.h> #include "harfbuzz/hb.h" -#if !ENABLE_INTL_API -static const uint32_t sScriptCodeToTag[] = { - HB_TAG('Z','y','y','y'), - HB_TAG('Z','i','n','h'), - HB_TAG('A','r','a','b'), - HB_TAG('A','r','m','n'), - HB_TAG('B','e','n','g'), - HB_TAG('B','o','p','o'), - HB_TAG('C','h','e','r'), - HB_TAG('C','o','p','t'), - HB_TAG('C','y','r','l'), - HB_TAG('D','s','r','t'), - HB_TAG('D','e','v','a'), - HB_TAG('E','t','h','i'), - HB_TAG('G','e','o','r'), - HB_TAG('G','o','t','h'), - HB_TAG('G','r','e','k'), - HB_TAG('G','u','j','r'), - HB_TAG('G','u','r','u'), - HB_TAG('H','a','n','i'), - HB_TAG('H','a','n','g'), - HB_TAG('H','e','b','r'), - HB_TAG('H','i','r','a'), - HB_TAG('K','n','d','a'), - HB_TAG('K','a','n','a'), - HB_TAG('K','h','m','r'), - HB_TAG('L','a','o','o'), - HB_TAG('L','a','t','n'), - HB_TAG('M','l','y','m'), - HB_TAG('M','o','n','g'), - HB_TAG('M','y','m','r'), - HB_TAG('O','g','a','m'), - HB_TAG('I','t','a','l'), - HB_TAG('O','r','y','a'), - HB_TAG('R','u','n','r'), - HB_TAG('S','i','n','h'), - HB_TAG('S','y','r','c'), - HB_TAG('T','a','m','l'), - HB_TAG('T','e','l','u'), - HB_TAG('T','h','a','a'), - HB_TAG('T','h','a','i'), - HB_TAG('T','i','b','t'), - HB_TAG('C','a','n','s'), - HB_TAG('Y','i','i','i'), - HB_TAG('T','g','l','g'), - HB_TAG('H','a','n','o'), - HB_TAG('B','u','h','d'), - HB_TAG('T','a','g','b'), - HB_TAG('B','r','a','i'), - HB_TAG('C','p','r','t'), - HB_TAG('L','i','m','b'), - HB_TAG('L','i','n','b'), - HB_TAG('O','s','m','a'), - HB_TAG('S','h','a','w'), - HB_TAG('T','a','l','e'), - HB_TAG('U','g','a','r'), - HB_TAG('H','r','k','t'), - HB_TAG('B','u','g','i'), - HB_TAG('G','l','a','g'), - HB_TAG('K','h','a','r'), - HB_TAG('S','y','l','o'), - HB_TAG('T','a','l','u'), - HB_TAG('T','f','n','g'), - HB_TAG('X','p','e','o'), - HB_TAG('B','a','l','i'), - HB_TAG('B','a','t','k'), - HB_TAG('B','l','i','s'), - HB_TAG('B','r','a','h'), - HB_TAG('C','h','a','m'), - HB_TAG('C','i','r','t'), - HB_TAG('C','y','r','s'), - HB_TAG('E','g','y','d'), - HB_TAG('E','g','y','h'), - HB_TAG('E','g','y','p'), - HB_TAG('G','e','o','k'), - HB_TAG('H','a','n','s'), - HB_TAG('H','a','n','t'), - HB_TAG('H','m','n','g'), - HB_TAG('H','u','n','g'), - HB_TAG('I','n','d','s'), - HB_TAG('J','a','v','a'), - HB_TAG('K','a','l','i'), - HB_TAG('L','a','t','f'), - HB_TAG('L','a','t','g'), - HB_TAG('L','e','p','c'), - HB_TAG('L','i','n','a'), - HB_TAG('M','a','n','d'), - HB_TAG('M','a','y','a'), - HB_TAG('M','e','r','o'), - HB_TAG('N','k','o','o'), - HB_TAG('O','r','k','h'), - HB_TAG('P','e','r','m'), - HB_TAG('P','h','a','g'), - HB_TAG('P','h','n','x'), - HB_TAG('P','l','r','d'), - HB_TAG('R','o','r','o'), - HB_TAG('S','a','r','a'), - HB_TAG('S','y','r','e'), - HB_TAG('S','y','r','j'), - HB_TAG('S','y','r','n'), - HB_TAG('T','e','n','g'), - HB_TAG('V','a','i','i'), - HB_TAG('V','i','s','p'), - HB_TAG('X','s','u','x'), - HB_TAG('Z','x','x','x'), - HB_TAG('Z','z','z','z'), - HB_TAG('C','a','r','i'), - HB_TAG('J','p','a','n'), - HB_TAG('L','a','n','a'), - HB_TAG('L','y','c','i'), - HB_TAG('L','y','d','i'), - HB_TAG('O','l','c','k'), - HB_TAG('R','j','n','g'), - HB_TAG('S','a','u','r'), - HB_TAG('S','g','n','w'), - HB_TAG('S','u','n','d'), - HB_TAG('M','o','o','n'), - HB_TAG('M','t','e','i'), - HB_TAG('A','r','m','i'), - HB_TAG('A','v','s','t'), - HB_TAG('C','a','k','m'), - HB_TAG('K','o','r','e'), - HB_TAG('K','t','h','i'), - HB_TAG('M','a','n','i'), - HB_TAG('P','h','l','i'), - HB_TAG('P','h','l','p'), - HB_TAG('P','h','l','v'), - HB_TAG('P','r','t','i'), - HB_TAG('S','a','m','r'), - HB_TAG('T','a','v','t'), - HB_TAG('Z','m','t','h'), - HB_TAG('Z','s','y','m'), - HB_TAG('B','a','m','u'), - HB_TAG('L','i','s','u'), - HB_TAG('N','k','g','b'), - HB_TAG('S','a','r','b'), - HB_TAG('B','a','s','s'), - HB_TAG('D','u','p','l'), - HB_TAG('E','l','b','a'), - HB_TAG('G','r','a','n'), - HB_TAG('K','p','e','l'), - HB_TAG('L','o','m','a'), - HB_TAG('M','e','n','d'), - HB_TAG('M','e','r','c'), - HB_TAG('N','a','r','b'), - HB_TAG('N','b','a','t'), - HB_TAG('P','a','l','m'), - HB_TAG('S','i','n','d'), - HB_TAG('W','a','r','a'), - HB_TAG('A','f','a','k'), - HB_TAG('J','u','r','c'), - HB_TAG('M','r','o','o'), - HB_TAG('N','s','h','u'), - HB_TAG('S','h','r','d'), - HB_TAG('S','o','r','a'), - HB_TAG('T','a','k','r'), - HB_TAG('T','a','n','g'), - HB_TAG('W','o','l','e'), - HB_TAG('H','l','u','w'), - HB_TAG('K','h','o','j'), - HB_TAG('T','i','r','h'), - HB_TAG('A','g','h','b'), - HB_TAG('M','a','h','j'), - HB_TAG('A','h','o','m'), - HB_TAG('H','a','t','r'), - HB_TAG('M','o','d','i'), - HB_TAG('M','u','l','t'), - HB_TAG('P','a','u','c'), - HB_TAG('S','i','d','d'), - HB_TAG('A','d','l','m'), - HB_TAG('B','h','k','s'), - HB_TAG('M','a','r','c'), - HB_TAG('N','e','w','a'), - HB_TAG('O','s','g','e'), - HB_TAG('H','a','n','b'), - HB_TAG('J','a','m','o'), - HB_TAG('Z','s','y','e') -}; -#endif - -#if !ENABLE_INTL_API -static const int16_t sMirrorOffsets[] = { - 0, - 1, - -1, - 2, - -2, - 16, - -16, - 3, - -3, - 2016, - 138, - 1824, - 2104, - 2108, - 2106, - -138, - 8, - 7, - -8, - -7, - -1824, - -2016, - -2104, - -2106, - -2108 -}; -#endif - - -#if !ENABLE_INTL_API -#define kCharProp1MaxPlane 1 -#define kCharProp1IndexBits 11 -#define kCharProp1CharBits 5 -static const uint8_t sCharProp1Planes[1] = {1}; - -static const uint8_t sCharProp1Pages[2][2048] = { - {0,1,2,2,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,5,6,7,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,9,10,11,0,12,0,13,14,0,0,15,16,17,18,19,0,0,0,0,20,21,22,23,0,0,0,24,25,0,26,27,0,0,26,28,0,0,26,28,0,0,26,28,0,0,26,28,0,0,0,28,0,0,0,29,0,0,26,28,0,0,30,28,0,0,0,31,0,0,32,33,0,0,34,35,0,36,37,0,38,39,0,40,0,0,41,0,0,42,0,0,0,43,43,43,44,44,45,46,46,0,0,0,0,0,0,0,0,0,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,49,49,0,0,0,0,50,0,0,0,0,0,0,51,0,0,0,52,0,0,0,0,0,0,53,0,0,54,0,55,0,0,0,56,57,58,0,59,0,60,0,61,0,0,0,0,62,63,0,0,0,0,0,0,64,65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,67,68,69,0,70,71,0,0,0,0,0,0,0,0,72,73,74,75,76,77,78,79,80,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,0,0,83,84,0,0,0,0,0,0,0,0,0,0,0,0,85,86,87,88,0,89,0,90,91,92,93,94,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,0,0,0,96,0,0,0,97,98,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,101,0,0,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,104,0,0,105,0,0,0,0,0,0,0,0,106,0,0,0,0,0,57,107,0,108,109,110,0,111,112,0,0,0,0,0,0,113,114,115,0,0,0,0,0,0,0,28,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,123,124,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,128,129,0,0,0,0,1,2,130,131,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,132,0,0,0,0,0,0,0,133,0,0,0,134,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,136,0,0,0,0,0,137,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,106,96,0,138,0,0,139,140,0,111,0,0,141,0,0,142,0,0,0,0,0,143,0,26,28,144,0,0,0,0,0,0,145,0,0,0,146,0,0,0,0,0,0,96,147,0,0,96,0,0,0,148,0,0,0,149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,150,0,151,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,0,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,153,0,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,155,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,156,157,158,0,0,0,0,159,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,160,161,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,162,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} -}; - -static const nsCharProps1 sCharProp1Values[164][32] = { - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {3,0,0}, {0,0,0}, {4,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {3,0,0}, {0,0,0}, {4,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {5,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {6,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,232}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,232}, {0,0,216}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220},}, - {{0,0,220}, {0,0,202}, {0,0,202}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,202}, {0,0,202}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,240}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,232}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,233}, {0,0,234}, {0,0,234}, {0,0,233},}, - {{0,0,234}, {0,0,234}, {0,0,233}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,222}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,222}, {0,0,228}, {0,0,230}, {0,0,10}, {0,0,11}, {0,0,12}, {0,0,13}, {0,0,14}, {0,0,15}, {0,0,16}, {0,0,17}, {0,0,18}, {0,0,19}, {0,0,19}, {0,0,20}, {0,0,21}, {0,0,22}, {0,0,0}, {0,0,23},}, - {{0,0,0}, {0,0,24}, {0,0,25}, {0,0,0}, {0,0,230}, {0,0,220}, {0,0,0}, {0,0,18}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,30}, {0,0,31}, {0,0,32}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,27}, {0,0,28}, {0,0,29}, {0,0,30}, {0,0,31}, {0,0,32}, {0,0,33}, {0,0,34}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,35}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,36}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,220}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,0}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,27}, {0,0,28}, {0,0,29}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,84}, {0,0,91}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,103}, {0,0,103}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,107}, {0,0,107}, {0,0,107}, {0,0,107}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,118}, {0,0,118}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,122}, {0,0,122}, {0,0,122}, {0,0,122}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,0}, {0,0,220}, {0,0,0}, {0,0,216}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,129}, {0,0,130}, {0,0,0}, {0,0,132}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,130}, {0,0,130}, {0,0,130}, {0,0,130}, {0,0,0}, {0,0,0},}, - {{0,0,130}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,9}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,9}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0},}, - {{0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0},}, - {{0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0},}, - {{0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,228}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,222}, {0,0,230}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,220},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,1}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220},}, - {{0,0,230}, {0,0,0}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,234}, {0,0,214}, {0,0,220}, {0,0,202}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,232}, {0,0,228}, {0,0,228}, {0,0,220}, {0,0,0}, {0,0,230}, {0,0,233}, {0,0,220}, {0,0,230}, {0,0,220},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,1}, {0,0,1}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,1}, {0,0,1}, {0,0,230}, {0,0,220}, {0,0,230}, {0,0,1}, {0,0,1}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {7,0,0}, {7,0,0}, {7,0,0}, {8,0,0}, {8,0,0}, {8,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {9,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {10,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0},}, - {{1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {11,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {12,0,0}, {0,0,0}, {13,0,0}, {14,0,0}, {0,0,0}, {14,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {15,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0},}, - {{1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {16,0,0}, {16,0,0}, {16,0,0}, {0,0,0}, {17,0,0}, {17,0,0}, {0,0,0}, {0,0,0}, {18,0,0}, {18,0,0}, {18,0,0}, {19,0,0}, {19,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {3,0,0}, {0,0,0}, {4,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {7,0,0}, {1,0,0}, {2,0,0}, {8,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {20,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {21,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0},}, - {{2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0},}, - {{2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {22,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {23,0,0}, {24,0,0}, {23,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0},}, - {{1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,218}, {0,0,228}, {0,0,232}, {0,0,222}, {0,0,224}, {0,0,224}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,8}, {0,0,8}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230},}, - {{0,0,0}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,3,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,3,0}, {0,7,0}, {0,7,0}, {0,7,0},}, - {{0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,3,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0},}, - {{0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,3,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0},}, - {{0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,3,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0},}, - {{0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,3,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0},}, - {{0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,3,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0},}, - {{0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,3,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,7,0},}, - {{0,7,0}, {0,7,0}, {0,7,0}, {0,7,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0},}, - {{0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,2,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0},}, - {{0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,4,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,26}, {0,0,0},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {1,0,0}, {2,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {3,0,0}, {0,0,0}, {4,0,0}, {0,0,0}, {1,0,0},}, - {{2,0,0}, {0,0,0}, {1,0,0}, {2,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,0}, {0,0,0},}, - {{0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,0}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,1}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,9}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,7}, {0,0,0}, {0,0,9}, {0,0,9}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,1}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,216}, {0,0,216}, {0,0,1}, {0,0,1}, {0,0,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,226}, {0,0,216}, {0,0,216}, {0,0,216}, {0,0,216}, {0,0,216}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220},}, - {{0,0,220}, {0,0,220}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,220}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230},}, - {{0,0,230}, {0,0,230}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,220}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},}, - {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,230}, {0,0,7}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},} -}; -#endif - -#if ENABLE_INTL_API #define kCharProp2MaxPlane 16 #define kCharProp2IndexBits 9 #define kCharProp2CharBits 7 static const uint8_t sCharProp2Planes[16] = {1,2,3,4,4,4,4,4,4,4,4,4,4,4,3,3}; static const uint8_t sCharProp2Pages[5][512] = { {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,34,35,36,37,38,39,34,34,34,34,16,16,40,16,41,16,16,16,16,16,16,16,42,16,16,43,44,45,46,47,48,49,50,51,16,52,53,54,34,16,55,56,34,57,58,16,16,16,16,16,16,59,60,16,16,61,62,16,34,34,34,63,64,65,66,34,34,67,34,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,69,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,70,34,34,34,34,34,34,34,34,34,71,16,16,72,73,74,75,16,16,76,77,78,16,79,16,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,81,34,16,16,16,16,16,16,82,16,83,84}, {16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,85,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,34,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,34,34,34,34,34,34,34,34,86,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,34,34,34,34,34,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,76,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,87,68,88,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,34,34,34,34,16,16,34,16,16,16,16,16,16,16,16,16,34,34,34,34,34,86,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,34,34,34,34,89,34,34,34,34,34,34,34,34,34,34,34,16,16,34,34,16,16,16,16,16,16,16,16,16,16,16,16}, @@ -564,1123 +152,16 @@ static const nsCharProps2 sCharProp2Valu {{2,0},{2,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, {{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, {{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}}, {{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,0},{0,0},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}}, {{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}}, {{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,0},{1,0}} }; -#endif - -#if !ENABLE_INTL_API -#define kCharProp2MaxPlane 16 -#define kCharProp2IndexBits 12 -#define kCharProp2CharBits 4 -static const uint8_t sCharProp2Planes[16] = {1,2,3,4,4,4,4,4,4,4,4,4,4,5,6,6}; - -static const uint16_t sCharProp2Pages[7][4096] = { - {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,16,17,18,16,16,19,20,21,22,23,24,25,26,27,16,28,29,30,31,32,33,33,33,34,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,56,56,57,57,57,58,58,59,60,60,60,61,60,60,60,60,60,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,78,79,80,81,82,83,78,78,78,78,84,85,86,87,88,89,90,91,78,78,78,92,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,106,106,107,108,109,110,111,112,113,114,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,193,194,195,196,197,197,198,199,200,201,202,203,197,197,204,205,206,207,208,209,210,211,212,213,214,215,216,217,197,197,218,218,219,220,221,222,223,224,225,226,227,227,228,229,229,230,231,231,231,231,231,232,233,234,234,234,235,236,236,236,236,236,237,237,237,237,238,239,237,237,238,237,237,240,241,242,237,237,237,241,237,237,237,243,244,245,237,246,247,247,247,247,247,248,249,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,251,250,252,253,254,254,254,254,255,256,257,258,259,260,261,262,263,264,265,265,266,267,268,269,270,271,272,273,274,274,275,274,274,276,277,274,278,250,250,250,250,279,280,281,282,283,284,285,286,287,288,288,289,288,290,291,292,292,293,294,295,295,295,296,297,298,299,299,300,301,197,197,197,197,302,303,303,304,305,306,307,308,309,310,311,312,313,313,314,315,316,316,317,318,319,320,321,322,323,197,197,197,324,325,326,327,33,33,328,329,329,330,331,332,33,333,329,334,335,335,335,336,16,16,16,16,16,16,16,16,16,337,16,16,16,16,16,338,339,340,339,339,340,341,339,342,343,343,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,376,379,380,381,382,383,384,385,386,387,388,389,390,391,387,387,392,387,393,394,395,396,397,397,397,398,399,400,387,401,402,403,404,405,399,399,406,407,408,407,409,410,411,412,413,413,413,413,414,415,416,416,416,416,417,416,416,418,416,419,420,421,422,423,424,425,426,427,399,428,429,430,431,432,399,433,434,435,436,437,438,439,440,399,441,399,442,443,444,445,446,447,376,448,449,387,450,387,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,387,387,387,387,387,387,387,387,452,453,387,387,387,454,387,455,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,376,456,399,387,457,458,376,459,376,460,376,461,462,463,464,407,465,465,466,467,467,468,469,470,471,471,471,471,471,471,472,473,474,474,475,476,476,476,477,478,237,479,480,480,480,480,481,481,482,483,484,485,486,197,197,197,487,488,487,487,487,487,487,489,487,487,487,487,487,487,487,487,487,487,487,487,487,490,407,491,492,493,494,495,496,497,498,497,499,500,501,502,503,502,504,505,506,507,508,509,510,510,511,510,512,513,507,514,515,515,516,517,518,519,520,521,522,523,518,524,520,521,521,525,526,527,527,528,529,529,529,529,529,530,521,531,521,521,521,521,521,532,521,533,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,535,399,399,399,399,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,536,537,538,539,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,540,541,541,541,542,543,543,544,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,546,545,547,197,58,58,548,549,58,550,551,551,551,551,552,553,39,554,555,556,557,557,557,558,559,560,561,562,197,197,197,563,564,565,566,567,568,568,568,569,570,571,571,572,573,574,575,576,577,578,579,580,581,582,231,583,584,585,585,586,587,588,589,590,591,591,592,593,594,595,218,596,597,597,597,598,599,600,601,602,603,604,480,33,33,605,606,607,607,607,607,607,608,608,609,610,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,615,613,611,612,613,614,613,616,234,617,236,236,618,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,