/*static*/ CprotoentObject* CNetdbClass::getprotoent(ScriptObject* self) { struct protoent *pp; pp = VMPI_getprotoent(); if( pp ) { ShellToplevel* shelltop = (ShellToplevel*)self->toplevel(); CprotoentClass *pc = shelltop->getShellClasses()->get_protoentClass(); CprotoentObject *po = pc->constructObject(); po->set_p_name( self->core()->newStringUTF8( pp->p_name ) ); po->set_p_proto( pp->p_proto ); Toplevel* toplevel = self->toplevel(); ArrayObject *aliases = toplevel->arrayClass()->newArray(); int count = 0; int i; for( i=0; pp->p_aliases[i] != NULL; ++i ) { aliases->setUintProperty( count++, self->core()->newStringUTF8( pp->p_aliases[i] )->atom()); } po->set_p_aliases( aliases ); return po; } return NULL; }
/** * Array.prototype.pop() * TRANSFERABLE: Needs to support generic objects as well as Array objects */ /*static*/ Atom ArrayClass::generic_pop(Toplevel* toplevel, Atom thisAtom) { ArrayObject *a = isArray(toplevel, thisAtom); if (a) return a->pop(); if (!AvmCore::isObject(thisAtom)) return undefinedAtom; // Different than Rhino (because of delete) but matches 262.pdf ScriptObject *d = AvmCore::atomToScriptObject(thisAtom); uint32 len = getLengthHelper(toplevel, d); if (!len) { setLengthHelper(toplevel, d, 0); return undefinedAtom; } else { Atom outAtom = d->getUintProperty (len-1); d->delUintProperty (len - 1); setLengthHelper(toplevel, d, len - 1); return outAtom; } }
/** * Array.prototype.reverse() * TRANSFERABLE: Needs to support generic objects as well as Array objects */ /*static*/ Atom ArrayClass::generic_reverse(Toplevel* toplevel, Atom thisAtom) { ArrayObject *a = isArray(toplevel, thisAtom); if (a && (a->isSimpleDense())) { a->m_denseArr.reverse(); return thisAtom; } // generic object version if (!AvmCore::isObject(thisAtom)) return thisAtom; ScriptObject *d = AvmCore::atomToScriptObject(thisAtom); uint32 j = getLengthHelper(toplevel, d); uint32 i = 0; if (j) j--; while (i < j) { Atom frontAtom = d->getUintProperty(i); Atom backAtom = d->getUintProperty(j); d->setUintProperty(i++, backAtom); d->setUintProperty(j--, frontAtom); } return thisAtom; }
bool SamplerScript::set_stack(ScriptObject* self, ClassFactoryClass* cf, const Sample& sample, SampleObject* sam) { if (sample.stack.depth > 0) { Toplevel* toplevel = self->toplevel(); AvmCore* core = toplevel->core(); Sampler* s = core->get_sampler(); StackFrameClass* sfcc = (StackFrameClass*)cf->get_StackFrameClass(); ArrayObject* stack = toplevel->arrayClass()->newArray(sample.stack.depth); StackTrace::Element* e = (StackTrace::Element*)sample.stack.trace; for(uint32_t i=0; i < sample.stack.depth; i++, e++) { StackFrameObject* sf = sfcc->constructObject(); // at every allocation the sample buffer could overflow and the samples could be deleted // the StackTrace::Element pointer is a raw pointer into that buffer so we need to check // that its still around before dereferencing e uint32_t num; if (s->getSamples(num) == NULL) return false; sf->setconst_name(e->name()); // NOT e->info()->name() because e->name() can be a fake name sf->setconst_file(e->filename()); sf->setconst_line(e->linenum()); sf->setconst_scriptID(static_cast<double>(e->functionId())); stack->setUintProperty(i, sf->atom()); } sam->setconst_stack(stack); } return true; }
ArrayObject * ProgramClass::_getEnviron() { Toplevel *toplevel = this->toplevel(); AvmCore *core = this->core(); ArrayObject *array = toplevel->arrayClass()->newArray(); #if AVMSYSTEM_WIN32 wchar **cur = VMPI_GetEnviron16(); int i = 0; while( cur[i] ) { Stringp value = core->newStringUTF16(cur[i]); StUTF8String valueUTF8(value); array->setUintProperty( i, core->newStringUTF8( valueUTF8.c_str() )->atom() ); i++; } #else char **cur = VMPI_GetEnviron(); int i = 0; while( cur[i] ) { array->setUintProperty( i, core->newStringUTF8( cur[i] )->atom() ); i++; } #endif return array; }
inline bool ForOfIterator::nextFromOptimizedArray(MutableHandleValue vp, bool* done) { MOZ_ASSERT(index != NOT_ARRAY); if (!CheckForInterrupt(cx_)) return false; ArrayObject* arr = &iterator->as<ArrayObject>(); if (index >= arr->length()) { vp.setUndefined(); *done = true; return true; } *done = false; // Try to get array element via direct access. if (index < arr->getDenseInitializedLength()) { vp.set(arr->getDenseElement(index)); if (!vp.isMagic(JS_ELEMENTS_HOLE)) { ++index; return true; } } return GetElement(cx_, iterator, iterator, index++, vp); }
JSObject * InitRestParameter(JSContext *cx, uint32_t length, Value *rest, HandleObject templateObj, HandleObject objRes) { if (objRes) { Rooted<ArrayObject*> arrRes(cx, &objRes->as<ArrayObject>()); JS_ASSERT(!arrRes->getDenseInitializedLength()); JS_ASSERT(arrRes->type() == templateObj->type()); // Fast path: we managed to allocate the array inline; initialize the // slots. if (length > 0) { if (!arrRes->ensureElements(cx, length)) return nullptr; arrRes->setDenseInitializedLength(length); arrRes->initDenseElements(0, rest, length); arrRes->setLengthInt32(length); } return arrRes; } NewObjectKind newKind = templateObj->type()->shouldPreTenure() ? TenuredObject : GenericObject; ArrayObject *arrRes = NewDenseCopiedArray(cx, length, rest, nullptr, newKind); if (arrRes) arrRes->setType(templateObj->type()); return arrRes; }
static Atom twoInts(ScriptObject *obj, unsigned int high, unsigned int low) { Atom highatom = obj->core()->uintToAtom(high); Atom lowatom = obj->core()->uintToAtom(low); ArrayObject *ret = obj->toplevel()->arrayClass()->newArray(2); ret->setUintProperty(0, highatom); ret->setUintProperty(1, lowatom); return ret->atom(); }
/*static*/ ChostentObject* CNetdbClass::gethostbyname(ScriptObject* self, Stringp name) { AvmCore *core = self->core(); Toplevel* toplevel = self->toplevel(); if( !name ) { toplevel->throwArgumentError(kNullArgumentError, "name"); } struct hostent *he; StUTF8String nameUTF8(name); he = VMPI_gethostbyname( nameUTF8.c_str() ); if( he ) { ShellToplevel* shelltop = (ShellToplevel*)self->toplevel(); ChostentClass *hc = shelltop->getShellClasses()->get_hostentClass(); ChostentObject *ho = hc->constructObject(); ho->set_h_name( core->newStringUTF8( he->h_name ) ); ArrayObject *aliases = toplevel->arrayClass()->newArray(); int count = 0; int i; for( i=0; he->h_aliases[i] != NULL; ++i ) { aliases->setUintProperty( count++, core->newStringUTF8( he->h_aliases[i] )->atom() ); } ho->set_h_aliases( aliases ); ho->set_h_addrtype( he->h_addrtype ); ho->set_h_length( he->h_length ); ArrayObject *addrlist = toplevel->arrayClass()->newArray(); count = 0; for( i=0; he->h_addr_list[i] != NULL; ++i ) { struct in_addr in; memcpy(&in.s_addr, he->h_addr_list[i], sizeof (in.s_addr)); CIn_AddrClass *ac = shelltop->getShellClasses()->get_in_addrClass(); CIn_AddrObject *ao = ac->constructObject(); ao->set_s_addr( in.s_addr ); addrlist->setUintProperty( count++, ao->toAtom() ); //addrlist->setUintProperty( count++, core->newStringUTF8( inet_ntoa(in) )->atom() ); } ho->set_h_addr_list( addrlist ); return ho; } return NULL; }
Atom RegExpObject::AS3_exec(Stringp subject) { if (!subject) { subject = core()->knull; } UsesUTF8String utf8Subject(subject); ArrayObject *result = _exec(subject, utf8Subject); return result ? result->atom() : nullStringAtom; }
ArrayObject* HTTPFormClass::convertForm(std::vector<FormEntry>& vec) { AvmCore *core = this->core(); ArrayObject *out = this->toplevel()->arrayClass->newArray(); for (std::vector<FormEntry>::iterator it=vec.begin(); it!=vec.end(); it++) { ArrayObject* arr; Stringp key = core->internStringUTF8((*it).name.data(), (*it).name.length()); Stringp value = core->internStringUTF8((*it).value.data(), (*it).value.length()); //we have it, append if (out->hasStringProperty(key)) { arr = (ArrayObject*) core->atomToScriptObject(out->getStringProperty(key)); arr->setUintProperty(arr->get_length(), value->atom()); } //create array else { arr = this->toplevel()->arrayClass->newArray(); arr->setUintProperty(0, value->atom()); out->setStringProperty(key, arr->atom()); } } return out; }
ArrayObject* StringClass::_split(Stringp in, Atom delimAtom, uint32 limit) { AvmCore* core = this->core(); if (limit == 0) return toplevel()->arrayClass->newArray(); if (in->length() == 0) { ArrayObject* out = toplevel()->arrayClass->newArray(); out->setUintProperty(0,in->atom()); return out; } // handle RegExp case if (AvmCore::istype(delimAtom, core->traits.regexp_itraits)) { RegExpObject *reObj = (RegExpObject*) AvmCore::atomToScriptObject(delimAtom); return reObj->split(in, limit); } ArrayObject *out = toplevel()->arrayClass->newArray(); Stringp delim = core->string(delimAtom); int ilen = in->length(); int dlen = delim->length(); int count = 0; if (dlen <= 0) { // delim is empty string, split on each char for (int i = 0; i < ilen && (unsigned)i < limit; i++) { Stringp sub = in->substr(i, 1); out->setUintProperty(count++, sub->atom()); } return out; } int32_t start = 0; while (start <= in->length()) { if ((limit != 0xFFFFFFFFUL) && (count >= (int) limit)) break; int32_t bgn = in->indexOf(delim, start); if (bgn < 0) // not found, use the string remainder bgn = in->length(); Stringp sub = in->substring(start, bgn); out->setUintProperty(count++, sub->atom()); start = bgn + delim->length(); } return out; }
bool SetObject::construct(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!ThrowIfNotConstructing(cx, args, "Set")) return false; RootedObject proto(cx); RootedObject newTarget(cx, &args.newTarget().toObject()); if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) return false; Rooted<SetObject*> obj(cx, SetObject::create(cx, proto)); if (!obj) return false; if (!args.get(0).isNullOrUndefined()) { RootedValue iterable(cx, args[0]); bool optimized = false; if (!IsOptimizableInitForSet<GlobalObject::getOrCreateSetPrototype, isBuiltinAdd>(cx, obj, iterable, &optimized)) return false; if (optimized) { RootedValue keyVal(cx); Rooted<HashableValue> key(cx); ValueSet* set = obj->getData(); ArrayObject* array = &iterable.toObject().as<ArrayObject>(); for (uint32_t index = 0; index < array->getDenseInitializedLength(); ++index) { keyVal.set(array->getDenseElement(index)); MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE)); if (!key.setValue(cx, keyVal)) return false; if (!WriteBarrierPost(cx->runtime(), obj, keyVal) || !set->put(key)) { ReportOutOfMemory(cx); return false; } } } else { FixedInvokeArgs<1> args2(cx); args2[0].set(args[0]); RootedValue thisv(cx, ObjectValue(*obj)); if (!CallSelfHostedFunction(cx, cx->names().SetConstructorInit, thisv, args2, args2.rval())) return false; } } args.rval().setObject(*obj); return true; }
ArrayObject* HTTPFormClass::listFileKeys() { AvmCore *core = this->core(); ArrayObject *out = this->toplevel()->arrayClass->newArray(); for (std::vector<FormFile>::iterator it=sapi->files.begin(); it!=sapi->files.end(); it++) { out->setUintProperty(out->get_length(), core->newStringUTF8((*it).name.data(), (*it).name.length())->atom()); } return out; }
ArrayObject * ProgramClass::_getArgv() { Toplevel *toplevel = this->toplevel(); AvmCore *core = this->core(); ArrayObject *array = toplevel->arrayClass()->newArray(); for( int i=0; i<user_argc; i++ ) { array->setUintProperty(i, core->newStringUTF8(user_argv[i])->atom()); } return array; }
ArrayObject* RegExpObject::match(Stringp subject) { UsesUTF8String utf8Subject(subject); if (!get_global()) { return _exec(subject, utf8Subject); } else { ArrayObject *a = toplevel()->arrayClass->newArray(); int oldLastIndex = m_lastIndex; m_lastIndex = 0; int n = 0; ArrayObject* matchArray; while (true) { int last = m_lastIndex; int matchIndex = 0, matchLen = 0; int startIndex = Utf16ToUtf8Index(subject, utf8Subject, m_lastIndex); matchArray = _exec(subject, utf8Subject, startIndex, matchIndex, matchLen); m_lastIndex = Utf8ToUtf16Index(subject, utf8Subject, matchIndex+matchLen); if ((matchArray == NULL) || (last == m_lastIndex)) break; a->setUintProperty(n++, matchArray->getUintProperty(0)); } if (m_lastIndex == oldLastIndex) { m_lastIndex++; } return a; } }
void DynamicObject::SetIsPrototype() { DynamicTypeHandler* currentTypeHandler = this->GetTypeHandler(); Js::DynamicType* oldType = this->GetDynamicType(); #if DBG bool wasShared = currentTypeHandler->GetIsShared(); bool wasPrototype = (currentTypeHandler->GetFlags() & DynamicTypeHandler::IsPrototypeFlag) != 0; Assert(!DynamicTypeHandler::IsolatePrototypes() || !currentTypeHandler->RespectsIsolatePrototypes() || !currentTypeHandler->GetIsOrMayBecomeShared() || !wasPrototype); #endif // If this handler is not shared and it already has a prototype flag then we must have taken the required // type transition (if any) earlier when the singleton object first became a prototype. if ((currentTypeHandler->GetFlags() & (DynamicTypeHandler::IsSharedFlag | DynamicTypeHandler::IsPrototypeFlag)) == DynamicTypeHandler::IsPrototypeFlag) { Assert(this->GetObjectArray() == nullptr || (this->GetObjectArray()->GetTypeHandler()->GetFlags() & DynamicTypeHandler::IsPrototypeFlag) != 0); return; } currentTypeHandler->SetIsPrototype(this); // Get type handler again, in case it got changed by SetIsPrototype. currentTypeHandler = this->GetTypeHandler(); // Set the object array as a prototype as well, so if it is an ES5 array, we will disable the array set element fast path ArrayObject * objectArray = this->GetObjectArray(); if (objectArray) { objectArray->SetIsPrototype(); } #if DBG Assert(currentTypeHandler->SupportsPrototypeInstances()); Assert(!DynamicTypeHandler::IsolatePrototypes() || !currentTypeHandler->RespectsIsolatePrototypes() || !currentTypeHandler->GetIsOrMayBecomeShared()); Assert((wasPrototype && !wasShared) || !DynamicTypeHandler::ChangeTypeOnProto() || !currentTypeHandler->RespectsChangeTypeOnProto() || this->GetDynamicType() != oldType); #endif // If we haven't changed type we must explicitly invalidate store field inline caches to avoid properties // getting added to this prototype object on the fast path without proper invalidation. if (this->GetDynamicType() == oldType) { currentTypeHandler->InvalidateStoreFieldCachesForAllProperties(this->GetScriptContext()); } }
ArrayObject *DomainObject::getVariables (Atom a) { ArrayObject *result = toplevel()->arrayClass->newArray(0); TraitsBindingsp traits = getTraits(a)->getTraitsBindings(); int i = 0; while ((i = traits->next(i)) != 0) { Namespace *ns = traits->nsAt(i); Stringp name = traits->keyAt(i); Binding b = traits->valueAt(i); if (core()->isVarBinding(b) && ns->getType() == Namespace::NS_Public) { Atom nameAtom = core()->internString(name)->atom(); result->push(&nameAtom, 1); } } return result; }
/** * Array.prototype.shift() * TRANSFERABLE: Needs to support generic objects as well as Array objects */ /*static*/ Atom ArrayClass::generic_shift(Toplevel* toplevel, Atom thisAtom) { ArrayObject *a = isArray(toplevel, thisAtom); if (a && a->isSimpleDense()) { if (!a->m_length) return undefinedAtom; a->m_length--; return (a->m_denseArr.shift()); } if (!AvmCore::isObject(thisAtom)) return undefinedAtom; Atom outAtom; ScriptObject *d = AvmCore::atomToScriptObject(thisAtom); uint32 len = getLengthHelper(toplevel, d); if (len == 0) { // set len to 0 (ecmascript spec) setLengthHelper(toplevel, d, 0); outAtom = undefinedAtom; } else { // Get the 0th element to return outAtom = d->getUintProperty(0); // Move all of the elements down for (uint32 i=0; i<len-1; i++) { d->setUintProperty(i, d->getUintProperty(i+1)); } d->delUintProperty (len - 1); setLengthHelper(toplevel, d, len - 1); } return outAtom; }
/*static*/ ChostentObject* CNetdbClass::gethostent(ScriptObject* self) { struct hostent *hh; hh = VMPI_gethostent(); if( hh ) { ShellToplevel* shelltop = (ShellToplevel*)self->toplevel(); ChostentClass *hc = shelltop->getShellClasses()->get_hostentClass(); ChostentObject *ho = hc->constructObject(); ho->set_h_name( self->core()->newStringUTF8( hh->h_name ) ); Toplevel* toplevel = self->toplevel(); ArrayObject *aliases = toplevel->arrayClass()->newArray(); int count = 0; int i; for( i=0; hh->h_aliases[i] != NULL; ++i ) { aliases->setUintProperty( count++, self->core()->newStringUTF8( hh->h_aliases[i] )->atom()); } ho->set_h_aliases( aliases ); ho->set_h_addrtype( hh->h_addrtype ); ho->set_h_length( hh->h_length ); ArrayObject *addrlist = toplevel->arrayClass()->newArray(); count = 0; for( i=0; hh->h_addr_list[i] != NULL; ++i ) { struct in_addr in; memcpy(&in.s_addr, hh->h_addr_list[i], sizeof (in.s_addr)); addrlist->setUintProperty( count++, self->core()->newStringUTF8( inet_ntoa(in) )->atom()); } ho->set_h_addr_list( addrlist ); return ho; } return NULL; }
bool RArrayState::recover(JSContext *cx, SnapshotIterator &iter) const { RootedValue result(cx); ArrayObject *object = &iter.read().toObject().as<ArrayObject>(); uint32_t initLength = iter.read().toInt32(); object->setDenseInitializedLength(initLength); for (size_t index = 0; index < numElements(); index++) { Value val = iter.read(); if (index >= initLength) { MOZ_ASSERT(val.isUndefined()); continue; } object->initDenseElement(index, val); } result.setObject(*object); iter.storeInstructionResult(result); return true; }
/** * Array.prototype.slice() * TRANSFERABLE: Needs to support generic objects as well as Array objects */ /*static*/ ArrayObject* ArrayClass::generic_slice(Toplevel* toplevel, Atom thisAtom, double A, double B) { if (!AvmCore::isObject(thisAtom)) return 0; ScriptObject *d = AvmCore::atomToScriptObject(thisAtom); uint32 len = getLengthHelper(toplevel, d); // if a param is passed then the first one is A // if no params are passed then A = 0 uint32 a = NativeObjectHelpers::ClampIndex(A, len); uint32 b = NativeObjectHelpers::ClampIndex(B, len); if (b < a) b = a; ArrayObject *out = toplevel->arrayClass->newArray(b-a); uint32 outIndex=0; for (uint32 i=a; i<b; i++) { out->setUintProperty (outIndex++, d->getUintProperty (i)); } return out; }
ArrayObject* RegExpObject::split(Stringp subject, uint32 limit) { AvmCore *core = this->core(); ArrayObject *out = toplevel()->arrayClass->newArray(); UsesUTF8String utf8Subject(subject); int startIndex=0; int matchIndex; int matchLen; ArrayObject* matchArray; unsigned n=0; bool isEmptyRE = m_source->length() == 0; while ((matchArray = _exec(subject, utf8Subject, startIndex, matchIndex, matchLen)) != NULL) { // [cn 11/22/04] when match is made, but is length 0 we've matched the empty // position between characters. Although we've "matched", its zero length so just break out. if (matchLen == 0 ) { matchLen = 0; matchIndex = startIndex+numBytesInUtf8Character((uint8*)(utf8Subject->c_str())+startIndex); // +1char will advance startIndex, extract just one char if( !isEmptyRE ) { // don't break if we're processing an empty regex - then we want to split the string into each character // so we want the loop to continue break; } } //[ed 8/10/04] don't go past end of string. not sure why pcre doesn't return null //for a match starting past the end. //[cn 12/3/04] because a regular expression which matches an empty position (space between characters) // will match the empty position just past the last character. This test is correct, though // it needs to come before we do any setProperties to avoid a bogus xtra result. if (matchIndex+matchLen > utf8Subject->length()) { startIndex = matchIndex+matchLen; break; } else { out->setUintProperty(n++, (core->newString(utf8Subject->c_str()+startIndex, matchIndex-startIndex))->atom()); if (n >= limit) break; for (uint32 j=1; j<matchArray->getLength(); j++) { out->setUintProperty(n++, matchArray->getUintProperty(j)); if (n >= limit) break; } // Advance past this match startIndex = matchIndex+matchLen; } } // If we found no match, or we did find a match and are still under limit, and there is a remainder left, add it if ((unsigned)n < limit && startIndex <= utf8Subject->length()) { out->setUintProperty(n++, (core->newString(utf8Subject->c_str()+startIndex, utf8Subject->length()-startIndex))->atom()); } return out; }
ArrayObject* RegExpObject::_exec(Stringp subject, UTF8String *utf8Subject, int startIndex, int& matchIndex, int& matchLen) { AvmAssert(subject != NULL); AvmAssert(utf8Subject != NULL); int ovector[OVECTOR_SIZE]; int results; int subjectLength = utf8Subject->length(); if( startIndex < 0 || startIndex > subjectLength || (results = pcre_exec((pcre*)m_pcreInst, NULL, utf8Subject->c_str(), subjectLength, startIndex, PCRE_NO_UTF8_CHECK, ovector, OVECTOR_SIZE)) < 0) { matchIndex = 0; matchLen = 0; return NULL; } AvmCore *core = this->core(); ArrayObject *a = toplevel()->arrayClass->newArray(results); a->setAtomProperty(toplevel()->regexpClass()->kindex, core->intToAtom(Utf8ToUtf16Index(subject, utf8Subject, ovector[0]))); a->setAtomProperty(toplevel()->regexpClass()->kinput, subject->atom()); a->setLength(results); // set array slots for (int i=0; i<results; i++) { if (ovector[i*2] > -1) { int length = ovector[i*2 + 1] - ovector[i*2]; Atom match = stringFromUTF8(utf8Subject->c_str()+ovector[i*2], length); a->setUintProperty(i, match); } else { a->setUintProperty(i, undefinedAtom); } } // handle named groups if (m_hasNamedGroups) { int entrySize; pcre_fullinfo((pcre*)m_pcreInst, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrySize); int nameCount; pcre_fullinfo((pcre*)m_pcreInst, NULL, PCRE_INFO_NAMECOUNT, &nameCount); // this space is freed when (pcre*)m_pcreInst is freed char *nameTable; pcre_fullinfo((pcre*)m_pcreInst, NULL, PCRE_INFO_NAMETABLE, &nameTable); /* nameTable is a series of fixed length entries (entrySize) the first two bytes are the index into the ovector and the result is a null terminated string (the subgroup name) */ for (int i = 0; i < nameCount; i++) { int nameIndex, length; nameIndex = (nameTable[0] << 8) + nameTable[1]; length = ovector[nameIndex * 2 + 1] - ovector[ nameIndex * 2 ]; Atom name = stringFromUTF8((char*)(nameTable+2), (uint32)strlen(nameTable+2)); name = core->internString(name)->atom(); Atom value = stringFromUTF8(utf8Subject->c_str()+ovector[nameIndex*2], length); a->setAtomProperty(name, value); nameTable += entrySize; } } matchIndex = ovector[0]; matchLen = ovector[1]-ovector[0]; return a; }
/** 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ] ] ] ) When the concat method is called with zero or more arguments item1, item2, etc., it returns an array containing the array elements of the object followed by the array elements of each argument in order. The following steps are taken: 1. Let A be a new array created as if by the expression new Array(). 2. Let n be 0. 3. Let E be this object. 4. If E is not an Array object, go to step 16. 5. Let k be 0. 6. Call the [[Get]] method of E with argument "length". 7. If k equals Result(6) go to step 19. 8. Call ToString(k). 9. If E has a property named by Result(8), go to step 10, but if E has no property named by Result(8), go to step 13. 10. Call ToString(n). 11. Call the [[Get]] method of E with argument Result(8). 12. Call the [[Put]] method of A with arguments Result(10) and Result(11). 13. Increase n by 1. 14. Increase k by 1. 15. Go to step 7. 16. Call ToString(n). 17. Call the [[Put]] method of A with arguments Result(16) and E. 18. Increase n by 1. 19. Get the next argument in the argument list; if there are no more arguments, go to step 22. 20. Let E be Result(19). 21. Go to step 4. 22. Call the [[Put]] method of A with arguments "length" and n. 23. Return A. The length property of the concat method is 1. NOTE The concat function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the concat function can be applied successfully to a host object is implementation-dependent. */ /*static*/ ArrayObject* ArrayClass::generic_concat(Toplevel* toplevel, Atom thisAtom, ArrayObject* args) { AvmCore* core = toplevel->core(); ScriptObject *d = AvmCore::isObject(thisAtom) ? AvmCore::atomToScriptObject(thisAtom) : 0; uint32 len = 0; if (d) { len = getLengthHelper(toplevel, d); } ArrayObject *a = isArray(toplevel, thisAtom); uint32 i; uint32 argc = args->getLength(); int newLength = len; for (i = 0; i< argc; i++) { Atom atom = args->getUintProperty(i); if (AvmCore::istype(atom, ARRAY_TYPE)) { ArrayObject *b = (ArrayObject*) AvmCore::atomToScriptObject(atom); newLength += b->getLength(); } else { newLength++; } } ArrayObject *out = toplevel->arrayClass->newArray(newLength); int denseLength = 0; // Only copy over elements for Arrays, not objects according to spec // 4. If E is not an Array object, go to step 16. if (a && newLength) { denseLength = a->getDenseLength(); // copy over our dense part out->m_denseArr.push (&a->m_denseArr); out->m_length += denseLength; // copy over any non-dense values (or all values if this isn't an array object) for (i = denseLength; i < len; i++) { out->setUintProperty(i, d->getUintProperty(i)); } } for (i = 0; i< (uint32)argc; i++) { Atom atom = args->getUintProperty(i); if (AvmCore::istype(atom, ARRAY_TYPE)) { ArrayObject *b = (ArrayObject*) AvmCore::atomToScriptObject(atom); // copy over dense parts out->m_denseArr.push (&b->m_denseArr); out->m_length += b->getDenseLength(); // copy over any non-dense values uint32 len = b->getLength(); for (uint32 j=b->getDenseLength(); j<len; j++) { out->m_denseArr.push (b->getUintProperty(j)); out->m_length++; } } else { out->m_denseArr.push (atom); out->m_length++; } } return out; }
/*static*/ ArrayObject* CNetdbClass::getaddrinfo(ScriptObject* self, Stringp nodename, Stringp servname, CaddrinfoObject* hints, CEAIrrorObject* eaierr) { AvmCore *core = self->core(); Toplevel* toplevel = self->toplevel(); ShellToplevel* shelltop = (ShellToplevel*)self->toplevel(); if( !hints ) { CaddrinfoClass *ai_c = shelltop->getShellClasses()->get_addrinfoClass(); CaddrinfoObject *hints = ai_c->constructObject(); //default properties hints->set_ai_family( AF_UNSPEC ); hints->set_ai_socktype( SOCK_STREAM ); } StUTF8String nodenameUTF8(nodename); StUTF8String servnameUTF8(servname); //(void)hints; struct addrinfo h; VMPI_memset(&h, 0, sizeof h); h.ai_flags = hints->get_ai_flags(); h.ai_family = hints->get_ai_family(); h.ai_socktype = hints->get_ai_socktype(); h.ai_protocol = hints->get_ai_protocol(); //ignore other propertiess struct addrinfo *res, *p; int result = VMPI_getaddrinfo( nodenameUTF8.c_str(), servnameUTF8.c_str(), &h, &res ); if( result != 0 ) { //printf( "getaddrinfo: %s\n", gai_strerror(result)); if( eaierr ) { eaierr->call_apply( result ); } return NULL; } ArrayObject *infolist = toplevel->arrayClass()->newArray(); int count = 0; for( p = res; p != NULL; p = p->ai_next ) { CaddrinfoClass *infoc = shelltop->getShellClasses()->get_addrinfoClass(); CaddrinfoObject *info = infoc->constructObject(); info->set_ai_flags( p->ai_flags ); info->set_ai_family( p->ai_family ); info->set_ai_socktype( p->ai_socktype ); info->set_ai_protocol( p->ai_protocol ); info->set_ai_addrlen( (int) p->ai_addrlen ); info->set_ai_canonname( core->newStringUTF8( p->ai_canonname ) ); if( p->ai_family == AF_INET ) { struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; CSockaddr_inClass *addr4c = shelltop->getShellClasses()->get_sockaddr_inClass(); CSockaddr_inObject *addr4o = addr4c->constructObject(); addr4o->set_sin_family( ipv4->sin_family ); addr4o->set_sin_port( ipv4->sin_port ); CIn_AddrClass *ac = shelltop->getShellClasses()->get_in_addrClass(); CIn_AddrObject *ao = ac->constructObject(); ao->set_s_addr( ipv4->sin_addr.s_addr ); addr4o->set_sin_addr( ao ); info->set_ai_addr( addr4o->toAtom() ); } else if( p->ai_family == AF_INET6 ) { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; CSockaddr_in6Class *addr6c = shelltop->getShellClasses()->get_sockaddr_in6Class(); CSockaddr_in6Object *addr6o = addr6c->constructObject(); addr6o->set_sin6_family( ipv6->sin6_family ); addr6o->set_sin6_port( ipv6->sin6_port ); addr6o->set_sin6_flowinfo( ipv6->sin6_flowinfo ); addr6o->set_sin6_scope_id( ipv6->sin6_scope_id ); CIn6_AddrClass *ac6 = shelltop->getShellClasses()->get_in6_addrClass(); CIn6_AddrObject *ao6 = ac6->constructObject(); ao6->fromStruct( ipv6->sin6_addr ); addr6o->set_sin6_addr( ao6 ); info->set_ai_addr( addr6o->toAtom() ); } infolist->setUintProperty( count++, info->toAtom() ); } VMPI_freeaddrinfo( res ); return infolist; }
ChostentObject* CNetdbClass::gethostbyaddr4(CIn_AddrObject* addr, int type) { Toplevel* toplevel = this->toplevel(); AvmCore* core = toplevel->core(); if( !addr ) { toplevel->throwArgumentError(kNullArgumentError, "addr"); } struct hostent *he; struct in_addr ipv4addr; ipv4addr.s_addr = addr->get_s_addr(); //uint if( addr->call_isValid() == false ) { return NULL; } he = VMPI_gethostbyaddr( (char *)&ipv4addr, sizeof ipv4addr, type ); if( he ) { ShellToplevel* shelltop = (ShellToplevel*)this->toplevel(); ChostentClass *hc = shelltop->getShellClasses()->get_hostentClass(); ChostentObject *ho = hc->constructObject(); ho->set_h_name( core->newStringUTF8( he->h_name ) ); ArrayObject *aliases = toplevel->arrayClass()->newArray(); int count = 0; int i; for( i=0; he->h_aliases[i] != NULL; ++i ) { aliases->setUintProperty( count++, core->newStringUTF8( he->h_aliases[i] )->atom() ); } ho->set_h_aliases( aliases ); ho->set_h_addrtype( he->h_addrtype ); ho->set_h_length( he->h_length ); ArrayObject *addrlist = toplevel->arrayClass()->newArray(); count = 0; for( i=0; he->h_addr_list[i] != NULL; ++i ) { struct in_addr in; memcpy(&in.s_addr, he->h_addr_list[i], sizeof (in.s_addr)); CIn_AddrClass *ac = shelltop->getShellClasses()->get_in_addrClass(); CIn_AddrObject *ao = ac->constructObject(); ao->set_s_addr( in.s_addr ); addrlist->setUintProperty( count++, ao->toAtom() ); } ho->set_h_addr_list( addrlist ); return ho; } return NULL; }