Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBradley Farias <bradley.meck@gmail.com>2020-07-17 20:39:02 +0300
committerBradley Farias <bradley.meck@gmail.com>2020-08-13 21:17:40 +0300
commite155d9601429057a34adbcdcb790a1c12bd2a163 (patch)
tree330623d1c4116c229e3b47c05c627522a4c1f27e /lib/internal/util
parentf8976a76bbb49d678056d6d2ddd57064cf9e63c2 (diff)
policy: support conditions for redirects
PR-URL: https://github.com/nodejs/node/pull/34414 Reviewed-By: Jan Krems <jan.krems@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com>
Diffstat (limited to 'lib/internal/util')
-rw-r--r--lib/internal/util/compositekey.js114
1 files changed, 114 insertions, 0 deletions
diff --git a/lib/internal/util/compositekey.js b/lib/internal/util/compositekey.js
new file mode 100644
index 00000000000..9b7c460231f
--- /dev/null
+++ b/lib/internal/util/compositekey.js
@@ -0,0 +1,114 @@
+'use strict';
+const {
+ codes: {
+ ERR_INVALID_ARG_VALUE,
+ },
+} = require('internal/errors');
+const {
+ ObjectCreate,
+ ObjectFreeze,
+ SafeMap,
+ SafeWeakMap,
+} = primordials;
+/**
+ * @param {any} value
+ * @returns {boolean}
+ */
+const hasLifetime = (value) => {
+ return value !== null && (
+ typeof value === 'object' ||
+ typeof value === 'function'
+ );
+};
+class CompositeNode {
+ /**
+ * @type {WeakMap<object, Map<number, CompositeNode>>}
+ */
+ lifetimeNodes;
+ /**
+ * @type {Map<any, Map<number, CompositeNode>>}
+ */
+ primitiveNodes;
+ /**
+ * @type {null | Readonly<{}>}
+ */
+ value;
+ constructor() {
+ this.value = null;
+ }
+ get() {
+ if (this.value === null) {
+ return this.value = ObjectFreeze(ObjectCreate(null));
+ }
+ return this.value;
+ }
+ /**
+ * @param {any} value
+ * @param {number} position
+ */
+ emplacePrimitive(value, position) {
+ if (!this.primitiveNodes) {
+ this.primitiveNodes = new SafeMap();
+ }
+ if (!this.primitiveNodes.has(value)) {
+ this.primitiveNodes.set(value, new SafeMap());
+ }
+ const positions = this.primitiveNodes.get(value);
+ if (!positions.has(position)) {
+ positions.set(position, new CompositeNode());
+ }
+ return positions.get(position);
+ }
+ /**
+ * @param {object} value
+ * @param {number} position
+ */
+ emplaceLifetime(value, position) {
+ if (!this.lifetimeNodes) {
+ this.lifetimeNodes = new SafeWeakMap();
+ }
+ if (!this.lifetimeNodes.has(value)) {
+ this.lifetimeNodes.set(value, new SafeMap());
+ }
+ const positions = this.lifetimeNodes.get(value);
+ if (!positions.has(position)) {
+ positions.set(position, new CompositeNode());
+ }
+ return positions.get(position);
+ }
+}
+const compoundStore = new CompositeNode();
+// Accepts objects as a key and does identity on the parts of the iterable
+/**
+ * @param {any[]} parts
+ */
+const compositeKey = (parts) => {
+ /**
+ * @type {CompositeNode}
+ */
+ let node = compoundStore;
+ for (let i = 0; i < parts.length; i++) {
+ const value = parts[i];
+ if (hasLifetime(value)) {
+ node = node.emplaceLifetime(value, i);
+ parts[i] = hasLifetime;
+ }
+ }
+ // Does not leak WeakMap paths since there are none added
+ if (node === compoundStore) {
+ throw new ERR_INVALID_ARG_VALUE(
+ 'parts',
+ parts,
+ 'must contain a non-primitive element');
+ }
+ for (let i = 0; i < parts.length; i++) {
+ const value = parts[i];
+ if (value !== hasLifetime) {
+ node = node.emplacePrimitive(value, i);
+ }
+ }
+ return node.get();
+};
+module.exports = {
+ compositeKey
+};