LCOV - code coverage report
Current view: directory - js/src/vm - GlobalObject.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 215 155 72.1 %
Date: 2012-04-07 Functions: 18 15 83.3 %

       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           23355 : js_InitObjectClass(JSContext *cx, JSObject *obj)
      66                 : {
      67           23355 :     JS_ASSERT(obj->isNative());
      68                 : 
      69           23355 :     return obj->asGlobal().getOrCreateObjectPrototype(cx);
      70                 : }
      71                 : 
      72                 : JSObject *
      73              10 : js_InitFunctionClass(JSContext *cx, JSObject *obj)
      74                 : {
      75              10 :     JS_ASSERT(obj->isNative());
      76                 : 
      77              10 :     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           23629 : GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
      92                 : {
      93           47258 :     RootedVar<GlobalObject*> self(cx, this);
      94                 : 
      95           23629 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
      96           23629 :     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           23629 :     if (!cx->globalObject)
     107           18666 :         JS_SetGlobalObject(cx, self);
     108                 : 
     109           47258 :     RootedVarObject objectProto(cx);
     110                 : 
     111                 :     /*
     112                 :      * Create |Object.prototype| first, mirroring CreateBlankProto but for the
     113                 :      * prototype of the created object.
     114                 :      */
     115           23629 :     objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, self);
     116           23629 :     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           23629 :     if (!objectProto->setNewTypeUnknown(cx))
     125               0 :         return NULL;
     126                 : 
     127                 :     /* Create |Function.prototype| next so we can create other functions. */
     128           47258 :     RootedVarFunction functionProto(cx);
     129                 :     {
     130           23629 :         JSObject *functionProto_ = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, self);
     131           23629 :         if (!functionProto_)
     132               0 :             return NULL;
     133           23629 :         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           23629 :                                          NULL, 0, JSFUN_INTERPRETED, self, NULL);
     141           23629 :         if (!proto)
     142               0 :             return NULL;
     143           23629 :         JS_ASSERT(proto == functionProto);
     144           23629 :         functionProto->flags |= JSFUN_PROTOTYPE;
     145                 : 
     146                 :         JSScript *script =
     147           23629 :             JSScript::NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, JSVERSION_DEFAULT);
     148           23629 :         if (!script)
     149               0 :             return NULL;
     150           23629 :         script->noScriptRval = true;
     151           23629 :         script->code[0] = JSOP_STOP;
     152           23629 :         script->code[1] = SRC_NULL;
     153           23629 :         functionProto->initScript(script);
     154           23629 :         functionProto->getType(cx)->interpretedFunction = functionProto;
     155           23629 :         script->setFunction(functionProto);
     156                 : 
     157           23629 :         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           23629 :         if (!functionProto->setNewTypeUnknown(cx))
     166               0 :             return NULL;
     167                 :     }
     168                 : 
     169                 :     /* Create the Object function now that we have a [[Prototype]] for it. */
     170           47258 :     RootedVarFunction objectCtor(cx);
     171                 :     {
     172           23629 :         JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
     173           23629 :         if (!ctor)
     174               0 :             return NULL;
     175                 :         objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, self,
     176           23629 :                                     CLASS_ATOM(cx, Object));
     177           23629 :         if (!objectCtor)
     178               0 :             return NULL;
     179                 :     }
     180                 : 
     181                 :     /*
     182                 :      * Install |Object| and |Object.prototype| for the benefit of subsequent
     183                 :      * code that looks for them.
     184                 :      */
     185           23629 :     self->setObjectClassDetails(objectCtor, objectProto);
     186                 : 
     187                 :     /* Create |Function| so it and |Function.prototype| can be installed. */
     188           47258 :     RootedVarFunction functionCtor(cx);
     189                 :     {
     190                 :         JSObject *ctor =
     191           23629 :             NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
     192           23629 :         if (!ctor)
     193               0 :             return NULL;
     194                 :         functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self,
     195           23629 :                                       CLASS_ATOM(cx, Function));
     196           23629 :         if (!functionCtor)
     197               0 :             return NULL;
     198           23629 :         JS_ASSERT(ctor == functionCtor);
     199                 :     }
     200                 : 
     201                 :     /*
     202                 :      * Install |Function| and |Function.prototype| so that we can freely create
     203                 :      * functions and objects without special effort.
     204                 :      */
     205           23629 :     self->setFunctionClassDetails(functionCtor, functionProto);
     206                 : 
     207                 :     /*
     208                 :      * The hard part's done: now go back and add all the properties these
     209                 :      * primordial values have.
     210                 :      */
     211          141774 :     if (!LinkConstructorAndPrototype(cx, objectCtor, objectProto) ||
     212           23629 :         !DefinePropertiesAndBrand(cx, objectProto, object_props, object_methods) ||
     213           23629 :         !DefinePropertiesAndBrand(cx, objectCtor, NULL, object_static_methods) ||
     214           23629 :         !LinkConstructorAndPrototype(cx, functionCtor, functionProto) ||
     215           23629 :         !DefinePropertiesAndBrand(cx, functionProto, NULL, function_methods) ||
     216           23629 :         !DefinePropertiesAndBrand(cx, functionCtor, NULL, NULL))
     217                 :     {
     218               0 :         return NULL;
     219                 :     }
     220                 : 
     221                 :     /* Add the global Function and Object properties now. */
     222           23629 :     jsid objectId = ATOM_TO_JSID(CLASS_ATOM(cx, Object));
     223           23629 :     if (!self->addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0))
     224               0 :         return NULL;
     225           23629 :     jsid functionId = ATOM_TO_JSID(CLASS_ATOM(cx, Function));
     226           23629 :     if (!self->addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0))
     227               0 :         return NULL;
     228                 : 
     229                 :     /* Heavy lifting done, but lingering tasks remain. */
     230                 : 
     231                 :     /* ES5 15.1.2.1. */
     232           23629 :     jsid id = ATOM_TO_JSID(cx->runtime->atomState.evalAtom);
     233           23629 :     JSObject *evalobj = js_DefineFunction(cx, self, id, eval, 1, JSFUN_STUB_GSOPS);
     234           23629 :     if (!evalobj)
     235               0 :         return NULL;
     236           23629 :     self->setOriginalEval(evalobj);
     237                 : 
     238                 :     /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
     239           47258 :     RootedVarFunction throwTypeError(cx);
     240           23629 :     throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL);
     241           23629 :     if (!throwTypeError)
     242               0 :         return NULL;
     243           47258 :     AutoIdVector ids(cx);
     244           23629 :     if (!throwTypeError->preventExtensions(cx, &ids))
     245               0 :         return NULL;
     246           23629 :     self->setThrowTypeError(throwTypeError);
     247                 : 
     248                 :     /*
     249                 :      * The global object should have |Object.prototype| as its [[Prototype]].
     250                 :      * Eventually we'd like to have standard classes be there from the start,
     251                 :      * and thus we would know we were always setting what had previously been a
     252                 :      * null [[Prototype]], but right now some code assumes it can set the
     253                 :      * [[Prototype]] before standard classes have been initialized.  For now,
     254                 :      * only set the [[Prototype]] if it hasn't already been set.
     255                 :      */
     256           23629 :     if (self->shouldSplicePrototype(cx) && !self->splicePrototype(cx, objectProto))
     257               0 :         return NULL;
     258                 : 
     259                 :     /*
     260                 :      * Notify any debuggers about the creation of the script for
     261                 :      * |Function.prototype| -- after all initialization, for simplicity.
     262                 :      */
     263           23629 :     js_CallNewScriptHook(cx, functionProto->script(), functionProto);
     264           23629 :     return functionProto;
     265                 : }
     266                 : 
     267                 : GlobalObject *
     268           23659 : GlobalObject::create(JSContext *cx, Class *clasp)
     269                 : {
     270           23659 :     JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
     271                 : 
     272           47318 :     RootedVar<GlobalObject*> obj(cx);
     273                 : 
     274           23659 :     JSObject *obj_ = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
     275           23659 :     if (!obj_)
     276               0 :         return NULL;
     277           23659 :     obj = &obj_->asGlobal();
     278                 : 
     279           23659 :     if (!obj->setSingletonType(cx) || !obj->setVarObj(cx))
     280               0 :         return NULL;
     281                 : 
     282                 :     /* Construct a regexp statics object for this global object. */
     283           23659 :     JSObject *res = RegExpStatics::create(cx, obj);
     284           23659 :     if (!res)
     285               0 :         return NULL;
     286           23659 :     obj->initSlot(REGEXP_STATICS, ObjectValue(*res));
     287           23659 :     obj->initFlags(0);
     288                 : 
     289           23659 :     return obj;
     290                 : }
     291                 : 
     292                 : bool
     293             264 : GlobalObject::initStandardClasses(JSContext *cx)
     294                 : {
     295             264 :     JSAtomState &state = cx->runtime->atomState;
     296                 : 
     297                 :     /* Define a top-level property 'undefined' with the undefined value. */
     298             264 :     if (!defineProperty(cx, state.typeAtoms[JSTYPE_VOID], UndefinedValue(),
     299             264 :                         JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY))
     300                 :     {
     301               0 :         return false;
     302                 :     }
     303                 : 
     304             264 :     if (!initFunctionAndObjectClasses(cx))
     305               0 :         return false;
     306                 : 
     307                 :     /* Initialize the rest of the standard objects and functions. */
     308             264 :     return js_InitArrayClass(cx, this) &&
     309             264 :            js_InitBooleanClass(cx, this) &&
     310             264 :            js_InitExceptionClasses(cx, this) &&
     311             264 :            js_InitMathClass(cx, this) &&
     312             264 :            js_InitNumberClass(cx, this) &&
     313             264 :            js_InitJSONClass(cx, this) &&
     314             264 :            js_InitRegExpClass(cx, this) &&
     315             264 :            js_InitStringClass(cx, this) &&
     316             264 :            js_InitTypedArrayClasses(cx, this) &&
     317                 : #if JS_HAS_XML_SUPPORT
     318             264 :            js_InitXMLClasses(cx, this) &&
     319                 : #endif
     320                 : #if JS_HAS_GENERATORS
     321             264 :            js_InitIteratorClasses(cx, this) &&
     322                 : #endif
     323             264 :            js_InitDateClass(cx, this) &&
     324             264 :            js_InitWeakMapClass(cx, this) &&
     325             264 :            js_InitProxyClass(cx, this) &&
     326             264 :            js_InitMapClass(cx, this) &&
     327            3960 :            js_InitSetClass(cx, this);
     328                 : }
     329                 : 
     330                 : void
     331               0 : GlobalObject::clear(JSContext *cx)
     332                 : {
     333               0 :     for (int key = JSProto_Null; key < JSProto_LIMIT * 3; key++)
     334               0 :         setSlot(key, UndefinedValue());
     335                 : 
     336                 :     /* Clear regexp statics. */
     337               0 :     getRegExpStatics()->clear();
     338                 : 
     339                 :     /* Clear the runtime-codegen-enabled cache. */
     340               0 :     setSlot(RUNTIME_CODEGEN_ENABLED, UndefinedValue());
     341                 : 
     342                 :     /*
     343                 :      * Clear the original-eval and [[ThrowTypeError]] slots, in case throwing
     344                 :      * trying to execute a script for this global must reinitialize standard
     345                 :      * classes.  See bug 470150.
     346                 :      */
     347               0 :     setSlot(EVAL, UndefinedValue());
     348               0 :     setSlot(THROWTYPEERROR, UndefinedValue());
     349                 : 
     350                 :     /*
     351                 :      * Mark global as cleared. If we try to execute any compile-and-go
     352                 :      * scripts from here on, we will throw.
     353                 :      */
     354               0 :     int32_t flags = getSlot(FLAGS).toInt32();
     355               0 :     flags |= FLAGS_CLEARED;
     356               0 :     setSlot(FLAGS, Int32Value(flags));
     357                 : 
     358                 :     /*
     359                 :      * Reset the new object cache in the compartment, which assumes that
     360                 :      * prototypes cached on the global object are immutable.
     361                 :      */
     362               0 :     cx->compartment->newObjectCache.reset();
     363                 : 
     364                 : #ifdef JS_METHODJIT
     365                 :     /*
     366                 :      * Destroy compiled code for any scripts parented to this global. Call ICs
     367                 :      * can directly call scripts which have associated JIT code, and do so
     368                 :      * without checking whether the script's global has been cleared.
     369                 :      */
     370               0 :     for (gc::CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
     371               0 :         JSScript *script = i.get<JSScript>();
     372               0 :         if (script->compileAndGo && script->hasJITCode() && script->hasClearedGlobal()) {
     373               0 :             mjit::Recompiler::clearStackReferences(cx->runtime->defaultFreeOp(), script);
     374               0 :             mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), script);
     375                 :         }
     376                 :     }
     377                 : #endif
     378               0 : }
     379                 : 
     380                 : bool
     381          108221 : GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
     382                 : {
     383          108221 :     HeapSlot &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
     384          108221 :     if (v.isUndefined()) {
     385                 :         /*
     386                 :          * If there are callbacks, make sure that the CSP callback is installed
     387                 :          * and that it permits runtime code generation, then cache the result.
     388                 :          */
     389            5334 :         JSCSPEvalChecker allows = cx->runtime->securityCallbacks->contentSecurityPolicyAllows;
     390            5334 :         v.set(this, RUNTIME_CODEGEN_ENABLED, BooleanValue(!allows || allows(cx)));
     391                 :     }
     392          108221 :     return !v.isFalse();
     393                 : }
     394                 : 
     395                 : JSFunction *
     396           69713 : GlobalObject::createConstructor(JSContext *cx, Native ctor, JSAtom *name, unsigned length,
     397                 :                                 gc::AllocKind kind)
     398                 : {
     399          139426 :     RootedVarObject self(cx, this);
     400           69713 :     return js_NewFunction(cx, NULL, ctor, length, JSFUN_CONSTRUCTOR, self, name, kind);
     401                 : }
     402                 : 
     403                 : static JSObject *
     404           71915 : CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
     405                 : {
     406           71915 :     JS_ASSERT(clasp != &ObjectClass);
     407           71915 :     JS_ASSERT(clasp != &FunctionClass);
     408                 : 
     409           71915 :     JSObject *blankProto = NewObjectWithGivenProto(cx, clasp, &proto, &global);
     410           71915 :     if (!blankProto || !blankProto->setSingletonType(cx))
     411               0 :         return NULL;
     412                 : 
     413           71915 :     return blankProto;
     414                 : }
     415                 : 
     416                 : JSObject *
     417           44811 : GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp)
     418                 : {
     419           44811 :     JSObject *objectProto = getOrCreateObjectPrototype(cx);
     420           44811 :     if (!objectProto)
     421               0 :         return NULL;
     422                 : 
     423           44811 :     return CreateBlankProto(cx, clasp, *objectProto, *this);
     424                 : }
     425                 : 
     426                 : JSObject *
     427           27104 : GlobalObject::createBlankPrototypeInheriting(JSContext *cx, Class *clasp, JSObject &proto)
     428                 : {
     429           27104 :     return CreateBlankProto(cx, clasp, proto, *this);
     430                 : }
     431                 : 
     432                 : bool
     433          322273 : LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto)
     434                 : {
     435          644546 :     RootObject ctorRoot(cx, &ctor);
     436          644546 :     RootObject protoRoot(cx, &proto);
     437                 : 
     438                 :     return ctor->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom,
     439          322273 :                                 ObjectValue(*proto), JS_PropertyStub, JS_StrictPropertyStub,
     440          322273 :                                 JSPROP_PERMANENT | JSPROP_READONLY) &&
     441                 :            proto->defineProperty(cx, cx->runtime->atomState.constructorAtom,
     442          322273 :                                  ObjectValue(*ctor), JS_PropertyStub, JS_StrictPropertyStub, 0);
     443                 : }
     444                 : 
     445                 : bool
     446          574608 : DefinePropertiesAndBrand(JSContext *cx, JSObject *obj, JSPropertySpec *ps, JSFunctionSpec *fs)
     447                 : {
     448         1149216 :     RootObject root(cx, &obj);
     449                 : 
     450          574608 :     if ((ps && !JS_DefineProperties(cx, obj, ps)) || (fs && !JS_DefineFunctions(cx, obj, fs)))
     451               0 :         return false;
     452          574608 :     return true;
     453                 : }
     454                 : 
     455                 : void
     456            3332 : GlobalDebuggees_finalize(FreeOp *fop, JSObject *obj)
     457                 : {
     458            3332 :     fop->delete_((GlobalObject::DebuggerVector *) obj->getPrivate());
     459            3332 : }
     460                 : 
     461                 : static Class
     462                 : GlobalDebuggees_class = {
     463                 :     "GlobalDebuggee", JSCLASS_HAS_PRIVATE,
     464                 :     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     465                 :     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, GlobalDebuggees_finalize
     466                 : };
     467                 : 
     468                 : GlobalObject::DebuggerVector *
     469          131913 : GlobalObject::getDebuggers()
     470                 : {
     471          131913 :     Value debuggers = getReservedSlot(DEBUGGERS);
     472          131913 :     if (debuggers.isUndefined())
     473            4535 :         return NULL;
     474          127378 :     JS_ASSERT(debuggers.toObject().getClass() == &GlobalDebuggees_class);
     475          127378 :     return (DebuggerVector *) debuggers.toObject().getPrivate();
     476                 : }
     477                 : 
     478                 : GlobalObject::DebuggerVector *
     479            4439 : GlobalObject::getOrCreateDebuggers(JSContext *cx)
     480                 : {
     481            4439 :     assertSameCompartment(cx, this);
     482            4439 :     DebuggerVector *debuggers = getDebuggers();
     483            4439 :     if (debuggers)
     484            1107 :         return debuggers;
     485                 : 
     486            3332 :     JSObject *obj = NewObjectWithGivenProto(cx, &GlobalDebuggees_class, NULL, this);
     487            3332 :     if (!obj)
     488               0 :         return NULL;
     489            3332 :     debuggers = cx->new_<DebuggerVector>();
     490            3332 :     if (!debuggers)
     491               0 :         return NULL;
     492            3332 :     obj->setPrivate(debuggers);
     493            3332 :     setReservedSlot(DEBUGGERS, ObjectValue(*obj));
     494            3332 :     return debuggers;
     495                 : }
     496                 : 
     497                 : bool
     498               0 : GlobalObject::addDebugger(JSContext *cx, Debugger *dbg)
     499                 : {
     500               0 :     DebuggerVector *debuggers = getOrCreateDebuggers(cx);
     501               0 :     if (!debuggers)
     502               0 :         return false;
     503                 : #ifdef DEBUG
     504               0 :     for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++)
     505               0 :         JS_ASSERT(*p != dbg);
     506                 : #endif
     507               0 :     if (debuggers->empty() && !compartment()->addDebuggee(cx, this))
     508               0 :         return false;
     509               0 :     if (!debuggers->append(dbg)) {
     510               0 :         compartment()->removeDebuggee(cx->runtime->defaultFreeOp(), this);
     511               0 :         return false;
     512                 :     }
     513               0 :     return true;
     514                 : }
     515                 : 
     516                 : } // namespace js

Generated by: LCOV version 1.7