testLookup.cpp (3140B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "js/PropertyAndElement.h" // JS_DefineProperty, JS_DefinePropertyById, JS_GetProperty 9 #include "jsapi-tests/tests.h" 10 #include "vm/JSFunction.h" // for js::IsInternalFunctionObject 11 12 #include "vm/JSObject-inl.h" 13 14 BEGIN_TEST(testLookup_bug522590) { 15 // Define a function that makes method-bearing objects. 16 JS::RootedValue x(cx); 17 EXEC("function mkobj() { return {f: function () {return 2;}} }"); 18 19 // Calling mkobj() multiple times must create multiple functions in ES5. 20 EVAL("mkobj().f !== mkobj().f", &x); 21 CHECK(x.isTrue()); 22 23 // Now make x.f a method. 24 EVAL("mkobj()", &x); 25 JS::RootedObject xobj(cx, x.toObjectOrNull()); 26 27 // This lookup must not return an internal function object. 28 JS::RootedValue r(cx); 29 CHECK(JS_GetProperty(cx, xobj, "f", &r)); 30 CHECK(r.isObject()); 31 JSObject* funobj = &r.toObject(); 32 CHECK(funobj->is<JSFunction>()); 33 CHECK(!js::IsInternalFunctionObject(*funobj)); 34 35 return true; 36 } 37 END_TEST(testLookup_bug522590) 38 39 static const JSClass DocumentAllClass = { 40 "DocumentAll", 41 JSCLASS_EMULATES_UNDEFINED, 42 }; 43 44 bool document_resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, 45 bool* resolvedp) { 46 // If id is "all", resolve document.all=true. 47 JS::RootedValue v(cx); 48 if (!JS_IdToValue(cx, id, &v)) { 49 return false; 50 } 51 52 if (v.isString()) { 53 JSString* str = v.toString(); 54 JSLinearString* linearStr = JS_EnsureLinearString(cx, str); 55 if (!linearStr) { 56 return false; 57 } 58 if (JS_LinearStringEqualsLiteral(linearStr, "all")) { 59 JS::Rooted<JSObject*> docAll(cx, JS_NewObject(cx, &DocumentAllClass)); 60 if (!docAll) { 61 return false; 62 } 63 64 JS::Rooted<JS::Value> allValue(cx, JS::ObjectValue(*docAll)); 65 if (!JS_DefinePropertyById(cx, obj, id, allValue, JSPROP_RESOLVING)) { 66 return false; 67 } 68 69 *resolvedp = true; 70 return true; 71 } 72 } 73 74 *resolvedp = false; 75 return true; 76 } 77 78 static const JSClassOps document_classOps = { 79 nullptr, // addProperty 80 nullptr, // delProperty 81 nullptr, // enumerate 82 nullptr, // newEnumerate 83 document_resolve, // resolve 84 nullptr, // mayResolve 85 nullptr, // finalize 86 nullptr, // call 87 nullptr, // construct 88 nullptr, // trace 89 }; 90 91 static const JSClass document_class = { 92 "document", 93 0, 94 &document_classOps, 95 }; 96 97 BEGIN_TEST(testLookup_bug570195) { 98 JS::RootedObject obj(cx, JS_NewObject(cx, &document_class)); 99 CHECK(obj); 100 CHECK(JS_DefineProperty(cx, global, "document", obj, 0)); 101 JS::RootedValue v(cx); 102 EVAL("document.all ? true : false", &v); 103 CHECK(v.isFalse()); 104 EVAL("document.hasOwnProperty('all')", &v); 105 CHECK(v.isTrue()); 106 return true; 107 } 108 END_TEST(testLookup_bug570195)