char* JSValue::description() { static const size_t size = 32; static char description[size]; if (!*this) snprintf(description, size, "<JSValue()>"); else if (isInt32()) snprintf(description, size, "Int32: %d", asInt32()); else if (isDouble()) snprintf(description, size, "Double: %lf", asDouble()); else if (isCell()) snprintf(description, size, "Cell: %p", asCell()); else if (isTrue()) snprintf(description, size, "True"); else if (isFalse()) snprintf(description, size, "False"); else if (isNull()) snprintf(description, size, "Null"); else { ASSERT(isUndefined()); snprintf(description, size, "Undefined"); } return description; }
Object c_GenMapWaitHandle::ti_create(const Variant& dependencies) { if (UNLIKELY(!dependencies.isObject() || dependencies.getObjectData()->getCollectionType() != Collection::MapType)) { Object e(SystemLib::AllocInvalidArgumentExceptionObject( "Expected dependencies to be an instance of Map")); throw e; } assert(dependencies.getObjectData()->instanceof(c_Map::classof())); auto deps = p_Map::attach(c_Map::Clone(dependencies.getObjectData())); for (ssize_t iter_pos = deps->iter_begin(); deps->iter_valid(iter_pos); iter_pos = deps->iter_next(iter_pos)) { auto* current = tvAssertCell(deps->iter_value(iter_pos)); if (UNLIKELY(!c_WaitHandle::fromCell(current))) { Object e(SystemLib::AllocInvalidArgumentExceptionObject( "Expected dependencies to be a map of WaitHandle instances")); throw e; } } Object exception; for (ssize_t iter_pos = deps->iter_begin(); deps->iter_valid(iter_pos); iter_pos = deps->iter_next(iter_pos)) { auto* current = tvAssertCell(deps->iter_value(iter_pos)); assert(current->m_type == KindOfObject); assert(current->m_data.pobj->instanceof(c_WaitHandle::classof())); auto child = static_cast<c_WaitHandle*>(current->m_data.pobj); if (child->isSucceeded()) { auto k = deps->iter_key(iter_pos); deps->set(k.asCell(), &child->getResult()); } else if (child->isFailed()) { putException(exception, child->getException()); } else { assert(child->instanceof(c_WaitableWaitHandle::classof())); auto child_wh = static_cast<c_WaitableWaitHandle*>(child); p_GenMapWaitHandle my_wh = NEWOBJ(c_GenMapWaitHandle)(); my_wh->initialize(exception, deps.get(), iter_pos, child_wh); AsioSession* session = AsioSession::Get(); if (UNLIKELY(session->hasOnGenMapCreateCallback())) { session->onGenMapCreate(my_wh.get(), dependencies); } return my_wh; } } if (exception.isNull()) { return Object::attach(c_StaticWaitHandle::CreateSucceeded( make_tv<KindOfObject>(deps.detach()))); } else { return Object::attach(c_StaticWaitHandle::CreateFailed(exception.detach())); } }
double JSValue::toNumberSlowCase(ExecState* exec) const { ASSERT(!isInt32() && !isDouble()); if (isCell()) return asCell()->toNumber(exec); if (isTrue()) return 1.0; return isUndefined() ? PNaN : 0; // null and false both convert to 0. }
void c_GenMapWaitHandle::onUnblocked() { assert(getState() == STATE_BLOCKED); for (; m_deps->iter_valid(m_iterPos); m_iterPos = m_deps->iter_next(m_iterPos)) { auto* current = tvAssertCell(m_deps->iter_value(m_iterPos)); assert(current->m_type == KindOfObject); assert(current->m_data.pobj->instanceof(c_WaitHandle::classof())); auto child = static_cast<c_WaitHandle*>(current->m_data.pobj); if (child->isSucceeded()) { auto k = m_deps->iter_key(m_iterPos); m_deps->set(k.asCell(), &child->getResult()); } else if (child->isFailed()) { putException(m_exception, child->getException()); } else { assert(child->instanceof(c_WaitHandle::classof())); auto child_wh = static_cast<c_WaitableWaitHandle*>(child); try { if (isInContext()) { child_wh->enterContext(getContextIdx()); } detectCycle(child_wh); blockOn(child_wh); return; } catch (const Object& cycle_exception) { putException(m_exception, cycle_exception.get()); } } } auto const parentChain = getFirstParent(); if (m_exception.isNull()) { setState(STATE_SUCCEEDED); tvWriteObject(m_deps.get(), &m_resultOrException); } else { setState(STATE_FAILED); tvWriteObject(m_exception.get(), &m_resultOrException); m_exception = nullptr; } m_deps = nullptr; UnblockChain(parentChain); decRefObj(this); }
void JSValue::dumpForBacktrace(PrintStream& out) const { if (!*this) out.print("<JSValue()>"); else if (isInt32()) out.printf("%d", asInt32()); else if (isDouble()) out.printf("%lf", asDouble()); else if (isCell()) { if (asCell()->inherits(JSString::info())) { JSString* string = jsCast<JSString*>(asCell()); const StringImpl* impl = string->tryGetValueImpl(); if (impl) out.print("\"", impl, "\""); else out.print("(unresolved string)"); } else if (asCell()->inherits(Structure::info())) { out.print("Structure[ ", asCell()->structure()->classInfo()->className); #if USE(JSVALUE64) out.print(" ID: ", asCell()->structureID()); #endif out.print("]: ", RawPointer(asCell())); } else { out.print("Cell[", asCell()->structure()->classInfo()->className); #if USE(JSVALUE64) out.print(" ID: ", asCell()->structureID()); #endif out.print("]: ", RawPointer(asCell())); } } else if (isTrue()) out.print("True"); else if (isFalse()) out.print("False"); else if (isNull()) out.print("Null"); else if (isUndefined()) out.print("Undefined"); else out.print("INVALID"); }
bool jsIsObjectType(AJValue v) { if (!v.isCell()) return v.isNull(); AJType type = asCell(v)->structure()->typeInfo().type(); if (type == NumberType || type == StringType) return false; if (type == ObjectType) { if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) return false; CallData callData; if (asObject(v)->getCallData(callData) != CallTypeNone) return false; } return true; }
JSString* JSValue::toStringSlowCase(ExecState* exec, bool returnEmptyStringOnError) const { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); auto errorValue = [&] () -> JSString* { if (returnEmptyStringOnError) return jsEmptyString(exec); return nullptr; }; ASSERT(!isString()); if (isInt32()) { auto integer = asInt32(); if (static_cast<unsigned>(integer) <= 9) return vm.smallStrings.singleCharacterString(integer + '0'); return jsNontrivialString(&vm, vm.numericStrings.add(integer)); } if (isDouble()) return jsString(&vm, vm.numericStrings.add(asDouble())); if (isTrue()) return vm.smallStrings.trueString(); if (isFalse()) return vm.smallStrings.falseString(); if (isNull()) return vm.smallStrings.nullString(); if (isUndefined()) return vm.smallStrings.undefinedString(); if (isSymbol()) { throwTypeError(exec, scope, ASCIILiteral("Cannot convert a symbol to a string")); return errorValue(); } ASSERT(isCell()); JSValue value = asCell()->toPrimitive(exec, PreferString); if (vm.exception()) return errorValue(); ASSERT(!value.isObject()); JSString* result = value.toString(exec); if (vm.exception()) return errorValue(); return result; }
JSValue* JSValue::getByIndex(ExecState* exec, unsigned propertyName) const { switch (type()) { case StringType: { UString s = static_cast<const StringImp*>(asCell())->value(); if (propertyName < static_cast<unsigned>(s.size())) { return jsString(s.substr(propertyName, 1)); } // fall through } default: { JSObject* obj = toObject(exec); PropertySlot slot; if (obj->getPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, obj, propertyName); return jsUndefined(); } } }
bool JSValue::isValidCallee() { return asObject(asCell())->globalObject(); }
void JSValue::dumpInContextAssumingStructure( PrintStream& out, DumpContext* context, Structure* structure) const { if (!*this) out.print("<JSValue()>"); else if (isInt32()) out.printf("Int32: %d", asInt32()); else if (isDouble()) { #if USE(JSVALUE64) out.printf("Double: %lld, %lf", (long long)reinterpretDoubleToInt64(asDouble()), asDouble()); #else union { double asDouble; uint32_t asTwoInt32s[2]; } u; u.asDouble = asDouble(); out.printf("Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble()); #endif } else if (isCell()) { if (structure->classInfo()->isSubClassOf(JSString::info())) { JSString* string = jsCast<JSString*>(asCell()); out.print("String"); if (string->isRope()) out.print(" (rope)"); const StringImpl* impl = string->tryGetValueImpl(); if (impl) { if (impl->isAtomic()) out.print(" (atomic)"); if (impl->isAtomic()) out.print(" (identifier)"); if (impl->isSymbol()) out.print(" (symbol)"); } else out.print(" (unresolved)"); out.print(": ", impl); } else if (structure->classInfo()->isSubClassOf(Symbol::info())) out.print("Symbol: ", RawPointer(asCell())); else if (structure->classInfo()->isSubClassOf(Structure::info())) out.print("Structure: ", inContext(*jsCast<Structure*>(asCell()), context)); else if (structure->classInfo()->isSubClassOf(JSObject::info())) { out.print("Object: ", RawPointer(asCell())); out.print(" with butterfly ", RawPointer(asObject(asCell())->butterfly())); out.print(" (", inContext(*structure, context), ")"); } else { out.print("Cell: ", RawPointer(asCell())); out.print(" (", inContext(*structure, context), ")"); } #if USE(JSVALUE64) out.print(", ID: ", asCell()->structureID()); #endif } else if (isTrue()) out.print("True"); else if (isFalse()) out.print("False"); else if (isNull()) out.print("Null"); else if (isUndefined()) out.print("Undefined"); else out.print("INVALID"); }
void JSValue::dumpInContext(PrintStream& out, DumpContext* context) const { dumpInContextAssumingStructure( out, context, (!!*this && isCell()) ? asCell()->structure() : nullptr); }
bool Variant::isResource() const { auto const cell = asCell(); return (cell->m_type == KindOfResource); }
Object c_GenMapWaitHandle::ti_create(const Variant& dependencies) { ObjectData* obj; if (UNLIKELY(!dependencies.isObject() || !(obj = dependencies.getObjectData())->isCollection() || obj->collectionType() != CollectionType::Map)) { SystemLib::throwInvalidArgumentExceptionObject( "Expected dependencies to be an instance of Map"); } assertx(obj->collectionType() == CollectionType::Map); auto deps = req::ptr<c_Map>::attach(c_Map::Clone(obj)); auto ctx_idx = std::numeric_limits<context_idx_t>::max(); for (ssize_t iter_pos = deps->iter_begin(); deps->iter_valid(iter_pos); iter_pos = deps->iter_next(iter_pos)) { auto* current = tvAssertCell(deps->iter_value(iter_pos)); auto const child = c_WaitHandle::fromCell(current); if (UNLIKELY(!child)) { SystemLib::throwInvalidArgumentExceptionObject( "Expected dependencies to be a map of WaitHandle instances"); } if (!child->isFinished()) { ctx_idx = std::min( ctx_idx, static_cast<c_WaitableWaitHandle*>(child)->getContextIdx() ); } } Object exception; for (ssize_t iter_pos = deps->iter_begin(); deps->iter_valid(iter_pos); iter_pos = deps->iter_next(iter_pos)) { auto* current = tvAssertCell(deps->iter_value(iter_pos)); assert(current->m_type == KindOfObject); assert(current->m_data.pobj->instanceof(c_WaitHandle::classof())); auto child = static_cast<c_WaitHandle*>(current->m_data.pobj); if (child->isSucceeded()) { auto k = deps->iter_key(iter_pos); auto result = child->getResult(); deps->set(k.asCell(), &result); } else if (child->isFailed()) { putException(exception, child->getException()); } else { assert(child->instanceof(c_WaitableWaitHandle::classof())); auto child_wh = static_cast<c_WaitableWaitHandle*>(child); auto my_wh = req::make<c_GenMapWaitHandle>(); my_wh->initialize(exception, deps.get(), iter_pos, ctx_idx, child_wh); AsioSession* session = AsioSession::Get(); if (UNLIKELY(session->hasOnGenMapCreate())) { session->onGenMapCreate(my_wh.get(), dependencies); } return Object(std::move(my_wh)); } } if (exception.isNull()) { return Object::attach(c_StaticWaitHandle::CreateSucceeded( make_tv<KindOfObject>(deps.detach()))); } else { return Object::attach(c_StaticWaitHandle::CreateFailed(exception.detach())); } }
bool JSValue::isValidCallee() { return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject(); }