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; }
Atom ScriptObject::getUintProperty(uint32_t i) const { // N.B.: a key present in ScriptObject must be interned string; // thus uninterned implies absent (cf. bugzilla 556023). AvmCore* core = this->core(); if (!(i&MAX_INTEGER_MASK)) { if (!traits()->needsHashtable()) { Stringp interned; bool present = core->isInternedUint(i, &interned); if (present) { Atom name = interned->atom(); return getAtomPropertyFromProtoChain(name, delegate, traits()); } else { return undefinedAtom; } } else { // dynamic lookup on this object Atom name = core->uintToAtom (i); const ScriptObject *o = this; do { // ensure prototype is dynamic if (!o->vtable->traits->getHashtableOffset()) continue; Atom const value = o->getTable()->getNonEmpty(name); if (!InlineHashtable::isEmpty(value)) return value; } while ((o = o->delegate) != NULL); return undefinedAtom; } } else { Stringp interned; bool present; present = core->isInternedUint(i, &interned); if (present) { return getAtomProperty(interned->atom()); } else { return undefinedAtom; } } }
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; }
Stringp StringClass::_replace(Stringp subject, Atom pattern, Atom replacementAtom) { AvmCore* core = this->core(); ScriptObject *replaceFunction = NULL; Stringp replacement = NULL; if (AvmCore::istype(replacementAtom, core->traits.function_itraits)) { replaceFunction = AvmCore::atomToScriptObject(replacementAtom); } else { replacement = core->string(replacementAtom); } if (AvmCore::istype(pattern, core->traits.regexp_itraits)) { // RegExp mode RegExpObject *reObj = (RegExpObject*) core->atomToScriptObject(pattern); if (replaceFunction) { return core->string(reObj->replace(subject, replaceFunction)); } else { return core->string(reObj->replace(subject, replacement)); } } else { // String replace mode Stringp searchString = core->string(pattern); int index = subject->indexOf(searchString); if (index == -1) { // Search string not found; return input unchanged. return subject; } if (replaceFunction) { // Invoke the replacement function to figure out the // replacement string Atom argv[4] = { undefinedAtom, searchString->atom(), core->uintToAtom(index), subject->atom() }; replacement = core->string(toplevel()->op_call(replaceFunction->atom(), 3, argv)); } Stringp out = subject->substring(0, index); out = String::concatStrings(out, replacement); out = String::concatStrings(out, subject->substring(index + searchString->length(), subject->length())); return out; } }
void Debugger::traceCallback(int line) { if (!(core->callStack && core->callStack->env())) return; Stringp file = ( core->callStack->filename() ) ? Stringp(core->callStack->filename()) : Stringp(core->kEmptyString); Stringp name = core->kEmptyString; Stringp args = core->kEmptyString; MethodEnv* env = core->callStack->env(); if (env->method) { // normally, getMethodName omits nonpublic namespaces, but for this purpose, // we want to include all namespaces. const bool includeAllNamespaces = true; name = env->method->getMethodName(includeAllNamespaces); if (!name) name = core->kEmptyString; if ((line == 0) && (astrace_callback == TRACE_METHODS_WITH_ARGS || astrace_callback == TRACE_METHODS_AND_LINES_WITH_ARGS)) args = traceArgumentsString(); } Atom argv[5] = { trace_callback->atom(), file->atom(), core->intToAtom(line), name->atom(), args->atom() }; int argc = 4; TRY(core, kCatchAction_ReportAsError) { trace_callback->call(argc, argv); }
Atom VectorClass::applyTypeArgs(int argc, Atom* argv) { //Vector only takes 1 type argument AvmAssert(argc==1); if (argc != 1) { toplevel()->typeErrorClass()->throwError(kWrongTypeArgCountError, traits()->formatClassName(), core()->toErrorString(1), core()->toErrorString(argc)); } Atom type = argv[0]; AvmCore* core = this->core(); if (ISNULL(type)) return toplevel()->objectVectorClass->atom(); if (atomKind(type) != kObjectType) toplevel()->throwVerifyError(kCorruptABCError); ScriptObject* so = AvmCore::atomToScriptObject(type); if (so == toplevel()->intClass) return toplevel()->intVectorClass->atom(); else if (so == toplevel()->numberClass) return toplevel()->doubleVectorClass->atom(); else if (so == toplevel()->uintClass) return toplevel()->uintVectorClass->atom(); Traits* param_traits = so->vtable->ivtable->traits; Stringp fullname = VectorClass::makeVectorClassName(core, param_traits); if (!instantiated_types->contains(fullname->atom())) { VTable* vtab = this->vtable->newParameterizedVTable(param_traits, fullname); ObjectVectorClass* new_type = new (vtab->gc(), vtab->getExtraSize()) ObjectVectorClass(vtab); new_type->index_type = (ClassClosure*)AvmCore::atomToScriptObject(type); new_type->setDelegate(toplevel()->classClass->prototype); // Is this right? Should each instantiation get its own prototype? new_type->prototype = toplevel()->objectVectorClass->prototype; instantiated_types->add(fullname->atom(), new_type->atom()); } return (Atom)instantiated_types->get(fullname->atom()); }
//#endif Atom ProxyObject::callFunction(MethodEnv* fun,const Stringp name,int argc,Atom*argv)const { //Atom*data=(Atom*)mmfx_alloc((argc+1)*sizeof(Atom)); //data[0]=argv[0]; //data[1]=name->atom(); //for(int i=1;i<=argc;i++) // data[i+1]=argv[i]; //Atom base=this->atom(); Atom ret=undefinedAtom; //#if (__CORE_VERSION__>=0x02070100) argv[0]=createLocalObject(name->atom()); //#else // argv[0]=name->atom(); //#endif TRY(core(),kCatchAction_ReportAsError) { ret=fun->coerceEnter(atom(),argc+1,argv); }
ArrayClass::ArrayClass(VTable* cvtable) : ClassClosure(cvtable), kComma(core()->internConstantStringLatin1(",")) { AvmCore* core = this->core(); Toplevel* toplevel = this->toplevel(); toplevel->arrayClass = this; AvmAssert(traits()->getSizeOfInstance() == sizeof(ArrayClass)); VTable* ivtable = this->ivtable(); ScriptObject* objectPrototype = toplevel->objectClass->prototype; prototype = new (core->GetGC(), ivtable->getExtraSize()) ArrayObject(ivtable, objectPrototype, 0); // According to ECMAscript spec (ECMA-262.pdf) // generic support: concat, join, pop, push, reverse, shift, slice, sort, splice, unshift // NOT generic: toString, toLocaleString // unknown: sortOn (our own extension) #if defined(_DEBUG) // AtomArray DRC unit tests, put here b/c this always runs once, has a GC * and // this class has to do with arrays. this is more convienent that trying to test // through actionscript // create an atom Stringp s = core->newConstantStringLatin1("foo"); Atom a = s->atom(); AvmAssert(s->RefCount()==0); AtomArray *ar = new (gc()) AtomArray(); // test push/pop ar->push(a); AvmAssert(s->RefCount()==1); ar->push(a); AvmAssert(s->RefCount()==2); ar->pop(); AvmAssert(s->RefCount()==1); // reverse ar->push(a); AvmAssert(s->RefCount()==2); ar->reverse(); AvmAssert(s->RefCount()==2); // shift ar->shift(); AvmAssert(s->RefCount()==1); // splice AtomArray *ar2 = new (gc()) AtomArray(); ar->push(a); ar2->push(ar); AvmAssert(s->RefCount()==4); ar->splice(1, 2, 1, ar2, 0); // [a,a,a] AvmAssert(s->RefCount()==5); // unshift Atom as[4] = {a,a,a,a}; ar->unshift(as, 4); AvmAssert(s->RefCount()==9); // removeAt ar->removeAt(1); AvmAssert(s->RefCount()==8); // setAt ar->setAt(2, a); AvmAssert(s->RefCount()==8); // insert ar->insert(2, a); AvmAssert(s->RefCount()==9); // clear ar->clear(); AvmAssert(s->RefCount() == 2); ar2->clear(); AvmAssert(s->RefCount() == 0); gc()->Free(ar); gc()->Free(ar2); #endif }
static inline Atom strAtom(Stringp s) { return s ? s->atom() : nullStringAtom; }
static void pushstr(ArrayObject* a, Stringp s) { a->setUintProperty(a->getLength(), s->atom()); }
Atom RegExpObject::replace(Stringp subject, ScriptObject* replaceFunction) { UsesUTF8String utf8Subject(subject); int ovector[OVECTOR_SIZE]; int subjectLength = utf8Subject->length(); int lastIndex=0; StringBuffer resultBuffer(core()); const char *src = utf8Subject->c_str(); // get start/end index of all matches int matchCount; while (lastIndex < subjectLength && (matchCount = pcre_exec((pcre*)m_pcreInst, NULL, src, subjectLength, lastIndex, PCRE_NO_UTF8_CHECK, ovector, OVECTOR_SIZE)) > 0) { int captureCount = matchCount-1; int matchIndex = ovector[0]; int matchLen = ovector[1]-ovector[0]; // copy in stuff leading up to match resultBuffer.write(src+lastIndex, matchIndex-lastIndex); // call the replace function Atom argv[NUM_MATCHES+4]; int argc = captureCount+3; argv[0] = undefinedAtom; // ECMA 15.5.4.11: Argument 1 is the substring that matched. argv[1] = core()->newString(src+matchIndex, matchLen)->atom(); // ECMA 15.5.4.11: The next m arguments are all of the captures in the // MatchResult for (int i=1; i<=captureCount; i++) { argv[i+1] = core()->newString(src+ovector[i*2], ovector[i*2+1]-ovector[i*2])->atom(); } // ECMA 15.5.4.11: Argument m+2 is the offset within string // where the match occurred argv[captureCount+2] = core()->uintToAtom(matchIndex); // ECMA 15.5.4.11: Argument m+3 is string argv[captureCount+3] = subject->atom(); resultBuffer << core()->string(toplevel()->op_call(replaceFunction->atom(), argc, argv)); int newLastIndex = ovector[0] + (ovector[1] - ovector[0]); // prevents infinite looping in certain cases fixReplaceLastIndex(src, subjectLength, lastIndex, newLastIndex, resultBuffer); lastIndex = newLastIndex; if (!get_global()) break; } // copy in stuff after last match if (lastIndex < subjectLength) { resultBuffer.write(src+lastIndex, subjectLength-lastIndex); } return stringFromUTF8(resultBuffer.c_str(), resultBuffer.length()); }