-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
feat: proof of concept for using proxies to track changes on arrays
- Loading branch information
Showing
19 changed files
with
1,332 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
'use strict'; | ||
|
||
/*! | ||
* Module dependencies. | ||
*/ | ||
|
||
const ArrayMethods = require('../array/methods'); | ||
const DocumentArrayMethods = require('./methods'); | ||
const Document = require('../../document'); | ||
|
||
const arrayAtomicsSymbol = require('../../helpers/symbols').arrayAtomicsSymbol; | ||
const arrayAtomicsBackupSymbol = require('../../helpers/symbols').arrayAtomicsBackupSymbol; | ||
const arrayParentSymbol = require('../../helpers/symbols').arrayParentSymbol; | ||
const arrayPathSymbol = require('../../helpers/symbols').arrayPathSymbol; | ||
const arraySchemaSymbol = require('../../helpers/symbols').arraySchemaSymbol; | ||
|
||
const _basePush = Array.prototype.push; | ||
|
||
/** | ||
* DocumentArray constructor | ||
* | ||
* @param {Array} values | ||
* @param {String} path the path to this array | ||
* @param {Document} doc parent document | ||
* @api private | ||
* @return {MongooseDocumentArray} | ||
* @inherits MongooseArray | ||
* @see http://bit.ly/f6CnZU | ||
*/ | ||
|
||
function MongooseDocumentArray(values, path, doc) { | ||
const arr = []; | ||
|
||
const internals = { | ||
[arrayAtomicsSymbol]: {}, | ||
[arrayAtomicsBackupSymbol]: void 0, | ||
[arrayPathSymbol]: path, | ||
[arraySchemaSymbol]: void 0, | ||
[arrayParentSymbol]: void 0 | ||
}; | ||
|
||
if (Array.isArray(values)) { | ||
if (values[arrayPathSymbol] === path && | ||
values[arrayParentSymbol] === doc) { | ||
internals[arrayAtomicsSymbol] = Object.assign({}, values[arrayAtomicsSymbol]); | ||
} | ||
values.forEach(v => { | ||
_basePush.call(arr, v); | ||
}); | ||
} | ||
internals[arrayPathSymbol] = path; | ||
|
||
// Because doc comes from the context of another function, doc === global | ||
// can happen if there was a null somewhere up the chain (see #3020 && #3034) | ||
// RB Jun 17, 2015 updated to check for presence of expected paths instead | ||
// to make more proof against unusual node environments | ||
if (doc && doc instanceof Document) { | ||
internals[arrayParentSymbol] = doc; | ||
internals[arraySchemaSymbol] = doc.schema.path(path); | ||
|
||
// `schema.path()` doesn't drill into nested arrays properly yet, see | ||
// gh-6398, gh-6602. This is a workaround because nested arrays are | ||
// always plain non-document arrays, so once you get to a document array | ||
// nesting is done. Matryoshka code. | ||
while (internals[arraySchemaSymbol] != null && | ||
internals[arraySchemaSymbol].$isMongooseArray && | ||
!internals[arraySchemaSymbol].$isMongooseDocumentArray) { | ||
internals[arraySchemaSymbol] = internals[arraySchemaSymbol].casterConstructor; | ||
} | ||
} | ||
|
||
const proxy = new Proxy(arr, { | ||
get: function(target, prop) { | ||
if (prop === 'isMongooseArray' || | ||
prop === 'isMongooseArrayProxy' || | ||
prop === 'isMongooseDocumentArray' || | ||
prop === 'isMongooseDocumentArrayProxy') { | ||
return true; | ||
} | ||
if (prop === '__array') { | ||
return arr; | ||
} | ||
if (prop === 'set') { | ||
return set; | ||
} | ||
if (internals.hasOwnProperty(prop)) { | ||
return internals[prop]; | ||
} | ||
if (DocumentArrayMethods.hasOwnProperty(prop)) { | ||
return DocumentArrayMethods[prop]; | ||
} | ||
if (ArrayMethods.hasOwnProperty(prop)) { | ||
return ArrayMethods[prop]; | ||
} | ||
|
||
return arr[prop]; | ||
}, | ||
set: function(target, prop, value) { | ||
if (typeof prop === 'string' && /^\d+$/.test(prop)) { | ||
set.call(proxy, prop, value); | ||
} else if (internals.hasOwnProperty(prop)) { | ||
internals[prop] = value; | ||
} else { | ||
arr[prop] = value; | ||
} | ||
|
||
return true; | ||
} | ||
}); | ||
|
||
return proxy; | ||
} | ||
|
||
function set(i, val, skipModified) { | ||
const arr = this.__array; | ||
if (skipModified) { | ||
arr[i] = val; | ||
return arr; | ||
} | ||
const value = DocumentArrayMethods._cast.call(this, val, i); | ||
arr[i] = value; | ||
DocumentArrayMethods._markModified.call(this, i); | ||
return arr; | ||
} | ||
|
||
/*! | ||
* Module exports. | ||
*/ | ||
|
||
module.exports = MongooseDocumentArray; |
Oops, something went wrong.