示例#1
0
文件: ScriptObject.cpp 项目: bsdf/trx
    // Execute the ToString algorithm as described in ECMA-262 Section 9.8.
    // This is ToString(ToPrimitive(input argument, hint String))
    // ToPrimitive(input argument, hint String) calls [[DefaultValue]]
    // described in ECMA-262 8.6.2.6.  The [[DefaultValue]] algorithm
    // with hint String is inlined here.
    Stringp ScriptObject::toString()
    {
        AvmCore *core = this->core();
        Toplevel* toplevel = this->toplevel();

        Atom atomv_out[1];

        // call this.toString()
        // NOTE use callers versioned public to get correct toString
        Multiname tempname(core->findPublicNamespace(), core->ktoString);
        atomv_out[0] = atom();
        Atom result = toplevel->callproperty(atom(), &tempname, 0, atomv_out, vtable);

        // if result is primitive, return its ToString
        if (atomKind(result) != kObjectType)
            return core->string(result);

        // otherwise call this.valueOf()
        tempname.setName(core->kvalueOf);
        atomv_out[0] = atom();
        result = toplevel->callproperty(atom(), &tempname, 0, atomv_out, vtable);

        // if result is primitive, return it
        if (atomKind(result) != kObjectType)
            return core->string(result);

        // could not convert to primitive.
        toplevel->throwTypeError(kConvertToPrimitiveError, core->toErrorString(traits()));
        return NULL; // unreachable
    }
示例#2
0
	// this = argv[0] (ignored)
	// arg1 = argv[1]
	// argN = argv[argc]
	Atom RegExpClass::construct(int argc, Atom* argv)
	{
		AvmCore* core = this->core();
		Stringp pattern;

		Atom patternAtom = (argc>0) ? argv[1] : undefinedAtom;
		Atom optionsAtom = (argc>1) ? argv[2] : undefinedAtom;

		if (AvmCore::istype(patternAtom, traits()->itraits)) {
			// Pattern is a RegExp object
			if (optionsAtom != undefinedAtom) {
				// ECMA 15.10.4.1 says to throw an error if flags specified
				toplevel()->throwTypeError(kRegExpFlagsArgumentError);
			}
			// Return a clone of the RegExp object
			RegExpObject* regExpObject = (RegExpObject*)AvmCore::atomToScriptObject(patternAtom);
			return (new (core->GetGC(), ivtable()->getExtraSize()) RegExpObject(regExpObject))->atom();
		} else {
			if (patternAtom != undefinedAtom) {
				pattern = core->string(argv[1]);
			} else {
				// cn:  disable this, breaking ecma3 tests.   was: todo look into this. it's what SpiderMonkey does.
				pattern = core->kEmptyString; //core->newConstantStringLatin1("(?:)");
			}
		}

		Stringp options = NULL;
		if (optionsAtom != undefinedAtom) {
			options = core->string(optionsAtom);
		}

		RegExpObject* inst = new (core->GetGC(), ivtable()->getExtraSize()) RegExpObject(this, pattern, options);
		return inst->atom();
	}
示例#3
0
    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;
        }
    }
示例#4
0
	void SystemClass::trace(ArrayObject* a)
	{
		if (!a)
			toplevel()->throwArgumentError(kNullArgumentError, "array");
		AvmCore* core = this->core();
		PrintWriter& console = core->console;
		for (int i=0, n = a->getLength(); i < n; i++)
		{
			if (i > 0)
                console << ' ';
			Stringp s = core->string(a->getUintProperty(i));
			for (int j = 0; j < s->length(); j++)
			{
				wchar c = (*s)[j];
				// '\r' gets converted into '\n'
				// '\n' is left alone
				// '\r\n' is left alone
				if (c == '\r')
				{
					if (((j+1) < s->length()) && (*s)[j+1] == '\n')
					{
						console << '\r';	
						j++;
					}

					console << '\n';
				}
				else
				{
					console << c;
				}
			}
		}
		console << '\n';
	}
示例#5
0
    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;
    }
示例#6
0
    int StringClass::_search(Stringp in, Atom regexpAtom)
    {
        AvmCore* core = this->core();

        if (!AvmCore::istype(regexpAtom, core->traits.regexp_itraits)) {
            // ECMA-262 15.5.4.10
            // If the argument is not a RegExp, invoke RegExp(exp)
            regexpAtom = core->newRegExp(toplevel()->regexpClass(),
                                                core->string(regexpAtom),
                                                core->kEmptyString)->atom();
        }

        RegExpObject *reObj = (RegExpObject*) AvmCore::atomToScriptObject(regexpAtom);
        return reObj->search(in);
    }
	// helper method
	// sets index to the uint32 value of name, if it can be converted
	// isNumber is set to true if name was a number (whether it was a uint32 value or not)
	bool VectorBaseObject::getVectorIndex(Atom name, uint32& index, bool& isNumber) const
	{
		AvmCore* core = this->core();
		isNumber = false;
		if (AvmCore::getIndexFromAtom(name, &index))
		{
			isNumber = true;
			return true;
		}
		else
		{
			if( AvmCore::isString(name) )
			{
				Stringp s = core->string(name);
				const wchar c = s->charAt(0);
				// Does it look like a number?
				if( s->length() > 0 && c >= '0' && c <= '9' )
				{
					double index_d = s->toNumber();
					if( !MathUtils::isNaN(index_d) )
					{
						isNumber = true;

						// name is a string that looks like a number
						int i = MathUtils::real2int(index_d);
						if ((double)i == index_d)
						{
							// It's an indexed property name
							index = i;
							return true;
						}
						else
						{
							return false;
						}
					}
				}
			}
		}
		return false;
	}
	Atom VectorBaseObject::getAtomProperty(Atom name) const
	{
		uint32 index;
		bool isNumber=false;
		AvmCore* core = this->core();
		if (getVectorIndex(name, index, isNumber))
		{
			return getUintProperty(index);
		}
		else
		{
			if(isNumber)
			{
				// Not a valid indexed name - has a decimal part
				Multiname mn(core->publicNamespace,core->string(name));
				toplevel()->throwReferenceError(kReadSealedError, &mn, traits());
			}
			// Check the prototype chain - that will throw if there is no match
			return getAtomPropertyFromProtoChain(name, getDelegate(), traits());
		}
	}
示例#9
0
    // this = argv[0] (ignored)
    // arg1 = argv[1]
    // argN = argv[argc]
    Atom NamespaceClass::construct(int argc, Atom* argv)
    {
        AvmCore* core = this->core();

        // See E4X 13.2.2, pg 65
        if (argc < 1)
            return core->newNamespace(core->kEmptyString->atom())->atom();
        else if (argc == 1)
            return core->newNamespace(argv[1])->atom();
        else
        {
            // Rhino throws an error when prefix is specified and uri is not a valid string
            String *p = core->string (argv[1]);
            String *u = core->string (argv[2]);
            if (p->length() && !u->length())
            {
                toplevel()->throwTypeError(kXMLNamespaceWithPrefixAndNoURI, p);
            }

            return core->newNamespace(argv[1], argv[2])->atom();
        }
    }
示例#10
0
    // E4X 10.4, pg 36
    Atom XMLListClass::ToXMLList(Atom arg)
    {
        AvmCore* core = this->core();

        if (AvmCore::isNullOrUndefined(arg))
        {
            toplevel()->throwTypeError(
                       (arg == undefinedAtom) ? kConvertUndefinedToObjectError :
                                            kConvertNullToObjectError);
            return arg;
        }

        if (AvmCore::isXMLList(arg))
        {
            return arg;
        }
        else if (AvmCore::isXML(arg))
        {
            XMLObject *x = AvmCore::atomToXMLObject(arg);
            Multiname m;
            bool bFound = x->getQName (&m);
            Atom parent = x->parent();
            if (parent == undefinedAtom)
                parent = nullObjectAtom;
            XMLListObject *xl = XMLListObject::create(core->GetGC(), toplevel()->xmlListClass(), parent, bFound ? &m : 0);

            xl->_append (arg);
            return xl->atom();
        }
        else
        {
            Toplevel* toplevel = this->toplevel();

            Stringp s = core->string(arg);

            if (s->matchesLatin1("<>", 2, 0) && s->matchesLatin1("</>", 3, s->length()-3))
                s = s->substr(2, s->length() - 5);

            Namespace *defaultNamespace = toplevel->getDefaultNamespace();
            // We handle this step in the XMLObject constructor to avoid concatenation huge strings together
            // parentString = <parent xnlns=defaultNamespace> s </parent>
            // 3. Parse parentString as a W3C element information info e
            // 4. If the parse fails, throw a SyntaxError exception
            // 5. x = toXML(e);
            //StringBuffer parentString (core);
            //parentString << "<parent xmlns=\"";
            //parentString << defaultNamespace->getURI();
            //parentString << "\">";
            //parentString << s;
            //parentString << "</parent>";
            XMLObject *x = XMLObject::create(core->GetGC(), toplevel->xmlClass(), s, defaultNamespace);

            XMLListObject *xl = XMLListObject::create(core->GetGC(), toplevel->xmlListClass());
            for (uint32_t i = 0; i < x->getNode()->_length(); i++)
            {
                E4XNode *c = x->getNode()->_getAt (i);
                c->setParent (NULL);

                // !!@ trying to emulate rhino behavior here
                // Add the default namespace to our top element.
                Namespace *ns = toplevel->getDefaultNamespace();
                c->_addInScopeNamespace (core, ns, core->findPublicNamespace());
                xl->_appendNode (c);
            }
            return xl->atom();
        }
    }
示例#11
0
	// E4X 10.3, page 32
	Atom XMLClass::ToXML(Atom arg)
	{
		Toplevel* toplevel = this->toplevel();
		AvmCore* core = this->core();

		if (AvmCore::isNullOrUndefined(arg))
		{
			toplevel->throwTypeError(
					   (arg == undefinedAtom) ? kConvertUndefinedToObjectError :
											kConvertNullToObjectError);
			return arg;
		}
		else if (AvmCore::isXML(arg))
		{
			return arg;
		}
		else if (AvmCore::isXMLList(arg))
		{
			XMLListObject *xl = AvmCore::atomToXMLList(arg);
			if (xl->_length() == 1)
			{
				return xl->_getAt(0)->atom();
			}
			else
			{
				toplevel->throwTypeError(kXMLMarkupMustBeWellFormed);
				return 0;//notreached
			}
		}
		else
		{
			Namespace *defaultNamespace = toplevel->getDefaultNamespace();

			// 2. Parse parentString as a W3C element information info e
			// 3. If the parse fails, throw a SyntaxError exception
			XMLObject *x = new (core->GetGC()) XMLObject(toplevel->xmlClass(), core->string(arg), defaultNamespace);

			// 4. x = toXML(e);
			// 5. if x.length == 0
			//       return new xml object
			if (!x->getNode()->_length())
			{
				x->setNode( new (core->GetGC()) TextE4XNode(0, core->kEmptyString) );
			}
			// 6. else if x.length == 1
			//       x[0].parent = null
			//		return x[0]
			else if (x->getNode()->_length() == 1)
			{
				x->setNode( x->getNode()->_getAt (0)); // discard parent node
				x->getNode()->setParent (0);
			}
			// 7. else throw a syntaxError
			else
			{
				// check for multiple nodes where the first n-1 are PI/comment nodes and the 
				// last one is an element node.  Just ignore the PI/comment nodes and return
				// the element node.  (bug 148526).
				// Will also now ignore any text nodes that just contain whitespace (leading
				// or trailing) the one valid element node.  If multiple element nodes are found,
				// that is a failing case as well. (bug 192355)
				E4XNode *node = x->getNode();
				E4XNode *validNode = NULL;

				for (uint32 i = 0; i < node->_length(); i++)
				{
					E4XNode *n = node->_getAt (i);
					if (n->getClass() == E4XNode::kElement)
					{
						if (validNode != NULL)
							toplevel->throwTypeError(kXMLMarkupMustBeWellFormed);

						validNode = n;
					}
					else if (n->getClass() == E4XNode::kText)
					{
						if (!n->getValue()->isWhitespace())
						{
							toplevel->throwTypeError(kXMLMarkupMustBeWellFormed);
						}
					}
				}

				// No valid nodes found
				if (!validNode)
					toplevel->throwTypeError(kXMLMarkupMustBeWellFormed);

				x->setNode( validNode ); // discard parent node
				validNode->setParent (0);
			}
			return x->atom();
		}
	}