6#include <private/qqmlengine_p.h>
7#include <private/qqmljavascriptexpression_p.h>
8#include <private/qqmljsast_p.h>
9#include <private/qqmltypewrapper_p.h>
10#include <private/qqmlvaluetypewrapper_p.h>
11#include <private/qv4argumentsobject_p.h>
12#include <private/qv4engine_p.h>
13#include <private/qv4function_p.h>
14#include <private/qv4generatorobject_p.h>
15#include <private/qv4global_p.h>
16#include <private/qv4globalobject_p.h>
17#include <private/qv4jscall_p.h>
18#include <private/qv4lookup_p.h>
19#include <private/qv4math_p.h>
20#include <private/qv4object_p.h>
21#include <private/qv4qmlcontext_p.h>
22#include <private/qv4qobjectwrapper_p.h>
23#include <private/qv4regexp_p.h>
24#include <private/qv4regexpobject_p.h>
25#include <private/qv4scopedvalue_p.h>
26#include <private/qv4stackframe_p.h>
27#include <private/qv4symbol_p.h>
29#include <wtf/MathExtras.h>
31#include <QtCore/private/qlocale_tools_p.h>
32#include <QtCore/qdebug.h>
34#ifdef QV4_COUNT_RUNTIME_FUNCTIONS
35# include <QtCore/qbuffer.h>
46#ifdef QV4_COUNT_RUNTIME_FUNCTIONS
47struct RuntimeCounters::Data {
58 static const char *pretty(
Type t) {
62 case Null:
return "Null";
65 case Managed:
return "Managed";
66 case Double:
return "Double";
67 default:
return "Unknown";
71 static unsigned mangle(
unsigned tag) {
73 case Value::Undefined_Type:
return Undefined;
74 case Value::Null_Type:
return Null;
75 case Value::Boolean_Type:
return Boolean;
76 case Value::Integer_Type:
return Integer;
77 case Value::Managed_Type:
return Managed;
82 static unsigned mangle(
unsigned tag1,
unsigned tag2) {
83 return (mangle(tag1) << 3) | mangle(tag2);
86 static void unmangle(
unsigned signature,
Type &tag1,
Type &tag2) {
87 tag1 =
Type((signature >> 3) & 7);
88 tag2 =
Type(signature & 7);
91 typedef QVector<quint64> Counters;
92 QHash<const char *, Counters>
counters;
105 cnt[mangle(
tag)] += 1;
108 inline void count(
const char *
func,
unsigned tag1,
unsigned tag2) {
112 cnt[mangle(tag1, tag2)] += 1;
120 static bool less(
const Line &line1,
const Line &line2) {
121 return line1.count > line2.count;
131 const Counters &fCount =
it.value();
132 for (
int i = 0, ei = fCount.size();
i != ei; ++
i) {
143 std::sort(lines.begin(), lines.end(), Line::less);
144 outs << lines.size() <<
" counters:" << endl;
148 <<
" | " << pretty(
line.tag1)
149 <<
" | " << pretty(
line.tag2)
155RuntimeCounters *RuntimeCounters::instance = 0;
156static RuntimeCounters runtimeCountersInstance;
157RuntimeCounters::RuntimeCounters()
164RuntimeCounters::~RuntimeCounters()
170void RuntimeCounters::count(
const char *
func)
175void RuntimeCounters::count(
const char *
func,
uint tag)
180void RuntimeCounters::count(
const char *
func,
uint tag1,
uint tag2)
182 d->count(
func, tag1, tag2);
189 return f->executableCompilationUnit()->runtimeLookups +
i;
196 if (std::isnan(
num)) {
207 const int ecma_shortest_low = -6;
208 const int ecma_shortest_high = 21;
217 if (decpt <= ecma_shortest_low || decpt > ecma_shortest_high) {
224 }
else if (decpt <= 0) {
226 }
else if (decpt < result->
size()) {
239 bool negative =
false;
246 double frac =
num - ::floor(
num);
247 num = Value::toInteger(
num);
250 char c = (char)::fmod(
num, radix);
251 c = (
c < 10) ? (
c +
'0') : (
c - 10 +
'a');
253 num = ::floor(
num / radix);
258 double magnitude = 1;
262 const int floored = ::floor(
next);
263 char c = char(floored);
264 c = (
c < 10) ? (
c +
'0') : (
c - 10 +
'a');
267 frac -= double(floored) * magnitude;
268 next -= double(floored);
273 }
while (frac > 0 && frac - magnitude != frac);
283 ->runtimeFunctions[functionId];
286 if (clos->isGenerator())
287 return GeneratorFunction::create(current, clos)->asReturnedValue();
288 return FunctionObject::createScriptFunction(current, clos)->asReturnedValue();
296 return Encode::undefined();
302 return o->deleteProperty(
key);
308 if (function->isStrict())
319 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
320 return engine->currentContext()->deleteProperty(
name);
325 if (!Runtime::DeleteName_NoThrow::call(
engine,
name)) {
326 if (function->isStrict())
339 return engine->throwTypeError();
344 if (
f &&
f->d()->prototype() ==
engine->functionPrototype()->d() && !
f->hasHasInstanceProperty())
345 return Object::checkedInstanceOf(
engine,
f, lval);
349 if (hasInstance->isUndefined())
354 return engine->throwTypeError();
356 return Encode(fHasInstance->call(&rval, &lval, 1));
375 return Encode::null();
379 return lval.asReturnedValue();
380 else if (
result->isBoolean())
381 return Encode::null();
384 if (Scoped<QQmlTypeWrapper> typeWrapper(scope, rval); typeWrapper)
385 return coerce(
engine, lval, typeWrapper->d()->type(),
false);
387 return Encode::undefined();
394 return engine->throwTypeError();
398 return Encode::undefined();
403double RuntimeHelpers::stringToNumber(
const QString &
string)
410 const int excessiveLength = 16 * 1024;
411 if (
string.
size() > excessiveLength)
435 const char *
end =
nullptr;
438 if (
ba ==
"Infinity" ||
ba ==
"+Infinity")
440 else if (
ba ==
"-Infinity")
443 d = std::numeric_limits<double>::quiet_NaN();
451 RuntimeHelpers::numberToString(&qstr,
number, 10);
452 return engine->newString(qstr);
459 return Encode::undefined();
477 return Encode::undefined();
481 return Encode::undefined();
482 if (!
result->isPrimitive())
483 return engine->throwTypeError();
484 return result->asReturnedValue();
489 return ordinaryToPrimitive(
engine,
object,
hint);
500 if (typeHint->propertyKey() ==
engine->id_number()->propertyKey()) {
503 Q_ASSERT(typeHint->propertyKey() ==
engine->id_string()->propertyKey());
511 result =
o->call(
object,
nullptr, 0);
513 return Encode::undefined();
514 if (
result->isPrimitive())
515 return result->asReturnedValue();
519 return Encode::undefined();
521 conv =
object->get(meth2);
523 result =
o->call(
object,
nullptr, 0);
525 return Encode::undefined();
526 if (
result->isPrimitive())
527 return result->asReturnedValue();
530 return engine->throwTypeError();
537 switch (
value.type()) {
538 case Value::Undefined_Type:
539 engine->throwTypeError(
QLatin1String(
"Value is undefined and could not be converted to an object"));
541 case Value::Null_Type:
542 engine->throwTypeError(
QLatin1String(
"Value is null and could not be converted to an object"));
544 case Value::Boolean_Type:
545 return engine->newBooleanObject(
value.booleanValue());
546 case Value::Managed_Type:
548 if (!
value.isString())
549 return engine->newSymbolObject(
value.symbolValue());
550 return engine->newStringObject(
value.stringValue());
551 case Value::Integer_Type:
560 switch (
value.type()) {
561 case Value::Empty_Type:
562 Q_ASSERT(!
"empty Value encountered");
564 case Value::Undefined_Type:
565 return engine->id_undefined()->d();
566 case Value::Null_Type:
567 return engine->id_null()->d();
568 case Value::Boolean_Type:
569 if (
value.booleanValue())
570 return engine->id_true()->d();
572 return engine->id_false()->d();
573 case Value::Managed_Type: {
574 if (
value.isString())
576 if (
value.isSymbol()) {
580 value = Value::fromReturnedValue(RuntimeHelpers::toPrimitive(
value,
hint));
582 if (
value.isString())
586 case Value::Integer_Type:
589 return RuntimeHelpers::stringFromNumber(
engine,
value.doubleValue());
608 if (sleft || sright) {
611 sleft =
static_cast<String *
>(pleft.ptr);
615 sright =
static_cast<String *
>(pright.ptr);
618 return Encode::undefined();
619 if (!sleft->d()->length())
620 return sright->asReturnedValue();
621 if (!sright->d()->length())
622 return sleft->asReturnedValue();
626 double x = RuntimeHelpers::toNumber(pleft);
627 double y = RuntimeHelpers::toNumber(pright);
633 return function->executableCompilationUnit()->templateObjectAt(
index)->asReturnedValue();
660 if (
const String *
str =
object.as<String>()) {
662 return Encode::undefined();
668 if (
object.isNullOrUndefined()) {
673 o = RuntimeHelpers::convertToObject(scope.
engine,
object);
677 if (
o->arrayData() && !
o->arrayData()->attrs) {
680 return v->asReturnedValue();
694 if (
object.isNullOrUndefined()) {
699 o = RuntimeHelpers::convertToObject(scope.
engine,
object);
705 return Encode::undefined();
711 if (
index.isPositiveInt()) {
714 if (
b->internalClass->vtable->isObject) {
715 Heap::Object *
o =
static_cast<Heap::Object *
>(
b);
716 if (
o->arrayData &&
o->arrayData->type == Heap::ArrayData::Simple) {
719 if (!
s->data(idx).isEmpty())
735 if (
engine->currentStackFrame->v4Function->isStrict()) {
745 if (
index.isPositiveInt()) {
747 if (
o->d()->arrayData &&
o->d()->arrayData->type == Heap::ArrayData::Simple) {
749 if (idx < s->
values.size) {
754 return o->put(idx,
value);
765 if (
index.isPositiveInt()) {
768 if (
b->internalClass->vtable->isObject) {
769 Heap::Object *
o =
static_cast<Heap::Object *
>(
b);
770 if (
o->arrayData &&
o->arrayData->type == Heap::ArrayData::Simple) {
772 if (idx < s->
values.size) {
789 if (!
in.isNullOrUndefined())
792 return Encode::undefined();
795 return engine->throwTypeError();
798 return engine->throwTypeError();
802 return Encode::undefined();
804 return engine->throwTypeError();
805 return it->asReturnedValue();
807 return engine->newForInIteratorObject(
o)->asReturnedValue();
834 bool done =
d->toBoolean();
836 *
value = Encode::undefined();
856 bool returnCalled =
false;
858 if (
engine->hasException) {
859 if (
engine->exceptionValue->isEmpty()) {
861 *
engine->exceptionValue = Encode::undefined();
862 engine->hasException =
false;
867 if (
ret->isUndefined()) {
869 return Encode::undefined();
876 *
engine->exceptionValue = Encode::undefined();
877 engine->hasException =
false;
882 if (
t->isUndefined()) {
884 IteratorClose::call(
engine, iterator);
885 if (!
engine->hasException)
890 arg = exceptionValue;
914 bool done =
d->toBoolean();
916 *
object =
o->get(
engine->id_value());
917 return (returnCalled && !
engine->hasException) ? Encode::undefined() :
Encode(
true);
929 bool hadException =
engine->hasException;
931 e = *
engine->exceptionValue;
932 engine->hasException =
false;
935 auto originalCompletion = [=]() {
937 *
engine->exceptionValue = e;
938 engine->hasException = hadException;
940 return Encode::undefined();
945 if (!
ret->isUndefined()) {
947 o =
f->call(&iterator,
nullptr, 0);
948 if (
engine->hasException && !hadException)
949 return Encode::undefined();
951 if (hadException ||
ret->isUndefined())
952 return originalCompletion();
955 return engine->throwTypeError();
957 return originalCompletion();
966 array->arrayCreate();
972 return Encode::undefined();
974 if (
done->booleanValue())
979 return array->asReturnedValue();
985 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
988 if (e == ExecutionContext::RangeError)
995 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
997 if (e == ExecutionContext::TypeError)
999 else if (e == ExecutionContext::RangeError)
1006 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
1010 return o->get(
name);
1012 if (
object.isNullOrUndefined()) {
1017 o = RuntimeHelpers::convertToObject(scope.
engine,
object);
1019 return Encode::undefined();
1020 return o->get(
name);
1026 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
1027 return engine->currentContext()->getProperty(
name);
1032 Scoped<JavaScriptFunctionObject>
f(scope);
1038 if (
frame->jsFrame->thisObject.isEmpty()) {
1044 f = Value::fromStaticValue(
frame->jsFrame->function);
1045 homeObject =
f->getHomeObject();
1050 if (
frame->thisObject() ==
nullptr) {
1062 f =
c->d()->function;
1070 homeObject =
f->getHomeObject();
1077 ScopedObject proto(scope, homeObject->getPrototypeOf());
1090 return Encode::undefined();
1092 if (
engine->hasException)
1093 return Encode::undefined();
1103 Scoped<QObjectWrapper>
wrapper(scope, QObjectWrapper::wrap(
engine,
frame->thisObject()));
1115 if (
engine->hasException)
1127 Scoped<QObjectWrapper>
wrapper(scope, QObjectWrapper::wrap(
engine,
frame->thisObject()));
1131 if (!
result &&
engine->currentStackFrame->v4Function->isStrict())
1132 engine->throwTypeError();
1165 engine->throwTypeError();
1170 if (
engine->currentStackFrame->isJSTypesFrame()) {
1172 if (
frame->thisObject() != Value::emptyValue().asReturnedValue()) {
1174 return engine->throwReferenceError(
1180 if (
frame->thisObject() !=
nullptr) {
1182 return engine->throwReferenceError(
1189 return engine->throwTypeError();
1190 Heap::Object *
c =
static_cast<const Object &
>(
t).getPrototypeOf();
1191 if (!
c->vtable()->callAsConstructor)
1192 return engine->throwTypeError();
1193 return c->asReturnedValue();
1198 Q_ASSERT(
x.type() !=
y.type() || (
x.isManaged() && (
x.isString() !=
y.isString())));
1200 if (
x.isNumber() &&
y.isNumber())
1201 return x.asDouble() ==
y.asDouble();
1202 if (
x.isNull() &&
y.isUndefined()) {
1204 }
else if (
x.isUndefined() &&
y.isNull()) {
1206 }
else if (
x.isNumber() &&
y.isString()) {
1207 double dy = RuntimeHelpers::toNumber(
y);
1208 return x.asDouble() == dy;
1209 }
else if (
x.isString() &&
y.isNumber()) {
1210 double dx = RuntimeHelpers::toNumber(
x);
1211 return dx ==
y.asDouble();
1212 }
else if (
x.isBoolean()) {
1213 return Runtime::CompareEqual::call(Value::fromDouble((
double)
x.booleanValue()),
y);
1214 }
else if (
y.isBoolean()) {
1215 return Runtime::CompareEqual::call(
x, Value::fromDouble((
double)
y.booleanValue()));
1219 if (yo && (
x.isNumber() ||
x.isString())) {
1220 Scope scope(yo->engine());
1222 return Runtime::CompareEqual::call(
x, py);
1223 }
else if (xo && (
y.isNumber() ||
y.isString())) {
1224 Scope scope(xo->engine());
1226 return Runtime::CompareEqual::call(px,
y);
1237 if (
x.rawValue() ==
y.rawValue())
1242 return y.isNumber() &&
x.asDouble() ==
y.asDouble();
1243 if (
x.isManaged()) {
1269 return Runtime::CompareGreaterThan::call(pl, pr);
1272 double dl = RuntimeHelpers::toNumber(l);
1273 double dr = RuntimeHelpers::toNumber(
r);
1297 return Runtime::CompareLessThan::call(pl, pr);
1300 double dl = RuntimeHelpers::toNumber(l);
1301 double dr = RuntimeHelpers::toNumber(
r);
1325 return Runtime::CompareGreaterEqual::call(pl, pr);
1328 double dl = RuntimeHelpers::toNumber(l);
1329 double dr = RuntimeHelpers::toNumber(
r);
1353 return Runtime::CompareLessEqual::call(pl, pr);
1356 double dl = RuntimeHelpers::toNumber(l);
1357 double dr = RuntimeHelpers::toNumber(
r);
1367 return v->booleanValue();
1376 return v->booleanValue();
1385 .arg(propertyName, objectAsString);
1386 return engine->throwTypeError(msg);
1394 Value thisObject = Value::undefinedValue();
1395 if (!function.isFunctionObject()) {
1397 engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->
nameIndex]->toQString());
1401 &thisObject, argv, argc));
1405 Value *argv,
int argc)
1411 if (!function.isFunctionObject()) {
1413 engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->
nameIndex]->toQString());
1417 thisObject, argv, argc));
1426 scope,
engine->currentContext()->getPropertyAndBase(
engine->id_eval(), thisObject));
1427 if (
engine->hasException)
1428 return Encode::undefined();
1433 if (function->d() ==
engine->evalFunction()->d())
1434 return static_cast<EvalFunction *
>(function.getPointer())->evalCall(thisObject, argv, argc,
true);
1443 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
1446 if (
engine->hasException)
1447 return Encode::undefined();
1451 engine, thisObject,
engine->currentStackFrame->v4Function->compilationUnit
1452 ->runtimeStrings[nameIndex]->toQString());
1464 engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
1467 if (!lookupObject) {
1469 if (
base->isNullOrUndefined()) {
1471 .arg(
name->toQString(),
base->toQStringNoThrow());
1475 if (
base->isManaged()) {
1478 Q_ASSERT(
m->internalClass()->prototype);
1480 lookupObject = RuntimeHelpers::convertToObject(
engine, *
base);
1481 if (
engine->hasException)
1482 return Encode::undefined();
1483 if (!
engine->currentStackFrame->v4Function->isStrict())
1484 base = lookupObject;
1492 .arg(
name->toQString(),
1493 base->toQStringNoThrow());
1513 .arg(
engine->currentStackFrame->v4Function->compilationUnit
1514 ->runtimeStrings[l->
nameIndex]->toQString())
1515 .arg(
base.toQStringNoThrow());
1521 if (!
func.isFunctionObject())
1523 Value undef = Value::undefinedValue();
1525 &undef, argv, argc));
1529 const Value &thisObject,
Value argv[],
int argc)
1531 if (!
func.isFunctionObject())
1534 &thisObject, argv, argc));
1551 for (
int i = 0;
i < argc; ++
i) {
1552 if (!argv[
i].isEmpty()) {
1555 v = scope.
alloc<Scope::Uninitialized>();
1560 it = Runtime::GetIterator::call(scope.
engine, argv[
i], 1);
1562 return {
nullptr, 0 };
1566 return {
nullptr, 0 };
1568 if (
done->booleanValue())
1571 constexpr auto safetyMargin = 100;
1574 return {
nullptr, 0 };
1576 v = scope.
alloc<Scope::Uninitialized>();
1585 if (!function.isFunctionObject())
1586 return engine->throwTypeError();
1590 if (
engine->hasException)
1591 return Encode::undefined();
1599 if (!function.isFunctionObject())
1600 return engine->throwTypeError();
1607 if (!function.isFunctionObject())
1608 return engine->throwTypeError();
1612 if (
engine->hasException)
1613 return Encode::undefined();
1624 const Value &function = tos[StackOffsets::tailCall_function];
1625 const Value &thisObject = tos[StackOffsets::tailCall_thisObject];
1626 Value *argv =
reinterpret_cast<Value *
>(
frame->jsFrame) + tos[StackOffsets::tailCall_argv].int_32();
1627 int argc = tos[StackOffsets::tailCall_argc].
int_32();
1634 return engine->throwTypeError();
1637 if (!
frame->callerCanHandleTailCall() || !jsfo->canBeTailCalled() ||
engine->debugger()
1638 || unsigned(argc) > jsfo->formalParameterCount()) {
1643 memmove(
frame->jsFrame->args, argv, argc *
sizeof(
Value));
1644 frame->init(jsfo->function(),
frame->jsFrame->argValues<
Value>(), argc,
1645 frame->callerCanHandleTailCall());
1646 frame->setupJSFrame(
frame->framePointer(), *jsfo, jsfo->scope(), thisObject,
1647 Primitive::undefinedValue());
1648 engine->jsStackTop =
frame->framePointer() +
frame->requiredJSStackFrameSize();
1649 frame->setPendingTailCall(
true);
1650 return Encode::undefined();
1655 if (!
value.isEmpty())
1663 switch (
value.type()) {
1664 case Value::Undefined_Type:
1667 case Value::Null_Type:
1670 case Value::Boolean_Type:
1673 case Value::Managed_Type:
1674 if (
value.isString())
1676 else if (
value.isSymbol())
1687 return res.asReturnedValue();
1693 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
1697 return TypeofValue::call(
engine, prop);
1702 frame->jsFrame->context = ExecutionContext::newCallContext(
frame)->asReturnedValue();
1710 newAcc = Value::fromHeapObject(acc.toObject(
engine));
1711 if (!
engine->hasException) {
1716 context = ec->newWithContext(
obj.d())->asReturnedValue();
1724 auto name =
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex];
1740 auto context =
static_cast<Heap::CallContext *
>(
1741 Value::fromStaticValue(
frame->jsFrame->context).m());
1742 frame->jsFrame->context =
1743 ExecutionContext::cloneBlockContext(
engine,
context)->asReturnedValue();
1749 Q_ASSERT(
engine->currentContext()->d()->type == Heap::ExecutionContext::Type_GlobalContext ||
1750 engine->currentContext()->d()->type == Heap::ExecutionContext::Type_QmlContext);
1760 engine->setScriptContext(root);
1767 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
1773 if (
v.isNullOrUndefined())
1774 engine->throwTypeError();
1779 if (!
t.isObject()) {
1780 if (
t.isNullOrUndefined()) {
1783 return t.toObject(
engine)->asReturnedValue();
1786 return t.asReturnedValue();
1792 ScopedString name(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
1793 engine->currentContext()->createMutableBinding(
name, deletable);
1804 Scoped<InternalClass> klass(scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeClasses[classId]);
1810 o->setProperty(
i, *
args++);
1812 Q_ASSERT((argc - klass->d()->size) % 3 == 0);
1813 int additionalArgs = (argc - int(klass->d()->size))/3;
1815 if (!additionalArgs)
1816 return o->asReturnedValue();
1823 for (
int i = 0;
i < additionalArgs; ++
i) {
1828 if (
engine->hasException)
1829 return Encode::undefined();
1830 if (
arg != ObjectLiteralArgument::Value) {
1832 int functionId =
args[2].integerValue();
1834 ->runtimeFunctions[functionId];
1838 if (
arg == ObjectLiteralArgument::Getter)
1839 prefix = PropertyKey::Getter;
1840 else if (
arg == ObjectLiteralArgument::Setter)
1841 prefix = PropertyKey::Setter;
1843 arg = ObjectLiteralArgument::Value;
1844 fnName =
name->asFunctionName(
engine, prefix);
1847 if (clos->isGenerator())
1848 value = MemberGeneratorFunction::create(current, clos,
o, fnName)->asReturnedValue();
1850 value = FunctionObject::createMemberFunction(current, clos,
o, fnName)->asReturnedValue();
1851 }
else if (
args[2].isFunctionObject()) {
1854 fnName =
name->asFunctionName(
engine, PropertyKey::None);
1855 fn->setName(fnName);
1858 Q_ASSERT(
arg == ObjectLiteralArgument::Value ||
value->isFunctionObject());
1859 if (
arg == ObjectLiteralArgument::Value ||
arg == ObjectLiteralArgument::Getter) {
1861 pd->
set = Value::emptyValue();
1863 pd->
value = Value::emptyValue();
1868 return engine->throwTypeError();
1872 return o.asReturnedValue();
1876 const Value &superClass,
Value computedNames[])
1879 =
engine->currentStackFrame->v4Function->executableCompilationUnit();
1886 if (superClass.
isNull()) {
1887 protoParent = Encode::null();
1891 if (!superFunction || !superFunction->isConstructor())
1896 return engine->throwTypeError(
QStringLiteral(
"The value of the superclass's prototype property is not an object."));
1898 constructorParent = superClass;
1908 constructor = FunctionObject::createConstructorFunction(current,
f, proto, !superClass.
isEmpty())->asReturnedValue();
1909 constructor->setPrototypeUnchecked(constructorParent);
1910 Value argCount = Value::fromInt32(
f ?
f->nFormals : 0);
1911 constructor->defineReadonlyConfigurableProperty(scope.
engine->
id_length(), argCount);
1912 constructor->defineReadonlyConfigurableProperty(
engine->id_prototype(), proto);
1916 if (cls->nameIndex != UINT_MAX) {
1918 constructor->defineReadonlyConfigurableProperty(
engine->id_name(),
name);
1926 for (
uint i = 0;
i < cls->nStaticMethods + cls->nMethods; ++
i) {
1927 if (
i == cls->nStaticMethods)
1930 propertyName = computedNames->toPropertyKey(
engine);
1932 return engine->throwTypeError(
QStringLiteral(
"Cannot declare a static method named 'prototype'."));
1933 if (
engine->hasException)
1934 return Encode::undefined();
1938 propertyName =
name->toPropertyKey();
1944 prefix = PropertyKey::Getter;
1945 else if (
methods[
i].
type == CompiledData::Method::Setter)
1946 prefix = PropertyKey::Setter;
1950 if (
f->isGenerator())
1951 function = MemberGeneratorFunction::create(current,
f, receiver,
name);
1953 function = FunctionObject::createMemberFunction(current,
f, receiver,
name);
1957 case CompiledData::Method::Getter:
1958 property->setGetter(function);
1959 property->set = Value::emptyValue();
1962 case CompiledData::Method::Setter:
1963 property->value = Value::emptyValue();
1964 property->setSetter(function);
1969 property->set = Value::emptyValue();
1976 return constructor->asReturnedValue();
1981 Q_ASSERT(
engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext);
1999 int nValues =
frame->argc() - argIndex;
2001 return engine->newArrayObject(0)->asReturnedValue();
2002 return engine->newArrayObject(
values, nValues)->asReturnedValue();
2008 =
engine->currentStackFrame->v4Function->compilationUnit->runtimeRegularExpressions[
id];
2009 Heap::RegExpObject *ro =
engine->newRegExpObject(Value::fromStaticValue(
val).as<RegExp>());
2010 return ro->asReturnedValue();
2016 return obj.asReturnedValue();
2018 return obj.toObject(
engine)->asReturnedValue();
2023 return obj.toBoolean();
2036 if (
value.isInteger() &&
value.integerValue() &&
2037 value.integerValue() != std::numeric_limits<int>::min())
2040 double n = RuntimeHelpers::toNumber(
value);
2052 return add_int32(
left.integerValue(),
right.integerValue());
2053 if (
left.isNumber() &&
right.isNumber())
2054 return Value::fromDouble(
left.asDouble() +
right.asDouble()).asReturnedValue();
2064 return sub_int32(
left.integerValue(),
right.integerValue());
2066 double lval =
left.isNumber() ?
left.asDouble() :
left.toNumberImpl();
2067 double rval =
right.isNumber() ?
right.asDouble() :
right.toNumberImpl();
2069 return Value::fromDouble(lval - rval).asReturnedValue();
2077 return mul_int32(
left.integerValue(),
right.integerValue());
2079 double lval =
left.isNumber() ?
left.asDouble() :
left.toNumberImpl();
2080 double rval =
right.isNumber() ?
right.asDouble() :
right.toNumberImpl();
2082 return Value::fromDouble(lval * rval).asReturnedValue();
2089 if (Value::integerCompatible(
left,
right)) {
2090 int lval =
left.integerValue();
2091 int rval =
right.integerValue();
2093 && !(lval == std::numeric_limits<int>::min() && rval == -1)
2094 && (lval % rval == 0)
2095 && !(lval == 0 && rval < 0))
2096 return Encode(
int(lval / rval));
2098 return Encode(
double(lval) / rval);
2101 double lval =
left.toNumber();
2102 double rval =
right.toNumber();
2103 return Value::fromDouble(lval / rval).asReturnedValue();
2110 if (Value::integerCompatible(
left,
right) &&
left.integerValue() >= 0 &&
right.integerValue() > 0) {
2119 double lval = RuntimeHelpers::toNumber(
left);
2120 double rval = RuntimeHelpers::toNumber(
right);
2124 return Value::fromDouble(std::fmod(lval, rval)).asReturnedValue();
2129 double b =
base.toNumber();
2130 double e = exp.toNumber();
2138 int lval =
left.toInt32();
2139 int rval =
right.toInt32();
2140 return Encode((
int)(lval & rval));
2147 int lval =
left.toInt32();
2148 int rval =
right.toInt32();
2149 return Encode((
int)(lval | rval));
2156 int lval =
left.toInt32();
2157 int rval =
right.toInt32();
2158 return Encode((
int)(lval ^ rval));
2165 int lval =
left.toInt32();
2166 int rval =
right.toInt32() & 0x1f;
2167 return Encode((
int)(lval << rval));
2174 int lval =
left.toInt32();
2175 unsigned rval =
right.toUInt32() & 0x1f;
2176 return Encode((
int)(lval >> rval));
2183 unsigned lval =
left.toUInt32();
2184 unsigned rval =
right.toUInt32() & 0x1f;
2194 bool r = CompareGreaterThan::call(
left,
right);
2210 bool r = CompareGreaterEqual::call(
left,
right);
2218 bool r = CompareLessEqual::call(
left,
right);
2228 engine->jsStackTop = stackMark;
2230 template <
typename T>
2234 stackMark =
engine->jsStackTop;
2238 **scopedValue =
value;
2250 Value *lhsGuard =
nullptr;
2251 Value *rhsGuard =
nullptr;
2255 return !lhs.
isNaN();
2261 if ((lt & (Value::ManagedMask >> Value::Tag_Shift)) == 0) {
2266 if ((rt & (Value::ManagedMask >> Value::Tag_Shift)) == 0) {
2274 if (l->
internalClass->vtable->isStringOrSymbol ==
r->internalClass->vtable->isStringOrSymbol)
2281 Q_ASSERT(
r->internalClass->vtable->isStringOrSymbol);
2289lhs_managed_and_rhs_not:
2297 rhs = Value::fromDouble(rhs.
int_32());
2301 return lhs.m()->internalClass->vtable->
isString ? (RuntimeHelpers::toNumber(lhs) == rhs.
doubleValue()) :
false;
2308 }
else if ((rt & (Value::ManagedMask >> Value::Tag_Shift)) == 0) {
2313 goto lhs_managed_and_rhs_not;
2369 bool r = RuntimeHelpers::strictEqual(
left,
right);
2377 bool r = ! RuntimeHelpers::strictEqual(
left,
right);
2385 return !Runtime::CompareEqual::call(
left,
right);
2392 return RuntimeHelpers::strictEqual(
left,
right);
2399 return ! RuntimeHelpers::strictEqual(
left,
right);
2402template<
typename Operation>
2405 return reinterpret_cast<void *
>(&Operation::call);
2408QHash<const void *, const char *> Runtime::symbolTable()
2410 static const QHash<const void *, const char *> symbols({
2412 {symbol<CallGlobalLookup>(),
"CallGlobalLookup" },
2413 {symbol<CallQmlContextPropertyLookup>(),
"CallQmlContextPropertyLookup" },
2414 {symbol<CallName>(),
"CallName" },
2415 {symbol<CallProperty>(),
"CallProperty" },
2416 {symbol<CallPropertyLookup>(),
"CallPropertyLookup" },
2417 {symbol<CallValue>(),
"CallValue" },
2418 {symbol<CallWithReceiver>(),
"CallWithReceiver" },
2419 {symbol<CallPossiblyDirectEval>(),
"CallPossiblyDirectEval" },
2420 {symbol<CallWithSpread>(),
"CallWithSpread" },
2421 {symbol<TailCall>(),
"TailCall" },
2423 {symbol<Construct>(),
"Construct" },
2424 {symbol<ConstructWithSpread>(),
"ConstructWithSpread" },
2426 {symbol<StoreNameStrict>(),
"StoreNameStrict" },
2427 {symbol<StoreNameSloppy>(),
"StoreNameSloppy" },
2428 {symbol<StoreProperty>(),
"StoreProperty" },
2429 {symbol<StoreElement>(),
"StoreElement" },
2430 {symbol<LoadProperty>(),
"LoadProperty" },
2431 {symbol<LoadName>(),
"LoadName" },
2432 {symbol<LoadElement>(),
"LoadElement" },
2433 {symbol<LoadSuperProperty>(),
"LoadSuperProperty" },
2434 {symbol<StoreSuperProperty>(),
"StoreSuperProperty" },
2435 {symbol<LoadSuperConstructor>(),
"LoadSuperConstructor" },
2436 {symbol<LoadGlobalLookup>(),
"LoadGlobalLookup" },
2437 {symbol<LoadQmlContextPropertyLookup>(),
"LoadQmlContextPropertyLookup" },
2438 {symbol<GetLookup>(),
"GetLookup" },
2439 {symbol<SetLookupStrict>(),
"SetLookupStrict" },
2440 {symbol<SetLookupSloppy>(),
"SetLookupSloppy" },
2442 {symbol<TypeofValue>(),
"TypeofValue" },
2443 {symbol<TypeofName>(),
"TypeofName" },
2445 {symbol<DeleteProperty_NoThrow>(),
"DeleteProperty_NoThrow" },
2446 {symbol<DeleteProperty>(),
"DeleteProperty" },
2447 {symbol<DeleteName_NoThrow>(),
"DeleteName_NoThrow" },
2448 {symbol<DeleteName>(),
"DeleteName" },
2450 {symbol<ThrowException>(),
"ThrowException" },
2451 {symbol<PushCallContext>(),
"PushCallContext" },
2452 {symbol<PushWithContext>(),
"PushWithContext" },
2453 {symbol<PushCatchContext>(),
"PushCatchContext" },
2454 {symbol<PushBlockContext>(),
"PushBlockContext" },
2455 {symbol<CloneBlockContext>(),
"CloneBlockContext" },
2456 {symbol<PushScriptContext>(),
"PushScriptContext" },
2457 {symbol<PopScriptContext>(),
"PopScriptContext" },
2458 {symbol<ThrowReferenceError>(),
"ThrowReferenceError" },
2459 {symbol<ThrowOnNullOrUndefined>(),
"ThrowOnNullOrUndefined" },
2461 {symbol<Closure>(),
"Closure" },
2463 {symbol<ConvertThisToObject>(),
"ConvertThisToObject" },
2464 {symbol<DeclareVar>(),
"DeclareVar" },
2465 {symbol<CreateMappedArgumentsObject>(),
"CreateMappedArgumentsObject" },
2466 {symbol<CreateUnmappedArgumentsObject>(),
"CreateUnmappedArgumentsObject" },
2467 {symbol<CreateRestParameter>(),
"CreateRestParameter" },
2469 {symbol<ArrayLiteral>(),
"ArrayLiteral" },
2470 {symbol<ObjectLiteral>(),
"ObjectLiteral" },
2471 {symbol<CreateClass>(),
"CreateClass" },
2473 {symbol<GetIterator>(),
"GetIterator" },
2474 {symbol<IteratorNext>(),
"IteratorNext" },
2475 {symbol<IteratorNextForYieldStar>(),
"IteratorNextForYieldStar" },
2476 {symbol<IteratorClose>(),
"IteratorClose" },
2477 {symbol<DestructureRestElement>(),
"DestructureRestElement" },
2479 {symbol<ToObject>(),
"ToObject" },
2480 {symbol<ToBoolean>(),
"ToBoolean" },
2481 {symbol<ToNumber>(),
"ToNumber" },
2483 {symbol<UMinus>(),
"UMinus" },
2485 {symbol<Instanceof>(),
"Instanceof" },
2486 {symbol<As>(),
"As" },
2487 {symbol<In>(),
"In" },
2488 {symbol<Add>(),
"Add" },
2489 {symbol<Sub>(),
"Sub" },
2490 {symbol<Mul>(),
"Mul" },
2491 {symbol<Div>(),
"Div" },
2492 {symbol<Mod>(),
"Mod" },
2493 {symbol<Exp>(),
"Exp" },
2494 {symbol<BitAnd>(),
"BitAnd" },
2495 {symbol<BitOr>(),
"BitOr" },
2496 {symbol<BitXor>(),
"BitXor" },
2497 {symbol<Shl>(),
"Shl" },
2498 {symbol<Shr>(),
"Shr" },
2499 {symbol<UShr>(),
"UShr" },
2500 {symbol<GreaterThan>(),
"GreaterThan" },
2501 {symbol<LessThan>(),
"LessThan" },
2502 {symbol<GreaterEqual>(),
"GreaterEqual" },
2503 {symbol<LessEqual>(),
"LessEqual" },
2504 {symbol<Equal>(),
"Equal" },
2505 {symbol<NotEqual>(),
"NotEqual" },
2506 {symbol<StrictEqual>(),
"StrictEqual" },
2507 {symbol<StrictNotEqual>(),
"StrictNotEqual" },
2509 {symbol<CompareGreaterThan>(),
"CompareGreaterThan" },
2510 {symbol<CompareLessThan>(),
"CompareLessThan" },
2511 {symbol<CompareGreaterEqual>(),
"CompareGreaterEqual" },
2512 {symbol<CompareLessEqual>(),
"CompareLessEqual" },
2513 {symbol<CompareEqual>(),
"CompareEqual" },
2514 {symbol<CompareNotEqual>(),
"CompareNotEqual" },
2515 {symbol<CompareStrictEqual>(),
"CompareStrictEqual" },
2516 {symbol<CompareStrictNotEqual>(),
"CompareStrictNotEqual" },
2518 {symbol<CompareInstanceof>(),
"CompareInstanceOf" },
2519 {symbol<CompareIn>(),
"CompareIn" },
2521 {symbol<RegexpLiteral>(),
"RegexpLiteral" },
2522 {symbol<GetTemplateObject>(),
"GetTemplateObject" }
static JNINativeMethod methods[]
\inmodule QtCore \reentrant
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
void throwError(const QString &message)
Throws a run-time error (exception) with the given message.
QJSValue globalObject() const
Returns this engine's Global Object.
QJSValue newObject()
Creates a JavaScript object of class Object.
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object's name property to value.
const_iterator cbegin() const noexcept
QStringView trimmed() const noexcept
Strips leading and trailing whitespace and returns the result.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString mid(qsizetype position, qsizetype n=-1) const &
qsizetype size() const noexcept
Returns the number of characters in this string.
qsizetype count(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const CompiledData::Unit * unitData() const
ManagedType::Data * alloc(Args &&... args)
QSet< QString >::iterator it
QList< QVariant > arguments
double jsExponentiate(double base, double exponent)
Combined button and popup list for selecting options.
static QV4::ReturnedValue doInstanceof(ExecutionEngine *engine, const Value &lval, const Value &rval)
static Q_NEVER_INLINE ReturnedValue getElementIntFallback(ExecutionEngine *engine, const Value &object, uint idx)
Scoped< FunctionObject > ScopedFunctionObject
static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine, const Value &object, const Value &index)
ReturnedValue coerce(ExecutionEngine *engine, const Value &value, const QQmlType &qmlType, bool isList)
static Heap::String * convert_to_string_add(ExecutionEngine *engine, Value value)
static ReturnedValue throwPropertyIsNotAFunctionTypeError(ExecutionEngine *engine, Value *thisObject, const QString &propertyName)
ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result)
Scoped< String > ScopedString
static QV4::Lookup * runtimeLookup(Function *f, uint i)
static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
static Object * getSuperBase(Scope &scope)
static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc)
static const void * symbol()
Scoped< ExecutionContext > ScopedContext
AudioChannelLayoutTag tag
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
static QDBusError::ErrorType get(const char *name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN()
static Q_DECL_CONST_FUNCTION bool qt_is_inf(double d)
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLint GLint GLsizei GLuint * counters
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint GLsizei const GLchar * message
static qreal dot(const QPointF &a, const QPointF &b)
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static QString dump(const QByteArray &)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
QTextStreamManipulator qSetFieldWidth(int width)
unsigned long long quint64
\inmodule QtCore \reentrant
QVector< QV4::Function * > runtimeFunctions
Heap::String ** runtimeStrings
const Class * classAt(int idx) const
bool isJSTypesFrame() const
bool isMetaTypesFrame() const
CppStackFrame * currentStackFrame
CallContext * asCallContext()
ReturnedValue throwRangeError(const Value &value)
String * id_length() const
ReturnedValue throwReferenceError(const Value &value)
String * id_prototype() const
QML_NEARLY_ALWAYS_INLINE Value * jsAlloca(int nValues)
Heap::String * newString(char16_t c)
ReturnedValue throwTypeError()
ExecutionContext * currentContext() const
WriteBarrier::HeapObjectWrapper< CompilationUnitRuntimeData, 1 > compilationUnit
bool isArrowFunction() const
ReturnedValue asReturnedValue() const
Pointer< InternalClass *, 0 > internalClass
void setData(EngineBase *e, uint index, Value newVal)
const Value & data(uint index) const
ExecutionContext * context() const
void set(Value **scopedValue, T value, ExecutionEngine *e)
ReturnedValue(* globalGetter)(Lookup *l, ExecutionEngine *engine)
ReturnedValue(* qmlContextPropertyGetter)(Lookup *l, ExecutionEngine *engine, Value *thisObject)
ReturnedValue(* getter)(Lookup *l, ExecutionEngine *engine, const Value &object)
bool(* setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v)
Heap::InternalClass * internalClass() const
void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes=Attr_Data|Attr_NotEnumerable)
bool defineOwnProperty(PropertyKey id, const Property *p, PropertyAttributes attrs)
bool hasProperty(PropertyKey id) const
void setPrototypeUnchecked(const Object *p)
ReturnedValue instanceOf(const Value &var) const
ReturnedValue get(StringOrSymbol *name, bool *hasProperty=nullptr, const Value *receiver=nullptr) const
Heap::String * asFunctionName(ExecutionEngine *e, FunctionNamePrefix prefix) const
Value * alloc(qint64 nValues) const =delete
bool hasException() const
quint64 quickType() const
const Value & asValue() const
constexpr ReturnedValue asReturnedValue() const
QV4_NEARLY_ALWAYS_INLINE double doubleValue() const
bool isNullOrUndefined() const
QV4_NEARLY_ALWAYS_INLINE constexpr int int_32() const
PropertyKey propertyKey() const
bool lessThan(const String *other)
bool isStringOrSymbol() const
QML_NEARLY_ALWAYS_INLINE String * stringValue() const
QML_NEARLY_ALWAYS_INLINE Object * objectValue() const
QString toQStringNoThrow() const