next-csrf
Version:
CSRF mitigation library for Next.js
182 lines (152 loc) • 5.84 kB
JavaScript
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
import getShadowHost from '../get/shadow-host';
import mergeInDomOrder from '../util/merge-dom-order';
import tabindexValue from '../util/tabindex-value';
var Shadows = function () {
function Shadows(context, sortElements) {
_classCallCheck(this, Shadows);
// document context we're working with
this.context = context;
// callback that sorts an array of elements
this.sortElements = sortElements;
// reference to create unique IDs for each ShadowHost
this.hostCounter = 1;
// reference map for child-ShadowHosts of a ShadowHost
this.inHost = {};
// reference map for child-ShadowHost of the document
this.inDocument = [];
// reference map for ShadowHosts
this.hosts = {};
// reference map for tabbable elements of a ShadowHost
this.elements = {};
}
// remember which hosts we have to sort within later
_createClass(Shadows, [{
key: '_registerHost',
value: function _registerHost(host) {
if (host._sortingId) {
return;
}
// make the ShadowHost identifiable (see cleanup() for undo)
host._sortingId = 'shadow-' + this.hostCounter++;
this.hosts[host._sortingId] = host;
// hosts may contain other hosts
var parentHost = getShadowHost({ context: host });
if (parentHost) {
this._registerHost(parentHost);
this._registerHostParent(host, parentHost);
} else {
this.inDocument.push(host);
}
}
// remember which host is the child of which other host
}, {
key: '_registerHostParent',
value: function _registerHostParent(host, parent) {
if (!this.inHost[parent._sortingId]) {
this.inHost[parent._sortingId] = [];
}
this.inHost[parent._sortingId].push(host);
}
// remember which elements a host contains
}, {
key: '_registerElement',
value: function _registerElement(element, host) {
if (!this.elements[host._sortingId]) {
this.elements[host._sortingId] = [];
}
this.elements[host._sortingId].push(element);
}
// remove shadowed elements from the sequence and register
// the ShadowHosts they belong to so we know what to sort
// later on
}, {
key: 'extractElements',
value: function extractElements(elements) {
return elements.filter(function (element) {
var host = getShadowHost({ context: element });
if (!host) {
return true;
}
this._registerHost(host);
this._registerElement(element, host);
return false;
}, this);
}
// inject hosts into the sequence, sort everything,
// and recoursively replace hosts by its descendants
}, {
key: 'sort',
value: function sort(elements) {
var _elements = this._injectHosts(elements);
_elements = this._replaceHosts(_elements);
this._cleanup();
return _elements;
}
// merge ShadowHosts into the element lists of other ShadowHosts
// or the document, then sort the individual lists
}, {
key: '_injectHosts',
value: function _injectHosts(elements) {
Object.keys(this.hosts).forEach(function (_sortingId) {
var _list = this.elements[_sortingId];
var _elements = this.inHost[_sortingId];
var _context = this.hosts[_sortingId].shadowRoot;
this.elements[_sortingId] = this._merge(_list, _elements, _context);
}, this);
return this._merge(elements, this.inDocument, this.context);
}
}, {
key: '_merge',
value: function _merge(list, elements, context) {
var merged = mergeInDomOrder({
list: list,
elements: elements
});
return this.sortElements(merged, context);
}
}, {
key: '_replaceHosts',
value: function _replaceHosts(elements) {
return mergeInDomOrder({
list: elements,
elements: this.inDocument,
resolveElement: this._resolveHostElement.bind(this)
});
}
}, {
key: '_resolveHostElement',
value: function _resolveHostElement(host) {
var merged = mergeInDomOrder({
list: this.elements[host._sortingId],
elements: this.inHost[host._sortingId],
resolveElement: this._resolveHostElement.bind(this)
});
var _tabindex = tabindexValue(host);
if (_tabindex !== null && _tabindex > -1) {
return [host].concat(merged);
}
return merged;
}
}, {
key: '_cleanup',
value: function _cleanup() {
// remove those identifers we put on the ShadowHost to avoid using Map()
Object.keys(this.hosts).forEach(function (key) {
delete this.hosts[key]._sortingId;
}, this);
}
}]);
return Shadows;
}();
export default function (elements, context, sortElements) {
var shadows = new Shadows(context, sortElements);
var _elements = shadows.extractElements(elements);
if (_elements.length === elements.length) {
// no shadowed content found, no need to continue
return sortElements(elements);
}
return shadows.sort(_elements);
}
//# sourceMappingURL=tabsequence.sort-shadowed.js.map