133 lines
5.0 KiB
JavaScript
133 lines
5.0 KiB
JavaScript
// Tests that the properties available on the 'this' object during js execution are only those found
|
|
// in the database's BSON object.
|
|
// @tags: [
|
|
// # mapReduce does not support afterClusterTime.
|
|
// does_not_support_causal_consistency,
|
|
// ]
|
|
(function() {
|
|
"use strict";
|
|
|
|
load("jstests/aggregation/extras/utils.js"); // For 'resultsEq'.
|
|
|
|
const testDB = db.getSiblingDB("js_object_properties");
|
|
const coll = testDB.test;
|
|
coll.drop();
|
|
|
|
assert.commandWorked(coll.insert({_id: 0, a: 1}));
|
|
|
|
// Test that $where cannot see any other properties.
|
|
assert.eq(1,
|
|
coll.find({
|
|
$where: function() {
|
|
const properties = new Set(Object.getOwnPropertyNames(this));
|
|
return properties.has("_id") && properties.has("a") && properties.size == 2;
|
|
}
|
|
})
|
|
.itcount());
|
|
|
|
// Test that $function cannot see any other properties.
|
|
assert.eq([{field: "_id"}, {field: "a"}],
|
|
coll.aggregate([
|
|
{
|
|
$replaceWith: {
|
|
field: {
|
|
$function: {
|
|
lang: "js",
|
|
args: ["$$ROOT"],
|
|
body: "function(obj) { return Object.getOwnPropertyNames(obj); }"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{$unwind: "$field"},
|
|
{$sort: {field: 1}},
|
|
])
|
|
.toArray());
|
|
|
|
// Test that the 'this' object doesn't have any properties in $function.
|
|
assert.eq([],
|
|
coll.aggregate([
|
|
{
|
|
$replaceWith: {
|
|
field: {
|
|
$function: {
|
|
lang: "js",
|
|
args: ["$$ROOT"],
|
|
body: "function(obj) { return Object.getOwnPropertyNames(this); }"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{$unwind: "$field"},
|
|
{$sort: {field: 1}},
|
|
])
|
|
.toArray());
|
|
|
|
// Test that mapReduce's 'map' function cannot see any other properties.
|
|
assert(resultsEq([{_id: "_id", value: 1}, {_id: "a", value: 1}],
|
|
assert
|
|
.commandWorked(coll.mapReduce(
|
|
function map() {
|
|
for (let prop of Object.getOwnPropertyNames(this)) {
|
|
emit(prop, 1);
|
|
}
|
|
},
|
|
function reduce(key, values) {
|
|
return Array.sum(values);
|
|
},
|
|
{out: {inline: 1}}))
|
|
.results));
|
|
|
|
// Test that mapReduce's 'reduce' function cannot see any other properties.
|
|
assert.eq([{_id: 0, value: []}],
|
|
assert
|
|
.commandWorked(coll.mapReduce(
|
|
function map() {
|
|
emit(this._id, "ignored");
|
|
},
|
|
function reduce(key, values) {
|
|
return Object.getOwnPropertyNames(this);
|
|
},
|
|
{out: {inline: 1}}))
|
|
.results);
|
|
|
|
assert.commandWorked(coll.insert({_id: 1, b: 1}));
|
|
|
|
// Test that $jsReduce cannot see any properties other than those on the backing db object.
|
|
assert.eq([{field: "_id"}, {field: "a"}, {field: "b"}],
|
|
coll.aggregate([
|
|
{
|
|
$group: {
|
|
_id: null,
|
|
field: {
|
|
$accumulator: {
|
|
init: function() {
|
|
return [];
|
|
},
|
|
accumulate: function acc(state, newObj) {
|
|
let stateSet = new Set(state);
|
|
for (let prop of Object.getOwnPropertyNames(newObj)) {
|
|
stateSet.add(prop);
|
|
}
|
|
return [...stateSet];
|
|
},
|
|
accumulateArgs: ["$$ROOT"],
|
|
merge: function merge(state1, state2) {
|
|
let newState = new Set(state1);
|
|
for (let elem of state2) {
|
|
newState.add(elem);
|
|
}
|
|
return [...newState];
|
|
},
|
|
lang: "js"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{$unset: "_id"},
|
|
{$unwind: "$field"},
|
|
{$sort: {field: 1}},
|
|
])
|
|
.toArray());
|
|
}());
|