1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /* Property and element API. */ 7 8 #ifndef js_PropertyAndElement_h 9 #define js_PropertyAndElement_h 10 11 #include <stddef.h> // size_t 12 #include <stdint.h> // uint32_t 13 14 #include "jstypes.h" // JS_PUBLIC_API 15 16 #include "js/CallArgs.h" // JSNative 17 #include "js/Class.h" // JS::ObjectOpResult 18 #include "js/GCVector.h" // JS::GCVector 19 #include "js/Id.h" // jsid 20 #include "js/PropertyDescriptor.h" // JS::PropertyDescriptor 21 #include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle 22 23 struct JSContext; 24 class JSFunction; 25 class JSObject; 26 class JSString; 27 28 namespace JS { 29 30 using IdVector = JS::GCVector<jsid>; 31 32 } /* namespace JS */ 33 34 /** 35 * Define a property on obj. 36 * 37 * This function uses JS::ObjectOpResult to indicate conditions that ES6 38 * specifies as non-error failures. This is inconvenient at best, so use this 39 * function only if you are implementing a proxy handler's defineProperty() 40 * method. For all other purposes, use one of the many DefineProperty functions 41 * below that throw an exception in all failure cases. 42 * 43 * Implements: ES6 [[DefineOwnProperty]] internal method. 44 */ 45 extern JS_PUBLIC_API bool JS_DefinePropertyById( 46 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 47 JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& result); 48 49 /** 50 * Define a property on obj, throwing a TypeError if the attempt fails. 51 * This is the C++ equivalent of `Object.defineProperty(obj, id, desc)`. 52 */ 53 extern JS_PUBLIC_API bool JS_DefinePropertyById( 54 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 55 JS::Handle<JS::PropertyDescriptor> desc); 56 57 extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, 58 JS::Handle<JSObject*> obj, 59 JS::Handle<jsid> id, 60 JS::Handle<JS::Value> value, 61 unsigned attrs); 62 63 extern JS_PUBLIC_API bool JS_DefinePropertyById( 64 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 65 JSNative getter, JSNative setter, unsigned attrs); 66 67 extern JS_PUBLIC_API bool JS_DefinePropertyById( 68 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 69 JS::Handle<JSObject*> getter, JS::Handle<JSObject*> setter, unsigned attrs); 70 71 extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, 72 JS::Handle<JSObject*> obj, 73 JS::Handle<jsid> id, 74 JS::Handle<JSObject*> value, 75 unsigned attrs); 76 77 extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, 78 JS::Handle<JSObject*> obj, 79 JS::Handle<jsid> id, 80 JS::Handle<JSString*> value, 81 unsigned attrs); 82 83 extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, 84 JS::Handle<JSObject*> obj, 85 JS::Handle<jsid> id, 86 int32_t value, unsigned attrs); 87 88 extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, 89 JS::Handle<JSObject*> obj, 90 JS::Handle<jsid> id, 91 uint32_t value, unsigned attrs); 92 93 extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, 94 JS::Handle<JSObject*> obj, 95 JS::Handle<jsid> id, 96 double value, unsigned attrs); 97 98 extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, 99 JS::Handle<JSObject*> obj, 100 const char* name, 101 JS::Handle<JS::Value> value, 102 unsigned attrs); 103 104 extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, 105 JS::Handle<JSObject*> obj, 106 const char* name, JSNative getter, 107 JSNative setter, unsigned attrs); 108 109 extern JS_PUBLIC_API bool JS_DefineProperty( 110 JSContext* cx, JS::Handle<JSObject*> obj, const char* name, 111 JS::Handle<JSObject*> getter, JS::Handle<JSObject*> setter, unsigned attrs); 112 113 extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, 114 JS::Handle<JSObject*> obj, 115 const char* name, 116 JS::Handle<JSObject*> value, 117 unsigned attrs); 118 119 extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, 120 JS::Handle<JSObject*> obj, 121 const char* name, 122 JS::Handle<JSString*> value, 123 unsigned attrs); 124 125 extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, 126 JS::Handle<JSObject*> obj, 127 const char* name, int32_t value, 128 unsigned attrs); 129 130 extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, 131 JS::Handle<JSObject*> obj, 132 const char* name, uint32_t value, 133 unsigned attrs); 134 135 extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, 136 JS::Handle<JSObject*> obj, 137 const char* name, double value, 138 unsigned attrs); 139 140 extern JS_PUBLIC_API bool JS_DefineUCProperty( 141 JSContext* cx, JS::Handle<JSObject*> obj, const char16_t* name, 142 size_t namelen, JS::Handle<JS::PropertyDescriptor> desc, 143 JS::ObjectOpResult& result); 144 145 extern JS_PUBLIC_API bool JS_DefineUCProperty( 146 JSContext* cx, JS::Handle<JSObject*> obj, const char16_t* name, 147 size_t namelen, JS::Handle<JS::PropertyDescriptor> desc); 148 149 extern JS_PUBLIC_API bool JS_DefineUCProperty( 150 JSContext* cx, JS::Handle<JSObject*> obj, const char16_t* name, 151 size_t namelen, JS::Handle<JS::Value> value, unsigned attrs); 152 153 extern JS_PUBLIC_API bool JS_DefineUCProperty( 154 JSContext* cx, JS::Handle<JSObject*> obj, const char16_t* name, 155 size_t namelen, JS::Handle<JSObject*> getter, JS::Handle<JSObject*> setter, 156 unsigned attrs); 157 158 extern JS_PUBLIC_API bool JS_DefineUCProperty( 159 JSContext* cx, JS::Handle<JSObject*> obj, const char16_t* name, 160 size_t namelen, JS::Handle<JSObject*> value, unsigned attrs); 161 162 extern JS_PUBLIC_API bool JS_DefineUCProperty( 163 JSContext* cx, JS::Handle<JSObject*> obj, const char16_t* name, 164 size_t namelen, JS::Handle<JSString*> value, unsigned attrs); 165 166 extern JS_PUBLIC_API bool JS_DefineUCProperty(JSContext* cx, 167 JS::Handle<JSObject*> obj, 168 const char16_t* name, 169 size_t namelen, int32_t value, 170 unsigned attrs); 171 172 extern JS_PUBLIC_API bool JS_DefineUCProperty(JSContext* cx, 173 JS::Handle<JSObject*> obj, 174 const char16_t* name, 175 size_t namelen, uint32_t value, 176 unsigned attrs); 177 178 extern JS_PUBLIC_API bool JS_DefineUCProperty(JSContext* cx, 179 JS::Handle<JSObject*> obj, 180 const char16_t* name, 181 size_t namelen, double value, 182 unsigned attrs); 183 184 extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, 185 JS::Handle<JSObject*> obj, 186 uint32_t index, 187 JS::Handle<JS::Value> value, 188 unsigned attrs); 189 190 extern JS_PUBLIC_API bool JS_DefineElement( 191 JSContext* cx, JS::Handle<JSObject*> obj, uint32_t index, 192 JS::Handle<JSObject*> getter, JS::Handle<JSObject*> setter, unsigned attrs); 193 194 extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, 195 JS::Handle<JSObject*> obj, 196 uint32_t index, 197 JS::Handle<JSObject*> value, 198 unsigned attrs); 199 200 extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, 201 JS::Handle<JSObject*> obj, 202 uint32_t index, 203 JS::Handle<JSString*> value, 204 unsigned attrs); 205 206 extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, 207 JS::Handle<JSObject*> obj, 208 uint32_t index, int32_t value, 209 unsigned attrs); 210 211 extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, 212 JS::Handle<JSObject*> obj, 213 uint32_t index, uint32_t value, 214 unsigned attrs); 215 216 extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, 217 JS::Handle<JSObject*> obj, 218 uint32_t index, double value, 219 unsigned attrs); 220 221 /** 222 * Compute the expression `id in obj`. 223 * 224 * If obj has an own or inherited property obj[id], set *foundp = true and 225 * return true. If not, set *foundp = false and return true. On error, return 226 * false with an exception pending. 227 * 228 * Implements: ES6 [[Has]] internal method. 229 */ 230 extern JS_PUBLIC_API bool JS_HasPropertyById(JSContext* cx, 231 JS::Handle<JSObject*> obj, 232 JS::Handle<jsid> id, bool* foundp); 233 234 extern JS_PUBLIC_API bool JS_HasProperty(JSContext* cx, 235 JS::Handle<JSObject*> obj, 236 const char* name, bool* foundp); 237 238 extern JS_PUBLIC_API bool JS_HasUCProperty(JSContext* cx, 239 JS::Handle<JSObject*> obj, 240 const char16_t* name, size_t namelen, 241 bool* vp); 242 243 extern JS_PUBLIC_API bool JS_HasElement(JSContext* cx, 244 JS::Handle<JSObject*> obj, 245 uint32_t index, bool* foundp); 246 247 /** 248 * Determine whether obj has an own property with the key `id`. 249 * 250 * Implements: ES6 7.3.11 HasOwnProperty(O, P). 251 */ 252 extern JS_PUBLIC_API bool JS_HasOwnPropertyById(JSContext* cx, 253 JS::Handle<JSObject*> obj, 254 JS::Handle<jsid> id, 255 bool* foundp); 256 257 extern JS_PUBLIC_API bool JS_HasOwnProperty(JSContext* cx, 258 JS::Handle<JSObject*> obj, 259 const char* name, bool* foundp); 260 261 /** 262 * Get the value of the property `obj[id]`, or undefined if no such property 263 * exists. This is the C++ equivalent of `vp = Reflect.get(obj, id, receiver)`. 264 * 265 * Most callers don't need the `receiver` argument. Consider using 266 * JS_GetProperty instead. (But if you're implementing a proxy handler's set() 267 * method, it's often correct to call this function and pass the receiver 268 * through.) 269 * 270 * Implements: ES6 [[Get]] internal method. 271 */ 272 extern JS_PUBLIC_API bool JS_ForwardGetPropertyTo( 273 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 274 JS::Handle<JS::Value> receiver, JS::MutableHandleValue vp); 275 276 extern JS_PUBLIC_API bool JS_ForwardGetElementTo(JSContext* cx, 277 JS::Handle<JSObject*> obj, 278 uint32_t index, 279 JS::Handle<JSObject*> receiver, 280 JS::MutableHandleValue vp); 281 282 /** 283 * Get the value of the property `obj[id]`, or undefined if no such property 284 * exists. The result is stored in vp. 285 * 286 * Implements: ES6 7.3.1 Get(O, P). 287 */ 288 extern JS_PUBLIC_API bool JS_GetPropertyById(JSContext* cx, 289 JS::Handle<JSObject*> obj, 290 JS::Handle<jsid> id, 291 JS::MutableHandleValue vp); 292 293 extern JS_PUBLIC_API bool JS_GetProperty(JSContext* cx, 294 JS::Handle<JSObject*> obj, 295 const char* name, 296 JS::MutableHandleValue vp); 297 298 extern JS_PUBLIC_API bool JS_GetUCProperty(JSContext* cx, 299 JS::Handle<JSObject*> obj, 300 const char16_t* name, size_t namelen, 301 JS::MutableHandleValue vp); 302 303 extern JS_PUBLIC_API bool JS_GetElement(JSContext* cx, 304 JS::Handle<JSObject*> obj, 305 uint32_t index, 306 JS::MutableHandleValue vp); 307 308 /** 309 * Perform the same property assignment as `Reflect.set(obj, id, v, receiver)`. 310 * 311 * This function has a `receiver` argument that most callers don't need. 312 * Consider using JS_SetProperty instead. 313 * 314 * Implements: ES6 [[Set]] internal method. 315 */ 316 extern JS_PUBLIC_API bool JS_ForwardSetPropertyTo( 317 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 318 JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver, 319 JS::ObjectOpResult& result); 320 321 /** 322 * Perform the assignment `obj[id] = v`. 323 * 324 * This function performs non-strict assignment, so if the property is 325 * read-only, nothing happens and no error is thrown. 326 */ 327 extern JS_PUBLIC_API bool JS_SetPropertyById(JSContext* cx, 328 JS::Handle<JSObject*> obj, 329 JS::Handle<jsid> id, 330 JS::Handle<JS::Value> v); 331 332 extern JS_PUBLIC_API bool JS_SetProperty(JSContext* cx, 333 JS::Handle<JSObject*> obj, 334 const char* name, 335 JS::Handle<JS::Value> v); 336 337 extern JS_PUBLIC_API bool JS_SetUCProperty(JSContext* cx, 338 JS::Handle<JSObject*> obj, 339 const char16_t* name, size_t namelen, 340 JS::Handle<JS::Value> v); 341 342 extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, 343 JS::Handle<JSObject*> obj, 344 uint32_t index, 345 JS::Handle<JS::Value> v); 346 347 extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, 348 JS::Handle<JSObject*> obj, 349 uint32_t index, 350 JS::Handle<JSObject*> v); 351 352 extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, 353 JS::Handle<JSObject*> obj, 354 uint32_t index, 355 JS::Handle<JSString*> v); 356 357 extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, 358 JS::Handle<JSObject*> obj, 359 uint32_t index, int32_t v); 360 361 extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, 362 JS::Handle<JSObject*> obj, 363 uint32_t index, uint32_t v); 364 365 extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, 366 JS::Handle<JSObject*> obj, 367 uint32_t index, double v); 368 369 /** 370 * Delete a property. This is the C++ equivalent of 371 * `result = Reflect.deleteProperty(obj, id)`. 372 * 373 * This function has a `result` out parameter that most callers don't need. 374 * Unless you can pass through an ObjectOpResult provided by your caller, it's 375 * probably best to use the JS_DeletePropertyById signature with just 3 376 * arguments. 377 * 378 * Implements: ES6 [[Delete]] internal method. 379 */ 380 extern JS_PUBLIC_API bool JS_DeletePropertyById(JSContext* cx, 381 JS::Handle<JSObject*> obj, 382 JS::Handle<jsid> id, 383 JS::ObjectOpResult& result); 384 385 extern JS_PUBLIC_API bool JS_DeleteProperty(JSContext* cx, 386 JS::Handle<JSObject*> obj, 387 const char* name, 388 JS::ObjectOpResult& result); 389 390 extern JS_PUBLIC_API bool JS_DeleteUCProperty(JSContext* cx, 391 JS::Handle<JSObject*> obj, 392 const char16_t* name, 393 size_t namelen, 394 JS::ObjectOpResult& result); 395 396 extern JS_PUBLIC_API bool JS_DeleteElement(JSContext* cx, 397 JS::Handle<JSObject*> obj, 398 uint32_t index, 399 JS::ObjectOpResult& result); 400 401 /** 402 * Delete a property, ignoring strict failures. This is the C++ equivalent of 403 * the JS `delete obj[id]` in non-strict mode code. 404 */ 405 extern JS_PUBLIC_API bool JS_DeletePropertyById(JSContext* cx, 406 JS::Handle<JSObject*> obj, 407 jsid id); 408 409 extern JS_PUBLIC_API bool JS_DeleteProperty(JSContext* cx, 410 JS::Handle<JSObject*> obj, 411 const char* name); 412 413 extern JS_PUBLIC_API bool JS_DeleteElement(JSContext* cx, 414 JS::Handle<JSObject*> obj, 415 uint32_t index); 416 417 /** 418 * Get an array of the non-symbol enumerable properties of obj. 419 * This function is roughly equivalent to: 420 * 421 * var result = []; 422 * for (key in obj) { 423 * result.push(key); 424 * } 425 * return result; 426 * 427 * This is the closest thing we currently have to the ES6 [[Enumerate]] 428 * internal method. 429 * 430 * The array of ids returned by JS_Enumerate must be rooted to protect its 431 * contents from garbage collection. Use JS::Rooted<JS::IdVector>. 432 */ 433 extern JS_PUBLIC_API bool JS_Enumerate(JSContext* cx, JS::Handle<JSObject*> obj, 434 JS::MutableHandle<JS::IdVector> props); 435 436 /*** Other property-defining functions **************************************/ 437 438 extern JS_PUBLIC_API JSObject* JS_DefineObject(JSContext* cx, 439 JS::Handle<JSObject*> obj, 440 const char* name, 441 const JSClass* clasp = nullptr, 442 unsigned attrs = 0); 443 444 extern JS_PUBLIC_API bool JS_DefineProperties(JSContext* cx, 445 JS::Handle<JSObject*> obj, 446 const JSPropertySpec* ps); 447 448 /* * */ 449 450 extern JS_PUBLIC_API bool JS_AlreadyHasOwnPropertyById( 451 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 452 bool* foundp); 453 454 extern JS_PUBLIC_API bool JS_AlreadyHasOwnProperty(JSContext* cx, 455 JS::Handle<JSObject*> obj, 456 const char* name, 457 bool* foundp); 458 459 extern JS_PUBLIC_API bool JS_AlreadyHasOwnUCProperty(JSContext* cx, 460 JS::Handle<JSObject*> obj, 461 const char16_t* name, 462 size_t namelen, 463 bool* foundp); 464 465 extern JS_PUBLIC_API bool JS_AlreadyHasOwnElement(JSContext* cx, 466 JS::Handle<JSObject*> obj, 467 uint32_t index, bool* foundp); 468 469 extern JS_PUBLIC_API bool JS_DefineFunctions(JSContext* cx, 470 JS::Handle<JSObject*> obj, 471 const JSFunctionSpec* fs); 472 473 extern JS_PUBLIC_API JSFunction* JS_DefineFunction( 474 JSContext* cx, JS::Handle<JSObject*> obj, const char* name, JSNative call, 475 unsigned nargs, unsigned attrs); 476 477 extern JS_PUBLIC_API JSFunction* JS_DefineUCFunction( 478 JSContext* cx, JS::Handle<JSObject*> obj, const char16_t* name, 479 size_t namelen, JSNative call, unsigned nargs, unsigned attrs); 480 481 extern JS_PUBLIC_API JSFunction* JS_DefineFunctionById( 482 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 483 JSNative call, unsigned nargs, unsigned attrs); 484 485 #endif /* js_PropertyAndElement_h */ 486