Example #1
0
    bool update()
    {
        if (!ic.generated) {
            Assembler masm;
            Value rval = f.regs.sp[-1];
            Value lval = f.regs.sp[-2];

            if (rval.isObject() && lval.isObject()) {
                generateObjectPath(masm);
                ic.generated = true;
            } else if (rval.isString() && lval.isString()) {
                generateStringPath(masm);
                ic.generated = true;
            } else {
                return true;
            }

            return linkForIC(masm);
        }

        return true;
    }
Example #2
0
JS_ALWAYS_INLINE bool
WeakMap_set_impl(JSContext *cx, CallArgs args)
{
    JS_ASSERT(IsWeakMap(args.thisv()));

    if (args.length() < 1) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                             "WeakMap.set", "0", "s");
        return false;
    }
    RootedObject key(cx, GetKeyArg(cx, args));
    if (!key)
        return false;

    Value value = (args.length() > 1) ? args[1] : UndefinedValue();

    Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
    ObjectValueMap *map = GetObjectMap(thisObj);
    if (!map) {
        map = cx->new_<ObjectValueMap>(cx, thisObj.get());
        if (!map->init()) {
            js_delete(map);
            JS_ReportOutOfMemory(cx);
            return false;
        }
        thisObj->setPrivate(map);
    }

    // Preserve wrapped native keys to prevent wrapper optimization.
    if (key->getClass()->ext.isWrappedNative ||
        (key->getClass()->flags & JSCLASS_IS_DOMJSCLASS) ||
        (key->isProxy() && GetProxyHandler(key)->family() == GetListBaseHandlerFamily()))
    {
        JS_ASSERT(cx->runtime->preserveWrapperCallback);
        if (!cx->runtime->preserveWrapperCallback(cx, key)) {
            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_WEAKMAP_KEY);
            return false;
        }
    }

    JS_ASSERT(key->compartment() == thisObj->compartment());
    JS_ASSERT_IF(value.isObject(), value.toObject().compartment() == thisObj->compartment());
    if (!map->put(key, value)) {
        JS_ReportOutOfMemory(cx);
        return false;
    }
    HashTableWriteBarrierPost(cx->compartment, map, key);

    args.rval().setUndefined();
    return true;
}
Example #3
0
    bool update()
    {
        if (!ic.generated) {
            MJITInstrumentation sps(&f.cx->runtime->spsProfiler);
            Assembler masm(&sps, &f);
            Value rval = f.regs.sp[-1];
            Value lval = f.regs.sp[-2];

            if (rval.isObject() && lval.isObject()) {
                generateObjectPath(masm);
                ic.generated = true;
            } else if (rval.isString() && lval.isString()) {
                generateStringPath(masm);
                ic.generated = true;
            } else {
                return true;
            }

            return linkForIC(masm);
        }

        return true;
    }
JSObject *
InlineFrameIterator::scopeChain() const
{
    SnapshotIterator s(si_);

    // scopeChain
    Value v = s.read();
    if (v.isObject()) {
        JS_ASSERT_IF(script()->hasAnalysis(), script()->analysis()->usesScopeChain());
        return &v.toObject();
    }

    return callee()->environment();
}
Example #5
0
bool
CrossCompartmentWrapper::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
                                    CallArgs srcArgs)
{
    RootedObject wrapper(cx, &srcArgs.thisv().toObject());
    JS_ASSERT(srcArgs.thisv().isMagic(JS_IS_CONSTRUCTING) ||
              !UncheckedUnwrap(wrapper)->isCrossCompartmentWrapper());

    RootedObject wrapped(cx, wrappedObject(wrapper));
    {
        AutoCompartment call(cx, wrapped);
        InvokeArgsGuard dstArgs;
        if (!cx->stack.pushInvokeArgs(cx, srcArgs.length(), &dstArgs))
            return false;

        Value *src = srcArgs.base();
        Value *srcend = srcArgs.array() + srcArgs.length();
        Value *dst = dstArgs.base();

        RootedValue source(cx);
        for (; src < srcend; ++src, ++dst) {
            source = *src;
            if (!cx->compartment->wrap(cx, &source))
                return false;
            *dst = source.get();

            // Handle |this| specially. When we rewrap on the other side of the
            // membrane, we might apply a same-compartment security wrapper that
            // will stymie this whole process. If that happens, unwrap the wrapper.
            // This logic can go away when same-compartment security wrappers go away.
            if ((src == srcArgs.base() + 1) && dst->isObject()) {
                RootedObject thisObj(cx, &dst->toObject());
                if (thisObj->isWrapper() &&
                    !Wrapper::wrapperHandler(thisObj)->isSafeToUnwrap())
                {
                    JS_ASSERT(!IsCrossCompartmentWrapper(thisObj));
                    *dst = ObjectValue(*Wrapper::wrappedObject(thisObj));
                }
            }
        }

        if (!CallNonGenericMethod(cx, test, impl, dstArgs))
            return false;

        srcArgs.rval().set(dstArgs.rval());
        dstArgs.pop();
    }
    return cx->compartment->wrap(cx, srcArgs.rval());
}
Example #6
0
void
StackSpace::markFrameSlots(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsbytecode *pc)
{
    Value *slotsBegin = fp->slots();

    if (!fp->isScriptFrame()) {
        JS_ASSERT(fp->isDummyFrame());
        gc::MarkValueRootRange(trc, slotsBegin, slotsEnd, "vm_stack");
        return;
    }

    /* If it's a scripted frame, we should have a pc. */
    JS_ASSERT(pc);

    JSScript *script = fp->script();
    if (!script->hasAnalysis() || !script->analysis()->ranLifetimes()) {
        gc::MarkValueRootRange(trc, slotsBegin, slotsEnd, "vm_stack");
        return;
    }

    /*
     * If the JIT ran a lifetime analysis, then it may have left garbage in the
     * slots considered not live. We need to avoid marking them. Additionally,
     * in case the analysis information is thrown out later, we overwrite these
     * dead slots with valid values so that future GCs won't crash. Analysis
     * results are thrown away during the sweeping phase, so we always have at
     * least one GC to do this.
     */
    analyze::AutoEnterAnalysis aea(script->compartment());
    analyze::ScriptAnalysis *analysis = script->analysis();
    uint32_t offset = pc - script->code;
    Value *fixedEnd = slotsBegin + script->nfixed;
    for (Value *vp = slotsBegin; vp < fixedEnd; vp++) {
        uint32_t slot = analyze::LocalSlot(script, vp - slotsBegin);

        /*
         * Will this slot be synced by the JIT? If not, replace with a dummy
         * value with the same type tag.
         */
        if (!analysis->trackSlot(slot) || analysis->liveness(slot).live(offset))
            gc::MarkValueRoot(trc, vp, "vm_stack");
        else if (vp->isObject())
            *vp = ObjectValue(fp->scopeChain()->global());
        else if (vp->isString())
            *vp = StringValue(trc->runtime->atomState.nullAtom);
    }

    gc::MarkValueRootRange(trc, fixedEnd, slotsEnd, "vm_stack");
}
Example #7
0
ErrorCopier::~ErrorCopier()
{
    JSContext *cx = ac.ref().context();
    if (ac.ref().origin() != cx->compartment && cx->isExceptionPending()) {
        Value exc = cx->getPendingException();
        if (exc.isObject() && exc.toObject().isError() && exc.toObject().getPrivate()) {
            cx->clearPendingException();
            ac.destroy();
            Rooted<JSObject*> errObj(cx, &exc.toObject());
            JSObject *copyobj = js_CopyErrorObject(cx, errObj, scope);
            if (copyobj)
                cx->setPendingException(ObjectValue(*copyobj));
        }
    }
}
Example #8
0
JSObject *
InlineFrameIterator::thisObject() const
{
    // JS_ASSERT(isConstructing(...));
    SnapshotIterator s(si_);

    // scopeChain
    s.skip();

    // In strict modes, |this| may not be an object and thus may not be
    // readable which can either segv in read or trigger the assertion.
    Value v = s.read();
    JS_ASSERT(v.isObject());
    return &v.toObject();
}
Example #9
0
bool rs::jsapi::Object::GetPrivate(const Value& value, uint64_t& data, void*& ptr) {
    auto get = false;
    if (value.isObject()) {
        auto obj = value.toObject();
        auto klass = JS_GetClass(obj);
        if (klass != nullptr && std::strcmp(klass->name, Object::class_.name) == 0) {
            auto state = GetState(obj);
            data = state->data;
            ptr = state->ptr;
            get = true;
        }
    }
    
    return get;
}
Example #10
0
bool rs::jsapi::Object::SetPrivate(Value& value, uint64_t data, void* ptr) {
    auto set = false;
    if (value.isObject()) {
        auto obj = value.toObject();
        auto klass = JS_GetClass(obj);
        if (klass != nullptr && std::strcmp(klass->name, Object::class_.name) == 0) {
            auto state = GetState(obj);
            state->data = data;
            state->ptr = ptr;
            set = true;
        }
    }
    
    return set;
}
Example #11
0
bool
js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
                             jsid *idp)
{
    JS_ASSERT(idval.isObject());
    if (obj->isXML()) {
        *idp = OBJECT_TO_JSID(&idval.toObject());
        return true;
    }

    if (js_GetLocalNameFromFunctionQName(&idval.toObject(), idp, cx))
        return true;

    return js_ValueToStringId(cx, idval, idp);
}
Example #12
0
ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, const Value &index)
{
    uint idx = index.asArrayIndex();
    if (idx == UINT_MAX || !object.isObject())
        return indexedGetterGeneric(l, object, index);

    Object *o = object.objectValue();
    if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
        Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
        if (idx < s->len)
            if (!s->data(idx).isEmpty())
                return s->data(idx).asReturnedValue();
    }

    return indexedGetterFallback(l, object, index);
}
Example #13
0
bool Wrapper::finalizeInBackground(Value priv)
{
    if (!priv.isObject())
        return true;

    /*
     * Make the 'background-finalized-ness' of the wrapper the same as the
     * wrapped object, to allow transplanting between them.
     *
     * If the wrapped object is in the nursery then we know it doesn't have a
     * finalizer, and so background finalization is ok.
     */
    if (IsInsideNursery(priv.toObject().runtimeFromMainThread(), &priv.toObject()))
        return true;
    return IsBackgroundFinalized(priv.toObject().tenuredGetAllocKind());
}
Example #14
0
bool
js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
                             jsid *idp)
{
    JS_ASSERT(idval.isObject());
    if (obj->isXML()) {
        *idp = OBJECT_TO_JSID(&idval.toObject());
        return true;
    }

    if (!js_IsFunctionQName(cx, &idval.toObject(), idp))
        return JS_FALSE;
    if (!JSID_IS_VOID(*idp))
        return true;

    return js_ValueToStringId(cx, idval, idp);
}
Example #15
0
ErrorCopier::~ErrorCopier()
{
    JSContext *cx = ac.context;
    if (cx->compartment == ac.destination &&
        ac.origin != ac.destination &&
        cx->isExceptionPending())
    {
        Value exc = cx->getPendingException();
        if (exc.isObject() && exc.toObject().isError() && exc.toObject().getPrivate()) {
            cx->clearPendingException();
            ac.leave();
            JSObject *copyobj = js_CopyErrorObject(cx, &exc.toObject(), scope);
            if (copyobj)
                cx->setPendingException(ObjectValue(*copyobj));
        }
    }
}
Example #16
0
bool
JSProxyHandler::construct(JSContext *cx, JSObject *proxy,
                          uintN argc, Value *argv, Value *rval)
{
    JS_ASSERT(OperationInProgress(cx, proxy));
    Value fval = GetConstruct(proxy);
    if (fval.isUndefined())
        return ExternalInvokeConstructor(cx, GetCall(proxy), argc, argv, rval);

    /*
     * FIXME: The Proxy proposal says to pass undefined as the this argument,
     * but primitive this is not supported yet. See bug 576644.
     */
    JS_ASSERT(fval.isObject());
    JSObject *thisobj = fval.toObject().getGlobal();
    return ExternalInvoke(cx, thisobj, fval, argc, argv, rval);
}
Example #17
0
Value& Path::make(Value& root) const {
  Value* node = &root;
  for (const auto& arg : args_) {
    if (arg.kind_ == PathArgument::kindIndex) {
      if (!node->isArray()) {
        // Error: node is not an array at position ...
      }
      node = &((*node)[arg.index_]);
    } else if (arg.kind_ == PathArgument::kindKey) {
      if (!node->isObject()) {
        // Error: node is not an object at position...
      }
      node = &((*node)[arg.key_]);
    }
  }
  return *node;
}
Example #18
0
void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value &index, const Value &v)
{
    uint idx = index.asArrayIndex();
    if (idx == UINT_MAX || !object.isObject()) {
        indexedSetterGeneric(l, object, index, v);
        return;
    }

    Object *o = object.objectValue();
    if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
        Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
        if (idx < s->len) {
            s->data(idx) = v;
            return;
        }
    }
    indexedSetterFallback(l, object, index, v);
}
Example #19
0
JSON_STATUS CVideoLibrary::GetTVShows(const CStdString &method, ITransportLayer *transport, IClient *client, const Value &parameterObject, Value &result)
{
  if (!(parameterObject.isObject() || parameterObject.isNull()))
    return InvalidParams;

  CVideoDatabase videodatabase;
  if (!videodatabase.Open())
    return InternalError;

//  int genreID = parameterObject.get("genreid", -1).asInt();

  CFileItemList items;
  if (videodatabase.GetTvShowsNav("videodb://", items))
    HandleFileItemList("tvshowid", false, "tvshows", items, parameterObject, result);

  videodatabase.Close();
  return OK;
}
Example #20
0
static bool
IsMaybeWrappedNativeFunction(const Value &v, Native native, JSFunction **fun = nullptr)
{
    if (!v.isObject())
        return false;

    JSObject *obj = CheckedUnwrap(&v.toObject());
    if (!obj)
        return false;

    if (!obj->is<JSFunction>())
        return false;

    if (fun)
        *fun = &obj->as<JSFunction>();

    return obj->as<JSFunction>().maybeNative() == native;
}
Example #21
0
 Value &Path::make(Value &root) const {
   Value *node = &root;
   for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
     const PathArgument &arg = *it;
     if (arg.kind_ == PathArgument::kindIndex) {
       if (!node->isArray()) {
         // Error: node is not an array at position ...
       }
       node = &((*node)[arg.index_]);
     } else if (arg.kind_ == PathArgument::kindKey) {
       if (!node->isObject()) {
         // Error: node is not an object at position...
       }
       node = &((*node)[arg.key_]);
     }
   }
   return *node;
 }
Example #22
0
static bool
GetDataProperty(JSContext *cx, const Value &objVal, HandlePropertyName field, MutableHandleValue v)
{
    if (!objVal.isObject())
        return LinkFail(cx, "accessing property of non-object");

    JSPropertyDescriptor desc;
    if (!JS_GetPropertyDescriptorById(cx, &objVal.toObject(), NameToId(field), 0, &desc))
        return false;

    if (!desc.obj)
        return LinkFail(cx, "property not present on object");

    if (desc.attrs & (JSPROP_GETTER | JSPROP_SETTER))
        return LinkFail(cx, "property is not a data property");

    v.set(desc.value);
    return true;
}
Example #23
0
static bool
GetDataProperty(JSContext *cx, const Value &objVal, HandlePropertyName field, MutableHandleValue v)
{
    if (!objVal.isObject())
        return LinkFail(cx, "accessing property of non-object");

    Rooted<JSPropertyDescriptor> desc(cx);
    if (!JS_GetPropertyDescriptorById(cx, &objVal.toObject(), NameToId(field), 0, &desc))
        return false;

    if (!desc.object())
        return LinkFail(cx, "property not present on object");

    if (desc.hasGetterOrSetterObject())
        return LinkFail(cx, "property is not a data property");

    v.set(desc.value());
    return true;
}
Example #24
0
JSON_STATUS CXBMCOperations::Log(const CStdString &method, ITransportLayer *transport, IClient *client, const Value &parameterObject, Value &result)
{
  if (parameterObject.isString())
    CLog::Log(LOGDEBUG, "%s", parameterObject.asString().c_str());
  else if (parameterObject.isObject() && parameterObject.isMember("message") && parameterObject["message"].isString())
  {
    if (parameterObject.isMember("level") && !parameterObject["level"].isString())
      return InvalidParams;

    CStdString strlevel = parameterObject.get("level", "debug").asString();
    int level = ParseLogLevel(strlevel.ToLower().c_str());

    CLog::Log(level, "%s", parameterObject["message"].asString().c_str());
  }
  else
    return InvalidParams;

  return ACK;
}
static JSBool
GC(JSContext *cx, unsigned argc, jsval *vp)
{
    /*
     * If the first argument is 'compartment', we collect any compartments
     * previously scheduled for GC via schedulegc. If the first argument is an
     * object, we collect the object's compartment (and any other compartments
     * scheduled for GC). Otherwise, we collect all compartments.
     */
    JSBool compartment = false;
    if (argc == 1) {
        Value arg = vp[2];
        if (arg.isString()) {
            if (!JS_StringEqualsAscii(cx, arg.toString(), "compartment", &compartment))
                return false;
        } else if (arg.isObject()) {
            PrepareZoneForGC(UnwrapObject(&arg.toObject())->zone());
            compartment = true;
        }
    }

#ifndef JS_MORE_DETERMINISTIC
    size_t preBytes = cx->runtime->gcBytes;
#endif

    if (compartment)
        PrepareForDebugGC(cx->runtime);
    else
        PrepareForFullGC(cx->runtime);
    GCForReason(cx->runtime, gcreason::API);

    char buf[256] = { '\0' };
#ifndef JS_MORE_DETERMINISTIC
    JS_snprintf(buf, sizeof(buf), "before %lu, after %lu\n",
                (unsigned long)preBytes, (unsigned long)cx->runtime->gcBytes);
#endif
    JSString *str = JS_NewStringCopyZ(cx, buf);
    if (!str)
        return false;
    *vp = STRING_TO_JSVAL(str);
    return true;
}
bool 
Reader::parse( const char *beginDoc, const char *endDoc, 
               Value &root,
               bool collectComments )
{
   if ( !features_.allowComments_ )
   {
      collectComments = false;
   }

   begin_ = beginDoc;
   end_ = endDoc;
   collectComments_ = collectComments;
   current_ = begin_;
   lastValueEnd_ = 0;
   lastValue_ = 0;
   commentsBefore_ = "";
   errors_.clear();
   while ( !nodes_.empty() )
      nodes_.pop();
   nodes_.push( &root );
   
   bool successful = readValue();
   Token token;
   skipCommentTokens( token );
   if ( collectComments_  &&  !commentsBefore_.empty() )
      root.setComment( commentsBefore_, commentAfter );
   if ( features_.strictRoot_ )
   {
      if ( !root.isArray()  &&  !root.isObject() )
      {
         // Set error location to start of doc, ideally should be first token found in doc
         token.type_ = tokenError;
         token.start_ = beginDoc;
         token.end_ = endDoc;
         addError( "A valid JSON document must be either an array or an object value.",
                   token );
         return false;
      }
   }
   return successful;
}
Example #27
0
bool
JSRuntime::cloneSelfHostedValueById(JSContext *cx, jsid id, HandleObject holder, Value *vp)
{
    Value funVal;
    {
        RootedObject shg(cx, selfHostedGlobal_);
        AutoCompartment ac(cx, shg);
        if (!JS_GetPropertyById(cx, shg, id, &funVal) || !funVal.isObject())
            return false;
    }

    RootedObject clone(cx, JS_CloneFunctionObject(cx, &funVal.toObject(), cx->global()));
    if (!clone)
        return false;

    vp->setObjectOrNull(clone);
    DebugOnly<bool> ok = JS_DefinePropertyById(cx, holder, id, *vp, NULL, NULL, 0);
    JS_ASSERT(ok);
    return true;
}
Example #28
0
bool
Wrapper::finalizeInBackground(const Value& priv) const
{
    if (!priv.isObject())
        return true;

    /*
     * Make the 'background-finalized-ness' of the wrapper the same as the
     * wrapped object, to allow transplanting between them.
     */
    JSObject* wrapped = MaybeForwarded(&priv.toObject());
    gc::AllocKind wrappedKind;
    if (IsInsideNursery(wrapped)) {
        JSRuntime *rt = wrapped->runtimeFromActiveCooperatingThread();
        wrappedKind = wrapped->allocKindForTenure(rt->gc.nursery());
    } else {
        wrappedKind = wrapped->asTenured().getAllocKind();
    }
    return IsBackgroundFinalized(wrappedKind);
}
Example #29
0
JSBool
js_ValueToBoolean(const Value &v)
{
    if (v.isInt32())
        return v.toInt32() != 0;
    if (v.isString())
        return v.toString()->length() != 0;
    if (v.isObject())
        return JS_TRUE;
    if (v.isNullOrUndefined())
        return JS_FALSE;
    if (v.isDouble()) {
        double d;

        d = v.toDouble();
        return !JSDOUBLE_IS_NaN(d) && d != 0;
    }
    JS_ASSERT(v.isBoolean());
    return v.toBoolean();
}
Example #30
0
void CFileItemHandler::Sort(CFileItemList &items, const Value &parameterObject)
{
  Value sort = parameterObject["sort"];

  if (sort.isObject())
  {
    CStdString method = sort["method"].isString() ? sort["method"].asString() : "none";
    CStdString order  = sort["order"].isString() ? sort["order"].asString() : "ascending";
    bool ignorethe    = sort["ignorethe"].isBool() ? sort["ignorethe"].asBool() : false;

    method = method.ToLower();
    order  = order.ToLower();

    SORT_METHOD sortmethod = SORT_METHOD_NONE;
    SORT_ORDER  sortorder  = SORT_ORDER_ASC;

    if (ParseSortMethods(method, ignorethe, order, sortmethod, sortorder))
      items.Sort(sortmethod, sortorder);
  }
}