LCOV - code coverage report
Current view: directory - js/src/vm - GlobalObject.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 221 177 80.1 %
Date: 2012-06-02 Functions: 18 16 88.9 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=99:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is SpiderMonkey global object code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * the Mozilla Foundation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2011
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Jeff Walden <jwalden+code@mit.edu> (original author)
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "GlobalObject.h"
      42                 : 
      43                 : #include "jscntxt.h"
      44                 : #include "jsexn.h"
      45                 : #include "jsmath.h"
      46                 : #include "json.h"
      47                 : #include "jsweakmap.h"
      48                 : 
      49                 : #include "builtin/MapObject.h"
      50                 : #include "builtin/RegExp.h"
      51                 : #include "frontend/BytecodeEmitter.h"
      52                 : #include "vm/GlobalObject-inl.h"
      53                 : 
      54                 : #include "jsobjinlines.h"
      55                 : #include "vm/RegExpObject-inl.h"
      56                 : #include "vm/RegExpStatics-inl.h"
      57                 : 
      58                 : #ifdef JS_METHODJIT
      59                 : #include "methodjit/Retcon.h"
      60                 : #endif
      61                 : 
      62                 : using namespace js;
      63                 : 
      64                 : JSObject *
      65           22858 : js_InitObjectClass(JSContext *cx, JSObject *obj)
      66                 : {
      67           22858 :     JS_ASSERT(obj->isNative());
      68                 : 
      69           22858 :     return obj->asGlobal().getOrCreateObjectPrototype(cx);
      70                 : }
      71                 : 
      72                 : JSObject *
      73              16 : js_InitFunctionClass(JSContext *cx, JSObject *obj)
      74                 : {
      75              16 :     JS_ASSERT(obj->isNative());
      76                 : 
      77              16 :     return obj->asGlobal().getOrCreateFunctionPrototype(cx);
      78                 : }
      79                 : 
      80                 : static JSBool
      81               0 : ThrowTypeError(JSContext *cx, unsigned argc, Value *vp)
      82                 : {
      83                 :     JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
      84               0 :                                  JSMSG_THROW_TYPE_ERROR);
      85               0 :     return false;
      86                 : }
      87                 : 
      88                 : namespace js {
      89                 : 
      90                 : JSObject *
      91           38637 : GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
      92                 : {
      93           77274 :     RootedVar<GlobalObject*> self(cx, this);
      94                 : 
      95           38637 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
      96           38637 :     JS_ASSERT(isNative());
      97                 : 
      98                 :     /*
      99                 :      * Calling a function from a cleared global triggers this (yeah, I know).
     100                 :      * Uncomment this once bug 470510 is fixed (if that bug doesn't remove
     101                 :      * isCleared entirely).
     102                 :      */
     103                 :     // JS_ASSERT(!isCleared());
     104                 : 
     105                 :     /* If cx has no global object, make this the global object. */
     106           38637 :     if (!cx->globalObject)
     107           31622 :         JS_SetGlobalObject(cx, self);
     108                 : 
     109           77274 :     RootedVarObject objectProto(cx);
     110                 : 
     111                 :     /*
     112                 :      * Create |Object.prototype| first, mirroring CreateBlankProto but for the
     113                 :      * prototype of the created object.
     114                 :      */
     115           38637 :     objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, self);
     116           38637 :     if (!objectProto || !objectProto->setSingletonType(cx))
     117               0 :         return NULL;
     118                 : 
     119                 :     /*
     120                 :      * The default 'new' type of Object.prototype is required by type inference
     121                 :      * to have unknown properties, to simplify handling of e.g. heterogenous
     122                 :      * objects in JSON and script literals.
     123                 :      */
     124           38637 :     if (!objectProto->setNewTypeUnknown(cx))
     125               0 :         return NULL;
     126                 : 
     127                 :     /* Create |Function.prototype| next so we can create other functions. */
     128           77274 :     RootedVarFunction functionProto(cx);
     129                 :     {
     130           38637 :         JSObject *functionProto_ = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, self);
     131           38637 :         if (!functionProto_)
     132               0 :             return NULL;
     133           38637 :         functionProto = functionProto_->toFunction();
     134                 : 
     135                 :         /*
     136                 :          * Bizarrely, |Function.prototype| must be an interpreted function, so
     137                 :          * give it the guts to be one.
     138                 :          */
     139                 :         JSObject *proto = js_NewFunction(cx, functionProto,
     140           38637 :                                          NULL, 0, JSFUN_INTERPRETED, self, NULL);
     141           38637 :         if (!proto)
     142               0 :             return NULL;
     143           38637 :         JS_ASSERT(proto == functionProto);
     144           38637 :         functionProto->flags |= JSFUN_PROTOTYPE;
     145                 : 
     146                 :         JSScript *script =
     147           38637 :             JSScript::NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, JSVERSION_DEFAULT);
     148           38637 :         if (!script)
     149               0 :             return NULL;
     150           38637 :         script->noScriptRval = true;
     151           38637 :         script->code[0] = JSOP_STOP;
     152           38637 :         script->code[1] = SRC_NULL;
     153           38637 :         functionProto->initScript(script);
     154           38637 :         functionProto->getType(cx)->interpretedFunction = functionProto;
     155           38637 :         script->setFunction(functionProto);
     156                 : 
     157           38637 :         if (!functionProto->setSingletonType(cx))
     158               0 :             return NULL;
     159                 : 
     160                 :         /*
     161                 :          * The default 'new' type of Function.prototype is required by type
     162                 :          * inference to have unknown properties, to simplify handling of e.g.
     163                 :          * CloneFunctionObject.
     164                 :          */
     165           38637 :         if (!functionProto->setNewTypeUnknown(cx))
     166               0 :             return NULL;
     167                 :     }
     168                 : 
     169                 :     /* Create the Object function now that we have a [[Prototype]] for it. */
     170           77274 :     RootedVarFunction objectCtor(cx);
     171                 :     {
     172           38637 :         JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
     173           38637 :         if (!ctor)
     174               0 :             return NULL;
     175                 :         objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, self,
     176           38637 :                                     CLASS_ATOM(cx, Object));
     177           38637 :         if (!objectCtor)
     178               0 :             return NULL;
     179                 : 
     180           38637 :         objectCtor->setConstructorClass(&ObjectClass);
     181                 :     }
     182                 : 
     183                 :     /*
     184                 :      * Install |Object| and |Object.prototype| for the benefit of subsequent
     185                 :      * code that looks for them.
     186                 :      */
     187           38637 :     self->setObjectClassDetails(objectCtor, objectProto);
     188                 : 
     189                 :     /* Create |Function| so it and |Function.prototype| can be installed. */
     190           77274 :     RootedVarFunction functionCtor(cx);
     191                 :     {
     192                 :         JSObject *ctor =
     193           38637 :             NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
     194           38637 :         if (!ctor)
     195               0 :             return NULL;
     196                 :         functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self,
     197           38637 :                                       CLASS_ATOM(cx, Function));
     198           38637 :         if (!functionCtor)
     199               0 :             return NULL;
     200           38637 :         JS_ASSERT(ctor == functionCtor);
     201                 : 
     202           38637 :         functionCtor->setConstructorClass(&FunctionClass);
     203                 :     }
     204                 : 
     205                 :     /*
     206                 :      * Install |Function| and |Function.prototype| so that we can freely create
     207                 :      * functions and objects without special effort.
     208                 :      */
     209           38637 :     self->setFunctionClassDetails(functionCtor, functionProto);
     210                 : 
     211                 :     /*
     212                 :      * The hard part's done: now go back and add all the properties these
     213                 :      * primordial values have.
     214                 :      */
     215          231822 :     if (!LinkConstructorAndPrototype(cx, objectCtor, objectProto) ||
     216           38637 :         !DefinePropertiesAndBrand(cx, objectProto, object_props, object_methods) ||
     217           38637 :         !DefinePropertiesAndBrand(cx, objectCtor, NULL, object_static_methods) ||
     218           38637 :         !LinkConstructorAndPrototype(cx, functionCtor, functionProto) ||
     219           38637 :         !DefinePropertiesAndBrand(cx, functionProto, NULL, function_methods) ||
     220           38637 :         !DefinePropertiesAndBrand(cx, functionCtor, NULL, NULL))
     221                 :     {
     222               0 :         return NULL;
     223                 :     }
     224                 : 
     225                 :     /* Add the global Function and Object properties now. */
     226           38637 :     jsid objectId = ATOM_TO_JSID(CLASS_ATOM(cx, Object));
     227           38637 :     if (!self->addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0))
     228               0 :         return NULL;
     229           38637 :     jsid functionId = ATOM_TO_JSID(CLASS_ATOM(cx, Function));
     230           38637 :     if (!self->addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0))
     231               0 :         return NULL;
     232                 : 
     233                 :     /* Heavy lifting done, but lingering tasks remain. */
     234                 : 
     235                 :     /* ES5 15.1.2.1. */
     236           38637 :     jsid id = ATOM_TO_JSID(cx->runtime->atomState.evalAtom);
     237           38637 :     JSObject *evalobj = js_DefineFunction(cx, self, id, eval, 1, JSFUN_STUB_GSOPS);
     238           38637 :     if (!evalobj)
     239               0 :         return NULL;
     240           38637 :     self->setOriginalEval(evalobj);
     241                 : 
     242                 :     /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
     243           77274 :     RootedVarFunction throwTypeError(cx);
     244           38637 :     throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL);
     245           38637 :     if (!throwTypeError)
     246               0 :         return NULL;
     247           77274 :     AutoIdVector ids(cx);
     248           38637 :     if (!throwTypeError->preventExtensions(cx, &ids))
     249               0 :         return NULL;
     250           38637 :     self->setThrowTypeError(throwTypeError);
     251                 : 
     252                 :     /*
     253                 :      * The global object should have |Object.prototype| as its [[Prototype]].
     254                 :      * Eventually we'd like to have standard classes be there from the start,
     255                 :      * and thus we would know we were always setting what had previously been a
     256                 :      * null [[Prototype]], but right now some code assumes it can set the
     257                 :      * [[Prototype]] before standard classes have been initialized.  For now,
     258                 :      * only set the [[Prototype]] if it hasn't already been set.
     259                 :      */
     260           38637 :     if (self->shouldSplicePrototype(cx) && !self->splicePrototype(cx, objectProto))
     261               0 :         return NULL;
     262                 : 
     263                 :     /*
     264                 :      * Notify any debuggers about the creation of the script for
     265                 :      * |Function.prototype| -- after all initialization, for simplicity.
     266                 :      */
     267           38637 :     js_CallNewScriptHook(cx, functionProto->script(), functionProto);
     268           38637 :     return functionProto;
     269                 : }
     270                 : 
     271                 : GlobalObject *
     272           38635 : GlobalObject::create(JSContext *cx, Class *clasp)
     273                 : {
     274           38635 :     JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
     275                 : 
     276           77270 :     RootedVar<GlobalObject*> obj(cx);
     277                 : 
     278           38635 :     JSObject *obj_ = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
     279           38635 :     if (!obj_)
     280               0 :         return NULL;
     281           38635 :     obj = &obj_->asGlobal();
     282                 : 
     283           38635 :     if (!obj->setSingletonType(cx) || !obj->setVarObj(cx))
     284               0 :         return NULL;
     285                 : 
     286                 :     /* Construct a regexp statics object for this global object. */
     287           38635 :     JSObject *res = RegExpStatics::create(cx, obj);
     288           38635 :     if (!res)
     289               0 :         return NULL;
     290           38635 :     obj->initSlot(REGEXP_STATICS, ObjectValue(*res));
     291           38635 :     obj->initFlags(0);
     292                 : 
     293           38635 :     return obj;
     294                 : }
     295                 : 
     296                 : bool
     297             533 : GlobalObject::initStandardClasses(JSContext *cx)
     298                 : {
     299             533 :     JSAtomState &state = cx->runtime->atomState;
     300                 : 
     301                 :     /* Define a top-level property 'undefined' with the undefined value. */
     302             533 :     if (!defineProperty(cx, state.typeAtoms[JSTYPE_VOID], UndefinedValue(),
     303             533 :                         JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY))
     304                 :     {
     305               0 :         return false;
     306                 :     }
     307                 : 
     308             533 :     if (!initFunctionAndObjectClasses(cx))
     309               0 :         return false;
     310                 : 
     311                 :     /* Initialize the rest of the standard objects and functions. */
     312             533 :     return js_InitArrayClass(cx, this) &&
     313             533 :            js_InitBooleanClass(cx, this) &&
     314             533 :            js_InitExceptionClasses(cx, this) &&
     315             533 :            js_InitMathClass(cx, this) &&
     316             533 :            js_InitNumberClass(cx, this) &&
     317             533 :            js_InitJSONClass(cx, this) &&
     318             533 :            js_InitRegExpClass(cx, this) &&
     319             533 :            js_InitStringClass(cx, this) &&
     320             533 :            js_InitTypedArrayClasses(cx, this) &&
     321                 : #if JS_HAS_XML_SUPPORT
     322             533 :            js_InitXMLClasses(cx, this) &&
     323                 : #endif
     324                 : #if JS_HAS_GENERATORS
     325             533 :            js_InitIteratorClasses(cx, this) &&
     326                 : #endif
     327             533 :            js_InitDateClass(cx, this) &&
     328             533 :            js_InitWeakMapClass(cx, this) &&
     329             533 :            js_InitProxyClass(cx, this) &&
     330             533 :            js_InitMapClass(cx, this) &&
     331            7995 :            js_InitSetClass(cx, this);
     332                 : }
     333                 : 
     334                 : void
     335           13212 : GlobalObject::clear(JSContext *cx)
     336                 : {
     337         1559016 :     for (int key = JSProto_Null; key < JSProto_LIMIT * 3; key++)
     338         1545804 :         setSlot(key, UndefinedValue());
     339                 : 
     340                 :     /* Clear regexp statics. */
     341           13212 :     getRegExpStatics()->clear();
     342                 : 
     343                 :     /* Clear the runtime-codegen-enabled cache. */
     344           13212 :     setSlot(RUNTIME_CODEGEN_ENABLED, UndefinedValue());
     345                 : 
     346                 :     /*
     347                 :      * Clear the original-eval and [[ThrowTypeError]] slots, in case throwing
     348                 :      * trying to execute a script for this global must reinitialize standard
     349                 :      * classes.  See bug 470150.
     350                 :      */
     351           13212 :     setSlot(EVAL, UndefinedValue());
     352           13212 :     setSlot(THROWTYPEERROR, UndefinedValue());
     353                 : 
     354                 :     /*
     355                 :      * Mark global as cleared. If we try to execute any compile-and-go
     356                 :      * scripts from here on, we will throw.
     357                 :      */
     358           13212 :     int32_t flags = getSlot(FLAGS).toInt32();
     359           13212 :     flags |= FLAGS_CLEARED;
     360           13212 :     setSlot(FLAGS, Int32Value(flags));
     361                 : 
     362                 :     /*
     363                 :      * Reset the new object cache in the compartment, which assumes that
     364                 :      * prototypes cached on the global object are immutable.
     365                 :      */
     366           13212 :     cx->compartment->newObjectCache.reset();
     367                 : 
     368                 : #ifdef JS_METHODJIT
     369                 :     /*
     370                 :      * Destroy compiled code for any scripts parented to this global. Call ICs
     371                 :      * can directly call scripts which have associated JIT code, and do so
     372                 :      * without checking whether the script's global has been cleared.
     373                 :      */
     374        12306111 :     for (gc::CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
     375        12292899 :         JSScript *script = i.get<JSScript>();
     376        12292899 :         if (script->compileAndGo && script->hasJITCode() && script->hasClearedGlobal()) {
     377               3 :             mjit::Recompiler::clearStackReferences(cx, script);
     378               3 :             mjit::ReleaseScriptCode(cx, script);
     379                 :         }
     380                 :     }
     381                 : #endif
     382           13212 : }
     383                 : 
     384                 : bool
     385          108318 : GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
     386                 : {
     387          108318 :     HeapSlot &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
     388          108318 :     if (v.isUndefined()) {
     389                 :         /*
     390                 :          * If there are callbacks, make sure that the CSP callback is installed
     391                 :          * and that it permits runtime code generation, then cache the result.
     392                 :          */
     393            5253 :         JSCSPEvalChecker allows = cx->runtime->securityCallbacks->contentSecurityPolicyAllows;
     394            5253 :         v.set(this, RUNTIME_CODEGEN_ENABLED, BooleanValue(!allows || allows(cx)));
     395                 :     }
     396          108318 :     return !v.isFalse();
     397                 : }
     398                 : 
     399                 : JSFunction *
     400          111277 : GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom *name,
     401                 :                                 unsigned length, gc::AllocKind kind)
     402                 : {
     403          222554 :     RootedVarObject self(cx, this);
     404                 : 
     405                 :     JSFunction *fun = js_NewFunction(cx, NULL, ctor, length,
     406          111277 :                                      JSFUN_CONSTRUCTOR, self, name, kind);
     407          111277 :     if (!fun)
     408               0 :         return NULL;
     409                 : 
     410                 :     /*
     411                 :      * Remember the class this function is a constructor for so that we know to
     412                 :      * create an object of this class when we call the constructor.
     413                 :      */
     414          111277 :     fun->setConstructorClass(clasp);
     415          111277 :     return fun;
     416                 : }
     417                 : 
     418                 : static JSObject *
     419          116291 : CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
     420                 : {
     421          116291 :     JS_ASSERT(clasp != &ObjectClass);
     422          116291 :     JS_ASSERT(clasp != &FunctionClass);
     423                 : 
     424          116291 :     JSObject *blankProto = NewObjectWithGivenProto(cx, clasp, &proto, &global);
     425          116291 :     if (!blankProto || !blankProto->setSingletonType(cx))
     426               0 :         return NULL;
     427                 : 
     428          116291 :     return blankProto;
     429                 : }
     430                 : 
     431                 : JSObject *
     432           80539 : GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp)
     433                 : {
     434           80539 :     JSObject *objectProto = getOrCreateObjectPrototype(cx);
     435           80539 :     if (!objectProto)
     436               0 :         return NULL;
     437                 : 
     438           80539 :     return CreateBlankProto(cx, clasp, *objectProto, *this);
     439                 : }
     440                 : 
     441                 : JSObject *
     442           35752 : GlobalObject::createBlankPrototypeInheriting(JSContext *cx, Class *clasp, JSObject &proto)
     443                 : {
     444           35752 :     return CreateBlankProto(cx, clasp, proto, *this);
     445                 : }
     446                 : 
     447                 : bool
     448          391646 : LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto)
     449                 : {
     450          783292 :     RootObject ctorRoot(cx, &ctor);
     451          783292 :     RootObject protoRoot(cx, &proto);
     452                 : 
     453                 :     return ctor->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom,
     454          391646 :                                 ObjectValue(*proto), JS_PropertyStub, JS_StrictPropertyStub,
     455          391646 :                                 JSPROP_PERMANENT | JSPROP_READONLY) &&
     456                 :            proto->defineProperty(cx, cx->runtime->atomState.constructorAtom,
     457          391646 :                                  ObjectValue(*ctor), JS_PropertyStub, JS_StrictPropertyStub, 0);
     458                 : }
     459                 : 
     460                 : bool
     461          683297 : DefinePropertiesAndBrand(JSContext *cx, JSObject *obj, JSPropertySpec *ps, JSFunctionSpec *fs)
     462                 : {
     463         1366594 :     RootObject root(cx, &obj);
     464                 : 
     465          683297 :     if ((ps && !JS_DefineProperties(cx, obj, ps)) || (fs && !JS_DefineFunctions(cx, obj, fs)))
     466               0 :         return false;
     467          683297 :     return true;
     468                 : }
     469                 : 
     470                 : void
     471            3260 : GlobalDebuggees_finalize(JSContext *cx, JSObject *obj)
     472                 : {
     473            3260 :     cx->delete_((GlobalObject::DebuggerVector *) obj->getPrivate());
     474            3260 : }
     475                 : 
     476                 : static Class
     477                 : GlobalDebuggees_class = {
     478                 :     "GlobalDebuggee", JSCLASS_HAS_PRIVATE,
     479                 :     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     480                 :     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, GlobalDebuggees_finalize
     481                 : };
     482                 : 
     483                 : GlobalObject::DebuggerVector *
     484          130671 : GlobalObject::getDebuggers()
     485                 : {
     486          130671 :     Value debuggers = getReservedSlot(DEBUGGERS);
     487          130671 :     if (debuggers.isUndefined())
     488            4461 :         return NULL;
     489          126210 :     JS_ASSERT(debuggers.toObject().getClass() == &GlobalDebuggees_class);
     490          126210 :     return (DebuggerVector *) debuggers.toObject().getPrivate();
     491                 : }
     492                 : 
     493                 : GlobalObject::DebuggerVector *
     494            4358 : GlobalObject::getOrCreateDebuggers(JSContext *cx)
     495                 : {
     496            4358 :     assertSameCompartment(cx, this);
     497            4358 :     DebuggerVector *debuggers = getDebuggers();
     498            4358 :     if (debuggers)
     499            1098 :         return debuggers;
     500                 : 
     501            3260 :     JSObject *obj = NewObjectWithGivenProto(cx, &GlobalDebuggees_class, NULL, this);
     502            3260 :     if (!obj)
     503               0 :         return NULL;
     504            3260 :     debuggers = cx->new_<DebuggerVector>();
     505            3260 :     if (!debuggers)
     506               0 :         return NULL;
     507            3260 :     obj->setPrivate(debuggers);
     508            3260 :     setReservedSlot(DEBUGGERS, ObjectValue(*obj));
     509            3260 :     return debuggers;
     510                 : }
     511                 : 
     512                 : bool
     513               0 : GlobalObject::addDebugger(JSContext *cx, Debugger *dbg)
     514                 : {
     515               0 :     DebuggerVector *debuggers = getOrCreateDebuggers(cx);
     516               0 :     if (!debuggers)
     517               0 :         return false;
     518                 : #ifdef DEBUG
     519               0 :     for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++)
     520               0 :         JS_ASSERT(*p != dbg);
     521                 : #endif
     522               0 :     if (debuggers->empty() && !compartment()->addDebuggee(cx, this))
     523               0 :         return false;
     524               0 :     if (!debuggers->append(dbg)) {
     525               0 :         compartment()->removeDebuggee(cx, this);
     526               0 :         return false;
     527                 :     }
     528               0 :     return true;
     529                 : }
     530                 : 
     531                 : } // namespace js

Generated by: LCOV version 1.7