js/src/vm/ArgumentsObject.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "vm/ArgumentsObject-inl.h"
     9 #include "jsinfer.h"
    11 #ifdef JS_ION
    12 #include "jit/IonFrames.h"
    13 #endif
    14 #include "vm/GlobalObject.h"
    15 #include "vm/Stack.h"
    17 #include "jsobjinlines.h"
    19 #include "vm/Stack-inl.h"
    21 using namespace js;
    22 using namespace js::gc;
    24 static void
    25 CopyStackFrameArguments(const AbstractFramePtr frame, HeapValue *dst, unsigned totalArgs)
    26 {
    27     JS_ASSERT_IF(frame.isInterpreterFrame(), !frame.asInterpreterFrame()->runningInJit());
    29     JS_ASSERT(Max(frame.numActualArgs(), frame.numFormalArgs()) == totalArgs);
    31     /* Copy arguments. */
    32     Value *src = frame.argv();
    33     Value *end = src + totalArgs;
    34     while (src != end)
    35         (dst++)->init(*src++);
    36 }
    38 /* static */ void
    39 ArgumentsObject::MaybeForwardToCallObject(AbstractFramePtr frame, JSObject *obj,
    40                                           ArgumentsData *data)
    41 {
    42     JSScript *script = frame.script();
    43     if (frame.fun()->isHeavyweight() && script->argsObjAliasesFormals()) {
    44         obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(frame.callObj()));
    45         for (AliasedFormalIter fi(script); fi; fi++)
    46             data->args[fi.frameIndex()] = JS::MagicValueUint32(fi.scopeSlot());
    47     }
    48 }
    50 #if defined(JS_ION)
    51 /* static */ void
    52 ArgumentsObject::MaybeForwardToCallObject(jit::IonJSFrameLayout *frame, HandleObject callObj,
    53                                           JSObject *obj, ArgumentsData *data)
    54 {
    55     JSFunction *callee = jit::CalleeTokenToFunction(frame->calleeToken());
    56     JSScript *script = callee->nonLazyScript();
    57     if (callee->isHeavyweight() && script->argsObjAliasesFormals()) {
    58         JS_ASSERT(callObj && callObj->is<CallObject>());
    59         obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(*callObj.get()));
    60         for (AliasedFormalIter fi(script); fi; fi++)
    61             data->args[fi.frameIndex()] = JS::MagicValueUint32(fi.scopeSlot());
    62     }
    63 }
    64 #endif
    66 struct CopyFrameArgs
    67 {
    68     AbstractFramePtr frame_;
    70     CopyFrameArgs(AbstractFramePtr frame)
    71       : frame_(frame)
    72     { }
    74     void copyArgs(JSContext *, HeapValue *dst, unsigned totalArgs) const {
    75         CopyStackFrameArguments(frame_, dst, totalArgs);
    76     }
    78     /*
    79      * If a call object exists and the arguments object aliases formals, the
    80      * call object is the canonical location for formals.
    81      */
    82     void maybeForwardToCallObject(JSObject *obj, ArgumentsData *data) {
    83         ArgumentsObject::MaybeForwardToCallObject(frame_, obj, data);
    84     }
    85 };
    87 #if defined(JS_ION)
    88 struct CopyIonJSFrameArgs
    89 {
    90     jit::IonJSFrameLayout *frame_;
    91     HandleObject callObj_;
    93     CopyIonJSFrameArgs(jit::IonJSFrameLayout *frame, HandleObject callObj)
    94       : frame_(frame), callObj_(callObj)
    95     { }
    97     void copyArgs(JSContext *, HeapValue *dstBase, unsigned totalArgs) const {
    98         unsigned numActuals = frame_->numActualArgs();
    99         unsigned numFormals = jit::CalleeTokenToFunction(frame_->calleeToken())->nargs();
   100         JS_ASSERT(numActuals <= totalArgs);
   101         JS_ASSERT(numFormals <= totalArgs);
   102         JS_ASSERT(Max(numActuals, numFormals) == totalArgs);
   104         /* Copy all arguments. */
   105         Value *src = frame_->argv() + 1;  /* +1 to skip this. */
   106         Value *end = src + numActuals;
   107         HeapValue *dst = dstBase;
   108         while (src != end)
   109             (dst++)->init(*src++);
   111         if (numActuals < numFormals) {
   112             HeapValue *dstEnd = dstBase + totalArgs;
   113             while (dst != dstEnd)
   114                 (dst++)->init(UndefinedValue());
   115         }
   116     }
   118     /*
   119      * If a call object exists and the arguments object aliases formals, the
   120      * call object is the canonical location for formals.
   121      */
   122     void maybeForwardToCallObject(JSObject *obj, ArgumentsData *data) {
   123         ArgumentsObject::MaybeForwardToCallObject(frame_, callObj_, obj, data);
   124     }
   125 };
   126 #endif
   128 struct CopyScriptFrameIterArgs
   129 {
   130     ScriptFrameIter &iter_;
   132     CopyScriptFrameIterArgs(ScriptFrameIter &iter)
   133       : iter_(iter)
   134     { }
   136     void copyArgs(JSContext *cx, HeapValue *dstBase, unsigned totalArgs) const {
   137         /* Copy actual arguments. */
   138         iter_.unaliasedForEachActual(cx, CopyToHeap(dstBase));
   140         /* Define formals which are not part of the actuals. */
   141         unsigned numActuals = iter_.numActualArgs();
   142         unsigned numFormals = iter_.callee()->nargs();
   143         JS_ASSERT(numActuals <= totalArgs);
   144         JS_ASSERT(numFormals <= totalArgs);
   145         JS_ASSERT(Max(numActuals, numFormals) == totalArgs);
   147         if (numActuals < numFormals) {
   148             HeapValue *dst = dstBase + numActuals, *dstEnd = dstBase + totalArgs;
   149             while (dst != dstEnd)
   150                 (dst++)->init(UndefinedValue());
   151         }
   152     }
   154     /*
   155      * Ion frames are copying every argument onto the stack, other locations are
   156      * invalid.
   157      */
   158     void maybeForwardToCallObject(JSObject *obj, ArgumentsData *data) {
   159         if (!iter_.isJit())
   160             ArgumentsObject::MaybeForwardToCallObject(iter_.abstractFramePtr(), obj, data);
   161     }
   162 };
   164 template <typename CopyArgs>
   165 /* static */ ArgumentsObject *
   166 ArgumentsObject::create(JSContext *cx, HandleScript script, HandleFunction callee, unsigned numActuals,
   167                         CopyArgs &copy)
   168 {
   169     RootedObject proto(cx, callee->global().getOrCreateObjectPrototype(cx));
   170     if (!proto)
   171         return nullptr;
   173     bool strict = callee->strict();
   174     const Class *clasp = strict ? &StrictArgumentsObject::class_ : &NormalArgumentsObject::class_;
   176     RootedTypeObject type(cx, cx->getNewType(clasp, proto.get()));
   177     if (!type)
   178         return nullptr;
   180     JSObject *metadata = nullptr;
   181     if (!NewObjectMetadata(cx, &metadata))
   182         return nullptr;
   184     RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, TaggedProto(proto),
   185                                                       proto->getParent(), metadata, FINALIZE_KIND,
   186                                                       BaseShape::INDEXED));
   187     if (!shape)
   188         return nullptr;
   190     unsigned numFormals = callee->nargs();
   191     unsigned numDeletedWords = NumWordsForBitArrayOfLength(numActuals);
   192     unsigned numArgs = Max(numActuals, numFormals);
   193     unsigned numBytes = offsetof(ArgumentsData, args) +
   194                         numDeletedWords * sizeof(size_t) +
   195                         numArgs * sizeof(Value);
   197     ArgumentsData *data = (ArgumentsData *)cx->malloc_(numBytes);
   198     if (!data)
   199         return nullptr;
   201     JSObject *obj = JSObject::create(cx, FINALIZE_KIND, GetInitialHeap(GenericObject, clasp),
   202                                      shape, type);
   203     if (!obj) {
   204         js_free(data);
   205         return nullptr;
   206     }
   208     data->numArgs = numArgs;
   209     data->callee.init(ObjectValue(*callee.get()));
   210     data->script = script;
   212     /* Copy [0, numArgs) into data->slots. */
   213     HeapValue *dst = data->args, *dstEnd = data->args + numArgs;
   214     copy.copyArgs(cx, dst, numArgs);
   216     data->deletedBits = reinterpret_cast<size_t *>(dstEnd);
   217     ClearAllBitArrayElements(data->deletedBits, numDeletedWords);
   219     obj->initFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(numActuals << PACKED_BITS_COUNT));
   220     obj->initFixedSlot(DATA_SLOT, PrivateValue(data));
   222     copy.maybeForwardToCallObject(obj, data);
   224     ArgumentsObject &argsobj = obj->as<ArgumentsObject>();
   225     JS_ASSERT(argsobj.initialLength() == numActuals);
   226     JS_ASSERT(!argsobj.hasOverriddenLength());
   227     return &argsobj;
   228 }
   230 ArgumentsObject *
   231 ArgumentsObject::createExpected(JSContext *cx, AbstractFramePtr frame)
   232 {
   233     JS_ASSERT(frame.script()->needsArgsObj());
   234     RootedScript script(cx, frame.script());
   235     RootedFunction callee(cx, frame.callee());
   236     CopyFrameArgs copy(frame);
   237     ArgumentsObject *argsobj = create(cx, script, callee, frame.numActualArgs(), copy);
   238     if (!argsobj)
   239         return nullptr;
   241     frame.initArgsObj(*argsobj);
   242     return argsobj;
   243 }
   245 ArgumentsObject *
   246 ArgumentsObject::createUnexpected(JSContext *cx, ScriptFrameIter &iter)
   247 {
   248     RootedScript script(cx, iter.script());
   249     RootedFunction callee(cx, iter.callee());
   250     CopyScriptFrameIterArgs copy(iter);
   251     return create(cx, script, callee, iter.numActualArgs(), copy);
   252 }
   254 ArgumentsObject *
   255 ArgumentsObject::createUnexpected(JSContext *cx, AbstractFramePtr frame)
   256 {
   257     RootedScript script(cx, frame.script());
   258     RootedFunction callee(cx, frame.callee());
   259     CopyFrameArgs copy(frame);
   260     return create(cx, script, callee, frame.numActualArgs(), copy);
   261 }
   263 #if defined(JS_ION)
   264 ArgumentsObject *
   265 ArgumentsObject::createForIon(JSContext *cx, jit::IonJSFrameLayout *frame, HandleObject scopeChain)
   266 {
   267     jit::CalleeToken token = frame->calleeToken();
   268     JS_ASSERT(jit::CalleeTokenIsFunction(token));
   269     RootedScript script(cx, jit::ScriptFromCalleeToken(token));
   270     RootedFunction callee(cx, jit::CalleeTokenToFunction(token));
   271     RootedObject callObj(cx, scopeChain->is<CallObject>() ? scopeChain.get() : nullptr);
   272     CopyIonJSFrameArgs copy(frame, callObj);
   273     return create(cx, script, callee, frame->numActualArgs(), copy);
   274 }
   275 #endif
   277 static bool
   278 args_delProperty(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
   279 {
   280     ArgumentsObject &argsobj = obj->as<ArgumentsObject>();
   281     if (JSID_IS_INT(id)) {
   282         unsigned arg = unsigned(JSID_TO_INT(id));
   283         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
   284             argsobj.markElementDeleted(arg);
   285     } else if (JSID_IS_ATOM(id, cx->names().length)) {
   286         argsobj.markLengthOverridden();
   287     } else if (JSID_IS_ATOM(id, cx->names().callee)) {
   288         argsobj.as<NormalArgumentsObject>().clearCallee();
   289     }
   290     *succeeded = true;
   291     return true;
   292 }
   294 static bool
   295 ArgGetter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
   296 {
   297     if (!obj->is<NormalArgumentsObject>())
   298         return true;
   300     NormalArgumentsObject &argsobj = obj->as<NormalArgumentsObject>();
   301     if (JSID_IS_INT(id)) {
   302         /*
   303          * arg can exceed the number of arguments if a script changed the
   304          * prototype to point to another Arguments object with a bigger argc.
   305          */
   306         unsigned arg = unsigned(JSID_TO_INT(id));
   307         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
   308             vp.set(argsobj.element(arg));
   309     } else if (JSID_IS_ATOM(id, cx->names().length)) {
   310         if (!argsobj.hasOverriddenLength())
   311             vp.setInt32(argsobj.initialLength());
   312     } else {
   313         JS_ASSERT(JSID_IS_ATOM(id, cx->names().callee));
   314         if (!argsobj.callee().isMagic(JS_OVERWRITTEN_CALLEE))
   315             vp.set(argsobj.callee());
   316     }
   317     return true;
   318 }
   320 static bool
   321 ArgSetter(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
   322 {
   323     if (!obj->is<NormalArgumentsObject>())
   324         return true;
   326     unsigned attrs;
   327     if (!baseops::GetAttributes(cx, obj, id, &attrs))
   328         return false;
   329     JS_ASSERT(!(attrs & JSPROP_READONLY));
   330     attrs &= (JSPROP_ENUMERATE | JSPROP_PERMANENT); /* only valid attributes */
   332     NormalArgumentsObject &argsobj = obj->as<NormalArgumentsObject>();
   333     RootedScript script(cx, argsobj.containingScript());
   335     if (JSID_IS_INT(id)) {
   336         unsigned arg = unsigned(JSID_TO_INT(id));
   337         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) {
   338             argsobj.setElement(cx, arg, vp);
   339             if (arg < script->functionNonDelazifying()->nargs())
   340                 types::TypeScript::SetArgument(cx, script, arg, vp);
   341             return true;
   342         }
   343     } else {
   344         JS_ASSERT(JSID_IS_ATOM(id, cx->names().length) || JSID_IS_ATOM(id, cx->names().callee));
   345     }
   347     /*
   348      * For simplicity we use delete/define to replace the property with one
   349      * backed by the default Object getter and setter. Note that we rely on
   350      * args_delProperty to clear the corresponding reserved slot so the GC can
   351      * collect its value. Note also that we must define the property instead
   352      * of setting it in case the user has changed the prototype to an object
   353      * that has a setter for this id.
   354      */
   355     bool succeeded;
   356     return baseops::DeleteGeneric(cx, obj, id, &succeeded) &&
   357            baseops::DefineGeneric(cx, obj, id, vp, nullptr, nullptr, attrs);
   358 }
   360 static bool
   361 args_resolve(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp)
   362 {
   363     objp.set(nullptr);
   365     Rooted<NormalArgumentsObject*> argsobj(cx, &obj->as<NormalArgumentsObject>());
   367     unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
   368     if (JSID_IS_INT(id)) {
   369         uint32_t arg = uint32_t(JSID_TO_INT(id));
   370         if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
   371             return true;
   373         attrs |= JSPROP_ENUMERATE;
   374     } else if (JSID_IS_ATOM(id, cx->names().length)) {
   375         if (argsobj->hasOverriddenLength())
   376             return true;
   377     } else {
   378         if (!JSID_IS_ATOM(id, cx->names().callee))
   379             return true;
   381         if (argsobj->callee().isMagic(JS_OVERWRITTEN_CALLEE))
   382             return true;
   383     }
   385     if (!baseops::DefineGeneric(cx, argsobj, id, UndefinedHandleValue, ArgGetter, ArgSetter, attrs))
   386         return false;
   388     objp.set(argsobj);
   389     return true;
   390 }
   392 static bool
   393 args_enumerate(JSContext *cx, HandleObject obj)
   394 {
   395     Rooted<NormalArgumentsObject*> argsobj(cx, &obj->as<NormalArgumentsObject>());
   396     RootedId id(cx);
   398     /*
   399      * Trigger reflection in args_resolve using a series of js_LookupProperty
   400      * calls.
   401      */
   402     int argc = int(argsobj->initialLength());
   403     for (int i = -2; i != argc; i++) {
   404         id = (i == -2)
   405              ? NameToId(cx->names().length)
   406              : (i == -1)
   407              ? NameToId(cx->names().callee)
   408              : INT_TO_JSID(i);
   410         RootedObject pobj(cx);
   411         RootedShape prop(cx);
   412         if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
   413             return false;
   414     }
   415     return true;
   416 }
   418 static bool
   419 StrictArgGetter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
   420 {
   421     if (!obj->is<StrictArgumentsObject>())
   422         return true;
   424     StrictArgumentsObject &argsobj = obj->as<StrictArgumentsObject>();
   426     if (JSID_IS_INT(id)) {
   427         /*
   428          * arg can exceed the number of arguments if a script changed the
   429          * prototype to point to another Arguments object with a bigger argc.
   430          */
   431         unsigned arg = unsigned(JSID_TO_INT(id));
   432         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
   433             vp.set(argsobj.element(arg));
   434     } else {
   435         JS_ASSERT(JSID_IS_ATOM(id, cx->names().length));
   436         if (!argsobj.hasOverriddenLength())
   437             vp.setInt32(argsobj.initialLength());
   438     }
   439     return true;
   440 }
   442 static bool
   443 StrictArgSetter(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
   444 {
   445     if (!obj->is<StrictArgumentsObject>())
   446         return true;
   448     unsigned attrs;
   449     if (!baseops::GetAttributes(cx, obj, id, &attrs))
   450         return false;
   451     JS_ASSERT(!(attrs & JSPROP_READONLY));
   452     attrs &= (JSPROP_ENUMERATE | JSPROP_PERMANENT); /* only valid attributes */
   454     Rooted<StrictArgumentsObject*> argsobj(cx, &obj->as<StrictArgumentsObject>());
   456     if (JSID_IS_INT(id)) {
   457         unsigned arg = unsigned(JSID_TO_INT(id));
   458         if (arg < argsobj->initialLength()) {
   459             argsobj->setElement(cx, arg, vp);
   460             return true;
   461         }
   462     } else {
   463         JS_ASSERT(JSID_IS_ATOM(id, cx->names().length));
   464     }
   466     /*
   467      * For simplicity we use delete/define to replace the property with one
   468      * backed by the default Object getter and setter. Note that we rely on
   469      * args_delProperty to clear the corresponding reserved slot so the GC can
   470      * collect its value.
   471      */
   472     bool succeeded;
   473     return baseops::DeleteGeneric(cx, argsobj, id, &succeeded) &&
   474            baseops::DefineGeneric(cx, argsobj, id, vp, nullptr, nullptr, attrs);
   475 }
   477 static bool
   478 strictargs_resolve(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp)
   479 {
   480     objp.set(nullptr);
   482     Rooted<StrictArgumentsObject*> argsobj(cx, &obj->as<StrictArgumentsObject>());
   484     unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
   485     PropertyOp getter = StrictArgGetter;
   486     StrictPropertyOp setter = StrictArgSetter;
   488     if (JSID_IS_INT(id)) {
   489         uint32_t arg = uint32_t(JSID_TO_INT(id));
   490         if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
   491             return true;
   493         attrs |= JSPROP_ENUMERATE;
   494     } else if (JSID_IS_ATOM(id, cx->names().length)) {
   495         if (argsobj->hasOverriddenLength())
   496             return true;
   497     } else {
   498         if (!JSID_IS_ATOM(id, cx->names().callee) && !JSID_IS_ATOM(id, cx->names().caller))
   499             return true;
   501         attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
   502         getter = CastAsPropertyOp(argsobj->global().getThrowTypeError());
   503         setter = CastAsStrictPropertyOp(argsobj->global().getThrowTypeError());
   504     }
   506     if (!baseops::DefineGeneric(cx, argsobj, id, UndefinedHandleValue, getter, setter, attrs))
   507         return false;
   509     objp.set(argsobj);
   510     return true;
   511 }
   513 static bool
   514 strictargs_enumerate(JSContext *cx, HandleObject obj)
   515 {
   516     Rooted<StrictArgumentsObject*> argsobj(cx, &obj->as<StrictArgumentsObject>());
   518     /*
   519      * Trigger reflection in strictargs_resolve using a series of
   520      * js_LookupProperty calls.
   521      */
   522     RootedObject pobj(cx);
   523     RootedShape prop(cx);
   524     RootedId id(cx);
   526     // length
   527     id = NameToId(cx->names().length);
   528     if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
   529         return false;
   531     // callee
   532     id = NameToId(cx->names().callee);
   533     if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
   534         return false;
   536     // caller
   537     id = NameToId(cx->names().caller);
   538     if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
   539         return false;
   541     for (uint32_t i = 0, argc = argsobj->initialLength(); i < argc; i++) {
   542         id = INT_TO_JSID(i);
   543         if (!baseops::LookupProperty<CanGC>(cx, argsobj, id, &pobj, &prop))
   544             return false;
   545     }
   547     return true;
   548 }
   550 void
   551 ArgumentsObject::finalize(FreeOp *fop, JSObject *obj)
   552 {
   553     fop->free_(reinterpret_cast<void *>(obj->as<ArgumentsObject>().data()));
   554 }
   556 void
   557 ArgumentsObject::trace(JSTracer *trc, JSObject *obj)
   558 {
   559     ArgumentsObject &argsobj = obj->as<ArgumentsObject>();
   560     ArgumentsData *data = argsobj.data();
   561     MarkValue(trc, &data->callee, js_callee_str);
   562     MarkValueRange(trc, data->numArgs, data->args, js_arguments_str);
   563     MarkScriptUnbarriered(trc, &data->script, "script");
   564 }
   566 /*
   567  * The classes below collaborate to lazily reflect and synchronize actual
   568  * argument values, argument count, and callee function object stored in a
   569  * stack frame with their corresponding property values in the frame's
   570  * arguments object.
   571  */
   572 const Class NormalArgumentsObject::class_ = {
   573     "Arguments",
   574     JSCLASS_NEW_RESOLVE | JSCLASS_IMPLEMENTS_BARRIERS |
   575     JSCLASS_HAS_RESERVED_SLOTS(NormalArgumentsObject::RESERVED_SLOTS) |
   576     JSCLASS_HAS_CACHED_PROTO(JSProto_Object) | JSCLASS_BACKGROUND_FINALIZE,
   577     JS_PropertyStub,         /* addProperty */
   578     args_delProperty,
   579     JS_PropertyStub,         /* getProperty */
   580     JS_StrictPropertyStub,   /* setProperty */
   581     args_enumerate,
   582     reinterpret_cast<JSResolveOp>(args_resolve),
   583     JS_ConvertStub,
   584     ArgumentsObject::finalize,
   585     nullptr,                 /* call        */
   586     nullptr,                 /* hasInstance */
   587     nullptr,                 /* construct   */
   588     ArgumentsObject::trace
   589 };
   591 /*
   592  * Strict mode arguments is significantly less magical than non-strict mode
   593  * arguments, so it is represented by a different class while sharing some
   594  * functionality.
   595  */
   596 const Class StrictArgumentsObject::class_ = {
   597     "Arguments",
   598     JSCLASS_NEW_RESOLVE | JSCLASS_IMPLEMENTS_BARRIERS |
   599     JSCLASS_HAS_RESERVED_SLOTS(StrictArgumentsObject::RESERVED_SLOTS) |
   600     JSCLASS_HAS_CACHED_PROTO(JSProto_Object) | JSCLASS_BACKGROUND_FINALIZE,
   601     JS_PropertyStub,         /* addProperty */
   602     args_delProperty,
   603     JS_PropertyStub,         /* getProperty */
   604     JS_StrictPropertyStub,   /* setProperty */
   605     strictargs_enumerate,
   606     reinterpret_cast<JSResolveOp>(strictargs_resolve),
   607     JS_ConvertStub,
   608     ArgumentsObject::finalize,
   609     nullptr,                 /* call        */
   610     nullptr,                 /* hasInstance */
   611     nullptr,                 /* construct   */
   612     ArgumentsObject::trace
   613 };

mercurial