1// Copyright JS Foundation and other contributors, http://js.foundation 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Copyright 2015 the V8 project authors. All rights reserved. 16// Use of this source code is governed by a BSD-style license that can be 17// found in the LICENSE file. 18 19var target = {}; 20var handler = { getOwnPropertyDescriptor (target) { 21 throw "cat"; 22}}; 23 24var proxy = new Proxy(target, handler); 25 26try { 27 // 19.1.3.2.5 28 Object.prototype.hasOwnProperty.call(proxy); 29 assert(false); 30} catch(e) { 31 assert(e == "cat"); 32} 33 34try { 35 // 19.1.3.4 36 Object.prototype.propertyIsEnumerable.call(proxy) 37 assert(false); 38} catch(e) { 39 assert(e == "cat"); 40} 41 42try { 43 // 19.1.2.6.5 44 Object.getOwnPropertyDescriptor(proxy) 45 assert(false); 46} catch(e) { 47 assert(e == "cat"); 48} 49 50var target = {}; 51var configurable_desc = { 52 value: 123, 53 configurable: true, 54 writable: true, 55 enumerable: false, 56}; 57Object.defineProperty(target, "configurable", configurable_desc); 58 59var nonconfigurable_desc = { 60 value: 234, 61 configurable: false, 62 writable: false, 63 enumerable: true 64} 65Object.defineProperty(target, "nonconfigurable", nonconfigurable_desc); 66 67var proxied_desc = { 68 value: 345, 69 configurable: true 70}; 71 72var proxied_desc = { 73 value: 345, 74 configurable: true 75}; 76 77var handler = { 78 "getOwnPropertyDescriptor": function(target, name) { 79 if (name === "proxied") { 80 return proxied_desc; 81 } 82 if (name === "return_null") { 83 return null; 84 } 85 return Object.getOwnPropertyDescriptor(target, name); 86 } 87}; 88 89var proxy = new Proxy(target, handler); 90var proxy_without_handler = new Proxy(target, {}); 91 92// Checking basic functionality: 93 94var configurable_obj = Object.getOwnPropertyDescriptor(proxy, "configurable"); 95 96assert(configurable_desc.value == configurable_obj.value); 97assert(configurable_desc.configurable == configurable_obj.configurable); 98assert(configurable_desc.writable == configurable_obj.writable); 99assert(configurable_desc.enumerable == configurable_obj.enumerable); 100 101var nonconfigurable_obj = Object.getOwnPropertyDescriptor(proxy, "nonconfigurable"); 102assert(nonconfigurable_obj.value == nonconfigurable_desc.value); 103assert(nonconfigurable_obj.configurable == nonconfigurable_desc.configurable); 104assert(nonconfigurable_obj.writable == nonconfigurable_desc.writable); 105assert(nonconfigurable_obj.enumerable == nonconfigurable_desc.enumerable); 106 107var other_obj = { value: proxied_desc.value, 108 configurable: proxied_desc.configurable, 109 enumerable: false, 110 writable: false } 111var proxied_obj = Object.getOwnPropertyDescriptor(proxy, "proxied"); 112 113assert(other_obj.value == proxied_obj.value); 114assert(other_obj.configurable == proxied_obj.configurable); 115assert(other_obj.writable == proxied_obj.writable); 116assert(other_obj.enumerable == proxied_obj.enumerable); 117 118var other_obj2 = Object.getOwnPropertyDescriptor(proxy_without_handler, "configurable"); 119 120assert(other_obj2.value == configurable_desc.value); 121assert(other_obj2.configurable == configurable_desc.configurable); 122assert(other_obj2.writable == configurable_desc.writable); 123assert(other_obj2.enumerable == configurable_desc.enumerable); 124 125var other_obj3 = Object.getOwnPropertyDescriptor(proxy_without_handler, "nonconfigurable"); 126 127assert(other_obj3.value == nonconfigurable_desc.value); 128assert(other_obj3.configurable == nonconfigurable_desc.configurable); 129assert(other_obj3.writable == nonconfigurable_desc.writable); 130assert(other_obj3.enumerable == nonconfigurable_desc.enumerable); 131 132try { 133 Object.getOwnPropertyDescriptor(proxy, "return_null"); 134 assert(false); 135} catch(e) { 136 assert(e instanceof TypeError); 137} 138 139// Checking invariants mentioned explicitly by the ES spec: 140 141// (Inv-1) "A property cannot be reported as non-existent, if it exists as a 142// non-configurable own property of the target object." 143handler.getOwnPropertyDescriptor = function(target, name) { return undefined; }; 144 145try { 146 Object.getOwnPropertyDescriptor(proxy, "nonconfigurable"); 147 assert(false); 148} catch(e) { 149 assert(e instanceof TypeError); 150} 151 152assert(Object.getOwnPropertyDescriptor(proxy, "configurable") == undefined) 153 154// (Inv-2) "A property cannot be reported as non-configurable, if it does not 155// exist as an own property of the target object or if it exists as a 156// configurable own property of the target object." 157handler.getOwnPropertyDescriptor = function(target, name) { 158 return {value: 234, configurable: false, enumerable: true}; 159}; 160 161try { 162 Object.getOwnPropertyDescriptor(proxy, "nonexistent"); 163 assert(false); 164} catch(e) { 165 assert(e instanceof TypeError); 166} 167 168try { 169 Object.getOwnPropertyDescriptor(proxy, "configurable"); 170 assert(false); 171} catch(e) { 172 assert(e instanceof TypeError); 173} 174 175assert(!Object.getOwnPropertyDescriptor(proxy, "nonconfigurable").configurable); 176 177// (Inv-3) "A property cannot be reported as non-existent, if it exists as an 178// own property of the target object and the target object is not extensible." 179Object.seal(target); 180handler.getOwnPropertyDescriptor = function(target, name) { return undefined; }; 181 182try { 183 Object.getOwnPropertyDescriptor(proxy, "configurable"); 184 assert(false); 185} catch(e) { 186 assert(e instanceof TypeError); 187} 188 189try { 190 Object.getOwnPropertyDescriptor(proxy, "nonconfigurable"); 191 assert(false); 192} catch(e) { 193 assert(e instanceof TypeError); 194} 195 196assert(undefined == Object.getOwnPropertyDescriptor(proxy, "nonexistent")); 197 198// (Inv-4) "A property cannot be reported as existent, if it does not exist as 199// an own property of the target object and the target object is not 200// extensible." 201var existent_desc = {value: "yes"}; 202handler.getOwnPropertyDescriptor = function() { return existent_desc; }; 203 204try { 205 Object.getOwnPropertyDescriptor(proxy, "nonexistent"); 206 assert(false); 207} catch(e) { 208 assert(e instanceof TypeError); 209} 210 211var new_obj = { value: "yes", 212 writable: false, 213 enumerable: false, 214 configurable: false }; 215var conf_proxied = Object.getOwnPropertyDescriptor(proxy, "configurable"); 216 217assert(new_obj.value == conf_proxied.value); 218assert(new_obj.configurable == conf_proxied.configurable); 219assert(new_obj.writable == conf_proxied.writable); 220assert(new_obj.enumerable == conf_proxied.enumerable); 221 222// Checking individual bailout points in the implementation: 223 224// Step 6: Trap is not callable. 225handler.getOwnPropertyDescriptor = {}; 226 227try { 228 Object.getOwnPropertyDescriptor(proxy, "configurable"); 229 assert(false); 230} catch(e) { 231 assert(e instanceof TypeError); 232} 233 234// Step 8: Trap throws. 235handler.getOwnPropertyDescriptor = function() { throw "unicorn"; }; 236 237try { 238 Object.getOwnPropertyDescriptor(proxy, "configurable"); 239 assert(false); 240} catch(e) { 241 assert(e == "unicorn"); 242} 243 244// Step 9: Trap result is neither undefined nor an object. 245handler.getOwnPropertyDescriptor = function() { return 1; } 246 247try { 248 Object.getOwnPropertyDescriptor(proxy, "configurable"); 249 assert(false); 250} catch(e) { 251 assert(e instanceof TypeError); 252} 253 254// Step 11b: See (Inv-1) above. 255// Step 11e: See (Inv-3) above. 256 257// Step 16: Incompatible PropertyDescriptor; a non-configurable property 258// cannot be reported as configurable. (Inv-4) above checks more cases. 259handler.getOwnPropertyDescriptor = function(target, name) { 260 return {value: 456, configurable: true, writable: true} 261}; 262 263try { 264 Object.getOwnPropertyDescriptor(proxy, "nonconfigurable"); 265 assert(false); 266} catch(e) { 267 assert(e instanceof TypeError); 268} 269 270// Step 17: See (Inv-2) above. 271