summaryrefslogtreecommitdiff
path: root/jstests/core/js_object_properties.js
blob: 8c42fb5b208375df7c5ef06bc9e2c1c4539296c9 (plain)
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 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());
}());