예제 #1
0
bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
{
    if (propertyName == exec->propertyNames().lastIndex) {
        RegExpObject* regExp = asRegExpObject(object);
        if (descriptor.configurablePresent() && descriptor.configurable())
            return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property.");
        if (descriptor.enumerablePresent() && descriptor.enumerable())
            return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property.");
        if (descriptor.isAccessorDescriptor())
            return reject(exec, shouldThrow, "Attempting to change access mechanism for an unconfigurable property.");
        if (!regExp->m_lastIndexIsWritable) {
            if (descriptor.writablePresent() && descriptor.writable())
                return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property.");
            if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
                return reject(exec, shouldThrow, "Attempting to change value of a readonly property.");
            return true;
        }
        if (descriptor.writablePresent() && !descriptor.writable())
            regExp->m_lastIndexIsWritable = false;
        if (descriptor.value())
            regExp->setLastIndex(exec, descriptor.value(), false);
        return true;
    }

    return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
}
예제 #2
0
bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (propertyName == vm.propertyNames->lastIndex) {
        RegExpObject* regExp = asRegExpObject(object);
        if (descriptor.configurablePresent() && descriptor.configurable())
            return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
        if (descriptor.enumerablePresent() && descriptor.enumerable())
            return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
        if (descriptor.isAccessorDescriptor())
            return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
        if (!regExp->m_lastIndexIsWritable) {
            if (descriptor.writablePresent() && descriptor.writable())
                return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
            if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
                return typeError(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyChangeError));
            return true;
        }
        if (descriptor.value()) {
            regExp->setLastIndex(exec, descriptor.value(), false);
            RETURN_IF_EXCEPTION(scope, false);
        }
        if (descriptor.writablePresent() && !descriptor.writable())
            regExp->m_lastIndexIsWritable = false;
        return true;
    }

    scope.release();
    return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
}
예제 #3
0
bool
js::XDRScriptRegExpObject(XDRState<mode> *xdr, HeapPtrObject *objp)
{
    /* NB: Keep this in sync with CloneScriptRegExpObject. */

    RootedAtom source(xdr->cx());
    uint32_t flagsword = 0;

    if (mode == XDR_ENCODE) {
        JS_ASSERT(objp);
        RegExpObject &reobj = (*objp)->asRegExp();
        source = reobj.getSource();
        flagsword = reobj.getFlags();
    }
    if (!XDRAtom(xdr, source.address()) || !xdr->codeUint32(&flagsword))
        return false;
    if (mode == XDR_DECODE) {
        RegExpFlag flags = RegExpFlag(flagsword);
        RegExpObject *reobj = RegExpObject::createNoStatics(xdr->cx(), source, flags, NULL);
        if (!reobj)
            return false;

        if (!reobj->clearParent(xdr->cx()))
            return false;
        if (!reobj->clearType(xdr->cx()))
            return false;
        objp->init(reobj);
    }
    return true;
}
EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
{
    JSValue thisValue = exec->hostThisValue();
    if (!thisValue.inherits(&RegExpObject::s_info)) {
        if (thisValue.inherits(&RegExpPrototype::s_info))
            return JSValue::encode(jsNontrivialString(exec, "//"));
        return throwVMTypeError(exec);
    }

    RegExpObject* thisObject = asRegExpObject(thisValue);

    StringRecursionChecker checker(exec, thisObject);
    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
        return earlyReturnValue;

    char postfix[5] = { '/', 0, 0, 0, 0 };
    int index = 1;
    if (thisObject->get(exec, exec->propertyNames().global).toBoolean(exec))
        postfix[index++] = 'g';
    if (thisObject->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
        postfix[index++] = 'i';
    if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec))
        postfix[index] = 'm';
    UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec);
    // If source is empty, use "/(?:)/" to avoid colliding with comment syntax
    return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix));
}
예제 #5
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();
	}
예제 #6
0
bool RegExpObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
    if (propertyName == exec->propertyNames().lastIndex) {
        RegExpObject* regExp = asRegExpObject(object);
        slot.setValue(regExp, regExp->getLastIndex());
        return true;
    }
    return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, slot);
}
예제 #7
0
bool RegExpObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
{
    if (propertyName == exec->propertyNames().lastIndex) {
        RegExpObject* regExp = asRegExpObject(object);
        descriptor.setDescriptor(regExp->getLastIndex(), regExp->m_lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly);
        return true;
    }
    return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, descriptor);
}
예제 #8
0
bool RegExpObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
    if (propertyName == exec->propertyNames().lastIndex) {
        RegExpObject* regExp = asRegExpObject(object);
        unsigned attributes = regExp->m_lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly;
        slot.setValue(regExp, attributes, regExp->getLastIndex());
        return true;
    }
    return Base::getOwnPropertySlot(object, exec, propertyName, slot);
}
예제 #9
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;
    }
예제 #10
0
void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
    RegExpObject* thisObject = jsCast<RegExpObject*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());

    Base::visitChildren(thisObject, visitor);
    visitor.append(&thisObject->m_regExp);
    visitor.append(&thisObject->m_lastIndex);
}
예제 #11
0
RegExpObject*
js::RegExpAlloc(ExclusiveContext* cx, HandleObject proto /* = nullptr */)
{
    // Note: RegExp objects are always allocated in the tenured heap. This is
    // not strictly required, but simplifies embedding them in jitcode.
    RegExpObject* regexp = NewObjectWithClassProto<RegExpObject>(cx, proto, TenuredObject);
    if (!regexp)
        return nullptr;
    regexp->initPrivate(nullptr);
    return regexp;
}
예제 #12
0
void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
    RegExpObject* thisObject = static_cast<RegExpObject*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
    Base::visitChildren(thisObject, visitor);
    if (thisObject->d->regExp)
        visitor.append(&thisObject->d->regExp);
    if (UNLIKELY(!thisObject->d->lastIndex.get().isInt32()))
        visitor.append(&thisObject->d->lastIndex);
}
예제 #13
0
JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UString s = thisValue.toThisString(exec);

    JSValue a0 = args.at(0);

    UString u = s;
    RefPtr<RegExp> reg;
    RegExpObject* imp = 0;
    if (a0.isObject(&RegExpObject::info))
        reg = asRegExpObject(a0)->regExp();
    else {
        /*
         *  ECMA 15.5.4.12 String.prototype.search (regexp)
         *  If regexp is not an object whose [[Class]] property is "RegExp", it is
         *  replaced with the result of the expression new RegExp(regexp).
         */
        reg = RegExp::create(&exec->globalData(), a0.toString(exec));
    }
    RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
    int pos;
    int matchLength;
    regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
    if (!(reg->global())) {
        // case without 'g' flag is handled like RegExp.prototype.exec
        if (pos < 0)
            return jsNull();
        return regExpConstructor->arrayOfMatches(exec);
    }

    // return array of matches
    MarkedArgumentBuffer list;
    int lastIndex = 0;
    while (pos >= 0) {
        list.append(jsSubstring(exec, u, pos, matchLength));
        lastIndex = pos;
        pos += matchLength == 0 ? 1 : matchLength;
        regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength);
    }
    if (imp)
        imp->setLastIndex(lastIndex);
    if (list.isEmpty()) {
        // if there are no matches at all, it's important to return
        // Null instead of an empty array, because this matches
        // other browsers and because Null is a false value.
        return jsNull();
    }

    return constructArray(exec, list);
}
예제 #14
0
JSObject *
js::CloneScriptRegExpObject(JSContext *cx, RegExpObject &reobj)
{
    /* NB: Keep this in sync with XDRScriptRegExpObject. */

    RootedAtom source(cx, reobj.getSource());
    RegExpObject *clone = RegExpObject::createNoStatics(cx, source, reobj.getFlags(), NULL);
    if (!clone)
        return NULL;
    if (!clone->clearParent(cx))
        return NULL;
    if (!clone->clearType(cx))
        return NULL;
    return clone;
}
예제 #15
0
static JSBool
regexp_compile(JSContext *cx, uintN argc, Value *vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    bool ok;
    JSObject *obj = NonGenericMethodGuard(cx, args, regexp_compile, &RegExpClass, &ok);
    if (!obj)
        return ok;

    RegExpObject *reobj = obj->asRegExp();
    ok = CompileRegExpObject(cx, reobj, args.length(), args.array(), &args.rval());
    JS_ASSERT_IF(ok, reobj->getPrivate());
    return ok;
}
예제 #16
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);
    }
예제 #17
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;
        }
    }
예제 #18
0
/* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
bool
js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
                        Handle<JSLinearString*> input, const jschar *chars, size_t length,
                        size_t *lastIndex, bool test, MutableHandleValue rval)
{
    RegExpGuard shared(cx);
    if (!reobj.getShared(cx, &shared))
        return false;

    ScopedMatchPairs matches(&cx->tempLifoAlloc());
    MatchConduit conduit(&matches);

    RegExpRunStatus status =
        ExecuteRegExpImpl(cx, res, *shared, input, chars, length, lastIndex, conduit);

    if (status == RegExpRunStatus_Error)
        return false;

    if (status == RegExpRunStatus_Success_NotFound) {
        /* ExecuteRegExp() previously returned an array or null. */
        rval.setNull();
        return true;
    }

    if (test) {
        /* Forbid an array, as an optimization. */
        rval.setBoolean(true);
        return true;
    }

    return CreateRegExpMatchResult(cx, input, chars, length, matches, rval);
}
예제 #19
0
EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec)
{
    JSValue thisValue = exec->hostThisValue();
    if (!thisValue.inherits(&RegExpObject::s_info))
        return throwVMTypeError(exec);

    JSValue arg = exec->argument(0);
    RegExpObject* reg = asRegExpObject(thisValue);
    JSValue result = jsBoolean(reg->test(exec, arg.toString(exec)));

#ifdef ARTEMIS
    if (arg.isSymbolic()) {
        result.makeSymbolic(new Symbolic::StringRegexSubmatch((Symbolic::StringExpression*)arg.asSymbolic(),
                                                              new std::string(reg->regExp()->pattern().ascii().data())),
                            exec->globalData());
    }
#endif

    return JSValue::encode(result);
}
예제 #20
0
JSBool
js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
{
    JSString *source = 0;
    uint32 flagsword = 0;

    if (xdr->mode == JSXDR_ENCODE) {
        JS_ASSERT(objp);
        RegExpObject *reobj = (*objp)->asRegExp();
        source = reobj->getSource();
        flagsword = reobj->getFlags();
    }
    if (!JS_XDRString(xdr, &source) || !JS_XDRUint32(xdr, &flagsword))
        return false;
    if (xdr->mode == JSXDR_DECODE) {
        JSAtom *atom = js_AtomizeString(xdr->cx, source);
        if (!atom)
            return false;
        RegExpObject *reobj = RegExpObject::createNoStatics(xdr->cx, atom, RegExpFlag(flagsword),
                                                            NULL);
        if (!reobj)
            return false;

        if (!reobj->clearParent(xdr->cx))
            return false;
        if (!reobj->clearType(xdr->cx))
            return false;
        *objp = reobj;
    }
    return true;
}
예제 #21
0
    bool dumpIfTerminal(JSValue value)
    {
        if (!value.isCell()) {
            dumpImmediate(value);
            return true;
        }

        if (value.isString()) {
            UString str = asString(value)->value(m_exec);
            dumpString(str);
            return true;
        }

        if (value.isNumber()) {
            write(DoubleTag);
            write(value.asNumber());
            return true;
        }

        if (value.isObject() && asObject(value)->inherits(&DateInstance::s_info)) {
            write(DateTag);
            write(asDateInstance(value)->internalNumber());
            return true;
        }

        if (isArray(value))
            return false;
           
        // Object cannot be serialized because the act of walking the object creates new objects
        if (value.isObject() && asObject(value)->inherits(&JSNavigator::s_info)) {
            fail();
            write(NullTag);
            return true; 
        }

        if (value.isObject()) {
            JSObject* obj = asObject(value);
            if (obj->inherits(&JSFile::s_info)) {
                write(FileTag);
                write(toFile(obj));
                return true;
            }
            if (obj->inherits(&JSFileList::s_info)) {
                FileList* list = toFileList(obj);
                write(FileListTag);
                unsigned length = list->length();
                write(length);
                for (unsigned i = 0; i < length; i++)
                    write(list->item(i));
                return true;
            }
            if (obj->inherits(&JSBlob::s_info)) {
                write(BlobTag);
                Blob* blob = toBlob(obj);
                write(blob->url());
                write(blob->type());
                write(blob->size());
                return true;
            }
            if (obj->inherits(&JSImageData::s_info)) {
                ImageData* data = toImageData(obj);
                write(ImageDataTag);
                write(data->width());
                write(data->height());
                write(data->data()->length());
                write(data->data()->data()->data(), data->data()->length());
                return true;
            }
            if (obj->inherits(&RegExpObject::s_info)) {
                RegExpObject* regExp = asRegExpObject(obj);
                char flags[3];
                int flagCount = 0;
                if (regExp->regExp()->global())
                    flags[flagCount++] = 'g';
                if (regExp->regExp()->ignoreCase())
                    flags[flagCount++] = 'i';
                if (regExp->regExp()->multiline())
                    flags[flagCount++] = 'm';
                write(RegExpTag);
                write(regExp->regExp()->pattern());
                write(UString(flags, flagCount));
                return true;
            }
            if (obj->inherits(&JSMessagePort::s_info)) {
                ObjectPool::iterator index = m_transferredMessagePorts.find(obj);
                if (index != m_transferredMessagePorts.end()) {
                    write(MessagePortReferenceTag);
                    uint32_t i = index->second;
                    write(i);
                    return true;
                }
                return false;
            }

            CallData unusedData;
            if (getCallData(value, unusedData) == CallTypeNone)
                return false;
        }
        // Any other types are expected to serialize as null.
        write(NullTag);
        return true;
    }