8#include <private/qv4mm_p.h>
11#include <private/qv4alloca_p.h>
14#include <QtCore/QDateTime>
15#include <QtCore/QDebug>
16#include <QtCore/QStringList>
17#include <QtQml/private/qv4runtime_p.h>
26# include "qplatformdefs.h"
37void Heap::StringObject::init()
40 Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
41 string.set(internalClass->engine, internalClass->engine->id_empty()->d());
48 string.set(internalClass->engine,
str->d());
57 return internalClass->engine->newString(
str.
mid(
index, 1));
60uint Heap::StringObject::length()
const
68 if (
id.isArrayIndex()) {
71 if (
index <
static_cast<uint>(
o->d()->string->toQString().size()))
88 if (arrayIndex < slen) {
96 }
else if (arrayIndex == slen) {
100 while (arrayNode && arrayNode->key() < slen)
120 if (
id.isArrayIndex()) {
123 if (
index <
uint(
s->d()->string->toQString().size())) {
154 obj->setProtoFromNewTarget(newTarget);
155 return obj->asReturnedValue();
172 for (
int i = 0, ei = argc;
i < ei; ++
i) {
186 for (
int i = 0;
i < argc; ++
i) {
190 int cp =
static_cast<int>(
num);
191 if (cp !=
num || cp < 0 || cp > 0x10ffff)
194 *
ch = QChar::highSurrogate(cp);
196 *
ch = QChar::lowSurrogate(cp);
225 uint literalSegments = raw->getLength();
226 if (!literalSegments)
232 val = raw->get(nextIndex);
233 result += val->toQString();
236 if (nextIndex + 1 == literalSegments)
239 if (nextIndex <
static_cast<uint>(argc))
258 ctor->defineReadonlyProperty(
engine->id_prototype(), (
o =
this));
265 defineDefaultProperty(
engine->id_toString(), method_toString);
266 defineDefaultProperty(
engine->id_valueOf(), method_toString);
267 defineDefaultProperty(
QStringLiteral(
"charAt"), method_charAt, 1);
268 defineDefaultProperty(
QStringLiteral(
"charCodeAt"), method_charCodeAt, 1);
269 defineDefaultProperty(
QStringLiteral(
"codePointAt"), method_codePointAt, 1);
270 defineDefaultProperty(
QStringLiteral(
"concat"), method_concat, 1);
271 defineDefaultProperty(
QStringLiteral(
"endsWith"), method_endsWith, 1);
272 defineDefaultProperty(
QStringLiteral(
"indexOf"), method_indexOf, 1);
273 defineDefaultProperty(
QStringLiteral(
"includes"), method_includes, 1);
274 defineDefaultProperty(
QStringLiteral(
"lastIndexOf"), method_lastIndexOf, 1);
275 defineDefaultProperty(
QStringLiteral(
"localeCompare"), method_localeCompare, 1);
277 defineDefaultProperty(
QStringLiteral(
"normalize"), method_normalize, 0);
278 defineDefaultProperty(
QStringLiteral(
"padEnd"), method_padEnd, 1);
279 defineDefaultProperty(
QStringLiteral(
"padStart"), method_padStart, 1);
280 defineDefaultProperty(
QStringLiteral(
"repeat"), method_repeat, 1);
281 defineDefaultProperty(
QStringLiteral(
"replace"), method_replace, 2);
282 defineDefaultProperty(
QStringLiteral(
"search"), method_search, 1);
285 defineDefaultProperty(
QStringLiteral(
"startsWith"), method_startsWith, 1);
286 defineDefaultProperty(
QStringLiteral(
"substr"), method_substr, 2);
287 defineDefaultProperty(
QStringLiteral(
"substring"), method_substring, 2);
288 defineDefaultProperty(
QStringLiteral(
"toLowerCase"), method_toLowerCase);
289 defineDefaultProperty(
QStringLiteral(
"toLocaleLowerCase"), method_toLocaleLowerCase);
290 defineDefaultProperty(
QStringLiteral(
"toUpperCase"), method_toUpperCase);
291 defineDefaultProperty(
QStringLiteral(
"toLocaleUpperCase"), method_toLocaleUpperCase);
293 defineDefaultProperty(
engine->symbol_iterator(), method_iterator);
301 return thisString->d()->string;
308 return s->toQString();
310 return thisString->d()->string->toQString();
327 return o->d()->string->asReturnedValue();
377 if (index < 0 || index >=
value.size())
383 if (QChar::isLowSurrogate(second))
384 return Encode(QChar::surrogateToUcs4(
first, second));
398 for (
int i = 0;
i < argc; ++
i) {
417 if (argc && argv[0].as<RegExpObject>())
431 return Encode(stringToSearch.endsWith(searchString));
450 if (!
value.isEmpty())
463 if (argc && argv[0].as<RegExpObject>())
471 const Value &posArg = argv[1];
473 if (!posArg.isInteger() && posArg.isNumber() &&
qIsInf(posArg.toNumber()))
481 return Encode(stringToSearch.contains(searchString));
528 if (argc && !argv[0].isNullOrUndefined()) {
533 if (!
f->isNullOrUndefined()) {
568 if (argc >= 1 && !argv[0].isUndefined()) {
598 return s->asReturnedValue();
601 if (maxLen <= s->
d()->
length())
602 return s->asReturnedValue();
603 QString fillString = (argc > 1 && !argv[1].
isUndefined()) ? argv[1].toQString() : u
" "_s;
607 if (fillString.isEmpty())
608 return s->asReturnedValue();
611 int oldLength = padded.
size();
612 int toFill = maxLen - oldLength;
616 int copy =
qMin(fillString.size(), toFill);
617 memcpy(
ch, fillString.constData(),
copy*
sizeof(
QChar));
637 return s->asReturnedValue();
640 if (maxLen <= s->
d()->
length())
641 return s->asReturnedValue();
642 QString fillString = (argc > 1 && !argv[1].
isUndefined()) ? argv[1].toQString() : u
" "_s;
646 if (fillString.isEmpty())
647 return s->asReturnedValue();
650 int oldLength = original.
size();
651 int toFill = maxLen - oldLength;
656 int copy =
qMin(fillString.size(), toFill);
657 memcpy(
ch, fillString.constData(),
copy*
sizeof(
QChar));
687 for (
int i = 0;
i < replaceValue.size(); ++
i) {
688 if (replaceValue.at(
i) ==
QLatin1Char(
'$') &&
i < replaceValue.size() - 1) {
689 ushort ch = replaceValue.at(
i + 1).unicode();
690 uint substStart = JSC::Yarr::offsetNoMatch;
691 uint substEnd = JSC::Yarr::offsetNoMatch;
697 }
else if (
ch ==
'&') {
698 substStart = matchOffsets[0];
699 substEnd = matchOffsets[1];
701 }
else if (
ch ==
'`') {
703 substEnd = matchOffsets[0];
705 }
else if (
ch ==
'\'') {
706 substStart = matchOffsets[1];
707 substEnd =
input.size();
709 }
else if (
ch >=
'0' &&
ch <=
'9') {
712 if (
i < replaceValue.size() - 2) {
713 ch = replaceValue.at(
i + 2).unicode();
714 if (
ch >=
'0' &&
ch <=
'9') {
715 uint c = capture*10 +
ch -
'0';
716 if (
c <
static_cast<uint>(captureCount)) {
722 if (capture > 0 && capture <
static_cast<uint>(captureCount)) {
723 substStart = matchOffsets[capture * 2];
724 substEnd = matchOffsets[capture * 2 + 1];
730 if (substStart != JSC::Yarr::offsetNoMatch && substEnd != JSC::Yarr::offsetNoMatch)
744 string = thisString->d()->string->toQString();
749 int numStringMatches = 0;
751 uint allocatedMatchOffsets = 64;
752 uint _matchOffsets[64];
753 uint *matchOffsets = _matchOffsets;
757 Scoped<RegExpObject> regExp(scope, searchValue);
760 uint nMatchOffsets = 0;
763 Scoped<RegExp> re(scope, regExp->value());
765 int oldSize = nMatchOffsets;
766 if (allocatedMatchOffsets < nMatchOffsets + re->captureCount() * 2) {
767 allocatedMatchOffsets =
qMax(allocatedMatchOffsets * 2, nMatchOffsets + re->captureCount() * 2);
768 uint *newOffsets = (
uint *)malloc(allocatedMatchOffsets*
sizeof(
uint));
769 memcpy(newOffsets, matchOffsets, nMatchOffsets*
sizeof(
uint));
770 if (matchOffsets != _matchOffsets)
772 matchOffsets = newOffsets;
774 if (re->match(
string,
offset, matchOffsets + oldSize) == JSC::Yarr::offsetNoMatch) {
775 nMatchOffsets = oldSize;
778 nMatchOffsets += re->captureCount() * 2;
779 if (!regExp->global())
783 if (regExp->global()) {
784 regExp->setLastIndex(0);
788 numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
789 numCaptures = regExp->value()->captureCount();
792 QString searchString = searchValue->toQString();
793 int idx =
string.
indexOf(searchString);
795 numStringMatches = 1;
796 matchOffsets[0] = idx;
797 matchOffsets[1] = idx + searchString.
size();
805 if (!!searchCallback) {
806 result.reserve(
string.
size() + 10*numStringMatches);
810 for (
int i = 0;
i < numStringMatches; ++
i) {
811 for (
int k = 0; k < numCaptures; ++k) {
812 int idx = (
i * numCaptures + k) * 2;
814 uint end = matchOffsets[idx + 1];
816 if (
start != JSC::Yarr::offsetNoMatch &&
end != JSC::Yarr::offsetNoMatch)
820 uint matchStart = matchOffsets[
i * numCaptures * 2];
822 uint matchEnd = matchOffsets[
i * numCaptures * 2 + 1];
827 replacement = searchCallback->call(&that,
arguments, numCaptures + 2);
835 QString newString = replaceValue->toQString();
839 for (
int i = 0;
i < numStringMatches; ++
i) {
840 int baseIndex =
i * numCaptures * 2;
841 uint matchStart = matchOffsets[baseIndex];
842 uint matchEnd = matchOffsets[baseIndex + 1];
843 if (matchStart == JSC::Yarr::offsetNoMatch)
853 if (matchOffsets != _matchOffsets)
874 Scoped<RegExp> re(scope, regExp->value());
876 uint result = re->match(
string, 0, matchOffsets);
877 if (
result == JSC::Yarr::offsetNoMatch)
892 const double length =
s->d()->length();
908 const int intStart = int(
start);
909 const int intEnd = int(
end);
928 if (separatorValue->isUndefined()) {
929 if (limitValue->isUndefined()) {
932 return array.asReturnedValue();
937 uint limit = limitValue->isUndefined() ? UINT_MAX : limitValue->toUInt32();
940 return array.asReturnedValue();
942 Scoped<RegExpObject> re(scope, separatorValue);
944 if (re->value()->pattern->isEmpty()) {
955 Scoped<RegExp> regexp(scope, re->value());
957 if (
result == JSC::Yarr::offsetNoMatch)
966 for (
int i = 1;
i < re->value()->captureCount(); ++
i) {
977 QString separator = separatorValue->toQString();
981 return array.asReturnedValue();
995 return array.asReturnedValue();
1005 if (argc && argv[0].as<RegExpObject>())
1063 if (argc > 1 && !argv[1].isUndefined())
1069 if (std::isnan(
end) ||
end < 0)
1101 return method_toLowerCase(
b, thisObject, argv, argc);
1116 return method_toUpperCase(
b, thisObject, argv, argc);
1126 const QChar *chars =
s.constData();
1129 if (!chars[
start].isSpace() && chars[
start].unicode() != 0xfeff)
1133 if (!chars[
end].isSpace() && chars[
end].unicode() != 0xfeff)
1150 return si->asReturnedValue();
constexpr QStringView left(qsizetype n) const noexcept
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString left(qsizetype n) const &
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
QString mid(qsizetype position, qsizetype n=-1) const &
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
bool isNull() const
Returns true if this string is null; otherwise returns false.
qsizetype size() const noexcept
Returns the number of characters in this string.
void push_back(QChar c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
QChar * data()
Returns a pointer to the data stored in the QString.
int localeAwareCompare(const QString &s) const
NormalizationForm
This enum describes the various normalized forms of Unicode text.
QString normalized(NormalizationForm mode, QChar::UnicodeVersion version=QChar::Unicode_Unassigned) const
Returns the string in the given Unicode normalization mode, according to the given version of the Uni...
qsizetype length() const noexcept
Returns the number of characters in this string.
void resize(qsizetype size)
Sets the size of the string to size characters.
ObjectType::Data * allocate(Args &&... args)
ManagedType::Data * alloc(Args &&... args)
QList< QVariant > arguments
Scoped< FunctionObject > ScopedFunctionObject
ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result)
Scoped< String > ScopedString
constexpr Initialization Uninitialized
static jboolean copy(JNIEnv *, jobject)
static const QCssKnownValue repeats[NumKnownRepeats - 1]
static struct AttrInfo attrs[]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qIsInf(qfloat16 f) noexcept
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf()
constexpr static Q_DECL_CONST_FUNCTION double qt_qnan() noexcept
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLenum GLuint GLintptr offset
GLint GLenum GLboolean normalized
GLenum GLenum GLenum input
GLsizei const GLchar *const * string
[0]
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define Q_ALLOCA_VAR(type, name, size)
#define CHECK_EXCEPTION()
static Heap::String * thisAsString(ExecutionEngine *v4, const QV4::Value *thisObject)
static QString getThisString(ExecutionEngine *v4, const QV4::Value *thisObject)
static void appendReplacementString(QString *result, const QString &input, const QString &replaceValue, uint *matchOffsets, int captureCount)
#define DEFINE_OBJECT_VTABLE(classname)
args<< 1<< 2;QJSValue threeAgain=fun.call(args);QString fileName="helloworld.qs";QFile scriptFile(fileName);if(!scriptFile.open(QIODevice::ReadOnly)) QTextStream stream(&scriptFile);QString contents=stream.readAll();scriptFile.close();myEngine.evaluate(contents, fileName);myEngine.globalObject().setProperty("myNumber", 123);...QJSValue myNumberPlusOne=myEngine.evaluate("myNumber + 1");QJSValue result=myEngine.evaluate(...);if(result.isError()) qDebug()<< "Uncaught exception at line"<< result.property("lineNumber").toInt()<< ":"<< result.toString();QPushButton *button=new QPushButton;QJSValue scriptButton=myEngine.newQObject(button);myEngine.globalObject().setProperty("button", scriptButton);myEngine.evaluate("button.checkable = true");qDebug()<< scriptButton.property("checkable").toBool();scriptButton.property("show").call();QJSEngine engine;QObject *myQObject=new QObject();myQObject- setProperty)("dynamicProperty", 3)
\inmodule QtCore \reentrant
static constexpr ReturnedValue undefined()
Heap::InternalClass * classes[NClasses]
MemoryManager * memoryManager
FunctionObject * regExpCtor() const
ReturnedValue throwRangeError(const Value &value)
Heap::String * newString(char16_t c)
Heap::String * newIdentifier(const QString &text)
String * id_empty() const
Object * objectPrototype() const
Symbol * symbol_match() const
Heap::ArrayObject * newArrayObject(int count=0)
Heap::Object * newStringObject(const String *string)
ReturnedValue throwTypeError()
ReturnedValue callAsConstructor(const Value *argv, int argc, const Value *newTarget=nullptr) const
ReturnedValue asReturnedValue() const
Pointer< InternalClass *, 0 > internalClass
Q_REQUIRED_RESULT InternalClass * changePrototype(Heap::Object *proto)
void init(QV4::ExecutionEngine *engine)
ExecutionEngine * engine() const
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
static PropertyKey fromArrayIndex(uint idx)
static double toNumber(const Value &value)
Value * alloc(qint64 nValues) const =delete
bool hasException() const
const SparseArrayNode * nextNode() const
QV4_NEARLY_ALWAYS_INLINE constexpr quint64 rawValue() const
constexpr ReturnedValue asReturnedValue() const
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 value() const
bool isNullOrUndefined() const
static ReturnedValue method_raw(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_fromCharCode(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_fromCodePoint(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static bool virtualDeleteProperty(Managed *m, PropertyKey id)
static ReturnedValue method_localeCompare(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_concat(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toLocaleUpperCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_indexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_includes(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_repeat(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toLocaleLowerCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_padEnd(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toLowerCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toUpperCase(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_charAt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_replace(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_normalize(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_substr(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_slice(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_match(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_codePointAt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_search(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_split(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_substring(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_trim(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
void init(ExecutionEngine *engine, Object *ctor)
static ReturnedValue method_lastIndexOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_charCodeAt(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_startsWith(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_endsWith(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_padStart(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_iterator(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static constexpr VTable::OwnPropertyKeys virtualOwnPropertyKeys
static constexpr VTable::GetOwnProperty virtualGetOwnProperty
static constexpr VTable::CallAsConstructor virtualCallAsConstructor
static constexpr VTable::Call virtualCall
static constexpr VTable::DeleteProperty virtualDeleteProperty
static constexpr Value fromInt32(int i)
Heap::String * toString(ExecutionEngine *e) const
QML_NEARLY_ALWAYS_INLINE String * stringValue() const
static constexpr Value undefinedValue()
QString toQString() const
QML_NEARLY_ALWAYS_INLINE Symbol * symbolValue() const
Heap::Object * toObject(ExecutionEngine *e) const
static Value fromUInt32(uint i)
~StringObjectOwnPropertyKeyIterator() override=default
PropertyKey next(const QV4::Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override