diff options
author | Gunnar Sletta <gunnar.sletta@nokia.com> | 2011-08-31 08:55:16 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@nokia.com> | 2011-08-31 08:55:16 +0200 |
commit | 71478352376022faa9be6d79f2a760c289945ff5 (patch) | |
tree | 0f8ff4a88c1b033367337a93d23a329d145ee903 | |
parent | c38efcb67cf93ba3e91e184c3b891efef4ef75a3 (diff) | |
parent | 05daa9bfe1a03ffe1cc580b6cfd88e093e2493c0 (diff) |
Merge branch 'master' into refactor
Conflicts:
src/3rdparty/v8
src/declarative/declarative.pro
src/declarative/items/qsgcanvas.cpp
src/declarative/items/qsgshadereffectsource_p.h
src/declarative/items/qsgview.cpp
src/declarative/particles/qsgcustomparticle.cpp
src/imports/gestures/gestures.pro
src/imports/particles/particles.pro
src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro
src/qtquick1/qtquick1.pro
tests/auto/declarative/examples/examples.pro
tests/auto/declarative/qsglistview/qsglistview.pro
tests/auto/qtquick1/qdeclarativeviewer/qdeclarativeviewer.pro
Change-Id: I423344f83e1835116cad531b877fde6e68a8849a
262 files changed, 11288 insertions, 12825 deletions
diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 183f5b46cc..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "src/3rdparty/v8"] - path = src/3rdparty/v8 - url = git://github.com/aaronkennedy/v8.git diff --git a/examples/declarative/particles/allsmiles/smile.qml b/examples/declarative/particles/allsmiles/smile.qml index 3eb57617ec..bfce60cc4a 100644 --- a/examples/declarative/particles/allsmiles/smile.qml +++ b/examples/declarative/particles/allsmiles/smile.qml @@ -70,47 +70,17 @@ Rectangle{ source: "content/particle.png" } vertexShader:" - attribute highp vec2 vPos; - attribute highp vec2 vTex; - attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize - attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration - attribute highp float r; - uniform highp float maxWidth; uniform highp float maxHeight; - - uniform highp mat4 qt_Matrix; - uniform highp float timestamp; - uniform lowp float qt_Opacity; - - varying highp vec2 fTex; - varying highp vec2 fTex2; + varying highp vec2 fTex2; varying lowp float fFade; + uniform lowp float qt_Opacity; void main() { - fTex = vTex; fTex2 = vec2(vPos.x / maxWidth, vPos.y / maxHeight); - highp float size = vData.z; - highp float endSize = vData.w; - highp float t = (timestamp - vData.x) / vData.y; - - highp float currentSize = mix(size, endSize, t * t); - - if (t < 0. || t > 1.) - currentSize = 0.; - - highp vec2 pos = vPos - - currentSize / 2. + currentSize * vTex // adjust size - + vVec.xy * t * vData.y // apply speed vector.. - + 0.5 * vVec.zw * pow(t * vData.y, 2.); - - gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); - - highp float fadeIn = min(t * 10., 1.); - highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.)); - - fFade = fadeIn * fadeOut * qt_Opacity; + fFade = min(t*4., (1.-t*t)*.75) * qt_Opacity; + defaultMain(); } " property variant particleTexture: particleSource @@ -120,7 +90,7 @@ Rectangle{ uniform sampler2D pictureTexture; varying highp vec2 fTex; varying highp vec2 fTex2; - varying highp float fFade; + varying lowp float fFade; void main() { gl_FragColor = texture2D(pictureTexture, fTex2) * texture2D(particleTexture, fTex).w * fFade; }" diff --git a/examples/declarative/particles/asteroid/blackhole.qml b/examples/declarative/particles/asteroid/blackhole.qml index 4a7ce02538..441f4c38d6 100644 --- a/examples/declarative/particles/asteroid/blackhole.qml +++ b/examples/declarative/particles/asteroid/blackhole.qml @@ -149,7 +149,7 @@ Rectangle{ id: gs; x: root.width/2; y: root.height/2; strength: 4000000; system: particles physics: PointAttractor.Acceleration - proportionalToDistance: PointAttractor.Quadratic + proportionalToDistance: PointAttractor.InverseQuadratic } Kill{ system: particles diff --git a/examples/declarative/particles/custom/blurparticles.qml b/examples/declarative/particles/custom/blurparticles.qml index 7974c6ab7c..238608c002 100644 --- a/examples/declarative/particles/custom/blurparticles.qml +++ b/examples/declarative/particles/custom/blurparticles.qml @@ -68,41 +68,14 @@ Rectangle{ CustomParticle{ system: sys - //TODO: Someway that you don't have to rewrite the basics for a simple addition vertexShader:" - attribute highp vec2 vPos; - attribute highp vec2 vTex; - attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize - attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration - attribute highp float r; - - uniform highp mat4 qt_Matrix; - uniform highp float timestamp; uniform lowp float qt_Opacity; - - varying highp vec2 fTex; varying lowp float fFade; varying lowp float fBlur; void main() { - fTex = vTex; - highp float size = vData.z; - highp float endSize = vData.w; - + defaultMain(); highp float t = (timestamp - vData.x) / vData.y; - - highp float currentSize = mix(size, endSize, t * t); - - if (t < 0. || t > 1.) - currentSize = 0.; - - highp vec2 pos = vPos - - currentSize / 2. + currentSize * vTex // adjust size - + vVec.xy * t * vData.y // apply speed vector.. - + 0.5 * vVec.zw * pow(t * vData.y, 2.); - - gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); - highp float fadeIn = min(t * 10., 1.); highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.)); diff --git a/examples/declarative/particles/custom/custom.qml b/examples/declarative/particles/custom/custom.qml index 9a562af3b6..4b75cf6ebe 100644 --- a/examples/declarative/particles/custom/custom.qml +++ b/examples/declarative/particles/custom/custom.qml @@ -44,18 +44,8 @@ ParticleSystem{ } } CustomParticle{ - //TODO: Someway that you don't have to rewrite the basics for a simple addition vertexShader:" - attribute highp vec2 vPos; - attribute highp vec2 vTex; - attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize - attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration - - uniform highp mat4 qt_ModelViewProjectionMatrix; - uniform highp float timestamp; uniform lowp float qt_Opacity; - - varying highp vec2 fTex; varying lowp float fFade; varying highp vec2 fPos; @@ -76,7 +66,7 @@ ParticleSystem{ + vVec.xy * t * vData.y // apply speed vector.. + 0.5 * vVec.zw * pow(t * vData.y, 2.); - gl_Position = qt_ModelViewProjectionMatrix * vec4(pos.x, pos.y, 0, 1); + gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); highp float fadeIn = min(t * 20., 1.); highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.)); diff --git a/examples/declarative/particles/custom/shader.qml b/examples/declarative/particles/custom/shader.qml index 329eaf226b..6253679cb7 100644 --- a/examples/declarative/particles/custom/shader.qml +++ b/examples/declarative/particles/custom/shader.qml @@ -27,19 +27,8 @@ ParticleSystem{ acceleration: PointDirection{x: -root.width/40; y: -root.height/40; xVariation: -root.width/20; yVariation: -root.width/20} } CustomParticle{ - //TODO: Someway that you don't have to rewrite the basics for a simple addition vertexShader:" - attribute highp vec2 vPos; - attribute highp vec2 vTex; - attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize - attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration - attribute highp float r; - - uniform highp mat4 qt_Matrix; - uniform highp float timestamp; uniform lowp float qt_Opacity; - - varying highp vec2 fTex; varying lowp float fFade; varying highp vec2 fPos; diff --git a/examples/declarative/particles/spaceexplorer/spaceexplorer.qml b/examples/declarative/particles/spaceexplorer/spaceexplorer.qml index 1bb3cdae02..727d711053 100644 --- a/examples/declarative/particles/spaceexplorer/spaceexplorer.qml +++ b/examples/declarative/particles/spaceexplorer/spaceexplorer.qml @@ -276,7 +276,7 @@ Rectangle{ } PointAttractor{ id: gs1; x: vorteX; y: vorteY; strength: 800000; - proportionalToDistance: PointAttractor.Quadratic; + proportionalToDistance: PointAttractor.InverseQuadratic; system: foreground } Kill{ @@ -289,7 +289,7 @@ Rectangle{ PointAttractor{ id: gs2; x: vorteX2; y: vorteY2; strength: 800000; - proportionalToDistance: PointAttractor.Quadratic; + proportionalToDistance: PointAttractor.InverseQuadratic; system: foreground } Kill{ @@ -302,7 +302,7 @@ Rectangle{ PointAttractor{ id: gs3; x: vorteX3; y: vorteY3; strength: 800000; - proportionalToDistance: PointAttractor.Quadratic; + proportionalToDistance: PointAttractor.InverseQuadratic; system: foreground } Kill{ diff --git a/src/3rdparty/v8 b/src/3rdparty/v8 deleted file mode 160000 -Subproject 472c04c9e7a64e8734c76d2cf97a7cc5b773b78 diff --git a/src/declarative/debugger/qdeclarativedebughelper.cpp b/src/declarative/debugger/qdeclarativedebughelper.cpp index 5f5d8754bb..cbe4a85c61 100644 --- a/src/declarative/debugger/qdeclarativedebughelper.cpp +++ b/src/declarative/debugger/qdeclarativedebughelper.cpp @@ -58,6 +58,7 @@ void QDeclarativeDebugHelper::setAnimationSlowDownFactor(qreal factor) } void QDeclarativeDebugHelper::enableDebugging() { + qWarning("QDeclarativeDebugHelper::enableDebugging() is deprecated! Add CONFIG += declarative_debug to your .pro file instead."); #ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { qWarning("Qml debugging is enabled. Only use this in a safe environment!"); diff --git a/src/declarative/debugger/qdeclarativedebughelper_p.h b/src/declarative/debugger/qdeclarativedebughelper_p.h index 60187112bf..d9ed5796ee 100644 --- a/src/declarative/debugger/qdeclarativedebughelper_p.h +++ b/src/declarative/debugger/qdeclarativedebughelper_p.h @@ -52,6 +52,10 @@ QT_BEGIN_NAMESPACE class QDeclarativeEngine; +#ifndef QT_BUILD_DECLARATIVE_LIB +#warning Use of this header file is deprecated! Add CONFIG += declarative_debug to your .pro file instead. +#endif + // Helper methods to access private API through a stable interface // This is used in the qmljsdebugger library of QtCreator. class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro index 89b94526af..5db77a79dd 100644 --- a/src/declarative/declarative.pro +++ b/src/declarative/declarative.pro @@ -6,7 +6,7 @@ QPRO_PWD = $$PWD CONFIG += module MODULE_PRI += ../../modules/qt_declarative.pri -QT = core-private gui gui-private network widgets-private sql +QT = core-private gui gui-private network widgets-private sql v8-private contains(QT_CONFIG, svg): QT += svg DEFINES += QT_BUILD_DECLARATIVE_LIB QT_NO_URL_CAST_FROM_STRING @@ -34,7 +34,6 @@ include(debugger/debugger.pri) include(scenegraph/scenegraph.pri) include(items/items.pri) include(particles/particles.pri) -include(v8/v8.pri) symbian: { TARGET.UID3=0x2001E623 diff --git a/src/declarative/items/items.pri b/src/declarative/items/items.pri index 848c782a6e..9880dd8dc6 100644 --- a/src/declarative/items/items.pri +++ b/src/declarative/items/items.pri @@ -53,6 +53,7 @@ HEADERS += \ $$PWD/qsgtranslate_p.h \ $$PWD/qsgclipnode_p.h \ $$PWD/qsgview.h \ + $$PWD/qsgview_p.h \ $$PWD/qsganimation_p.h \ $$PWD/qsganimation_p_p.h \ $$PWD/qsgstateoperations_p.h \ diff --git a/src/declarative/items/qsganimatedimage.cpp b/src/declarative/items/qsganimatedimage.cpp index ea36153ef0..e4bba512af 100644 --- a/src/declarative/items/qsganimatedimage.cpp +++ b/src/declarative/items/qsganimatedimage.cpp @@ -264,7 +264,6 @@ void QSGAnimatedImage::load() if (d->progress != oldProgress) emit progressChanged(d->progress); } else { -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url); if (!lf.isEmpty()) { //### should be unified with movieRequestFinished @@ -298,7 +297,7 @@ void QSGAnimatedImage::load() emit progressChanged(d->progress); return; } -#endif + d->status = Loading; d->progress = 0; emit statusChanged(d->status); diff --git a/src/declarative/items/qsgborderimage.cpp b/src/declarative/items/qsgborderimage.cpp index 8d54bce419..30b10321a0 100644 --- a/src/declarative/items/qsgborderimage.cpp +++ b/src/declarative/items/qsgborderimage.cpp @@ -306,15 +306,12 @@ void QSGBorderImage::load() } else { d->status = Loading; if (d->url.path().endsWith(QLatin1String("sci"))) { -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url); if (!lf.isEmpty()) { QFile file(lf); file.open(QIODevice::ReadOnly); setGridScaledImage(QSGGridScaledImage(&file)); - } else -#endif - { + } else { QNetworkRequest req(d->url); d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp index 8ff7d17837..95ee95d0f7 100644 --- a/src/declarative/items/qsgcanvas.cpp +++ b/src/declarative/items/qsgcanvas.cpp @@ -153,17 +153,17 @@ public: Focus behavior ============== -Prior to being added to a valid canvas items can set and clear focus with no +Prior to being added to a valid canvas items can set and clear focus with no effect. Only once items are added to a canvas (by way of having a parent set that -already belongs to a canvas) do the focus rules apply. Focus goes back to +already belongs to a canvas) do the focus rules apply. Focus goes back to having no effect if an item is removed from a canvas. When an item is moved into a new focus scope (either being added to a canvas -for the first time, or having its parent changed), if the focus scope already has +for the first time, or having its parent changed), if the focus scope already has a scope focused item that takes precedence over the item being added. Otherwise, -the focus of the added tree is used. In the case of of a tree of items being +the focus of the added tree is used. In the case of of a tree of items being added to a canvas for the first time, which may have a conflicted focus state (two -or more items in one scope having focus set), the same rule is applied item by item - +or more items in one scope having focus set), the same rule is applied item by item - thus the first item that has focus will get it (assuming the scope doesn't already have a scope focused item), and the other items will have their focus cleared. */ @@ -478,7 +478,7 @@ void QSGCanvasPrivate::sceneMouseEventForTransform(QGraphicsSceneMouseEvent &sce sceneEvent.setLastPos(transform.map(sceneEvent.lastScenePos())); for (int ii = 0; ii < 5; ++ii) { if (sceneEvent.buttons() & (1 << ii)) { - sceneEvent.setButtonDownPos((Qt::MouseButton)(1 << ii), + sceneEvent.setButtonDownPos((Qt::MouseButton)(1 << ii), transform.map(sceneEvent.buttonDownScenePos((Qt::MouseButton)(1 << ii)))); } } @@ -692,7 +692,7 @@ void QSGCanvasPrivate::setFocusInScope(QSGItem *scope, QSGItem *item, FocusOptio updateInputMethodData(); QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason); - q->sendEvent(newActiveFocusItem, &event); + q->sendEvent(newActiveFocusItem, &event); } else { updateInputMethodData(); } @@ -778,12 +778,12 @@ void QSGCanvasPrivate::clearFocusInScope(QSGItem *scope, QSGItem *item, FocusOpt updateInputMethodData(); QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason); - q->sendEvent(newActiveFocusItem, &event); + q->sendEvent(newActiveFocusItem, &event); } else { updateInputMethodData(); } - if (!changed.isEmpty()) + if (!changed.isEmpty()) notifyFocusChangesRecur(changed.data(), changed.count() - 1); } @@ -807,7 +807,7 @@ void QSGCanvasPrivate::notifyFocusChangesRecur(QSGItem **items, int remaining) itemPrivate->itemChange(QSGItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus); emit item->activeFocusChanged(itemPrivate->activeFocus); } - } + } } void QSGCanvasPrivate::updateInputMethodData() @@ -891,21 +891,21 @@ QSGCanvas::~QSGCanvas() QSGItem *QSGCanvas::rootItem() const { Q_D(const QSGCanvas); - + return d->rootItem; } QSGItem *QSGCanvas::activeFocusItem() const { Q_D(const QSGCanvas); - + return d->activeFocusItem; } QSGItem *QSGCanvas::mouseGrabberItem() const { Q_D(const QSGCanvas); - + return d->mouseGrabberItem; } @@ -1016,7 +1016,7 @@ bool QSGCanvasPrivate::deliverInitialMousePressEvent(QSGItem *item, QGraphicsSce event->accept(); mouseGrabberItem = item; q->sendEvent(item, event); - if (event->isAccepted()) + if (event->isAccepted()) return true; mouseGrabberItem->ungrabMouse(); mouseGrabberItem = 0; @@ -1030,10 +1030,10 @@ bool QSGCanvasPrivate::deliverMouseEvent(QGraphicsSceneMouseEvent *sceneEvent) { Q_Q(QSGCanvas); - if (!mouseGrabberItem && + if (!mouseGrabberItem && sceneEvent->type() == QEvent::GraphicsSceneMousePress && (sceneEvent->button() & sceneEvent->buttons()) == sceneEvent->buttons()) { - + return deliverInitialMousePressEvent(rootItem, sceneEvent); } @@ -1053,7 +1053,7 @@ bool QSGCanvasPrivate::deliverMouseEvent(QGraphicsSceneMouseEvent *sceneEvent) void QSGCanvas::mousePressEvent(QMouseEvent *event) { Q_D(QSGCanvas); - + #ifdef MOUSE_DEBUG qWarning() << "QSGCanvas::mousePressEvent()" << event->pos() << event->button() << event->buttons(); #endif @@ -1068,7 +1068,7 @@ void QSGCanvas::mousePressEvent(QMouseEvent *event) void QSGCanvas::mouseReleaseEvent(QMouseEvent *event) { Q_D(QSGCanvas); - + #ifdef MOUSE_DEBUG qWarning() << "QSGCanvas::mouseReleaseEvent()" << event->pos() << event->button() << event->buttons(); #endif @@ -1090,7 +1090,7 @@ void QSGCanvas::mouseReleaseEvent(QMouseEvent *event) void QSGCanvas::mouseDoubleClickEvent(QMouseEvent *event) { Q_D(QSGCanvas); - + #ifdef MOUSE_DEBUG qWarning() << "QSGCanvas::mouseDoubleClickEvent()" << event->pos() << event->button() << event->buttons(); #endif @@ -1104,7 +1104,7 @@ void QSGCanvas::mouseDoubleClickEvent(QMouseEvent *event) else event->ignore(); return; - } + } d->deliverMouseEvent(&sceneEvent); event->setAccepted(sceneEvent.isAccepted()); @@ -1129,7 +1129,7 @@ bool QSGCanvasPrivate::sendHoverEvent(QEvent::Type type, QSGItem *item, void QSGCanvas::mouseMoveEvent(QMouseEvent *event) { Q_D(QSGCanvas); - + #ifdef MOUSE_DEBUG qWarning() << "QSGCanvas::mouseMoveEvent()" << event->pos() << event->button() << event->buttons(); #endif @@ -1173,7 +1173,7 @@ bool QSGCanvasPrivate::deliverHoverEvent(QSGItem *item, const QPointF &scenePos, QList<QSGItem *> children = itemPrivate->paintOrderChildItems(); for (int ii = children.count() - 1; ii >= 0; --ii) { QSGItem *child = children.at(ii); - if (!child->isEnabled()) + if (!child->isVisible() || !child->isEnabled()) continue; if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted)) return true; @@ -1186,38 +1186,36 @@ bool QSGCanvasPrivate::deliverHoverEvent(QSGItem *item, const QPointF &scenePos, //move accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted); } else { - QList<QSGItem*> parents; + QList<QSGItem *> itemsToHover; QSGItem* parent = item; - parents << item; + itemsToHover << item; while ((parent = parent->parentItem())) - parents << parent; + itemsToHover << parent; - //exit from previous (excepting ancestors) - while (!hoverItems.isEmpty() && !parents.contains(hoverItems[0])){ + // Leaving from previous hovered items until we reach the item or one of its ancestors. + while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) { sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted); hoverItems.removeFirst(); } if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item + // ### Shouldn't we send moves for the parent items as well? accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted); } else { - //enter any ancestors that also wish to be hovered and aren't + // Enter items that are not entered yet. int startIdx = -1; if (!hoverItems.isEmpty()) - startIdx = parents.indexOf(hoverItems[0]); + startIdx = itemsToHover.indexOf(hoverItems[0]) - 1; if (startIdx == -1) - startIdx = parents.count() - 1; + startIdx = itemsToHover.count() - 1; for (int i = startIdx; i >= 0; i--) { - if (QSGItemPrivate::get(parents[i])->hoverEnabled) { - hoverItems.prepend(parents[i]); - sendHoverEvent(QEvent::HoverEnter, parents[i], scenePos, lastScenePos, modifiers, accepted); + QSGItem *itemToHover = itemsToHover[i]; + if (QSGItemPrivate::get(itemToHover)->hoverEnabled) { + hoverItems.prepend(itemToHover); + sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted); } } - - //enter new item - hoverItems.prepend(item); - accepted = sendHoverEvent(QEvent::HoverEnter, item, scenePos, lastScenePos, modifiers, accepted); } } return true; @@ -1505,17 +1503,17 @@ bool QSGCanvasPrivate::sendFilteredMouseEvent(QSGItem *target, QSGItem *item, QG return true; QSGItemPrivate *targetPrivate = QSGItemPrivate::get(target); - if (targetPrivate->filtersChildMouseEvents) + if (targetPrivate->filtersChildMouseEvents) if (target->childMouseEventFilter(item, event)) return true; return false; } -bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e) -{ +bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e) +{ Q_D(QSGCanvas); - + if (!item) { qWarning("QSGCanvas::sendEvent: Cannot send event to a null item"); return false; @@ -1549,7 +1547,7 @@ bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e) case QEvent::GraphicsSceneMouseRelease: case QEvent::GraphicsSceneMouseDoubleClick: case QEvent::GraphicsSceneMouseMove: - // XXX todo - should sendEvent be doing this? how does it relate to forwarded events? + // XXX todo - should sendEvent be doing this? how does it relate to forwarded events? { QGraphicsSceneMouseEvent *se = static_cast<QGraphicsSceneMouseEvent *>(e); if (!d->sendFilteredMouseEvent(item->parentItem(), item, se)) { @@ -1581,7 +1579,7 @@ bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e) break; } - return false; + return false; } void QSGCanvasPrivate::cleanupNodes() @@ -1626,12 +1624,12 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item) itemPriv->dirtyAttributes = 0; if ((dirty & QSGItemPrivate::TransformUpdateMask) || - (dirty & QSGItemPrivate::Size && itemPriv->origin != QSGItem::TopLeft && + (dirty & QSGItemPrivate::Size && itemPriv->origin != QSGItem::TopLeft && (itemPriv->scale != 1. || itemPriv->rotation != 0.))) { QMatrix4x4 matrix; - if (itemPriv->x != 0. || itemPriv->y != 0.) + if (itemPriv->x != 0. || itemPriv->y != 0.) matrix.translate(itemPriv->x, itemPriv->y); for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii) @@ -1779,10 +1777,10 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item) if (dirty & QSGItemPrivate::ContentUpdateMask) { if (itemPriv->flags & QSGItem::ItemHasContents) { - updatePaintNodeData.transformNode = itemPriv->itemNode(); + updatePaintNodeData.transformNode = itemPriv->itemNode(); itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData); - Q_ASSERT(itemPriv->paintNode == 0 || + Q_ASSERT(itemPriv->paintNode == 0 || itemPriv->paintNode->parent() == 0 || itemPriv->paintNode->parent() == itemPriv->childContainerNode()); @@ -1957,7 +1955,7 @@ void QSGCanvasRenderThread::run() } else { makeCurrent(); } - + while (!shouldExit) { lock(); diff --git a/src/declarative/items/qsgpositioners.cpp b/src/declarative/items/qsgpositioners.cpp index fca0aa1877..0401494d3b 100644 --- a/src/declarative/items/qsgpositioners.cpp +++ b/src/declarative/items/qsgpositioners.cpp @@ -93,6 +93,9 @@ QSGBasePositioner::QSGBasePositioner(PositionerType at, QSGItem *parent) for the child items. Depending on the chosen type, only x or y changes will be applied. Note that the subclass is responsible for adding the spacing in between items. + + Positioning is usually delayed until before a frame is rendered, to batch multiple repositioning + changes into one calculation. */ QSGBasePositioner::QSGBasePositioner(QSGBasePositionerPrivate &dd, PositionerType at, QSGItem *parent) @@ -110,6 +113,13 @@ QSGBasePositioner::~QSGBasePositioner() positionedItems.clear(); } +void QSGBasePositioner::updatePolish() +{ + Q_D(QSGBasePositioner); + if (d->positioningDirty) + prePositioning(); +} + int QSGBasePositioner::spacing() const { Q_D(const QSGBasePositioner); @@ -122,7 +132,7 @@ void QSGBasePositioner::setSpacing(int s) if (s==d->spacing) return; d->spacing = s; - prePositioning(); + d->setPositioningDirty(); emit spacingChanged(); } @@ -169,7 +179,7 @@ void QSGBasePositioner::itemChange(ItemChange change, const ItemChangeData &valu { Q_D(QSGBasePositioner); if (change == ItemChildAddedChange){ - prePositioning(); + d->setPositioningDirty(); } else if (change == ItemChildRemovedChange) { QSGItem *child = value.item; QSGBasePositioner::PositionedItem posItem(child); @@ -178,7 +188,7 @@ void QSGBasePositioner::itemChange(ItemChange change, const ItemChangeData &valu d->unwatchChanges(child); positionedItems.remove(idx); } - prePositioning(); + d->setPositioningDirty(); } QSGItem::itemChange(change, value); @@ -193,7 +203,7 @@ void QSGBasePositioner::prePositioning() if (d->doingPositioning) return; - d->queuedPositioning = false; + d->positioningDirty = false; d->doingPositioning = true; //Need to order children by creation order modified by stacking order QList<QSGItem *> children = childItems(); @@ -463,6 +473,10 @@ void QSGPositionerAttached::setIsLastItem(bool isLastItem) Items with a width or height of 0 will not be positioned. + Positioning is batched and syncronized with painting to reduce the number of + calculations needed. This means that positioners may not reposition items immediately + when changes occur, but it will have moved by the next frame. + \sa Row, Grid, Flow, Positioner, {declarative/positioners}{Positioners example} */ /*! @@ -607,6 +621,10 @@ void QSGColumn::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. + Positioning is batched and syncronized with painting to reduce the number of + calculations needed. This means that positioners may not reposition items immediately + when changes occur, but it will have moved by the next frame. + \sa Column, Grid, Flow, Positioner, {declarative/positioners}{Positioners example} */ /*! @@ -838,6 +856,10 @@ void QSGRow::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. + Positioning is batched and syncronized with painting to reduce the number of + calculations needed. This means that positioners may not reposition items immediately + when changes occur, but it will have moved by the next frame. + \sa Flow, Row, Column, Positioner, {declarative/positioners}{Positioners example} */ /*! @@ -1265,6 +1287,10 @@ void QSGGrid::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. + Positioning is batched and syncronized with painting to reduce the number of + calculations needed. This means that positioners may not reposition items immediately + when changes occur, but it will have moved by the next frame. + \sa Column, Row, Grid, Positioner, {declarative/positioners}{Positioners example} */ /*! diff --git a/src/declarative/items/qsgpositioners_p.h b/src/declarative/items/qsgpositioners_p.h index 7200b6da8d..f8711251d3 100644 --- a/src/declarative/items/qsgpositioners_p.h +++ b/src/declarative/items/qsgpositioners_p.h @@ -121,6 +121,8 @@ protected: virtual void itemChange(ItemChange, const ItemChangeData &); void finishApplyTransitions(); + virtual void updatePolish(); + Q_SIGNALS: void spacingChanged(); void moveChanged(); diff --git a/src/declarative/items/qsgpositioners_p_p.h b/src/declarative/items/qsgpositioners_p_p.h index a29982b1b7..3c1185378b 100644 --- a/src/declarative/items/qsgpositioners_p_p.h +++ b/src/declarative/items/qsgpositioners_p_p.h @@ -74,7 +74,7 @@ class QSGBasePositionerPrivate : public QSGImplicitSizeItemPrivate, public QSGIt public: QSGBasePositionerPrivate() : spacing(0), type(QSGBasePositioner::None) - , moveTransition(0), addTransition(0), queuedPositioning(false) + , moveTransition(0), addTransition(0), positioningDirty(false) , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight) { } @@ -97,25 +97,23 @@ public: void watchChanges(QSGItem *other); void unwatchChanges(QSGItem* other); - bool queuedPositioning : 1; + void setPositioningDirty() { + Q_Q(QSGBasePositioner); + if (!positioningDirty) { + positioningDirty = true; + q->polish(); + } + } + + bool positioningDirty : 1; bool doingPositioning : 1; bool anchorConflict : 1; Qt::LayoutDirection layoutDirection; - void schedulePositioning() - { - Q_Q(QSGBasePositioner); - if(!queuedPositioning){ - QTimer::singleShot(0,q,SLOT(prePositioning())); - queuedPositioning = true; - } - } - void mirrorChange() { - Q_Q(QSGBasePositioner); if (type != QSGBasePositioner::Vertical) - q->prePositioning(); + setPositioningDirty(); } bool isLeftToRight() const { if (type == QSGBasePositioner::Vertical) @@ -127,26 +125,18 @@ public: virtual void itemSiblingOrderChanged(QSGItem* other) { Q_UNUSED(other); - //Delay is due to many children often being reordered at once - //And we only want to reposition them all once - schedulePositioning(); + setPositioningDirty(); } void itemGeometryChanged(QSGItem *, const QRectF &newGeometry, const QRectF &oldGeometry) { - Q_Q(QSGBasePositioner); if (newGeometry.size() != oldGeometry.size()) - q->prePositioning(); + setPositioningDirty(); } virtual void itemVisibilityChanged(QSGItem *) { - schedulePositioning(); - } - virtual void itemOpacityChanged(QSGItem *) - { - Q_Q(QSGBasePositioner); - q->prePositioning(); + setPositioningDirty(); } void itemDestroyed(QSGItem *item) diff --git a/src/declarative/items/qsgshadereffect.cpp b/src/declarative/items/qsgshadereffect.cpp index ff131509f3..b81e7f15af 100644 --- a/src/declarative/items/qsgshadereffect.cpp +++ b/src/declarative/items/qsgshadereffect.cpp @@ -98,7 +98,7 @@ QSGShaderEffectItem::QSGShaderEffectItem(QSGItem *parent) /*! \qmlclass ShaderEffect QSGShaderEffect - \since 5.0 + \inqmlmodule QtQuick 2 \ingroup qml-basic-visual-elements \brief The ShaderEffect element applies custom shaders to a rectangle. \inherits Item @@ -214,7 +214,7 @@ void QSGShaderEffect::componentComplete() } /*! - \qmlproperty string ShaderEffect::fragmentShader + \qmlproperty string QtQuick2::ShaderEffect::fragmentShader This property holds the fragment shader's GLSL source code. The default shader passes the texture coordinate along to the fragment @@ -234,7 +234,7 @@ void QSGShaderEffect::setFragmentShader(const QByteArray &code) } /*! - \qmlproperty string ShaderEffect::vertexShader + \qmlproperty string QtQuick2::ShaderEffect::vertexShader This property holds the vertex shader's GLSL source code. The default shader expects the texture coordinate to be passed from the @@ -255,7 +255,7 @@ void QSGShaderEffect::setVertexShader(const QByteArray &code) } /*! - \qmlproperty bool ShaderEffect::blending + \qmlproperty bool QtQuick2::ShaderEffect::blending If this property is true, the output from the \l fragmentShader is blended with the background using source-over blend mode. If false, the background @@ -275,7 +275,7 @@ void QSGShaderEffect::setBlending(bool enable) } /*! - \qmlproperty size ShaderEffect::mesh + \qmlproperty size QtQuick2::ShaderEffect::mesh This property holds the mesh resolution. The default resolution is 1x1 which is the minimum and corresponds to a mesh with four vertices. @@ -358,7 +358,7 @@ void QSGShaderEffect::setMesh(const QVariant &mesh) } /*! - \qmlproperty enumeration ShaderEffect::cullMode + \qmlproperty enumeration QtQuick2::ShaderEffect::cullMode This property defines which sides of the element should be visible. diff --git a/src/declarative/items/qsgshadereffectsource.cpp b/src/declarative/items/qsgshadereffectsource.cpp index 4035608a6e..bb55af524b 100644 --- a/src/declarative/items/qsgshadereffectsource.cpp +++ b/src/declarative/items/qsgshadereffectsource.cpp @@ -406,6 +406,14 @@ void QSGShaderEffectTexture::grab() markDirtyTexture(); // Continuously update if 'live' and 'recursive'. } +QImage QSGShaderEffectTexture::toImage() const +{ + if (m_fbo) + return m_fbo->toImage(); + + return QImage(); +} + /*! \qmlclass ShaderEffectSource QSGShaderEffectSource \since 5.0 diff --git a/src/declarative/items/qsgshadereffectsource_p.h b/src/declarative/items/qsgshadereffectsource_p.h index 6cb76ddba4..77cb412884 100644 --- a/src/declarative/items/qsgshadereffectsource_p.h +++ b/src/declarative/items/qsgshadereffectsource_p.h @@ -117,6 +117,7 @@ public: void scheduleUpdate(); void scheduleForCleanup(); + QImage toImage() const; Q_SIGNALS: void textureChanged(); diff --git a/src/declarative/items/qsgview.cpp b/src/declarative/items/qsgview.cpp index 48b3074363..236fd4ec1f 100644 --- a/src/declarative/items/qsgview.cpp +++ b/src/declarative/items/qsgview.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qsgview.h" +#include "qsgview_p.h" #include "qsgcanvas_p.h" #include "qsgitem_p.h" @@ -52,45 +53,13 @@ #include <private/qdeclarativeengine_p.h> #include <QtCore/qbasictimer.h> -// XXX todo - This whole class should probably be merged with QDeclarativeView for + +// XXX todo - This whole class should probably be merged with QDeclarativeView for // maximum seamlessness QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE) -class QSGViewPrivate : public QSGCanvasPrivate, - public QSGItemChangeListener -{ - Q_DECLARE_PUBLIC(QSGView) -public: - QSGViewPrivate(); - ~QSGViewPrivate(); - - void execute(); - void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); - void initResize(); - void updateSize(); - void setRootObject(QObject *); - - void init(); - - QSize rootObjectSize() const; - - QPointer<QSGItem> root; - - QUrl source; - - QDeclarativeEngine engine; - QDeclarativeComponent *component; - QBasicTimer resizetimer; - - QSGView::ResizeMode resizeMode; - QSize initialSize; - QElapsedTimer frameTimer; - - bool resized; -}; - void QSGViewPrivate::init() { QDeclarativeEnginePrivate::get(&engine)->sgContext = QSGCanvasPrivate::context; @@ -103,8 +72,8 @@ QSGViewPrivate::QSGViewPrivate() { } -QSGViewPrivate::~QSGViewPrivate() -{ +QSGViewPrivate::~QSGViewPrivate() +{ QDeclarativeInspectorService::instance()->removeView(q_func()); delete root; @@ -126,7 +95,7 @@ void QSGViewPrivate::execute() if (!component->isLoading()) { q->continueExecute(); } else { - QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), + QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), q, SLOT(continueExecute())); } } @@ -397,9 +366,9 @@ QSGItem *QSGView::rootObject() const void QSGView::resizeEvent(QResizeEvent *e) { Q_D(QSGView); - if (d->resizeMode == SizeRootObjectToView) + if (d->resizeMode == SizeRootObjectToView) d->updateSize(); - + QSGCanvas::resizeEvent(e); } diff --git a/tests/auto/declarative/qdeclarativedebughelper/private_headers/qdeclarativedebughelper_p.h b/src/declarative/items/qsgview_p.h index c08f6fd639..3f8d69e8c0 100644 --- a/tests/auto/declarative/qdeclarativedebughelper/private_headers/qdeclarativedebughelper_p.h +++ b/src/declarative/items/qsgview_p.h @@ -39,33 +39,70 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVEDEBUGHELPER_P_H -#define QDECLARATIVEDEBUGHELPER_P_H +#ifndef QSGVIEW_P_H +#define QSGVIEW_P_H -#include <QtCore/qglobal.h> +#include "qsgview.h" + +#include <QtCore/qurl.h> +#include <QtCore/qelapsedtimer.h> +#include <QtCore/qtimer.h> +#include <QtCore/qpointer.h> +#include <QtDeclarative/qsgview.h> +#include <QtDeclarative/qdeclarativeengine.h> +#include <QtDeclarative/private/qsgcanvas_p.h> + +#include "qsgitemchangelistener_p.h" QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QJSEngine; -class QDeclarativeEngine; +QT_MODULE(Declarative) + +class QDeclarativeContext; +class QDeclarativeError; +class QSGItem; +class QDeclarativeComponent; -// Helper methods to access private API through a stable interface -// This is used in the qmljsdebugger library of QtCreator. -class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper +class QSGViewPrivate : public QSGCanvasPrivate, + public QSGItemChangeListener { + Q_DECLARE_PUBLIC(QSGView) public: - static QJSEngine *getScriptEngine(QDeclarativeEngine *engine); - static void setAnimationSlowDownFactor(qreal factor); + static QSGViewPrivate* get(QSGView *view) { return view->d_func(); } + static const QSGViewPrivate* get(const QSGView *view) { return view->d_func(); } + + QSGViewPrivate(); + ~QSGViewPrivate(); + + void execute(); + void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); + void initResize(); + void updateSize(); + void setRootObject(QObject *); + + void init(); + + QSize rootObjectSize() const; + + QPointer<QSGItem> root; + + QUrl source; + + QDeclarativeEngine engine; + QDeclarativeComponent *component; + QBasicTimer resizetimer; + + QSGView::ResizeMode resizeMode; + QSize initialSize; + QElapsedTimer frameTimer; - // Enables remote debugging functionality - // Only use this for debugging in a safe environment! - static void enableDebugging(); + bool resized; }; QT_END_NAMESPACE QT_END_HEADER -#endif // QDECLARATIVEDEBUGHELPER_P_H +#endif // QSGVIEW_P_H diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp index 5dfe01dd2b..4dd508d0aa 100644 --- a/src/declarative/items/qsgvisualitemmodel.cpp +++ b/src/declarative/items/qsgvisualitemmodel.cpp @@ -1511,7 +1511,7 @@ void QSGVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourc Q_D(QSGVisualDataModel); const int count = sourceEnd - sourceStart + 1; if (destinationParent == d->m_root && sourceParent == d->m_root) { - _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-1, count); + _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-count, count); } else if (sourceParent == d->m_root) { _q_itemsRemoved(sourceStart, count); } else if (destinationParent == d->m_root) { diff --git a/src/declarative/particles/defaultshaders/imagevertex.shader b/src/declarative/particles/defaultshaders/imagevertex.shader index e1033c9165..9967ef85a2 100644 --- a/src/declarative/particles/defaultshaders/imagevertex.shader +++ b/src/declarative/particles/defaultshaders/imagevertex.shader @@ -75,8 +75,9 @@ void main() { currentSize = currentSize * sizetable[int(floor(t*64.))]; fade = fade * opacitytable[int(floor(t*64.))]; #endif + if (entry == 1.) - fade = fadeIn * fadeOut; + fade = fade * fadeIn * fadeOut; else if(entry == 2.) currentSize = currentSize * fadeIn * fadeOut; diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp index db544d20e8..12d32a27b4 100644 --- a/src/declarative/particles/qsgcustomparticle.cpp +++ b/src/declarative/particles/qsgcustomparticle.cpp @@ -45,17 +45,17 @@ QT_BEGIN_NAMESPACE -//TODO: Can we make the code such that you don't have to copy the whole vertex shader just to add one little calculation? //Includes comments because the code isn't self explanatory -static const char qt_particles_default_vertex_code[] = +static const char qt_particles_template_vertex_code[] = "attribute highp vec2 vPos; \n" "attribute highp vec2 vTex; \n" "attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize \n" "attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration \n" + "attribute highp float r; \n" "uniform highp mat4 qt_Matrix; \n" "uniform highp float timestamp; \n" "varying highp vec2 fTex; \n" - "void main() { \n" + "void defaultMain() { \n" " fTex = vTex; \n" " highp float size = vData.z; \n" " highp float endSize = vData.w; \n" @@ -68,6 +68,10 @@ static const char qt_particles_default_vertex_code[] = " + vVec.xy * t * vData.y // apply speed vector.. \n" " + 0.5 * vVec.zw * pow(t * vData.y, 2.); \n" " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); \n" + "}\n"; +static const char qt_particles_default_vertex_code[] = + "void main() { \n" + " defaultMain(); \n" "}"; static const char qt_particles_default_fragment_code[] =//TODO: Default frag requires source? @@ -78,9 +82,6 @@ static const char qt_particles_default_fragment_code[] =//TODO: Default frag req " gl_FragColor = texture2D(source, fTex) * qt_Opacity; \n" "}"; -static const char qt_position_attribute_name[] = "qt_Vertex"; -static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0"; - static QSGGeometry::Attribute PlainParticle_Attributes[] = { { 0, 2, GL_FLOAT }, // Position { 1, 2, GL_FLOAT }, // TexCoord @@ -157,8 +158,9 @@ void QSGCustomParticle::componentComplete() \qmlproperty string QtQuick.Particles2::CustomParticle::fragmentShader This property holds the fragment shader's GLSL source code. - The default shader passes the texture coordinate along to the fragment - shader as "varying highp vec2 qt_TexCoord0". + The default shader expects the texture coordinate to be passed from the + vertex shader as "varying highp vec2 fTex", and it samples from a + sampler2D named "source". */ void QSGCustomParticle::setFragmentShader(const QByteArray &code) @@ -176,9 +178,41 @@ void QSGCustomParticle::setFragmentShader(const QByteArray &code) \qmlproperty string QtQuick.Particles2::CustomParticle::vertexShader This property holds the vertex shader's GLSL source code. - The default shader expects the texture coordinate to be passed from the - vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a - sampler2D named "source". + + The default shader passes the texture coordinate along to the fragment + shader as "varying highp vec2 fTex". + + To aid writing a particle vertex shader, the following GLSL code is prepended + to your vertex shader: + \code + attribute highp vec2 vPos; + attribute highp vec2 vTex; + attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize + attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration + attribute highp float r; + uniform highp mat4 qt_Matrix; + uniform highp float timestamp; + varying highp vec2 fTex; + void defaultMain() { + fTex = vTex; + highp float size = vData.z; + highp float endSize = vData.w; + highp float t = (timestamp - vData.x) / vData.y; + highp float currentSize = mix(size, endSize, t * t); + if (t < 0. || t > 1.) + currentSize = 0.; + highp vec2 pos = vPos + - currentSize / 2. + currentSize * vTex // adjust size + + vVec.xy * t * vData.y // apply speed vector.. + + 0.5 * vVec.zw * pow(t * vData.y, 2.); + gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); + } + \endcode + + defaultMain() is the same code as in the default shader, you can call this for basic + particle functions and then add additional variables for custom effects. Note that + the vertex shader for particles is responsible for simulating the movement of particles + over time, the particle data itself only has the starting position and spawn time. */ void QSGCustomParticle::setVertexShader(const QByteArray &code) @@ -311,6 +345,7 @@ void QSGCustomParticle::updateProperties() vertexCode = qt_particles_default_vertex_code; if (fragmentCode.isEmpty()) fragmentCode = qt_particles_default_fragment_code; + vertexCode = qt_particles_template_vertex_code + vertexCode; m_source.attributeNames.clear(); m_source.attributeNames << "vPos" << "vTex" << "vData" << "vVec" << "r"; @@ -318,10 +353,6 @@ void QSGCustomParticle::updateProperties() lookThroughShaderCode(vertexCode); lookThroughShaderCode(fragmentCode); - if (!m_source.attributeNames.contains(qt_position_attribute_name)) - qWarning("QSGCustomParticle: Missing reference to \'%s\'.", qt_position_attribute_name); - if (!m_source.attributeNames.contains(qt_texcoord_attribute_name)) - qWarning("QSGCustomParticle: Missing reference to \'%s\'.", qt_texcoord_attribute_name); if (!m_source.respectsMatrix) qWarning("QSGCustomParticle: Missing reference to \'qt_Matrix\'."); if (!m_source.respectsOpacity) @@ -352,17 +383,13 @@ void QSGCustomParticle::lookThroughShaderCode(const QByteArray &code) QByteArray name = re.cap(3).toLatin1(); // variable name if (decl == "attribute") { - if (!m_source.attributeNames.contains(name))//TODO: Can they add custom attributes? + if (!m_source.attributeNames.contains(name)) qWarning() << "Custom Particle: Unknown attribute " << name; } else { Q_ASSERT(decl == "uniform");//TODO: Shouldn't assert if (name == "qt_Matrix") { m_source.respectsMatrix = true; - } else if (name == "qt_ModelViewProjectionMatrix") { - // TODO: Remove after grace period. - qWarning("ShaderEffect: qt_ModelViewProjectionMatrix is deprecated. Use qt_Matrix instead."); - m_source.respectsMatrix = true; } else if (name == "qt_Opacity") { m_source.respectsOpacity = true; } else if (name == "timestamp") { @@ -443,7 +470,9 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNodes() m_material = new QSGShaderEffectMaterialObject; } + s.vertexCode = qt_particles_template_vertex_code + s.vertexCode; m_material->setProgramSource(s); + foreach (const QString &str, m_particles){ int gIdx = m_system->m_groupIds[str]; int count = m_system->m_groupData[gIdx]->size(); diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp index 737b393de7..853a08a890 100644 --- a/src/declarative/particles/qsgimageparticle.cpp +++ b/src/declarative/particles/qsgimageparticle.cpp @@ -258,7 +258,7 @@ public: m_animcount_id = program()->uniformLocation("animcount"); m_entry_id = program()->uniformLocation("entry"); m_sizetable_id = program()->uniformLocation("sizetable"); - m_opacitytable_id = program()->uniformLocation("sizetable"); + m_opacitytable_id = program()->uniformLocation("opacitytable"); } void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) { @@ -432,7 +432,7 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size) { if (img.isNull()){ for (int i=0; i<size; i++) - array[i] = 1; + array[i] = 1.0; return; } QImage scaled = img.scaled(size,1); diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp index 4cb3e49403..331310625f 100644 --- a/src/declarative/particles/qsgparticleaffector.cpp +++ b/src/declarative/particles/qsgparticleaffector.cpp @@ -42,6 +42,7 @@ #include "qsgparticleaffector_p.h" #include <QDebug> QT_BEGIN_NAMESPACE + /*! \qmlclass Affector QSGParticleAffector \inqmlmodule QtQuick.Particles 2 @@ -159,8 +160,10 @@ void QSGParticleAffector::affectSystem(qreal dt) if ((m_onceOff && m_onceOffed.contains(qMakePair(d->group, d->index))) || !d->stillAlive()) continue; - //Need to have previous location for affected. if signal || shape might be faster? - QPointF curPos = QPointF(d->curX(), d->curY()); + //Need to have previous location for affected anyways + QPointF curPos; + if (m_signal || (width() && height())) + curPos = QPointF(d->curX(), d->curY()); if (width() == 0 || height() == 0 || m_shape->contains(QRectF(m_offset.x(), m_offset.y(), width(), height()),curPos)){ if (m_collisionParticles.isEmpty() || isColliding(d)){ @@ -181,8 +184,9 @@ void QSGParticleAffector::affectSystem(qreal dt) bool QSGParticleAffector::affectParticle(QSGParticleData *d, qreal dt) { if (isAffectConnected()){ + d->update = 0.0; emit affectParticle(d->v8Value(), dt); - return true; + return d->update == 1.0; } return m_signal;//If signalling, then we always 'null affect' it. } diff --git a/src/declarative/particles/qsgparticlesystem_p.h b/src/declarative/particles/qsgparticlesystem_p.h index 9f4020d041..abb7f52c31 100644 --- a/src/declarative/particles/qsgparticlesystem_p.h +++ b/src/declarative/particles/qsgparticlesystem_p.h @@ -202,6 +202,7 @@ public: float r; QSGItem* delegate; int modelIndex; + float update;//Used by custom affectors void debugDump(); bool stillAlive(); diff --git a/src/declarative/particles/qsgpointattractor.cpp b/src/declarative/particles/qsgpointattractor.cpp index 1a3c3c25c5..21eaeaac12 100644 --- a/src/declarative/particles/qsgpointattractor.cpp +++ b/src/declarative/particles/qsgpointattractor.cpp @@ -65,21 +65,31 @@ bool QSGPointAttractorAffector::affectParticle(QSGParticleData *d, qreal dt) { if (m_strength == 0.0) return false; - qreal dx = m_y - d->curX(); - qreal dy = m_x - d->curY(); + qreal dx = m_x - d->curX(); + qreal dy = m_y - d->curY(); qreal r = sqrt((dx*dx) + (dy*dy)); qreal theta = atan2(dy,dx); qreal ds = 0; switch (m_proportionalToDistance){ + case InverseQuadratic: + ds = (m_strength / qMax<qreal>(1.,r*r)); + break; + case InverseLinear: + ds = (m_strength / qMax<qreal>(1.,r)); + break; case Quadratic: - ds = (m_strength / qMax<qreal>(1.,r*r)) * dt; + ds = (m_strength * qMax<qreal>(1.,r*r)); break; - case Linear://also default - default: - ds = (m_strength / qMax<qreal>(1.,r)) * dt; + case Linear: + ds = (m_strength * qMax<qreal>(1.,r)); + break; + default: //also Constant + ds = m_strength; } + ds *= dt; dx = ds * cos(theta); dy = ds * sin(theta); + qreal vx,vy; switch (m_physics){ case Position: d->x = (d->x + dx); @@ -91,8 +101,10 @@ bool QSGPointAttractorAffector::affectParticle(QSGParticleData *d, qreal dt) break; case Velocity: //also default default: - d->setInstantaneousVX(d->vx + dx); - d->setInstantaneousVY(d->vy + dy); + vx = d->curVX(); + vy = d->curVY(); + d->setInstantaneousVX(vx + dx); + d->setInstantaneousVY(vy + dy); } return true; diff --git a/src/declarative/particles/qsgpointattractor_p.h b/src/declarative/particles/qsgpointattractor_p.h index 95716483ed..298965a5c9 100644 --- a/src/declarative/particles/qsgpointattractor_p.h +++ b/src/declarative/particles/qsgpointattractor_p.h @@ -64,8 +64,11 @@ class QSGPointAttractorAffector : public QSGParticleAffector public: enum Proportion{ + Constant, Linear, - Quadratic + Quadratic, + InverseLinear, + InverseQuadratic }; enum PhysicsAffects { diff --git a/src/declarative/particles/qsgv8particledata.cpp b/src/declarative/particles/qsgv8particledata.cpp index b3ff482d8b..72c0b7c2de 100644 --- a/src/declarative/particles/qsgv8particledata.cpp +++ b/src/declarative/particles/qsgv8particledata.cpp @@ -150,6 +150,7 @@ FLOAT_GETTER_AND_SETTER(frameDuration) FLOAT_GETTER_AND_SETTER(frameCount) FLOAT_GETTER_AND_SETTER(animT) FLOAT_GETTER_AND_SETTER(r) +FLOAT_GETTER_AND_SETTER(update) FAKE_FLOAT_GETTER_AND_SETTER(curX, curX, setInstantaneousX) FAKE_FLOAT_GETTER_AND_SETTER(curVX, curVX, setInstantaneousVX) FAKE_FLOAT_GETTER_AND_SETTER(curAX, curAX, setInstantaneousAX) @@ -157,7 +158,7 @@ FAKE_FLOAT_GETTER_AND_SETTER(curY, curY, setInstantaneousY) FAKE_FLOAT_GETTER_AND_SETTER(curVY, curVY, setInstantaneousVY) FAKE_FLOAT_GETTER_AND_SETTER(curAY, curAY, setInstantaneousAY) -//TODO: Non-floats (color) and special floats (curX) once basic floats are working well +//TODO: Non-floats (color, update?) once floats are working well QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine) { @@ -189,6 +190,7 @@ QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine) FLOAT_REGISTER_ACCESSOR(ft, engine, frameCount); FLOAT_REGISTER_ACCESSOR(ft, engine, animT); FLOAT_REGISTER_ACCESSOR(ft, engine, r); + FLOAT_REGISTER_ACCESSOR(ft, engine, update); FLOAT_REGISTER_ACCESSOR(ft, engine, curX); FLOAT_REGISTER_ACCESSOR(ft, engine, curVX); FLOAT_REGISTER_ACCESSOR(ft, engine, curAX); diff --git a/src/declarative/qml/ftw/ftw.pri b/src/declarative/qml/ftw/ftw.pri new file mode 100644 index 0000000000..545c47e3c6 --- /dev/null +++ b/src/declarative/qml/ftw/ftw.pri @@ -0,0 +1,23 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qbitfield_p.h \ + $$PWD/qintrusivelist_p.h \ + $$PWD/qmetaobjectbuilder_p.h \ + $$PWD/qpodvector_p.h \ + $$PWD/qhashedstring_p.h \ + $$PWD/qdeclarativerefcount_p.h \ + $$PWD/qdeclarativepool_p.h \ + $$PWD/qfieldlist_p.h \ + $$PWD/qdeclarativeutils_p.h \ + $$PWD/qfastmetabuilder_p.h \ + $$PWD/qhashfield_p.h \ + +SOURCES += \ + $$PWD/qintrusivelist.cpp \ + $$PWD/qmetaobjectbuilder.cpp \ + $$PWD/qhashedstring.cpp \ + $$PWD/qdeclarativerefcount.cpp \ + $$PWD/qdeclarativepool.cpp \ + $$PWD/qfastmetabuilder.cpp \ + diff --git a/src/declarative/qml/qbitfield_p.h b/src/declarative/qml/ftw/qbitfield_p.h index 67f578beda..67f578beda 100644 --- a/src/declarative/qml/qbitfield_p.h +++ b/src/declarative/qml/ftw/qbitfield_p.h diff --git a/src/declarative/qml/ftw/qdeclarativepool.cpp b/src/declarative/qml/ftw/qdeclarativepool.cpp new file mode 100644 index 0000000000..94bb89bd46 --- /dev/null +++ b/src/declarative/qml/ftw/qdeclarativepool.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativepool_p.h" + +// #define POOL_DEBUG + +QT_BEGIN_NAMESPACE + +void QDeclarativePool::newpage() +{ +#ifdef POOL_DEBUG + qWarning("QDeclarativePool: Allocating page"); +#endif + + Page *page = (Page *)malloc(sizeof(Page)); + page->header.next = _page; + page->header.free = page->memory; + _page = page; +} + +void QDeclarativePool::clear() +{ +#ifdef POOL_DEBUG + int count = 0; +#endif + + Class *c = _classList; + while (c) { + Class *n = c->_next; + c->_destroy(c); +#ifdef POOL_DEBUG + ++count; +#endif + c = n; + } + +#ifdef POOL_DEBUG + qWarning("QDeclarativePool: Destroyed %d objects", count); +#endif + + Page *p = _page; + while (p) { + Page *n = p->header.next; + free(p); + p = n; + } + + _classList = 0; + _page = 0; +} + + +QT_END_NAMESPACE diff --git a/src/declarative/qml/ftw/qdeclarativepool_p.h b/src/declarative/qml/ftw/qdeclarativepool_p.h new file mode 100644 index 0000000000..8935046cc3 --- /dev/null +++ b/src/declarative/qml/ftw/qdeclarativepool_p.h @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPOOL_P_H +#define QDECLARATIVEPOOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtCore/qstring.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativePool +{ +public: + // The class has a destructor that needs to be called + class Class { + public: + inline QDeclarativePool *pool() const; + + private: + void *operator new(size_t); + void *operator new(size_t, void *m) { return m; } + friend class QDeclarativePool; + + QDeclarativePool *_pool; + Class *_next; + void (*_destroy)(Class *); + }; + + // The class is plain old data and no destructor needs to + // be called + class POD { + public: + inline QDeclarativePool *pool() const; + + private: + void *operator new(size_t); + void *operator new(size_t, void *m) { return m; } + friend class QDeclarativePool; + + QDeclarativePool *_pool; + }; + + inline QDeclarativePool(); + inline ~QDeclarativePool(); + + void clear(); + + template<typename T> + inline T *New(); + template<typename T> + inline T *NewRaw(); + template<typename T> + inline T *NewRawArray(int length); + + inline QString *NewString(const QString &); + inline QByteArray *NewByteArray(const QByteArray &); + + template<typename T> + struct List { + List() : m_length(0), m_data(0) {} + List(const List &o) : m_length(o.m_length), m_data(o.m_data) {} + List &operator=(const List &o) { + m_length = o.m_length; + m_data = o.m_data; + return *this; + } + + int count() const { + return m_length; + } + int length() const { + return m_length; + } + const T &at(int index) const { + Q_ASSERT(index < m_length); + return m_data[index]; + }; + T &operator[](int index) { + Q_ASSERT(index < m_length); + return m_data[index]; + }; + private: + friend class QDeclarativePool; + List(T *d, int l) : m_length(l), m_data(d) {} + int m_length; + T *m_data; + }; + + template<typename T> + inline List<T> NewRawList(int length); + +private: + struct StringClass : public QString, public Class { + }; + struct ByteArrayClass : public QByteArray, public Class { + }; + + inline void *allocate(int size); + void newpage(); + + template<typename T> + inline void initialize(POD *); + template<typename T> + inline void initialize(Class *); + template<typename T> + static void destroy(Class *c); + + struct Page { + struct Header { + Page *next; + char *free; + } header; + + static const int pageSize = 4 * 4096 - sizeof(Header); + + char memory[pageSize]; + }; + + Page *_page; + Class *_classList; +}; + +QDeclarativePool::QDeclarativePool() +: _page(0), _classList(0) +{ +} + +QDeclarativePool::~QDeclarativePool() +{ + clear(); +} + +template<typename T> +T *QDeclarativePool::New() +{ + T *rv = new (allocate(sizeof(T))) T; + initialize<T>(rv); + rv->_pool = this; + return rv; +} + +template<typename T> +T *QDeclarativePool::NewRaw() +{ + return (T*)allocate(sizeof(T)); +} + +template<typename T> +T *QDeclarativePool::NewRawArray(int length) +{ + return (T*)allocate(length * sizeof(T)); +} + +template<typename T> +QDeclarativePool::List<T> QDeclarativePool::NewRawList(int length) +{ + return List<T>(NewRawArray<T>(length), length); +} + +QString *QDeclarativePool::NewString(const QString &s) +{ + QString *rv = New<StringClass>(); + *rv = s; + return rv; +} + +QByteArray *QDeclarativePool::NewByteArray(const QByteArray &s) +{ + QByteArray *rv = New<ByteArrayClass>(); + *rv = s; + return rv; +} + +void *QDeclarativePool::allocate(int size) +{ + if (!_page || (_page->header.free + size) > (_page->memory + Page::pageSize)) + newpage(); + + void *rv = _page->header.free; + _page->header.free += size + ((8 - size) & 7); // ensure 8 byte alignment; + return rv; +} + +template<typename T> +void QDeclarativePool::initialize(QDeclarativePool::POD *) +{ +} + +template<typename T> +void QDeclarativePool::initialize(QDeclarativePool::Class *c) +{ + c->_next = _classList; + c->_destroy = &destroy<T>; + _classList = c; +} + +template<typename T> +void QDeclarativePool::destroy(Class *c) +{ + static_cast<T *>(c)->~T(); +} + +QDeclarativePool *QDeclarativePool::Class::pool() const +{ + return _pool; +} + +QDeclarativePool *QDeclarativePool::POD::pool() const +{ + return _pool; +} + +QT_END_NAMESPACE + +#endif // QDECLARATIVEPOOL_P_H + diff --git a/src/declarative/qml/qdeclarativerefcount.cpp b/src/declarative/qml/ftw/qdeclarativerefcount.cpp index a17d5b7142..a17d5b7142 100644 --- a/src/declarative/qml/qdeclarativerefcount.cpp +++ b/src/declarative/qml/ftw/qdeclarativerefcount.cpp diff --git a/src/declarative/qml/qdeclarativerefcount_p.h b/src/declarative/qml/ftw/qdeclarativerefcount_p.h index 381327098c..381327098c 100644 --- a/src/declarative/qml/qdeclarativerefcount_p.h +++ b/src/declarative/qml/ftw/qdeclarativerefcount_p.h diff --git a/src/declarative/qml/ftw/qdeclarativeutils_p.h b/src/declarative/qml/ftw/qdeclarativeutils_p.h new file mode 100644 index 0000000000..63e90012c2 --- /dev/null +++ b/src/declarative/qml/ftw/qdeclarativeutils_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEUTIL_P_H +#define QDECLARATIVEUTIL_P_H + +#include <QtCore/QString> + +QT_BEGIN_NAMESPACE + +namespace QDeclarativeUtils { + +inline bool isUpper(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'A' && c <= 'Z') || (c > 127 && QChar::category(c) == QChar::Letter_Uppercase)); +} + +inline bool isLower(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'a' && c <= 'z') || (c > 127 && QChar::category(c) == QChar::Letter_Lowercase)); +} + +inline bool isLetter(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c > 127 && qc.isLetter())); +} + +inline bool isDigit(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= '0' && c <= '9') || (c > 127 && qc.isDigit())); +} + +inline bool isLetterOrNumber(const QChar &qc) +{ + ushort c = qc.unicode(); + return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c > 127 && qc.isLetterOrNumber())); +} + +inline bool isSpace(const QChar &qc) +{ + ushort c = qc.unicode(); + return (c == 0x20 || (c >= 0x09 && c <= 0x0D) || c == 0x85 || (c > 127 && qc.isSpace())); +} + +} // namespace QDeclarative + +QT_END_NAMESPACE + +#endif // QDECLARATIVEUTIL_P_H diff --git a/src/declarative/qml/ftw/qfastmetabuilder.cpp b/src/declarative/qml/ftw/qfastmetabuilder.cpp new file mode 100644 index 0000000000..20c5e08499 --- /dev/null +++ b/src/declarative/qml/ftw/qfastmetabuilder.cpp @@ -0,0 +1,371 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfastmetabuilder_p.h" + +QT_BEGIN_NAMESPACE + +struct QFastMetaBuilderHeader +{ + int fieldCount; +}; + +struct QMetaObjectPrivate +{ + int revision; + int className; + int classInfoCount, classInfoData; + int methodCount, methodData; + int propertyCount, propertyData; + int enumeratorCount, enumeratorData; + int constructorCount, constructorData; //since revision 2 + int flags; //since revision 3 + int signalCount; //since revision 4 +}; + +enum MetaObjectFlag { + DynamicMetaObject = 0x01 +}; + +enum PropertyFlags { + Invalid = 0x00000000, + Readable = 0x00000001, + Writable = 0x00000002, + Resettable = 0x00000004, + EnumOrFlag = 0x00000008, + StdCppSet = 0x00000100, +// Override = 0x00000200, + Constant = 0x00000400, + Final = 0x00000800, + Designable = 0x00001000, + ResolveDesignable = 0x00002000, + Scriptable = 0x00004000, + ResolveScriptable = 0x00008000, + Stored = 0x00010000, + ResolveStored = 0x00020000, + Editable = 0x00040000, + ResolveEditable = 0x00080000, + User = 0x00100000, + ResolveUser = 0x00200000, + Notify = 0x00400000, + Revisioned = 0x00800000 +}; + +enum MethodFlags { + AccessPrivate = 0x00, + AccessProtected = 0x01, + AccessPublic = 0x02, + AccessMask = 0x03, //mask + + MethodMethod = 0x00, + MethodSignal = 0x04, + MethodSlot = 0x08, + MethodConstructor = 0x0c, + MethodTypeMask = 0x0c, + + MethodCompatibility = 0x10, + MethodCloned = 0x20, + MethodScriptable = 0x40, + MethodRevisioned = 0x80 +}; + +#define FMBHEADER_FIELD_COUNT 1 + +#define HEADER_FIELD_COUNT 14 +#define CLASSINFO_FIELD_COUNT 2 +#define METHOD_FIELD_COUNT 5 +#define PROPERTY_FIELD_COUNT 3 +#define PROPERTY_NOTIFY_FIELD_COUNT 1 + +static inline uint *fieldPointer(QByteArray &data) +{ return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; } + +static inline const uint *fieldPointer(const QByteArray &data) +{ return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; } + +static inline QMetaObjectPrivate *priv(QByteArray &data) +{ return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); } + +static inline const QMetaObjectPrivate *priv(const QByteArray &data) +{ return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); } + +static inline QFastMetaBuilderHeader *header(QByteArray &data) +{ return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); } + +static inline const QFastMetaBuilderHeader *header(const QByteArray &data) +{ return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); } + +QFastMetaBuilder::QFastMetaBuilder() +: m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0) +{ +} + +QFastMetaBuilder::~QFastMetaBuilder() +{ +} + +QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength, + int propertyCount, int methodCount, + int signalCount, int classInfoCount) +{ + Q_ASSERT(m_data.isEmpty()); + Q_ASSERT(classNameLength > 0); + Q_ASSERT(propertyCount >= 0); + Q_ASSERT(methodCount >= 0); + Q_ASSERT(signalCount >= 0); + Q_ASSERT(classInfoCount >= 0); + + int fieldCount = FMBHEADER_FIELD_COUNT + + HEADER_FIELD_COUNT + + propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) + + methodCount * (METHOD_FIELD_COUNT) + + signalCount * (METHOD_FIELD_COUNT) + + classInfoCount * CLASSINFO_FIELD_COUNT; + + m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1); + m_stringData = m_data.data() + m_data.size() - classNameLength - 1; + m_stringDataLength = classNameLength + 1; + m_stringDataAllocated = classNameLength + 1; + m_stringData[classNameLength] = 0; + m_zeroPtr = classNameLength; + + header(m_data)->fieldCount = fieldCount; + + QMetaObjectPrivate *p = priv(m_data); + + int dataIndex = HEADER_FIELD_COUNT; + + p->revision = 4; + p->className = 0; + + // Class infos + p->classInfoCount = classInfoCount; + if (p->classInfoCount) { + p->classInfoData = dataIndex; + dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT; + } else { + p->classInfoData = 0; + } + + // Methods + p->methodCount = methodCount + signalCount; + if (p->methodCount) { + p->methodData = dataIndex; + dataIndex += p->methodCount * METHOD_FIELD_COUNT; + } else { + p->methodData = 0; + } + p->signalCount = signalCount; + + // Properties + p->propertyCount = propertyCount; + if (p->propertyCount) { + p->propertyData = dataIndex; + dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT); + } else { + p->propertyData = 0; + } + + // Flags + p->flags = DynamicMetaObject; // Always dynamic + + // Enums and constructors not supported + p->enumeratorCount = 0; + p->enumeratorData = 0; + p->constructorCount = 0; + p->constructorData = 0; + + StringRef className; + className._b = this; + className._o = 0; + className._l = classNameLength; + return className; +} + +// Allocate a string of \a length. \a length should *not* include the null terminator. +QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length) +{ + Q_ASSERT(length > 0); + + StringRef sr; + sr._b = this; + sr._o = m_stringDataLength; + sr._l = length; + + m_stringDataLength += length + 1 /* for null terminator */; + + return sr; +} + +void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!key.isEmpty() && !value.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < p->classInfoCount); + + uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT; + // classinfo: key, value + ptr[0] = key.offset(); ptr[1] = value.offset(); +} + +void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, + QMetaType::Type mtype, PropertyFlag flags, int notifySignal) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!name.isEmpty() && !type.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < p->propertyCount); + + uint qtType = mtype; + if ((int)qtType == qMetaTypeId<QVariant>()) + qtType = 0xFF; // Special handling for QVariant + + uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT; + // properties: name, type, flags + ptr[0] = name.offset(); + ptr[1] = type.offset(); + if (notifySignal == -1) { + ptr[2] = qtType << 24; + ptr[2] |= flags | Scriptable | Readable; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0; + } else { + ptr[2] = qtType << 24; + ptr[2] |= flags | Scriptable | Readable | Notify; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal; + } +} + +void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, + QFastMetaBuilder::PropertyFlag flags, int notifySignal) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!name.isEmpty() && !type.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < p->propertyCount); + + uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT; + // properties: name, type, flags + ptr[0] = name.offset(); + ptr[1] = type.offset(); + if (notifySignal == -1) { + ptr[2] = flags | Scriptable | Readable; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0; + } else { + ptr[2] = flags | Scriptable | Readable | Notify; + *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal; + } +} + +void QFastMetaBuilder::setSignal(int index, const StringRef &signature, + const StringRef ¶meterNames, + const StringRef &type) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!signature.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + int mindex = metaObjectIndexForSignal(index); + + uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT; + // methods: signature, parameters, type, tag, flags + ptr[0] = signature.offset(); + ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset(); + ptr[2] = type.isEmpty()?m_zeroPtr:type.offset(); + ptr[3] = m_zeroPtr; + ptr[4] = AccessProtected | MethodSignal; +} + +void QFastMetaBuilder::setMethod(int index, const StringRef &signature, + const StringRef ¶meterNames, + const StringRef &type) +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(!signature.isEmpty()); + + QMetaObjectPrivate *p = priv(m_data); + int mindex = metaObjectIndexForMethod(index); + + uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT; + // methods: signature, parameters, type, tag, flags + ptr[0] = signature.offset(); + ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset(); + ptr[2] = type.isEmpty()?m_zeroPtr:type.offset(); + ptr[3] = m_zeroPtr; + ptr[4] = AccessProtected | MethodSlot; +} + +int QFastMetaBuilder::metaObjectIndexForSignal(int index) const +{ + Q_ASSERT(!m_data.isEmpty()); + Q_ASSERT(index < priv(m_data)->signalCount); + return index; +} + +int QFastMetaBuilder::metaObjectIndexForMethod(int index) const +{ + Q_ASSERT(!m_data.isEmpty()); + + const QMetaObjectPrivate *p = priv(m_data); + Q_ASSERT(index < (p->methodCount - p->signalCount)); + return index + p->signalCount; +} + +void QFastMetaBuilder::allocateStringData() +{ + if (m_stringDataAllocated < m_stringDataLength) { + m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated); + m_stringDataAllocated = m_stringDataLength; + m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint); + } +} + +void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data) +{ + output->d.superdata = parent; + output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint); + output->d.data = fieldPointer(data); +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/ftw/qfastmetabuilder_p.h b/src/declarative/qml/ftw/qfastmetabuilder_p.h new file mode 100644 index 0000000000..9a6971d652 --- /dev/null +++ b/src/declarative/qml/ftw/qfastmetabuilder_p.h @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFASTMETABUILDER_P_H +#define QFASTMETABUILDER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of moc. This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtCore/qmetatype.h> + +#include <private/qhashedstring_p.h> + +QT_BEGIN_NAMESPACE + +class QFastMetaBuilder +{ +public: + QFastMetaBuilder(); + ~QFastMetaBuilder(); + + struct StringRef { + public: + inline StringRef(); + inline StringRef(const StringRef &); + inline StringRef &operator=(const StringRef &); + + inline void load(const QHashedStringRef &); + inline void load(const QByteArray &); + inline void load(const char *); + + inline bool isEmpty() const; + inline QFastMetaBuilder *builder() const; + inline int offset() const; + inline char *data(); + inline int length() const; + private: + friend class QFastMetaBuilder; + + QFastMetaBuilder *_b; + int _o; + int _l; + }; + StringRef newString(int length); + + // Returns class name + StringRef init(int classNameLength, + int propertyCount, int methodCount, + int signalCount, int classInfoCount); + + void setClassInfo(int index, const StringRef &key, const StringRef &value); + + enum PropertyFlag { + None = 0x00000000, + Writable = 0x00000002, + Resettable = 0x00000004, + Constant = 0x00000400, + Final = 0x00000800 + }; + // void setProperty(int index, const StringRef &name, QMetaType::Type type, int notifySignal = -1); + void setProperty(int index, const StringRef &name, const StringRef &type, + QMetaType::Type mtype, PropertyFlag flags, int notifySignal = -1); + void setProperty(int index, const StringRef &name, const StringRef &type, + PropertyFlag flags, int notifySignal = -1); + void setMethod(int index, const StringRef &signature, + const StringRef ¶meterNames = StringRef(), + const StringRef &type = StringRef()); + void setSignal(int index, const StringRef &signature, + const StringRef ¶meterNames = StringRef(), + const StringRef &type = StringRef()); + + int metaObjectIndexForSignal(int) const; + int metaObjectIndexForMethod(int) const; + + QByteArray toData() const { return m_data; } + static void fromData(QMetaObject *, const QMetaObject *parent, const QByteArray &); +private: + friend class StringRef; + + QByteArray m_data; + int m_zeroPtr; + + void allocateStringData(); + char *m_stringData; + int m_stringDataLength; + int m_stringDataAllocated; +}; + +QFastMetaBuilder::StringRef::StringRef() +: _b(0), _o(0), _l(0) +{ +} + +QFastMetaBuilder::StringRef::StringRef(const StringRef &o) +: _b(o._b), _o(o._o), _l(o._l) +{ +} + +QFastMetaBuilder::StringRef &QFastMetaBuilder::StringRef::operator=(const StringRef &o) +{ + _b = o._b; + _o = o._o; + _l = o._l; + return *this; +} + +bool QFastMetaBuilder::StringRef::isEmpty() const +{ + return _l == 0; +} + +QFastMetaBuilder *QFastMetaBuilder::StringRef::builder() const +{ + return _b; +} + +int QFastMetaBuilder::StringRef::offset() const +{ + return _o; +} + +char *QFastMetaBuilder::StringRef::data() +{ + Q_ASSERT(_b); + if (_b->m_stringDataLength != _b->m_stringDataAllocated) + _b->allocateStringData(); + return _b->m_stringData + _o; +} + +int QFastMetaBuilder::StringRef::length() const +{ + return _l; +} + +void QFastMetaBuilder::StringRef::load(const QHashedStringRef &str) +{ + Q_ASSERT(str.utf8length() == _l); + str.writeUtf8(data()); + *(data() + _l) = 0; +} + +void QFastMetaBuilder::StringRef::load(const QByteArray &str) +{ + Q_ASSERT(str.length() == _l); + strcpy(data(), str.constData()); +} + +void QFastMetaBuilder::StringRef::load(const char *str) +{ + Q_ASSERT(strlen(str) == (uint)_l); + strcpy(data(), str); +} + +QT_END_NAMESPACE + +#endif // QFASTMETABUILDER_P_H + diff --git a/src/declarative/qml/ftw/qfieldlist_p.h b/src/declarative/qml/ftw/qfieldlist_p.h new file mode 100644 index 0000000000..65b1d4b4ee --- /dev/null +++ b/src/declarative/qml/ftw/qfieldlist_p.h @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFIELDLIST_P_H +#define QFIELDLIST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +template<class N, N *N::*nextMember> +class QFieldList +{ +public: + inline QFieldList(); + inline N *first() const; + inline void append(N *); + inline void prepend(N *); + + inline bool isEmpty() const; + inline bool isOne() const; + inline bool isMany() const; + inline int count() const; + + inline void append(QFieldList<N, nextMember> &); + inline void prepend(QFieldList<N, nextMember> &); + inline void insertAfter(N *, QFieldList<N, nextMember> &); + + static inline N *next(N *v); + +private: + N *_first; + N *_last; + int _count; +}; + +template<class N, N *N::*nextMember> +QFieldList<N, nextMember>::QFieldList() +: _first(0), _last(0), _count(0) +{ +} + +template<class N, N *N::*nextMember> +N *QFieldList<N, nextMember>::first() const +{ + return _first; +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::append(N *v) +{ + Q_ASSERT(v->*nextMember == 0); + if (isEmpty()) { + _first = v; + _last = v; + } else { + _last->*nextMember = v; + _last = v; + } + ++_count; +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::prepend(N *v) +{ + Q_ASSERT(v->*nextMember == 0); + if (isEmpty()) { + _first = v; + _last = v; + } else { + v->*nextMember = _first; + _first = v; + } + ++_count; +} + +template<class N, N *N::*nextMember> +bool QFieldList<N, nextMember>::isEmpty() const +{ + return _count == 0; +} + +template<class N, N *N::*nextMember> +bool QFieldList<N, nextMember>::isOne() const +{ + return _count == 1; +} + +template<class N, N *N::*nextMember> +bool QFieldList<N, nextMember>::isMany() const +{ + return _count > 1; +} + +template<class N, N *N::*nextMember> +int QFieldList<N, nextMember>::count() const +{ + return _count; +} + +template<class N, N *N::*nextMember> +N *QFieldList<N, nextMember>::next(N *v) +{ + Q_ASSERT(v); + return v->*nextMember; +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::append(QFieldList<N, nextMember> &o) +{ + if (!o.isEmpty()) { + if (isEmpty()) { + _first = o._first; + _last = o._last; + _count = o._count; + } else { + _last->*nextMember = o._first; + _last = o._last; + _count += o._count; + } + o._first = o._last = 0; o._count = 0; + } +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::prepend(QFieldList<N, nextMember> &o) +{ + if (!o.isEmpty()) { + if (isEmpty()) { + _first = o._first; + _last = o._last; + _count = o._count; + } else { + o._last->*nextMember = _first; + _first = o._first; + _count += o._count; + } + o._first = o._last = 0; o._count = 0; + } +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::insertAfter(N *after, QFieldList<N, nextMember> &o) +{ + if (after == 0) { + prepend(o); + } else if (after == _last) { + append(o); + } else if (!o.isEmpty()) { + if (isEmpty()) { + _first = o._first; + _last = o._last; + _count = o._count; + } else { + o._last->*nextMember = after->*nextMember; + after->*nextMember = o._first; + _count += o._count; + } + o._first = o._last = 0; o._count = 0; + } +} + +#endif // QFIELDLIST_P_H diff --git a/src/declarative/qml/ftw/qhashedstring.cpp b/src/declarative/qml/ftw/qhashedstring.cpp new file mode 100644 index 0000000000..4a7b3376cc --- /dev/null +++ b/src/declarative/qml/ftw/qhashedstring.cpp @@ -0,0 +1,479 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhashedstring_p.h" + +// This is a reimplementation of V8's string hash algorithm. It is significantly +// faster to do it here than call into V8, but it adds the maintainence burden of +// ensuring that the two hashes are identical. We Q_ASSERT() that the two return +// the same value. If these asserts start to fail, the hash code needs to be +// synced with V8. +namespace String { + static const int kMaxArrayIndexSize = 10; + static const int kMaxHashCalcLength = 16383; + static const int kNofHashBitFields = 2; + static const int kHashShift = kNofHashBitFields; + static const int kIsNotArrayIndexMask = 1 << 1; + static const int kArrayIndexValueBits = 24; + static const int kArrayIndexHashLengthShift = kArrayIndexValueBits + kNofHashBitFields; + static const int kMaxCachedArrayIndexLength = 7; +}; + +template <typename schar> +uint32_t calculateHash(const schar* chars, int length) { + if (length > String::kMaxHashCalcLength) { + // V8 trivial hash + return (length << String::kHashShift) | String::kIsNotArrayIndexMask; + } + + uint32_t raw_running_hash = 0; + uint32_t array_index = 0; + bool is_array_index = (0 < length && length <= String::kMaxArrayIndexSize); + bool is_first_char = true; + + int ii = 0; + for (;is_array_index && ii < length; ++ii) { + quint32 c = *chars++; + + raw_running_hash += c; + raw_running_hash += (raw_running_hash << 10); + raw_running_hash ^= (raw_running_hash >> 6); + + if (c < '0' || c > '9') { + is_array_index = false; + } else { + int d = c - '0'; + if (is_first_char) { + is_first_char = false; + if (c == '0' && length > 1) { + is_array_index = false; + continue; + } + } + if (array_index > 429496729U - ((d + 2) >> 3)) { + is_array_index = false; + } else { + array_index = array_index * 10 + d; + } + } + } + + for (;ii < length; ++ii) { + raw_running_hash += *chars++; + raw_running_hash += (raw_running_hash << 10); + raw_running_hash ^= (raw_running_hash >> 6); + } + + if (is_array_index) { + array_index <<= String::kHashShift; + array_index |= length << String::kArrayIndexHashLengthShift; + return array_index; + } else { + raw_running_hash += (raw_running_hash << 3); + raw_running_hash ^= (raw_running_hash >> 11); + raw_running_hash += (raw_running_hash << 15); + if (raw_running_hash == 0) { + raw_running_hash = 27; + } + + return (raw_running_hash << String::kHashShift) | String::kIsNotArrayIndexMask; + } +} + +inline quint32 stringHash(const QChar* data, int length) +{ + quint32 rv = calculateHash<quint16>((quint16*)data, length) >> String::kHashShift; + Q_ASSERT(rv == v8::String::ComputeHash((uint16_t*)data, length)); + return rv; +} + +inline quint32 stringHash(const char *data, int length) +{ + quint32 rv = calculateHash<quint8>((quint8*)data, length) >> String::kHashShift; + Q_ASSERT(rv == v8::String::ComputeHash((char *)data, length)); + return rv; +} + +void QHashedString::computeHash() const +{ + m_hash = stringHash(constData(), length()); +} + +void QHashedStringRef::computeHash() const +{ + m_hash = stringHash(m_data, m_length); +} + +void QHashedCStringRef::computeHash() const +{ + m_hash = stringHash(m_data, m_length); +} + +/* + A QHash has initially around pow(2, MinNumBits) buckets. For + example, if MinNumBits is 4, it has 17 buckets. +*/ +const int MinNumBits = 4; + +/* + The prime_deltas array is a table of selected prime values, even + though it doesn't look like one. The primes we are using are 1, + 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate + surrounding of a power of two. + + The primeForNumBits() function returns the prime associated to a + power of two. For example, primeForNumBits(8) returns 257. +*/ + +static const uchar prime_deltas[] = { + 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, + 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 +}; + +static inline int primeForNumBits(int numBits) +{ + return (1 << numBits) + prime_deltas[numBits]; +} + +void QStringHashData::rehashToSize(int size) +{ + short bits = qMax(MinNumBits, (int)numBits); + while (primeForNumBits(bits) < size) bits++; + + if (bits > numBits) + rehashToBits(bits); +} + +void QStringHashData::rehashToBits(short bits) +{ + numBits = qMax(MinNumBits, (int)bits); + + int nb = primeForNumBits(numBits); + if (nb == numBuckets && buckets) + return; + + numBuckets = nb; + + delete [] buckets; + buckets = new QStringHashNode *[numBuckets]; + ::memset(buckets, 0, sizeof(QStringHashNode *) * numBuckets); + + QStringHashNode *nodeList = nodes; + while (nodeList) { + int bucket = nodeList->hash % numBuckets; + nodeList->next = buckets[bucket]; + buckets[bucket] = nodeList; + + nodeList = nodeList->nlist; + } +} + +// Copy of QString's qMemCompare +bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length) +{ + Q_ASSERT(lhs && rhs); + const quint16 *a = (const quint16 *)lhs; + const quint16 *b = (const quint16 *)rhs; + + if (a == b || !length) + return true; + + register union { + const quint16 *w; + const quint32 *d; + quintptr value; + } sa, sb; + sa.w = a; + sb.w = b; + + // check alignment + if ((sa.value & 2) == (sb.value & 2)) { + // both addresses have the same alignment + if (sa.value & 2) { + // both addresses are not aligned to 4-bytes boundaries + // compare the first character + if (*sa.w != *sb.w) + return false; + --length; + ++sa.w; + ++sb.w; + + // now both addresses are 4-bytes aligned + } + + // both addresses are 4-bytes aligned + // do a fast 32-bit comparison + register const quint32 *e = sa.d + (length >> 1); + for ( ; sa.d != e; ++sa.d, ++sb.d) { + if (*sa.d != *sb.d) + return false; + } + + // do we have a tail? + return (length & 1) ? *sa.w == *sb.w : true; + } else { + // one of the addresses isn't 4-byte aligned but the other is + register const quint16 *e = sa.w + length; + for ( ; sa.w != e; ++sa.w, ++sb.w) { + if (*sa.w != *sb.w) + return false; + } + } + return true; +} + +// Unicode stuff +static inline bool isUnicodeNonCharacter(uint ucs4) +{ + // Unicode has a couple of "non-characters" that one can use internally, + // but are not allowed to be used for text interchange. + // + // Those are the last two entries each Unicode Plane (U+FFFE, U+FFFF, + // U+1FFFE, U+1FFFF, etc.) as well as the entries between U+FDD0 and + // U+FDEF (inclusive) + + return (ucs4 & 0xfffe) == 0xfffe + || (ucs4 - 0xfdd0U) < 16; +} + +static int utf8LengthFromUtf16(const QChar *uc, int len) +{ + int length = 0; + + int surrogate_high = -1; + + const QChar *ch = uc; + int invalid = 0; + + const QChar *end = ch + len; + while (ch < end) { + uint u = ch->unicode(); + if (surrogate_high >= 0) { + if (u >= 0xdc00 && u < 0xe000) { + u = (surrogate_high - 0xd800)*0x400 + (u - 0xdc00) + 0x10000; + surrogate_high = -1; + } else { + // high surrogate without low + ++ch; + ++invalid; + surrogate_high = -1; + continue; + } + } else if (u >= 0xdc00 && u < 0xe000) { + // low surrogate without high + ++ch; + ++invalid; + continue; + } else if (u >= 0xd800 && u < 0xdc00) { + surrogate_high = u; + ++ch; + continue; + } + + if (u < 0x80) { + ++length; + } else { + if (u < 0x0800) { + ++length; + } else { + // is it one of the Unicode non-characters? + if (isUnicodeNonCharacter(u)) { + ++length; + ++ch; + ++invalid; + continue; + } + + if (u > 0xffff) { + ++length; + ++length; + } else { + ++length; + } + ++length; + } + ++length; + } + ++ch; + } + + return length; +} + +// Writes the utf8 version of uc to output. uc is of length len. +// There must be at least utf8LengthFromUtf16(uc, len) bytes in output. +// A null terminator is not written. +static void utf8FromUtf16(char *output, const QChar *uc, int len) +{ + uchar replacement = '?'; + int surrogate_high = -1; + + uchar* cursor = (uchar*)output; + const QChar *ch = uc; + int invalid = 0; + + const QChar *end = ch + len; + while (ch < end) { + uint u = ch->unicode(); + if (surrogate_high >= 0) { + if (u >= 0xdc00 && u < 0xe000) { + u = (surrogate_high - 0xd800)*0x400 + (u - 0xdc00) + 0x10000; + surrogate_high = -1; + } else { + // high surrogate without low + *cursor = replacement; + ++ch; + ++invalid; + surrogate_high = -1; + continue; + } + } else if (u >= 0xdc00 && u < 0xe000) { + // low surrogate without high + *cursor = replacement; + ++ch; + ++invalid; + continue; + } else if (u >= 0xd800 && u < 0xdc00) { + surrogate_high = u; + ++ch; + continue; + } + + if (u < 0x80) { + *cursor++ = (uchar)u; + } else { + if (u < 0x0800) { + *cursor++ = 0xc0 | ((uchar) (u >> 6)); + } else { + // is it one of the Unicode non-characters? + if (isUnicodeNonCharacter(u)) { + *cursor++ = replacement; + ++ch; + ++invalid; + continue; + } + + if (u > 0xffff) { + *cursor++ = 0xf0 | ((uchar) (u >> 18)); + *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f); + } else { + *cursor++ = 0xe0 | (((uchar) (u >> 12)) & 0x3f); + } + *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f); + } + *cursor++ = 0x80 | ((uchar) (u&0x3f)); + } + ++ch; + } +} + +void QHashedStringRef::computeUtf8Length() const +{ + if (m_length) + m_utf8length = utf8LengthFromUtf16(m_data, m_length); + else + m_utf8length = 0; +} + +QHashedStringRef QHashedStringRef::mid(int offset, int length) const +{ + Q_ASSERT(offset < m_length); + return QHashedStringRef(m_data + offset, + (length == -1 || (offset + length) > m_length)?(m_length - offset):length); +} + +bool QHashedStringRef::endsWith(const QString &s) const +{ + return s.length() < m_length && + QHashedString::compare(s.constData(), m_data + m_length - s.length(), s.length()); +} + +bool QHashedStringRef::startsWith(const QString &s) const +{ + return s.length() < m_length && + QHashedString::compare(s.constData(), m_data, s.length()); +} + +QString QHashedStringRef::toString() const +{ + if (m_length == 0) + return QString(); + return QString(m_data, m_length); +} + +QByteArray QHashedStringRef::toUtf8() const +{ + if (m_length == 0) + return QByteArray(); + + QByteArray result; + result.resize(utf8length()); + writeUtf8(result.data()); + return result; +} + +void QHashedStringRef::writeUtf8(char *output) const +{ + if (m_length) { + int ulen = utf8length(); + if (ulen == m_length) { + // Must be a latin1 string + uchar *o = (uchar *)output; + const QChar *c = m_data; + while (ulen--) + *o++ = (uchar)((*c++).unicode()); + } else { + utf8FromUtf16(output, m_data, m_length); + } + } +} + +QString QHashedCStringRef::toUtf16() const +{ + if (m_length == 0) + return QString(); + + QString rv; + rv.resize(m_length); + writeUtf16((uint16_t*)rv.data()); + return rv; +} + diff --git a/src/declarative/qml/ftw/qhashedstring_p.h b/src/declarative/qml/ftw/qhashedstring_p.h new file mode 100644 index 0000000000..f6c7f20d3a --- /dev/null +++ b/src/declarative/qml/ftw/qhashedstring_p.h @@ -0,0 +1,1130 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHASHEDSTRING_P_H +#define QHASHEDSTRING_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtCore/qstring.h> +#include <private/qv8_p.h> + +QT_BEGIN_NAMESPACE + +class QHashedStringRef; +class Q_AUTOTEST_EXPORT QHashedString : public QString +{ +public: + inline QHashedString(); + inline QHashedString(const QString &string); + inline QHashedString(const QString &string, quint32); + inline QHashedString(const QHashedString &string); + + inline QHashedString &operator=(const QHashedString &string); + inline bool operator==(const QHashedString &string) const; + inline bool operator==(const QHashedStringRef &string) const; + + inline quint32 hash() const; + inline quint32 existingHash() const; + + static inline bool isUpper(const QChar &); + + static bool compare(const QChar *lhs, const QChar *rhs, int length); + static inline bool compare(const QChar *lhs, const char *rhs, int length); + static inline bool compare(const char *lhs, const char *rhs, int length); +private: + friend class QHashedStringRef; + friend class QStringHashNode; + + void computeHash() const; + mutable quint32 m_hash; +}; + +class Q_AUTOTEST_EXPORT QHashedV8String +{ +public: + inline QHashedV8String(); + explicit inline QHashedV8String(v8::Handle<v8::String>); + inline QHashedV8String(const QHashedV8String &string); + inline QHashedV8String &operator=(const QHashedV8String &other); + + inline bool operator==(const QHashedV8String &string); + + inline quint32 hash() const; + inline int length() const; + inline quint32 symbolId() const; + + inline v8::Handle<v8::String> string() const; + +private: + v8::String::CompleteHashData m_hash; + v8::Handle<v8::String> m_string; +}; + +class QHashedCStringRef; +class Q_AUTOTEST_EXPORT QHashedStringRef +{ +public: + inline QHashedStringRef(); + inline QHashedStringRef(const QString &); + inline QHashedStringRef(const QStringRef &); + inline QHashedStringRef(const QChar *, int); + inline QHashedStringRef(const QChar *, int, quint32); + inline QHashedStringRef(const QHashedString &); + inline QHashedStringRef(const QHashedStringRef &); + inline QHashedStringRef &operator=(const QHashedStringRef &); + + inline bool operator==(const QString &string) const; + inline bool operator==(const QHashedString &string) const; + inline bool operator==(const QHashedStringRef &string) const; + inline bool operator==(const QHashedCStringRef &string) const; + inline bool operator!=(const QString &string) const; + inline bool operator!=(const QHashedString &string) const; + inline bool operator!=(const QHashedStringRef &string) const; + inline bool operator!=(const QHashedCStringRef &string) const; + + inline quint32 hash() const; + + inline const QChar &at(int) const; + inline const QChar *constData() const; + bool startsWith(const QString &) const; + bool endsWith(const QString &) const; + QHashedStringRef mid(int, int) const; + + inline bool isEmpty() const; + inline int length() const; + inline bool startsWithUpper() const; + + QString toString() const; + + inline int utf8length() const; + QByteArray toUtf8() const; + void writeUtf8(char *) const; +private: + friend class QHashedString; + + void computeHash() const; + void computeUtf8Length() const; + + const QChar *m_data; + int m_length; + mutable int m_utf8length; + mutable quint32 m_hash; +}; + +class Q_AUTOTEST_EXPORT QHashedCStringRef +{ +public: + inline QHashedCStringRef(); + inline QHashedCStringRef(const char *, int); + inline QHashedCStringRef(const char *, int, quint32); + inline QHashedCStringRef(const QHashedCStringRef &); + + inline quint32 hash() const; + + inline const char *constData() const; + inline int length() const; + + QString toUtf16() const; + inline int utf16length() const; + inline void writeUtf16(QChar *) const; + inline void writeUtf16(uint16_t *) const; +private: + friend class QHashedStringRef; + + void computeHash() const; + + const char *m_data; + int m_length; + mutable quint32 m_hash; +}; + +class QStringHashData; +class Q_AUTOTEST_EXPORT QStringHashNode +{ +public: + QStringHashNode() + : nlist(0), next(0), length(0), hash(0), pooled(0), ckey(0), ukey(0), symbolId() + { + } + + QStringHashNode(const QHashedString &key) + : nlist(0), next(0), length(key.length()), hash(key.hash()), pooled(0), ckey(0), key(key), + ukey(key.constData()), symbolId(0) { + } + + QStringHashNode(const QHashedCStringRef &key) + : nlist(0), next(0), length(key.length()), hash(key.hash()), pooled(0), ckey(key.constData()), + ukey(0), symbolId(0) { + } + + QStringHashNode(const QStringHashNode &o) + : nlist(0), next(0), length(o.length), hash(o.hash), pooled(0), ckey(o.ckey), key(o.key), + ukey(o.ukey), symbolId(o.symbolId) { + } + + QStringHashNode *nlist; + QStringHashNode *next; + qint32 length; + quint32 hash; + + quint32 pooled:1; + const char *ckey; + QString key; + const QChar *ukey; + + quint32 symbolId; + + inline bool equals(v8::Handle<v8::String> string) { + return ckey?string->Equals((char*)ckey, length): + string->Equals((uint16_t*)ukey, length); + } + + inline bool symbolEquals(const QHashedV8String &string) { + Q_ASSERT(string.symbolId() != 0); + return length == string.length() && hash == string.hash() && + (string.symbolId() == symbolId || equals(string.string())); + } + + inline bool equals(const QHashedV8String &string) { + return length == string.length() && hash == string.hash() && + equals(string.string()); + } + + inline bool equals(const QHashedStringRef &string) { + return length == string.length() && + hash == string.hash() && + (ckey?(QHashedString::compare(string.constData(), ckey, length)): + (QHashedString::compare(string.constData(), ukey, length))); + } + + inline bool equals(const QHashedCStringRef &string) { + return length == string.length() && + hash == string.hash() && + (ckey?(QHashedString::compare(string.constData(), ckey, length)): + (QHashedString::compare(ukey, string.constData(), length))); + } +}; + +struct Q_AUTOTEST_EXPORT QStringHashData +{ +public: + QStringHashData() + : nodes(0), buckets(0), numBuckets(0), size(0), numBits(0) {} + + QStringHashNode *nodes; + QStringHashNode **buckets; + int numBuckets; + int size; + short numBits; + + void rehashToBits(short); + void rehashToSize(int); + +private: + QStringHashData(const QStringHashData &); + QStringHashData &operator=(const QStringHashData &); +}; + +template<class T, int SmallThreshold = 0> +class Q_AUTOTEST_EXPORT QStringHash +{ +public: + struct Node : public QStringHashNode { + Node(const QHashedString &key, const T &value) : QStringHashNode(key), value(value) {} + Node(const QHashedCStringRef &key, const T &value) : QStringHashNode(key), value(value) {} + Node(const Node &o) : QStringHashNode(o), value(o.value) {} + Node() {} + T value; + }; + struct ReservedNodePool + { + ReservedNodePool() : count(0), used(0), nodes(0) {} + ~ReservedNodePool() { delete [] nodes; } + int count; + int used; + Node *nodes; + }; + + QStringHashData data; + ReservedNodePool *nodePool; + + inline Node *findNode(const QString &) const; + inline Node *findNode(const QHashedString &) const; + inline Node *findNode(const QHashedStringRef &) const; + inline Node *findNode(const QHashedCStringRef &) const; + inline Node *findNode(const QHashedV8String &) const; + inline Node *findSymbolNode(const QHashedV8String &) const; + inline Node *createNode(const QHashedString &, const T &); + inline Node *createNode(const QHashedCStringRef &, const T &); + + inline Node *takeNode(const QHashedString &key, const T &value); + inline Node *takeNode(const QHashedCStringRef &key, const T &value); + inline Node *takeNode(const Node &o); + + inline void copy(const QStringHash<T,SmallThreshold> &); +public: + inline QStringHash(); + inline QStringHash(const QStringHash &); + inline ~QStringHash(); + + QStringHash &operator=(const QStringHash<T,SmallThreshold> &); + + void copyAndReserve(const QStringHash<T,SmallThreshold> &other, int additionalReserve); + + inline bool isEmpty() const; + inline void clear(); + inline int count() const; + + inline void insert(const QString &, const T &); + inline void insert(const QHashedString &, const T &); + inline void insert(const QHashedStringRef &, const T &); + inline void insert(const QHashedCStringRef &, const T &); + + inline T *value(const QString &) const; + inline T *value(const QHashedString &) const; + inline T *value(const QHashedStringRef &) const; + inline T *value(const QHashedV8String &) const; + inline T *value(const QHashedCStringRef &) const; + + inline bool contains(const QString &) const; + inline bool contains(const QHashedString &) const; + inline bool contains(const QHashedStringRef &) const; + inline bool contains(const QHashedCStringRef &) const; + + T &operator[](const QString &); + T &operator[](const QHashedString &); + T &operator[](const QHashedStringRef &); + T &operator[](const QHashedCStringRef &); + + class ConstIterator { + public: + ConstIterator() : n(0) {} + ConstIterator(Node *n) : n(n) {} + + ConstIterator &operator++() { n = (Node *)n->nlist; return *this; } + bool operator==(const ConstIterator &o) const { return n == o.n; } + bool operator!=(const ConstIterator &o) const { return n != o.n; } + + QHashedString key() const { + if (n->ckey) { + return QHashedString(QString::fromLatin1(n->ckey, n->length), n->hash); + } else { + return QHashedString(n->key, n->hash); + } + } + const T &value() const { return n->value; } + const T &operator*() const { return n->value; } + private: + Node *n; + }; + + ConstIterator begin() const { return ConstIterator((Node *)data.nodes); } + ConstIterator end() const { return ConstIterator(); } + + inline void reserve(int); +}; + +template<class T, int SmallThreshold> +QStringHash<T,SmallThreshold>::QStringHash() +: nodePool(0) +{ +} + +template<class T, int SmallThreshold> +QStringHash<T,SmallThreshold>::QStringHash(const QStringHash<T,SmallThreshold> &other) +: nodePool(0) +{ + data.numBits = other.data.numBits; + data.size = other.data.size; + reserve(other.count()); + copy(other); +} + +template<class T, int SmallThreshold> +QStringHash<T,SmallThreshold> &QStringHash<T,SmallThreshold>::operator=(const QStringHash<T,SmallThreshold> &other) +{ + if (&other == this) + return *this; + + clear(); + + data.numBits = other.data.numBits; + data.size = other.data.size; + reserve(other.count()); + copy(other); + + return *this; +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::copyAndReserve(const QStringHash<T,SmallThreshold> &other, int additionalReserve) +{ + clear(); + + data.numBits = other.data.numBits; + data.size = other.data.size;; + reserve(other.count() + additionalReserve); + copy(other); +} + +template<class T, int SmallThreshold> +QStringHash<T,SmallThreshold>::~QStringHash() +{ + clear(); +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::clear() +{ + // If all the nodes were allocated from the node pool, we + // don't need to clean them individually + if (!nodePool || data.size != nodePool->used) { + QStringHashNode *n = data.nodes; + while (n) { + Node *o = (Node *)n; + n = n->nlist; + if (!o->pooled) delete o; + } + } + if (nodePool) delete nodePool; + delete [] data.buckets; + + data.nodes = 0; + data.buckets = 0; + data.numBuckets = 0; + data.numBits = 0; + data.size = 0; + + nodePool = 0; +} + +template<class T, int SmallThreshold> +bool QStringHash<T,SmallThreshold>::isEmpty() const +{ + return data.nodes == 0; +} + +template<class T, int SmallThreshold> +int QStringHash<T,SmallThreshold>::count() const +{ + return data.size; +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::takeNode(const QHashedString &key, const T &value) +{ + if (nodePool && nodePool->used != nodePool->count) { + Node *rv = nodePool->nodes + nodePool->used++; + rv->length = key.length(); + rv->hash = key.hash(); + rv->key = key; + rv->ukey = rv->key.constData(); + rv->pooled = 1; + rv->value = value; + return rv; + } else { + return new Node(key, value); + } +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::takeNode(const QHashedCStringRef &key, const T &value) +{ + if (nodePool && nodePool->used != nodePool->count) { + Node *rv = nodePool->nodes + nodePool->used++; + rv->length = key.length(); + rv->hash = key.hash(); + rv->ckey = key.constData(); + rv->pooled = 1; + rv->value = value; + return rv; + } else { + return new Node(key, value); + } +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::takeNode(const Node &o) +{ + if (nodePool && nodePool->used != nodePool->count) { + Node *rv = nodePool->nodes + nodePool->used++; + rv->length = o.length; + rv->hash = o.hash; + rv->ckey = o.ckey; + rv->key = o.key; + rv->ukey = o.ukey; + rv->pooled = 1; + rv->symbolId = o.symbolId; + rv->value = o.value; + return rv; + } else { + return new Node(o); + } +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::copy(const QStringHash<T,SmallThreshold> &other) +{ + Q_ASSERT(data.nodes == 0); + + if (other.data.size <= SmallThreshold) { + QStringHashNode *n = other.data.nodes; + while (n) { + Node *o = (Node *)n; + Node *mynode = takeNode(*o); + mynode->nlist = data.nodes; + mynode->next = data.nodes; + data.nodes = mynode; + + n = o->nlist; + } + } else { + // Ensure buckets array is created + data.rehashToBits(data.numBits); + + QStringHashNode *n = other.data.nodes; + while (n) { + Node *o = (Node *)n; + Node *mynode = takeNode(*o); + mynode->nlist = data.nodes; + data.nodes = mynode; + + int bucket = mynode->hash % data.numBuckets; + mynode->next = data.buckets[bucket]; + data.buckets[bucket] = mynode; + + n = o->nlist; + } + } +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::createNode(const QHashedString &key, const T &value) +{ + Node *n = takeNode(key, value); + + if (data.size < SmallThreshold) { + + n->nlist = data.nodes; + n->next = data.nodes; + data.nodes = n; + + } else { + if (data.size >= data.numBuckets) + data.rehashToBits(data.numBits + 1); + + n->nlist = data.nodes; + data.nodes = n; + + int bucket = key.hash() % data.numBuckets; + n->next = data.buckets[bucket]; + data.buckets[bucket] = n; + } + + data.size++; + + return n; +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::createNode(const QHashedCStringRef &key, const T &value) +{ + Node *n = takeNode(key, value); + + if (data.size < SmallThreshold) { + + n->nlist = data.nodes; + n->next = data.nodes; + data.nodes = n; + + } else { + if (data.size >= data.numBuckets) + data.rehashToBits(data.numBits + 1); + + n->nlist = data.nodes; + data.nodes = n; + + int bucket = key.hash() % data.numBuckets; + n->next = data.buckets[bucket]; + data.buckets[bucket] = n; + } + + data.size++; + + return n; +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::insert(const QString &key, const T &value) +{ + QHashedStringRef ch(key); + Node *n = findNode(key); + if (n) n->value = value; + else createNode(QHashedString(key, ch.hash()), value); +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::insert(const QHashedString &key, const T &value) +{ + Node *n = findNode(key); + if (n) n->value = value; + else createNode(key, value); +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::insert(const QHashedStringRef &key, const T &value) +{ + Node *n = findNode(key); + if (n) n->value = value; + else createNode(key, value); +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::insert(const QHashedCStringRef &key, const T &value) +{ + Node *n = findNode(key); + if (n) n->value = value; + else createNode(key, value); +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::findNode(const QString &string) const +{ + return findNode(QHashedStringRef(string)); +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::findNode(const QHashedString &string) const +{ + return findNode(QHashedStringRef(string.constData(), string.length(), string.hash())); +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::findNode(const QHashedStringRef &string) const +{ + QStringHashNode *node = (data.size <= SmallThreshold)?data.nodes:data.buckets[string.hash() % data.numBuckets]; + while (node && !node->equals(string)) + node = node->next; + + return (Node *)node; +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::findNode(const QHashedCStringRef &string) const +{ + QStringHashNode *node = (data.size <= SmallThreshold)?data.nodes:data.buckets[string.hash() % data.numBuckets]; + while (node && !node->equals(string)) + node = node->next; + + return (Node *)node; +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::findNode(const QHashedV8String &string) const +{ + QStringHashNode *node = (data.size <= SmallThreshold)?data.nodes:data.buckets[string.hash() % data.numBuckets]; + while (node && !node->equals(string)) + node = node->next; + + return (Node *)node; +} + +template<class T, int SmallThreshold> +typename QStringHash<T,SmallThreshold>::Node *QStringHash<T,SmallThreshold>::findSymbolNode(const QHashedV8String &string) const +{ + Q_ASSERT(string.symbolId() != 0); + + QStringHashNode *node = (data.size <= SmallThreshold)?data.nodes:data.buckets[string.hash() % data.numBuckets]; + while (node && !node->symbolEquals(string)) + node = node->next; + + if (node) + node->symbolId = string.symbolId(); + + return (Node *)node; +} + +template<class T, int SmallThreshold> +T *QStringHash<T,SmallThreshold>::value(const QString &key) const +{ + Node *n = findNode(key); + return n?&n->value:0; +} + +template<class T, int SmallThreshold> +T *QStringHash<T,SmallThreshold>::value(const QHashedString &key) const +{ + Node *n = findNode(key); + return n?&n->value:0; +} + +template<class T, int SmallThreshold> +T *QStringHash<T,SmallThreshold>::value(const QHashedStringRef &key) const +{ + Node *n = findNode(key); + return n?&n->value:0; +} + +template<class T, int SmallThreshold> +T *QStringHash<T,SmallThreshold>::value(const QHashedCStringRef &key) const +{ + Node *n = findNode(key); + return n?&n->value:0; +} + +template<class T, int SmallThreshold> +T *QStringHash<T,SmallThreshold>::value(const QHashedV8String &string) const +{ + Node *n = string.symbolId()?findSymbolNode(string):findNode(string); + return n?&n->value:0; +} + +template<class T, int SmallThreshold> +bool QStringHash<T,SmallThreshold>::contains(const QString &s) const +{ + return 0 != value(s); +} + +template<class T, int SmallThreshold> +bool QStringHash<T,SmallThreshold>::contains(const QHashedString &s) const +{ + return 0 != value(s); +} + +template<class T, int SmallThreshold> +bool QStringHash<T,SmallThreshold>::contains(const QHashedStringRef &s) const +{ + return 0 != value(s); +} + +template<class T, int SmallThreshold> +bool QStringHash<T,SmallThreshold>::contains(const QHashedCStringRef &s) const +{ + return 0 != value(s); +} + +template<class T, int SmallThreshold> +T &QStringHash<T,SmallThreshold>::operator[](const QString &key) +{ + QHashedStringRef cs(key); + Node *n = findNode(cs); + if (n) return n->value; + else return createNode(QHashedString(key, cs.hash()), T())->value; +} + +template<class T, int SmallThreshold> +T &QStringHash<T,SmallThreshold>::operator[](const QHashedString &key) +{ + Node *n = findNode(key); + if (n) return n->value; + else return createNode(key, T())->value; +} + +template<class T, int SmallThreshold> +T &QStringHash<T,SmallThreshold>::operator[](const QHashedStringRef &key) +{ + Node *n = findNode(key); + if (n) return n->value; + else return createNode(key, T())->value; +} + +template<class T, int SmallThreshold> +T &QStringHash<T,SmallThreshold>::operator[](const QHashedCStringRef &key) +{ + Node *n = findNode(key); + if (n) return n->value; + else return createNode(key, T())->value; +} + +template<class T, int SmallThreshold> +void QStringHash<T,SmallThreshold>::reserve(int n) +{ + if (nodePool || 0 == n) + return; + nodePool = new ReservedNodePool; + nodePool->count = n; + nodePool->used = 0; + nodePool->nodes = new Node[n]; + + if (n > SmallThreshold) + data.rehashToSize(n); +} + +inline uint qHash(const QHashedString &string) +{ + return uint(string.hash()); +} + +inline uint qHash(const QHashedStringRef &string) +{ + return uint(string.hash()); +} + +QHashedString::QHashedString() +: QString(), m_hash(0) +{ +} + +QHashedString::QHashedString(const QString &string) +: QString(string), m_hash(0) +{ +} + +QHashedString::QHashedString(const QString &string, quint32 hash) +: QString(string), m_hash(hash) +{ +} + +QHashedString::QHashedString(const QHashedString &string) +: QString(string), m_hash(string.m_hash) +{ +} + +QHashedString &QHashedString::operator=(const QHashedString &string) +{ + static_cast<QString &>(*this) = string; + m_hash = string.m_hash; + return *this; +} + +bool QHashedString::operator==(const QHashedString &string) const +{ + return (string.m_hash == m_hash || !string.m_hash || !m_hash) && + static_cast<const QString &>(*this) == static_cast<const QString &>(string); +} + +bool QHashedString::operator==(const QHashedStringRef &string) const +{ + return length() == string.m_length && + (string.m_hash == m_hash || !string.m_hash || !m_hash) && + QHashedString::compare(constData(), string.m_data, string.m_length); +} + +quint32 QHashedString::hash() const +{ + if (!m_hash) computeHash(); + return m_hash; +} + +quint32 QHashedString::existingHash() const +{ + return m_hash; +} + +bool QHashedString::isUpper(const QChar &qc) +{ + ushort c = qc.unicode(); + // Optimize for _, a-z and A-Z. + return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) && + ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase)); +} + +QHashedV8String::QHashedV8String() +{ +} + +QHashedV8String::QHashedV8String(v8::Handle<v8::String> string) +: m_hash(string->CompleteHash()), m_string(string) +{ + Q_ASSERT(!m_string.IsEmpty()); +} + +QHashedV8String::QHashedV8String(const QHashedV8String &string) +: m_hash(string.m_hash), m_string(string.m_string) +{ +} + +QHashedV8String &QHashedV8String::operator=(const QHashedV8String &other) +{ + m_hash = other.m_hash; + m_string = other.m_string; + return *this; +} + +bool QHashedV8String::operator==(const QHashedV8String &string) +{ + return m_hash.hash == string.m_hash.hash && m_hash.length == string.m_hash.length && + m_string.IsEmpty() == m_string.IsEmpty() && + (m_string.IsEmpty() || m_string->StrictEquals(string.m_string)); +} + +quint32 QHashedV8String::hash() const +{ + return m_hash.hash; +} + +int QHashedV8String::length() const +{ + return m_hash.length; +} + +quint32 QHashedV8String::symbolId() const +{ + return m_hash.symbol_id; +} + +v8::Handle<v8::String> QHashedV8String::string() const +{ + return m_string; +} + +QHashedStringRef::QHashedStringRef() +: m_data(0), m_length(0), m_utf8length(-1), m_hash(0) +{ +} + +QHashedStringRef::QHashedStringRef(const QString &str) +: m_data(str.constData()), m_length(str.length()), m_utf8length(0), m_hash(0) +{ +} + +QHashedStringRef::QHashedStringRef(const QStringRef &str) +: m_data(str.constData()), m_length(str.length()), m_utf8length(0), m_hash(0) +{ +} + +QHashedStringRef::QHashedStringRef(const QChar *data, int length) +: m_data(data), m_length(length), m_utf8length(0), m_hash(0) +{ +} + +QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash) +: m_data(data), m_length(length), m_utf8length(0), m_hash(hash) +{ +} + +QHashedStringRef::QHashedStringRef(const QHashedString &string) +: m_data(string.constData()), m_length(string.length()), m_utf8length(0), m_hash(string.m_hash) +{ +} + +QHashedStringRef::QHashedStringRef(const QHashedStringRef &string) +: m_data(string.m_data), m_length(string.m_length), m_utf8length(string.m_utf8length), + m_hash(string.m_hash) +{ +} + +QHashedStringRef &QHashedStringRef::operator=(const QHashedStringRef &o) +{ + m_data = o.m_data; + m_length = o.m_length; + m_utf8length = o.m_utf8length; + m_hash = o.m_hash; + return *this; +} + +bool QHashedStringRef::operator==(const QString &string) const +{ + return m_length == string.length() && + QHashedString::compare(string.constData(), m_data, m_length); +} + +bool QHashedStringRef::operator==(const QHashedString &string) const +{ + return m_length == string.length() && + (m_hash == string.m_hash || !m_hash || !string.m_hash) && + QHashedString::compare(string.constData(), m_data, m_length); +} + +bool QHashedStringRef::operator==(const QHashedStringRef &string) const +{ + return m_length == string.m_length && + (m_hash == string.m_hash || !m_hash || !string.m_hash) && + QHashedString::compare(string.m_data, m_data, m_length); +} + +bool QHashedStringRef::operator==(const QHashedCStringRef &string) const +{ + return m_length == string.m_length && + (m_hash == string.m_hash || !m_hash || !string.m_hash) && + QHashedString::compare(m_data, string.m_data, m_length); +} + +bool QHashedStringRef::operator!=(const QString &string) const +{ + return m_length != string.length() || + !QHashedString::compare(string.constData(), m_data, m_length); +} + +bool QHashedStringRef::operator!=(const QHashedString &string) const +{ + return m_length != string.length() || + (m_hash != string.m_hash && m_hash && string.m_hash) || + !QHashedString::compare(string.constData(), m_data, m_length); +} + +bool QHashedStringRef::operator!=(const QHashedStringRef &string) const +{ + return m_length != string.m_length || + (m_hash != string.m_hash && m_hash && string.m_hash) || + QHashedString::compare(string.m_data, m_data, m_length); +} + +bool QHashedStringRef::operator!=(const QHashedCStringRef &string) const +{ + return m_length != string.m_length || + (m_hash != string.m_hash && m_hash && string.m_hash) || + QHashedString::compare(m_data, string.m_data, m_length); +} + +const QChar &QHashedStringRef::at(int index) const +{ + Q_ASSERT(index < m_length); + return m_data[index]; +} + +const QChar *QHashedStringRef::constData() const +{ + return m_data; +} + +bool QHashedStringRef::isEmpty() const +{ + return m_length == 0; +} + +int QHashedStringRef::length() const +{ + return m_length; +} + +int QHashedStringRef::utf8length() const +{ + if (m_utf8length < m_length) + computeUtf8Length(); + return m_utf8length; +} + +bool QHashedStringRef::startsWithUpper() const +{ + if (m_length < 1) return false; + return QHashedString::isUpper(m_data[0]); +} + +quint32 QHashedStringRef::hash() const +{ + if (!m_hash) computeHash(); + return m_hash; +} + +QHashedCStringRef::QHashedCStringRef() +: m_data(0), m_length(0), m_hash(0) +{ +} + +QHashedCStringRef::QHashedCStringRef(const char *data, int length) +: m_data(data), m_length(length), m_hash(0) +{ +} + +QHashedCStringRef::QHashedCStringRef(const char *data, int length, quint32 hash) +: m_data(data), m_length(length), m_hash(hash) +{ +} + +QHashedCStringRef::QHashedCStringRef(const QHashedCStringRef &o) +: m_data(o.m_data), m_length(o.m_length), m_hash(o.m_hash) +{ +} + +quint32 QHashedCStringRef::hash() const +{ + if (!m_hash) computeHash(); + return m_hash; +} + +const char *QHashedCStringRef::constData() const +{ + return m_data; +} + +int QHashedCStringRef::length() const +{ + return m_length; +} + +int QHashedCStringRef::utf16length() const +{ + return m_length; +} + +void QHashedCStringRef::writeUtf16(QChar *output) const +{ + writeUtf16((uint16_t *)output); +} + +void QHashedCStringRef::writeUtf16(uint16_t *output) const +{ + int l = m_length; + const char *d = m_data; + while (l--) + *output++ = *d++; +} + +bool QHashedString::compare(const QChar *lhs, const char *rhs, int length) +{ + Q_ASSERT(lhs && rhs); + const quint16 *l = (const quint16*)lhs; + while (length--) + if (*l++ != *rhs++) return false; + return true; +} + +bool QHashedString::compare(const char *lhs, const char *rhs, int length) +{ + Q_ASSERT(lhs && rhs); + return 0 == ::memcmp(lhs, rhs, length); +} + +QT_END_NAMESPACE + +#endif // QHASHEDSTRING_P_H diff --git a/src/declarative/qml/ftw/qhashfield_p.h b/src/declarative/qml/ftw/qhashfield_p.h new file mode 100644 index 0000000000..874626496a --- /dev/null +++ b/src/declarative/qml/ftw/qhashfield_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHASHFIELD_P_H +#define QHASHFIELD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +// QHashField can be used for doing coarse grained set testing, in +// cases where you do not expect the set to contain the item. For +// example where you would write: +// QSet<QString> strings; +// for (int ii = 0; ii < mystrings.count(); ++ii) { +// if (strings.contains(mystrings.at(ii))) +// qFatal("Duplication!"); +// strings.insert(mystrings); +// } +// You may write: +// QHashField strings; +// for (int ii = 0; ii < mystrings.count(); ++ii) { +// if (strings.testAndSet(qHash(mystrings.at(ii)))) { +// // The string *might* be duplicated +// for (int jj = 0; jj < ii; ++jj) { +// if (mystrings.at(ii) == mystrings.at(jj)) +// qFatal("Duplication!"); +// } +// } +// } +// For small lists of things, where the hash is cheap to calculate +// and you don't expect duplication this will be much faster. +class QHashField { +public: + inline QHashField(); + + inline void clear(); + + inline bool test(quint32 hash); + inline bool testAndSet(quint32 hash); +private: + quint32 m_field; +}; + +QHashField::QHashField() +: m_field(0) +{ +} + +void QHashField::clear() +{ + m_field = 0; +} + +bool QHashField::test(quint32 hash) +{ + return m_field & (1 << (hash % 31)); +} + +bool QHashField::testAndSet(quint32 hash) +{ + quint32 mask = 1 << (hash % 31); + bool rv = m_field & mask; + m_field |= mask; + return rv; +} + +QT_END_NAMESPACE + +#endif // QHASHFIELD_P_H diff --git a/src/declarative/qml/qintrusivelist.cpp b/src/declarative/qml/ftw/qintrusivelist.cpp index dabb893e91..dabb893e91 100644 --- a/src/declarative/qml/qintrusivelist.cpp +++ b/src/declarative/qml/ftw/qintrusivelist.cpp diff --git a/src/declarative/qml/qintrusivelist_p.h b/src/declarative/qml/ftw/qintrusivelist_p.h index 717b11c344..717b11c344 100644 --- a/src/declarative/qml/qintrusivelist_p.h +++ b/src/declarative/qml/ftw/qintrusivelist_p.h diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/ftw/qmetaobjectbuilder.cpp index f5e8369ebc..f5e8369ebc 100644 --- a/src/declarative/qml/qmetaobjectbuilder.cpp +++ b/src/declarative/qml/ftw/qmetaobjectbuilder.cpp diff --git a/src/declarative/qml/qmetaobjectbuilder_p.h b/src/declarative/qml/ftw/qmetaobjectbuilder_p.h index a80ba904b6..a80ba904b6 100644 --- a/src/declarative/qml/qmetaobjectbuilder_p.h +++ b/src/declarative/qml/ftw/qmetaobjectbuilder_p.h diff --git a/src/declarative/qml/qpodvector_p.h b/src/declarative/qml/ftw/qpodvector_p.h index 7b50463145..7b50463145 100644 --- a/src/declarative/qml/qpodvector_p.h +++ b/src/declarative/qml/ftw/qpodvector_p.h diff --git a/src/declarative/qml/parser/parser.pri b/src/declarative/qml/parser/parser.pri index fd4361c2df..4f1ff2fd21 100644 --- a/src/declarative/qml/parser/parser.pri +++ b/src/declarative/qml/parser/parser.pri @@ -8,9 +8,9 @@ HEADERS += \ $$PWD/qdeclarativejsgrammar_p.h \ $$PWD/qdeclarativejslexer_p.h \ $$PWD/qdeclarativejsmemorypool_p.h \ - $$PWD/qdeclarativejsnodepool_p.h \ $$PWD/qdeclarativejsparser_p.h \ - $$PWD/qdeclarativejsglobal_p.h + $$PWD/qdeclarativejsglobal_p.h \ + $$PWD/qdeclarativejskeywords_p.h SOURCES += \ $$PWD/qdeclarativejsast.cpp \ diff --git a/src/declarative/qml/parser/qdeclarativejs.g b/src/declarative/qml/parser/qdeclarativejs.g index a57ecba3f9..6487379f06 100644 --- a/src/declarative/qml/parser/qdeclarativejs.g +++ b/src/declarative/qml/parser/qdeclarativejs.g @@ -29,7 +29,7 @@ %token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" %token T_BREAK "break" T_CASE "case" T_CATCH "catch" -%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue" +%token T_COLON ":" T_COMMA "," T_CONTINUE "continue" %token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/" %token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "." %token T_ELSE "else" T_EQ "=" T_EQ_EQ "==" @@ -67,6 +67,8 @@ %token T_AS "as" %token T_ON "on" +%token T_ERROR + --- feed tokens %token T_FEED_UI_PROGRAM %token T_FEED_UI_OBJECT_MEMBER @@ -130,7 +132,7 @@ #include "qdeclarativejsengine_p.h" #include "qdeclarativejslexer_p.h" #include "qdeclarativejsast_p.h" -#include "qdeclarativejsnodepool_p.h" +#include "qdeclarativejsmemorypool_p.h" ./ @@ -208,7 +210,6 @@ QT_QML_BEGIN_NAMESPACE namespace QDeclarativeJS { class Engine; -class NameId; class QML_PARSER_EXPORT Parser: protected $table { @@ -216,7 +217,6 @@ public: union Value { int ival; double dval; - NameId *sval; AST::ArgumentList *ArgumentList; AST::CaseBlock *CaseBlock; AST::CaseClause *CaseClause; @@ -332,6 +332,9 @@ protected: inline Value &sym(int index) { return sym_stack [tos + index - 1]; } + inline QStringRef &stringRef(int index) + { return string_stack [tos + index - 1]; } + inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } @@ -339,11 +342,13 @@ protected: protected: Engine *driver; + MemoryPool *pool; int tos; int stack_size; Value *sym_stack; int *state_stack; AST::SourceLocation *location_stack; + QStringRef *string_stack; AST::Node *program; @@ -354,9 +359,11 @@ protected: int token; double dval; AST::SourceLocation loc; + QStringRef spell; }; double yylval; + QStringRef yytokenspell; AST::SourceLocation yylloc; AST::SourceLocation yyprevlloc; @@ -397,6 +404,7 @@ void Parser::reallocateStack() sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int))); location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); + string_stack = reinterpret_cast<QStringRef*> (qRealloc(string_stack, stack_size * sizeof(QStringRef))); } inline static bool automatic(Engine *driver, int token) @@ -409,11 +417,13 @@ inline static bool automatic(Engine *driver, int token) Parser::Parser(Engine *engine): driver(engine), + pool(engine->pool()), tos(0), stack_size(0), sym_stack(0), state_stack(0), location_stack(0), + string_stack(0), first_token(0), last_token(0) { @@ -425,6 +435,7 @@ Parser::~Parser() qFree(sym_stack); qFree(state_stack); qFree(location_stack); + qFree(string_stack); } } @@ -433,14 +444,14 @@ static inline AST::SourceLocation location(Lexer *lexer) AST::SourceLocation loc; loc.offset = lexer->tokenOffset(); loc.length = lexer->tokenLength(); - loc.startLine = lexer->startLineNo(); - loc.startColumn = lexer->startColumnNo(); + loc.startLine = lexer->tokenStartLine(); + loc.startColumn = lexer->tokenStartColumn(); return loc; } AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { - QVarLengthArray<NameId *, 4> nameIds; + QVarLengthArray<QStringRef, 4> nameIds; QVarLengthArray<AST::SourceLocation, 4> locations; AST::ExpressionNode *it = expr; @@ -451,12 +462,12 @@ AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) } if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) { - AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name); + AST::UiQualifiedId *q = new (pool) AST::UiQualifiedId(idExpr->name); q->identifierToken = idExpr->identifierToken; AST::UiQualifiedId *currentId = q; for (int i = nameIds.size() - 1; i != -1; --i) { - currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]); + currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); currentId->identifierToken = locations[i]; } @@ -492,11 +503,13 @@ bool Parser::parse(int startToken) if (first_token == last_token) { yytoken = lexer->lex(); - yylval = lexer->dval(); + yylval = lexer->tokenValue(); + yytokenspell = lexer->tokenSpell(); yylloc = location(lexer); } else { yytoken = first_token->token; yylval = first_token->dval; + yytokenspell = first_token->spell; yylloc = first_token->loc; ++first_token; } @@ -507,6 +520,7 @@ bool Parser::parse(int startToken) if (action != ACCEPT_STATE) { yytoken = -1; sym(1).dval = yylval; + stringRef(1) = yytokenspell; loc(1) = yylloc; } else { --tos; @@ -574,7 +588,7 @@ case $rule_number: { UiProgram: UiImportListOpt UiRootMember ; /. case $rule_number: { - sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList, + sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); } break; ./ @@ -590,15 +604,14 @@ case $rule_number: { UiImportList: UiImport ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport); + sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImport); } break; ./ UiImportList: UiImportList UiImport ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), - sym(1).UiImportList, sym(2).UiImport); + sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImportList, sym(2).UiImport); } break; ./ @@ -628,7 +641,7 @@ case $rule_number: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->asToken = loc(3); sym(1).UiImport->importIdToken = loc(4); - sym(1).UiImport->importId = sym(4).sval; + sym(1).UiImport->importId = stringRef(4); sym(1).UiImport->semicolonToken = loc(5); } break; ./ @@ -639,7 +652,7 @@ UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ; case $rule_number: { sym(1).UiImport->asToken = loc(2); sym(1).UiImport->importIdToken = loc(3); - sym(1).UiImport->importId = sym(3).sval; + sym(1).UiImport->importId = stringRef(3); sym(1).UiImport->semicolonToken = loc(4); } break; ./ @@ -651,10 +664,10 @@ case $rule_number: { AST::UiImport *node = 0; if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { - node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value); + node = new (pool) AST::UiImport(importIdLiteral->value); node->fileNameToken = loc(2); } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { - node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId); + node = new (pool) AST::UiImport(qualifiedId); node->fileNameToken = loc(2); } @@ -681,21 +694,21 @@ case $rule_number: { UiRootMember: UiObjectDefinition ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ UiObjectMemberList: UiObjectMember ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ UiObjectMemberList: UiObjectMemberList UiObjectMember ; /. case $rule_number: { - AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(), + AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList( sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; @@ -704,14 +717,14 @@ case $rule_number: { UiArrayMemberList: UiObjectDefinition ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); } break; ./ UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; /. case $rule_number: { - AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), + AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList( sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; @@ -721,7 +734,7 @@ case $rule_number: { UiObjectInitializer: T_LBRACE T_RBRACE ; /. case $rule_number: { - AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0); + AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; @@ -731,7 +744,7 @@ case $rule_number: { UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ; /. case $rule_number: { - AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish()); + AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; @@ -741,7 +754,7 @@ case $rule_number: { UiObjectDefinition: UiQualifiedId UiObjectInitializer ; /. case $rule_number: { - AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId, + AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); sym(1).Node = node; } break; @@ -752,7 +765,7 @@ UiObjectMember: UiObjectDefinition ; UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; /. case $rule_number: { - AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), + AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding( sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); @@ -764,7 +777,7 @@ case $rule_number: { UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { - AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); sym(1).Node = node; @@ -774,7 +787,7 @@ case $rule_number: { UiObjectMember: UiQualifiedId T_ON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { - AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); node->hasOnToken = true; @@ -791,7 +804,7 @@ UiObjectMember: UiQualifiedId T_COLON UiScriptStatement ; /. case $rule_number: { - AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), + AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding( sym(1).UiQualifiedId, sym(3).Statement); node->colonToken = loc(2); sym(1).Node = node; @@ -799,17 +812,7 @@ case $rule_number: ./ UiPropertyType: T_VAR ; -/. -case $rule_number: -./ UiPropertyType: T_RESERVED_WORD ; -/. -case $rule_number: { - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); - break; -} -./ - UiPropertyType: T_IDENTIFIER ; UiParameterListOpt: ; @@ -829,7 +832,7 @@ case $rule_number: { UiParameterList: UiPropertyType JsIdentifier ; /. case $rule_number: { - AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval); + AST::UiParameterList *node = new (pool) AST::UiParameterList(stringRef(1), stringRef(2)); node->identifierToken = loc(2); sym(1).Node = node; } break; @@ -838,7 +841,7 @@ case $rule_number: { UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ; /. case $rule_number: { - AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); + AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, stringRef(3), stringRef(4)); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; @@ -849,7 +852,7 @@ UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUT UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); @@ -864,7 +867,7 @@ UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); @@ -878,8 +881,8 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_SEMICOLON ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval); - node->typeModifier = sym(2).sval; + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); + node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); @@ -893,7 +896,7 @@ UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); @@ -906,7 +909,7 @@ UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEM UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); @@ -920,7 +923,7 @@ case $rule_number: { UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval, + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3), sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -933,7 +936,7 @@ case $rule_number: { UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); @@ -948,7 +951,7 @@ case $rule_number: { UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); @@ -963,19 +966,19 @@ case $rule_number: { UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval); - node->typeModifier = sym(2).sval; + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); + node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); // insert a fake ';' before ':' - AST::UiQualifiedId *propertyName = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), sym(6).sval); + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); propertyName->identifierToken = loc(6); propertyName->next = 0; - AST::UiArrayBinding *binding = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), + AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding( propertyName, sym(9).UiArrayMemberList->finish()); binding->colonToken = loc(7); binding->lbracketToken = loc(8); @@ -990,17 +993,17 @@ case $rule_number: { UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); // insert a fake ';' before ':' - AST::UiQualifiedId *propertyName = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), sym(3).sval); + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); propertyName->identifierToken = loc(3); propertyName->next = 0; - AST::UiObjectBinding *binding = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); binding->colonToken = loc(4); @@ -1013,54 +1016,23 @@ case $rule_number: { UiObjectMember: FunctionDeclaration ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; ./ UiObjectMember: VariableStatement ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; ./ JsIdentifier: T_IDENTIFIER; JsIdentifier: T_PROPERTY ; -/. -case $rule_number: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_PROPERTY]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} -./ - JsIdentifier: T_SIGNAL ; -/. -case $rule_number: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_SIGNAL]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} -./ - JsIdentifier: T_READONLY ; -/. -case $rule_number: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_READONLY]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} -./ - JsIdentifier: T_ON ; -/. -case $rule_number: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_ON]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} -./ -------------------------------------------------------------------------------------------------------- -- Expressions @@ -1069,7 +1041,7 @@ case $rule_number: { PrimaryExpression: T_THIS ; /. case $rule_number: { - AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool()); + AST::ThisExpression *node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; @@ -1078,7 +1050,7 @@ case $rule_number: { PrimaryExpression: JsIdentifier ; /. case $rule_number: { - AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval); + AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; @@ -1087,7 +1059,7 @@ case $rule_number: { PrimaryExpression: T_NULL ; /. case $rule_number: { - AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool()); + AST::NullExpression *node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; @@ -1096,7 +1068,7 @@ case $rule_number: { PrimaryExpression: T_TRUE ; /. case $rule_number: { - AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool()); + AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; @@ -1105,7 +1077,7 @@ case $rule_number: { PrimaryExpression: T_FALSE ; /. case $rule_number: { - AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool()); + AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; @@ -1114,7 +1086,7 @@ case $rule_number: { PrimaryExpression: T_NUMERIC_LITERAL ; /. case $rule_number: { - AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval); + AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; @@ -1126,7 +1098,7 @@ PrimaryExpression: T_MULTILINE_STRING_LITERAL ; PrimaryExpression: T_STRING_LITERAL ; /. case $rule_number: { - AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval); + AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; @@ -1146,7 +1118,8 @@ case $rule_number: { loc(1).length = lexer->tokenLength(); - AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( + driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; @@ -1166,7 +1139,8 @@ case $rule_number: { loc(1).length = lexer->tokenLength(); - AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( + driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; @@ -1175,7 +1149,7 @@ case $rule_number: { PrimaryExpression: T_LBRACKET T_RBRACKET ; /. case $rule_number: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0); + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; @@ -1185,7 +1159,7 @@ case $rule_number: { PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; /. case $rule_number: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish()); + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; @@ -1195,7 +1169,7 @@ case $rule_number: { PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ; /. case $rule_number: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ()); + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; @@ -1205,7 +1179,7 @@ case $rule_number: { PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; /. case $rule_number: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); node->commaToken = loc(3); @@ -1217,7 +1191,7 @@ case $rule_number: { PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; /. case $rule_number: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); @@ -1229,7 +1203,7 @@ case $rule_number: { -- PrimaryExpression: T_LBRACE T_RBRACE ; -- /. -- case $rule_number: { --- sym(1).Node = makeAstNode<AST::ObjectLiteral> (driver->nodePool()); +-- sym(1).Node = new (pool) AST::ObjectLiteral(); -- } break; -- ./ @@ -1238,10 +1212,10 @@ PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ; case $rule_number: { AST::ObjectLiteral *node = 0; if (sym(2).Node) - node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); else - node = makeAstNode<AST::ObjectLiteral> (driver->nodePool()); + node = new (pool) AST::ObjectLiteral(); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; @@ -1251,7 +1225,7 @@ case $rule_number: { PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ; /. case $rule_number: { - AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); node->rbraceToken = loc(4); @@ -1262,7 +1236,7 @@ case $rule_number: { PrimaryExpression: T_LPAREN Expression T_RPAREN ; /. case $rule_number: { - AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression); + AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; @@ -1295,21 +1269,21 @@ case $rule_number: { ElementList: AssignmentExpression ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); + sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; ./ ElementList: Elision AssignmentExpression ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); + sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; ./ ElementList: ElementList T_COMMA AssignmentExpression ; /. case $rule_number: { - AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, + AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; @@ -1319,7 +1293,7 @@ case $rule_number: { ElementList: ElementList T_COMMA Elision AssignmentExpression ; /. case $rule_number: { - AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), + AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; @@ -1329,7 +1303,7 @@ case $rule_number: { Elision: T_COMMA ; /. case $rule_number: { - AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); + AST::Elision *node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; @@ -1338,7 +1312,7 @@ case $rule_number: { Elision: Elision T_COMMA ; /. case $rule_number: { - AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); + AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; @@ -1347,7 +1321,7 @@ case $rule_number: { PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ; /. case $rule_number: { - AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; @@ -1357,7 +1331,7 @@ case $rule_number: { PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ; /. case $rule_number: { - AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); @@ -1368,7 +1342,7 @@ case $rule_number: { PropertyName: T_IDENTIFIER %prec SHIFT_THERE ; /. case $rule_number: { - AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; @@ -1380,7 +1354,7 @@ PropertyName: T_SIGNAL ; PropertyName: T_PROPERTY ; /. case $rule_number: { - AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; @@ -1389,7 +1363,7 @@ case $rule_number: { PropertyName: T_STRING_LITERAL ; /. case $rule_number: { - AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); + AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; @@ -1398,7 +1372,7 @@ case $rule_number: { PropertyName: T_NUMERIC_LITERAL ; /. case $rule_number: { - AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); + AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; @@ -1407,139 +1381,43 @@ case $rule_number: { PropertyName: ReservedIdentifier ; /. case $rule_number: { - AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ ReservedIdentifier: T_BREAK ; -/. -case $rule_number: -./ ReservedIdentifier: T_CASE ; -/. -case $rule_number: -./ ReservedIdentifier: T_CATCH ; -/. -case $rule_number: -./ ReservedIdentifier: T_CONTINUE ; -/. -case $rule_number: -./ ReservedIdentifier: T_DEFAULT ; -/. -case $rule_number: -./ ReservedIdentifier: T_DELETE ; -/. -case $rule_number: -./ ReservedIdentifier: T_DO ; -/. -case $rule_number: -./ ReservedIdentifier: T_ELSE ; -/. -case $rule_number: -./ ReservedIdentifier: T_FALSE ; -/. -case $rule_number: -./ ReservedIdentifier: T_FINALLY ; -/. -case $rule_number: -./ ReservedIdentifier: T_FOR ; -/. -case $rule_number: -./ ReservedIdentifier: T_FUNCTION ; -/. -case $rule_number: -./ ReservedIdentifier: T_IF ; -/. -case $rule_number: -./ ReservedIdentifier: T_IN ; -/. -case $rule_number: -./ ReservedIdentifier: T_INSTANCEOF ; -/. -case $rule_number: -./ ReservedIdentifier: T_NEW ; -/. -case $rule_number: -./ ReservedIdentifier: T_NULL ; -/. -case $rule_number: -./ ReservedIdentifier: T_RETURN ; -/. -case $rule_number: -./ ReservedIdentifier: T_SWITCH ; -/. -case $rule_number: -./ ReservedIdentifier: T_THIS ; -/. -case $rule_number: -./ ReservedIdentifier: T_THROW ; -/. -case $rule_number: -./ ReservedIdentifier: T_TRUE ; -/. -case $rule_number: -./ ReservedIdentifier: T_TRY ; -/. -case $rule_number: -./ ReservedIdentifier: T_TYPEOF ; -/. -case $rule_number: -./ ReservedIdentifier: T_VAR ; -/. -case $rule_number: -./ ReservedIdentifier: T_VOID ; -/. -case $rule_number: -./ ReservedIdentifier: T_WHILE ; -/. -case $rule_number: -./ ReservedIdentifier: T_CONST ; -/. -case $rule_number: -./ ReservedIdentifier: T_DEBUGGER ; -/. -case $rule_number: -./ ReservedIdentifier: T_RESERVED_WORD ; -/. -case $rule_number: -./ ReservedIdentifier: T_WITH ; -/. -case $rule_number: -{ - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); -} break; -./ PropertyIdentifier: JsIdentifier ; PropertyIdentifier: ReservedIdentifier ; @@ -1550,7 +1428,7 @@ MemberExpression: FunctionExpression ; MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ; /. case $rule_number: { - AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; @@ -1560,7 +1438,7 @@ case $rule_number: { MemberExpression: MemberExpression T_DOT PropertyIdentifier ; /. case $rule_number: { - AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; @@ -1570,7 +1448,7 @@ case $rule_number: { MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { - AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); + AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); node->rparenToken = loc(5); @@ -1583,7 +1461,7 @@ NewExpression: MemberExpression ; NewExpression: T_NEW NewExpression ; /. case $rule_number: { - AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression); + AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; @@ -1592,7 +1470,7 @@ case $rule_number: { CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { - AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; @@ -1602,7 +1480,7 @@ case $rule_number: { CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { - AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; @@ -1612,7 +1490,7 @@ case $rule_number: { CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ; /. case $rule_number: { - AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; @@ -1622,7 +1500,7 @@ case $rule_number: { CallExpression: CallExpression T_DOT PropertyIdentifier ; /. case $rule_number: { - AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; @@ -1646,14 +1524,14 @@ case $rule_number: { ArgumentList: AssignmentExpression ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression); + sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; ./ ArgumentList: ArgumentList T_COMMA AssignmentExpression ; /. case $rule_number: { - AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); + AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; @@ -1666,7 +1544,7 @@ PostfixExpression: LeftHandSideExpression ; PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ; /. case $rule_number: { - AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression); + AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; @@ -1675,7 +1553,7 @@ case $rule_number: { PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ; /. case $rule_number: { - AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression); + AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; @@ -1686,7 +1564,7 @@ UnaryExpression: PostfixExpression ; UnaryExpression: T_DELETE UnaryExpression ; /. case $rule_number: { - AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression); + AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; @@ -1695,7 +1573,7 @@ case $rule_number: { UnaryExpression: T_VOID UnaryExpression ; /. case $rule_number: { - AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression); + AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; @@ -1704,7 +1582,7 @@ case $rule_number: { UnaryExpression: T_TYPEOF UnaryExpression ; /. case $rule_number: { - AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression); + AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; @@ -1713,7 +1591,7 @@ case $rule_number: { UnaryExpression: T_PLUS_PLUS UnaryExpression ; /. case $rule_number: { - AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression); + AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; @@ -1722,7 +1600,7 @@ case $rule_number: { UnaryExpression: T_MINUS_MINUS UnaryExpression ; /. case $rule_number: { - AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression); + AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; @@ -1731,7 +1609,7 @@ case $rule_number: { UnaryExpression: T_PLUS UnaryExpression ; /. case $rule_number: { - AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression); + AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; @@ -1740,7 +1618,7 @@ case $rule_number: { UnaryExpression: T_MINUS UnaryExpression ; /. case $rule_number: { - AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression); + AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; @@ -1749,7 +1627,7 @@ case $rule_number: { UnaryExpression: T_TILDE UnaryExpression ; /. case $rule_number: { - AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression); + AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; @@ -1758,7 +1636,7 @@ case $rule_number: { UnaryExpression: T_NOT UnaryExpression ; /. case $rule_number: { - AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression); + AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; @@ -1769,7 +1647,7 @@ MultiplicativeExpression: UnaryExpression ; MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1779,7 +1657,7 @@ case $rule_number: { MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1789,7 +1667,7 @@ case $rule_number: { MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1801,7 +1679,7 @@ AdditiveExpression: MultiplicativeExpression ; AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1811,7 +1689,7 @@ case $rule_number: { AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1823,7 +1701,7 @@ ShiftExpression: AdditiveExpression ; ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1833,7 +1711,7 @@ case $rule_number: { ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1843,7 +1721,7 @@ case $rule_number: { ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1855,7 +1733,7 @@ RelationalExpression: ShiftExpression ; RelationalExpression: RelationalExpression T_LT ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1865,7 +1743,7 @@ case $rule_number: { RelationalExpression: RelationalExpression T_GT ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1875,7 +1753,7 @@ case $rule_number: { RelationalExpression: RelationalExpression T_LE ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1885,7 +1763,7 @@ case $rule_number: { RelationalExpression: RelationalExpression T_GE ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1895,7 +1773,7 @@ case $rule_number: { RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1905,7 +1783,7 @@ case $rule_number: { RelationalExpression: RelationalExpression T_IN ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1917,7 +1795,7 @@ RelationalExpressionNotIn: ShiftExpression ; RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1927,7 +1805,7 @@ case $rule_number: { RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1937,7 +1815,7 @@ case $rule_number: { RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1947,7 +1825,7 @@ case $rule_number: { RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1957,7 +1835,7 @@ case $rule_number: { RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1969,7 +1847,7 @@ EqualityExpression: RelationalExpression ; EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1979,7 +1857,7 @@ case $rule_number: { EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1989,7 +1867,7 @@ case $rule_number: { EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1999,7 +1877,7 @@ case $rule_number: { EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2011,7 +1889,7 @@ EqualityExpressionNotIn: RelationalExpressionNotIn ; EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2021,7 +1899,7 @@ case $rule_number: { EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2031,7 +1909,7 @@ case $rule_number: { EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2041,7 +1919,7 @@ case $rule_number: { EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2053,7 +1931,7 @@ BitwiseANDExpression: EqualityExpression ; BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2065,7 +1943,7 @@ BitwiseANDExpressionNotIn: EqualityExpressionNotIn ; BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2077,7 +1955,7 @@ BitwiseXORExpression: BitwiseANDExpression ; BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2089,7 +1967,7 @@ BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ; BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2101,7 +1979,7 @@ BitwiseORExpression: BitwiseXORExpression ; BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2113,7 +1991,7 @@ BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ; BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2125,7 +2003,7 @@ LogicalANDExpression: BitwiseORExpression ; LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2137,7 +2015,7 @@ LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ; LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2149,7 +2027,7 @@ LogicalORExpression: LogicalANDExpression ; LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2161,7 +2039,7 @@ LogicalORExpressionNotIn: LogicalANDExpressionNotIn ; LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2173,7 +2051,7 @@ ConditionalExpression: LogicalORExpression ; ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ; /. case $rule_number: { - AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); @@ -2186,7 +2064,7 @@ ConditionalExpressionNotIn: LogicalORExpressionNotIn ; ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ; /. case $rule_number: { - AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); @@ -2199,7 +2077,7 @@ AssignmentExpression: ConditionalExpression ; AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2211,7 +2089,7 @@ AssignmentExpressionNotIn: ConditionalExpressionNotIn ; AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ; /. case $rule_number: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -2307,7 +2185,7 @@ Expression: AssignmentExpression ; Expression: Expression T_COMMA AssignmentExpression ; /. case $rule_number: { - AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; @@ -2327,7 +2205,7 @@ ExpressionNotIn: AssignmentExpressionNotIn ; ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ; /. case $rule_number: { - AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; @@ -2362,7 +2240,7 @@ Statement: DebuggerStatement ; Block: T_LBRACE StatementListOpt T_RBRACE ; /. case $rule_number: { - AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList); + AST::Block *node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; @@ -2372,14 +2250,14 @@ case $rule_number: { StatementList: Statement ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement); + sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; ./ StatementList: StatementList Statement ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement); + sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; ./ @@ -2401,7 +2279,7 @@ VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_S VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ; /. case $rule_number: { - AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(), + AST::VariableStatement *node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); node->semicolonToken = loc(3); @@ -2426,14 +2304,14 @@ case $rule_number: { VariableDeclarationList: VariableDeclaration ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; ./ VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ; /. case $rule_number: { - AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), + AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; @@ -2443,21 +2321,21 @@ case $rule_number: { VariableDeclarationListNotIn: VariableDeclarationNotIn ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; ./ VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; ./ VariableDeclaration: JsIdentifier InitialiserOpt ; /. case $rule_number: { - AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; @@ -2466,7 +2344,7 @@ case $rule_number: { VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ; /. case $rule_number: { - AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; @@ -2509,7 +2387,7 @@ InitialiserNotInOpt: InitialiserNotIn ; EmptyStatement: T_SEMICOLON ; /. case $rule_number: { - AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool()); + AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; @@ -2519,7 +2397,7 @@ ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ExpressionStatement: Expression T_SEMICOLON ; /. case $rule_number: { - AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); + AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; @@ -2528,11 +2406,11 @@ case $rule_number: { IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ; /. case $rule_number: { - AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); + AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); - node->elseToken = loc(5); + node->elseToken = loc(6); sym(1).Node = node; } break; ./ @@ -2540,7 +2418,7 @@ case $rule_number: { IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { - AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -2553,7 +2431,7 @@ IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMA IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ; /. case $rule_number: { - AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression); + AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); node->lparenToken = loc(4); @@ -2566,7 +2444,7 @@ case $rule_number: { IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { - AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -2577,7 +2455,7 @@ case $rule_number: { IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; /. case $rule_number: { - AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression, + AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); node->lparenToken = loc(2); @@ -2591,7 +2469,7 @@ case $rule_number: { IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; /. case $rule_number: { - AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(), + AST::LocalForStatement *node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); node->forToken = loc(1); @@ -2607,7 +2485,7 @@ case $rule_number: { IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ; /. case $rule_number: { - AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression, + AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); node->lparenToken = loc(2); @@ -2620,7 +2498,7 @@ case $rule_number: { IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ; /. case $rule_number: { - AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(), + AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); node->lparenToken = loc(2); @@ -2635,7 +2513,7 @@ ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ContinueStatement: T_CONTINUE T_SEMICOLON ; /. case $rule_number: { - AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool()); + AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; @@ -2646,7 +2524,7 @@ ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ; /. case $rule_number: { - AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval); + AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); @@ -2658,7 +2536,7 @@ BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon BreakStatement: T_BREAK T_SEMICOLON ; /. case $rule_number: { - AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool()); + AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; @@ -2669,7 +2547,7 @@ BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semic BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ; /. case $rule_number: { - AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval); + AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); @@ -2681,7 +2559,7 @@ ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic se ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ; /. case $rule_number: { - AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression); + AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; @@ -2691,7 +2569,7 @@ case $rule_number: { WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { - AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -2702,7 +2580,7 @@ case $rule_number: { SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ; /. case $rule_number: { - AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); + AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -2713,7 +2591,7 @@ case $rule_number: { CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ; /. case $rule_number: { - AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses); + AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; @@ -2723,7 +2601,7 @@ case $rule_number: { CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ; /. case $rule_number: { - AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); + AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; @@ -2733,14 +2611,14 @@ case $rule_number: { CaseClauses: CaseClause ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause); + sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; ./ CaseClauses: CaseClauses CaseClause ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); + sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; ./ @@ -2761,7 +2639,7 @@ case $rule_number: { CaseClause: T_CASE Expression T_COLON StatementListOpt ; /. case $rule_number: { - AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList); + AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; @@ -2771,7 +2649,7 @@ case $rule_number: { DefaultClause: T_DEFAULT T_COLON StatementListOpt ; /. case $rule_number: { - AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList); + AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; @@ -2784,7 +2662,7 @@ LabelledStatement: T_SIGNAL T_COLON Statement ; LabelledStatement: T_PROPERTY T_COLON Statement ; /. case $rule_number: { - AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); + AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; @@ -2794,7 +2672,7 @@ case $rule_number: { LabelledStatement: T_IDENTIFIER T_COLON Statement ; /. case $rule_number: { - AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement); + AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; @@ -2805,7 +2683,7 @@ ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicol ThrowStatement: T_THROW Expression T_SEMICOLON ; /. case $rule_number: { - AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression); + AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; @@ -2815,7 +2693,7 @@ case $rule_number: { TryStatement: T_TRY Block Catch ; /. case $rule_number: { - AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch); + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; @@ -2824,7 +2702,7 @@ case $rule_number: { TryStatement: T_TRY Block Finally ; /. case $rule_number: { - AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally); + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; @@ -2833,7 +2711,7 @@ case $rule_number: { TryStatement: T_TRY Block Catch Finally ; /. case $rule_number: { - AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; @@ -2842,7 +2720,7 @@ case $rule_number: { Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ; /. case $rule_number: { - AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block); + AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); node->identifierToken = loc(3); @@ -2854,7 +2732,7 @@ case $rule_number: { Finally: T_FINALLY Block ; /. case $rule_number: { - AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block); + AST::Finally *node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; @@ -2864,7 +2742,7 @@ DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon DebuggerStatement: T_DEBUGGER T_SEMICOLON ; /. case $rule_number: { - AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool()); + AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; @@ -2874,7 +2752,7 @@ case $rule_number: { FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; /. case $rule_number: { - AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); node->lparenToken = loc(3); @@ -2888,9 +2766,9 @@ case $rule_number: { FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; /. case $rule_number: { - AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); - if (sym(2).sval) + if (! stringRef(2).isNull()) node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); @@ -2903,7 +2781,7 @@ case $rule_number: { FormalParameterList: JsIdentifier ; /. case $rule_number: { - AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval); + AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; @@ -2912,7 +2790,7 @@ case $rule_number: { FormalParameterList: FormalParameterList T_COMMA JsIdentifier ; /. case $rule_number: { - AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); + AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; @@ -2945,49 +2823,49 @@ FunctionBodyOpt: FunctionBody ; FunctionBody: SourceElements ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ()); + sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; ./ Program: SourceElements ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ()); + sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; ./ SourceElements: SourceElement ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement); + sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; ./ SourceElements: SourceElements SourceElement ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); + sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; ./ SourceElement: Statement ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement); + sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; ./ SourceElement: FunctionDeclaration ; /. case $rule_number: { - sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration); + sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; ./ IdentifierOpt: ; /. case $rule_number: { - sym(1).sval = 0; + stringRef(1) = QStringRef(); } break; ./ @@ -3016,6 +2894,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; + tk.spell = yytokenspell; tk.loc = yylloc; yylloc = yyprevlloc; @@ -3041,11 +2920,13 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; token_buffer[0].token = yytoken; token_buffer[0].dval = yylval; + token_buffer[0].spell = yytokenspell; token_buffer[0].loc = yylloc; - token_buffer[1].token = yytoken = lexer->lex(); - token_buffer[1].dval = yylval = lexer->dval(); - token_buffer[1].loc = yylloc = location(lexer); + token_buffer[1].token = yytoken = lexer->lex(); + token_buffer[1].dval = yylval = lexer->tokenValue(); + token_buffer[1].spell = yytokenspell = lexer->tokenSpell(); + token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { QString msg; diff --git a/src/declarative/qml/parser/qdeclarativejsast_p.h b/src/declarative/qml/parser/qdeclarativejsast_p.h index 0fc989c333..b2c441d37b 100644 --- a/src/declarative/qml/parser/qdeclarativejsast_p.h +++ b/src/declarative/qml/parser/qdeclarativejsast_p.h @@ -55,6 +55,7 @@ #include "qdeclarativejsastvisitor_p.h" #include "qdeclarativejsglobal_p.h" +#include "qdeclarativejsmemorypool_p.h" #include <QtCore/QString> @@ -107,7 +108,7 @@ enum Op { } // namespace QSOperator namespace QDeclarativeJS { -class NameId; + namespace AST { template <typename _T1, typename _T2> @@ -119,7 +120,7 @@ _T1 cast(_T2 *ast) return 0; } -class QML_PARSER_EXPORT Node +class QML_PARSER_EXPORT Node: public Managed { public: enum Kind { @@ -273,7 +274,7 @@ class QML_PARSER_EXPORT UiFormal: public Node public: QDECLARATIVEJS_DECLARE_AST_NODE(UiFormal) - UiFormal(NameId *name, NameId *alias = 0) + UiFormal(const QStringRef &name, const QStringRef &alias) : name(name), alias(alias) { } @@ -286,8 +287,8 @@ public: virtual void accept0(Visitor *visitor); // attributes - NameId *name; - NameId *alias; + QStringRef name; + QStringRef alias; SourceLocation identifierToken; SourceLocation asToken; SourceLocation aliasToken; @@ -398,7 +399,7 @@ class QML_PARSER_EXPORT IdentifierExpression: public ExpressionNode public: QDECLARATIVEJS_DECLARE_AST_NODE(IdentifierExpression) - IdentifierExpression(NameId *n): + IdentifierExpression(const QStringRef &n): name (n) { kind = K; } virtual void accept0(Visitor *visitor); @@ -410,7 +411,7 @@ public: { return identifierToken; } // attributes - NameId *name; + QStringRef name; SourceLocation identifierToken; }; @@ -497,7 +498,7 @@ class QML_PARSER_EXPORT StringLiteral: public ExpressionNode public: QDECLARATIVEJS_DECLARE_AST_NODE(StringLiteral) - StringLiteral(NameId *v): + StringLiteral(const QStringRef &v): value (v) { kind = K; } virtual void accept0(Visitor *visitor); @@ -509,7 +510,7 @@ public: { return literalToken; } // attributes: - NameId *value; + QStringRef value; SourceLocation literalToken; }; @@ -518,7 +519,7 @@ class QML_PARSER_EXPORT RegExpLiteral: public ExpressionNode public: QDECLARATIVEJS_DECLARE_AST_NODE(RegExpLiteral) - RegExpLiteral(NameId *p, int f): + RegExpLiteral(const QStringRef &p, int f): pattern (p), flags (f) { kind = K; } virtual void accept0(Visitor *visitor); @@ -530,7 +531,7 @@ public: { return literalToken; } // attributes: - NameId *pattern; + QStringRef pattern; int flags; SourceLocation literalToken; }; @@ -705,13 +706,13 @@ class QML_PARSER_EXPORT IdentifierPropertyName: public PropertyName public: QDECLARATIVEJS_DECLARE_AST_NODE(IdentifierPropertyName) - IdentifierPropertyName(NameId *n): + IdentifierPropertyName(const QStringRef &n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes - NameId *id; + QStringRef id; }; class QML_PARSER_EXPORT StringLiteralPropertyName: public PropertyName @@ -719,13 +720,13 @@ class QML_PARSER_EXPORT StringLiteralPropertyName: public PropertyName public: QDECLARATIVEJS_DECLARE_AST_NODE(StringLiteralPropertyName) - StringLiteralPropertyName(NameId *n): + StringLiteralPropertyName(const QStringRef &n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes - NameId *id; + QStringRef id; }; class QML_PARSER_EXPORT NumericLiteralPropertyName: public PropertyName @@ -771,7 +772,7 @@ class QML_PARSER_EXPORT FieldMemberExpression: public ExpressionNode public: QDECLARATIVEJS_DECLARE_AST_NODE(FieldMemberExpression) - FieldMemberExpression(ExpressionNode *b, NameId *n): + FieldMemberExpression(ExpressionNode *b, const QStringRef &n): base (b), name (n) { kind = K; } @@ -785,7 +786,7 @@ public: // attributes ExpressionNode *base; - NameId *name; + QStringRef name; SourceLocation dotToken; SourceLocation identifierToken; }; @@ -1277,14 +1278,14 @@ class QML_PARSER_EXPORT VariableDeclaration: public Node public: QDECLARATIVEJS_DECLARE_AST_NODE(VariableDeclaration) - VariableDeclaration(NameId *n, ExpressionNode *e): + VariableDeclaration(const QStringRef &n, ExpressionNode *e): name (n), expression (e), readOnly(false) { kind = K; } virtual void accept0(Visitor *visitor); // attributes - NameId *name; + QStringRef name; ExpressionNode *expression; bool readOnly; SourceLocation identifierToken; @@ -1570,7 +1571,7 @@ class QML_PARSER_EXPORT ContinueStatement: public Statement public: QDECLARATIVEJS_DECLARE_AST_NODE(ContinueStatement) - ContinueStatement(NameId *l = 0): + ContinueStatement(const QStringRef &l = QStringRef()): label (l) { kind = K; } virtual void accept0(Visitor *visitor); @@ -1582,7 +1583,7 @@ public: { return semicolonToken; } // attributes - NameId *label; + QStringRef label; SourceLocation continueToken; SourceLocation identifierToken; SourceLocation semicolonToken; @@ -1593,7 +1594,7 @@ class QML_PARSER_EXPORT BreakStatement: public Statement public: QDECLARATIVEJS_DECLARE_AST_NODE(BreakStatement) - BreakStatement(NameId *l = 0): + BreakStatement(const QStringRef &l): label (l) { kind = K; } virtual void accept0(Visitor *visitor); @@ -1605,7 +1606,7 @@ public: { return semicolonToken; } // attributes - NameId *label; + QStringRef label; SourceLocation breakToken; SourceLocation identifierToken; SourceLocation semicolonToken; @@ -1773,7 +1774,7 @@ class QML_PARSER_EXPORT LabelledStatement: public Statement public: QDECLARATIVEJS_DECLARE_AST_NODE(LabelledStatement) - LabelledStatement(NameId *l, Statement *stmt): + LabelledStatement(const QStringRef &l, Statement *stmt): label (l), statement (stmt) { kind = K; } @@ -1786,7 +1787,7 @@ public: { return statement->lastSourceLocation(); } // attributes - NameId *label; + QStringRef label; Statement *statement; SourceLocation identifierToken; SourceLocation colonToken; @@ -1819,14 +1820,14 @@ class QML_PARSER_EXPORT Catch: public Node public: QDECLARATIVEJS_DECLARE_AST_NODE(Catch) - Catch(NameId *n, Block *stmt): + Catch(const QStringRef &n, Block *stmt): name (n), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); // attributes - NameId *name; + QStringRef name; Block *statement; SourceLocation catchToken; SourceLocation lparenToken; @@ -1894,7 +1895,7 @@ class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode public: QDECLARATIVEJS_DECLARE_AST_NODE(FunctionExpression) - FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b): + FunctionExpression(const QStringRef &n, FormalParameterList *f, FunctionBody *b): name (n), formals (f), body (b) { kind = K; } @@ -1907,7 +1908,7 @@ public: { return rbraceToken; } // attributes - NameId *name; + QStringRef name; FormalParameterList *formals; FunctionBody *body; SourceLocation functionToken; @@ -1923,7 +1924,7 @@ class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression public: QDECLARATIVEJS_DECLARE_AST_NODE(FunctionDeclaration) - FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b): + FunctionDeclaration(const QStringRef &n, FormalParameterList *f, FunctionBody *b): FunctionExpression(n, f, b) { kind = K; } @@ -1935,11 +1936,11 @@ class QML_PARSER_EXPORT FormalParameterList: public Node public: QDECLARATIVEJS_DECLARE_AST_NODE(FormalParameterList) - FormalParameterList(NameId *n): + FormalParameterList(const QStringRef &n): name (n), next (this) { kind = K; } - FormalParameterList(FormalParameterList *previous, NameId *n): + FormalParameterList(FormalParameterList *previous, const QStringRef &n): name (n) { kind = K; @@ -1957,7 +1958,7 @@ public: } // attributes - NameId *name; + QStringRef name; FormalParameterList *next; SourceLocation commaToken; SourceLocation identifierToken; @@ -2105,11 +2106,11 @@ class QML_PARSER_EXPORT UiQualifiedId: public Node public: QDECLARATIVEJS_DECLARE_AST_NODE(UiQualifiedId) - UiQualifiedId(NameId *name) + UiQualifiedId(const QStringRef &name) : next(this), name(name) { kind = K; } - UiQualifiedId(UiQualifiedId *previous, NameId *name) + UiQualifiedId(UiQualifiedId *previous, const QStringRef &name) : name(name) { kind = K; @@ -2128,7 +2129,7 @@ public: // attributes UiQualifiedId *next; - NameId *name; + QStringRef name; SourceLocation identifierToken; }; @@ -2137,12 +2138,12 @@ class QML_PARSER_EXPORT UiImport: public Node public: QDECLARATIVEJS_DECLARE_AST_NODE(UiImport) - UiImport(NameId *fileName) - : fileName(fileName), importUri(0), importId(0) + UiImport(const QStringRef &fileName) + : fileName(fileName), importUri(0) { kind = K; } UiImport(UiQualifiedId *uri) - : fileName(0), importUri(uri), importId(0) + : importUri(uri) { kind = K; } virtual SourceLocation firstSourceLocation() const @@ -2154,9 +2155,9 @@ public: virtual void accept0(Visitor *visitor); // attributes - NameId *fileName; + QStringRef fileName; UiQualifiedId *importUri; - NameId *importId; + QStringRef importId; SourceLocation importToken; SourceLocation fileNameToken; SourceLocation versionToken; @@ -2306,11 +2307,11 @@ class QML_PARSER_EXPORT UiParameterList: public Node public: QDECLARATIVEJS_DECLARE_AST_NODE(UiParameterList) - UiParameterList(NameId *t, NameId *n): + UiParameterList(const QStringRef &t, const QStringRef &n): type (t), name (n), next (this) { kind = K; } - UiParameterList(UiParameterList *previous, NameId *t, NameId *n): + UiParameterList(UiParameterList *previous, const QStringRef &t, const QStringRef &n): type (t), name (n) { kind = K; @@ -2328,8 +2329,8 @@ public: } // attributes - NameId *type; - NameId *name; + QStringRef type; + QStringRef name; UiParameterList *next; SourceLocation commaToken; SourceLocation identifierToken; @@ -2340,15 +2341,15 @@ class QML_PARSER_EXPORT UiPublicMember: public UiObjectMember public: QDECLARATIVEJS_DECLARE_AST_NODE(UiPublicMember) - UiPublicMember(NameId *memberType, - NameId *name) - : type(Property), typeModifier(0), memberType(memberType), name(name), statement(0), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) + UiPublicMember(const QStringRef &memberType, + const QStringRef &name) + : type(Property), memberType(memberType), name(name), statement(0), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) { kind = K; } - UiPublicMember(NameId *memberType, - NameId *name, + UiPublicMember(const QStringRef &memberType, + const QStringRef &name, Statement *statement) - : type(Property), typeModifier(0), memberType(memberType), name(name), statement(statement), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) + : type(Property), memberType(memberType), name(name), statement(statement), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) { kind = K; } virtual SourceLocation firstSourceLocation() const @@ -2375,9 +2376,9 @@ public: // attributes enum { Signal, Property } type; - NameId *typeModifier; - NameId *memberType; - NameId *name; + QStringRef typeModifier; + QStringRef memberType; + QStringRef name; Statement *statement; // initialized with a JS expression UiObjectMember *binding; // initialized with a QML object or array. bool isDefaultMember; diff --git a/src/declarative/qml/parser/qdeclarativejsengine_p.cpp b/src/declarative/qml/parser/qdeclarativejsengine_p.cpp index a449f779b7..233ff7f20e 100644 --- a/src/declarative/qml/parser/qdeclarativejsengine_p.cpp +++ b/src/declarative/qml/parser/qdeclarativejsengine_p.cpp @@ -40,66 +40,16 @@ ****************************************************************************/ #include "qdeclarativejsengine_p.h" - #include "qdeclarativejsglobal_p.h" -#include "qdeclarativejsnodepool_p.h" #include <qnumeric.h> #include <QHash> +#include <QDebug> QT_QML_BEGIN_NAMESPACE namespace QDeclarativeJS { -uint qHash(const QDeclarativeJS::NameId &id) -{ return qHash(id.asString()); } - -QString numberToString(double value) -{ return QString::number(value); } - -int Ecma::RegExp::flagFromChar(const QChar &ch) -{ - static QHash<QChar, int> flagsHash; - if (flagsHash.isEmpty()) { - flagsHash[QLatin1Char('g')] = Global; - flagsHash[QLatin1Char('i')] = IgnoreCase; - flagsHash[QLatin1Char('m')] = Multiline; - } - QHash<QChar, int>::const_iterator it; - it = flagsHash.constFind(ch); - if (it == flagsHash.constEnd()) - return 0; - return it.value(); -} - -QString Ecma::RegExp::flagsToString(int flags) -{ - QString result; - if (flags & Global) - result += QLatin1Char('g'); - if (flags & IgnoreCase) - result += QLatin1Char('i'); - if (flags & Multiline) - result += QLatin1Char('m'); - return result; -} - -NodePool::NodePool(const QString &fileName, Engine *engine) - : m_fileName(fileName), m_engine(engine) -{ - m_engine->setNodePool(this); -} - -NodePool::~NodePool() -{ -} - -Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &) -{ - Q_ASSERT(0); - return 0; -} - static int toDigit(char c) { if ((c >= '0') && (c <= '9')) @@ -172,14 +122,14 @@ double integerFromString(const QString &str, int radix) Engine::Engine() - : _lexer(0), _nodePool(0) + : _lexer(0) { } Engine::~Engine() { } -QSet<NameId> Engine::literals() const -{ return _literals; } +void Engine::setCode(const QString &code) +{ _code = code; } void Engine::addComment(int pos, int len, int line, int col) { if (len > 0) _comments.append(QDeclarativeJS::AST::SourceLocation(pos, len, line, col)); } @@ -187,25 +137,24 @@ void Engine::addComment(int pos, int len, int line, int col) QList<QDeclarativeJS::AST::SourceLocation> Engine::comments() const { return _comments; } -NameId *Engine::intern(const QChar *u, int s) -{ return const_cast<NameId *>(&*_literals.insert(NameId(u, s))); } - -QString Engine::toString(NameId *id) -{ return id->asString(); } - Lexer *Engine::lexer() const { return _lexer; } void Engine::setLexer(Lexer *lexer) { _lexer = lexer; } -NodePool *Engine::nodePool() const -{ return _nodePool; } - -void Engine::setNodePool(NodePool *nodePool) -{ _nodePool = nodePool; } +MemoryPool *Engine::pool() +{ return &_pool; } +QStringRef Engine::newStringRef(const QString &text) +{ + const int pos = _extraCode.length(); + _extraCode += text; + return _extraCode.midRef(pos, text.length()); +} +QStringRef Engine::newStringRef(const QChar *chars, int size) +{ return newStringRef(QString(chars, size)); } } // end of namespace QDeclarativeJS diff --git a/src/declarative/qml/parser/qdeclarativejsengine_p.h b/src/declarative/qml/parser/qdeclarativejsengine_p.h index e366e8b9b3..13389434f4 100644 --- a/src/declarative/qml/parser/qdeclarativejsengine_p.h +++ b/src/declarative/qml/parser/qdeclarativejsengine_p.h @@ -55,6 +55,7 @@ #include "qdeclarativejsglobal_p.h" #include "qdeclarativejsastfwd_p.h" +#include "qdeclarativejsmemorypool_p.h" #include <QString> #include <QSet> @@ -62,54 +63,9 @@ QT_QML_BEGIN_NAMESPACE namespace QDeclarativeJS { -class QML_PARSER_EXPORT NameId -{ - QString _text; - -public: - NameId(const QChar *u, int s) - : _text(u, s) - { } - - const QString asString() const - { return _text; } - - bool operator == (const NameId &other) const - { return _text == other._text; } - - bool operator != (const NameId &other) const - { return _text != other._text; } - - bool operator < (const NameId &other) const - { return _text < other._text; } -}; - -uint qHash(const QDeclarativeJS::NameId &id); - -} // end of namespace QDeclarativeJS - -namespace QDeclarativeJS { class Lexer; -class NodePool; - -namespace Ecma { - -class QML_PARSER_EXPORT RegExp -{ -public: - enum RegExpFlag { - Global = 0x01, - IgnoreCase = 0x02, - Multiline = 0x04 - }; - -public: - static int flagFromChar(const QChar &); - static QString flagsToString(int flags); -}; - -} // end of namespace Ecma +class MemoryPool; class QML_PARSER_EXPORT DiagnosticMessage { @@ -136,30 +92,33 @@ public: class QML_PARSER_EXPORT Engine { Lexer *_lexer; - NodePool *_nodePool; - QSet<NameId> _literals; - QList<QDeclarativeJS::AST::SourceLocation> _comments; + MemoryPool _pool; + QList<AST::SourceLocation> _comments; + QString _extraCode; + QString _code; public: Engine(); ~Engine(); - QSet<NameId> literals() const; + void setCode(const QString &code); void addComment(int pos, int len, int line, int col); - QList<QDeclarativeJS::AST::SourceLocation> comments() const; - - NameId *intern(const QChar *u, int s); - - static QString toString(NameId *id); + QList<AST::SourceLocation> comments() const; Lexer *lexer() const; void setLexer(Lexer *lexer); - NodePool *nodePool() const; - void setNodePool(NodePool *nodePool); + MemoryPool *pool(); + + inline QStringRef midRef(int position, int size) { return _code.midRef(position, size); } + + QStringRef newStringRef(const QString &s); + QStringRef newStringRef(const QChar *chars, int size); }; +double integerFromString(const char *buf, int size, int radix); + } // end of namespace QDeclarativeJS QT_QML_END_NAMESPACE diff --git a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp index 38bd46bfcf..89c00c2839 100644 --- a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp +++ b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE const char *const QDeclarativeJSGrammar::spell [] = { - "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue", + "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ",", "continue", "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier", "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=", @@ -55,44 +55,44 @@ const char *const QDeclarativeJSGrammar::spell [] = { "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public", "import", "as", "on", 0, 0, 0, 0, 0, 0, 0, - 0}; + 0, 0}; const short QDeclarativeJSGrammar::lhs [] = { - 101, 101, 101, 101, 101, 101, 102, 108, 108, 111, - 111, 113, 112, 112, 112, 112, 112, 112, 112, 112, - 115, 110, 109, 118, 118, 119, 119, 120, 120, 117, - 106, 106, 106, 106, 122, 122, 122, 122, 106, 127, - 127, 127, 128, 128, 129, 129, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 116, 116, 116, 116, 116, 132, 132, - 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, - 132, 132, 132, 132, 132, 132, 121, 134, 134, 134, - 134, 133, 133, 136, 136, 138, 138, 138, 138, 138, - 138, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 140, 140, 114, 114, 114, 114, 114, 143, - 143, 144, 144, 144, 144, 142, 142, 145, 145, 146, - 146, 147, 147, 147, 148, 148, 148, 148, 148, 148, - 148, 148, 148, 148, 149, 149, 149, 149, 150, 150, - 150, 151, 151, 151, 151, 152, 152, 152, 152, 152, - 152, 152, 153, 153, 153, 153, 153, 153, 154, 154, - 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, - 157, 157, 158, 158, 159, 159, 160, 160, 161, 161, - 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, - 167, 167, 137, 137, 168, 168, 169, 169, 169, 169, - 169, 169, 169, 169, 169, 169, 169, 169, 104, 104, - 170, 170, 171, 171, 172, 172, 103, 103, 103, 103, - 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, - 103, 123, 184, 184, 183, 183, 131, 131, 185, 185, - 186, 186, 188, 188, 187, 189, 192, 190, 190, 193, - 191, 191, 124, 125, 125, 126, 126, 173, 173, 173, - 173, 173, 173, 173, 174, 174, 174, 174, 175, 175, - 175, 175, 176, 176, 177, 179, 194, 194, 197, 197, - 195, 195, 198, 196, 178, 178, 178, 180, 180, 181, - 181, 181, 199, 200, 182, 182, 130, 141, 204, 204, - 201, 201, 202, 202, 205, 107, 206, 206, 105, 105, - 203, 203, 135, 135, 207}; + 102, 102, 102, 102, 102, 102, 103, 109, 109, 112, + 112, 114, 113, 113, 113, 113, 113, 113, 113, 113, + 116, 111, 110, 119, 119, 120, 120, 121, 121, 118, + 107, 107, 107, 107, 123, 123, 123, 123, 107, 128, + 128, 128, 129, 129, 130, 130, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 117, 117, 117, 117, 117, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 122, 135, 135, 135, + 135, 134, 134, 137, 137, 139, 139, 139, 139, 139, + 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 141, 141, 115, 115, 115, 115, 115, 144, + 144, 145, 145, 145, 145, 143, 143, 146, 146, 147, + 147, 148, 148, 148, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 150, 150, 150, 150, 151, 151, + 151, 152, 152, 152, 152, 153, 153, 153, 153, 153, + 153, 153, 154, 154, 154, 154, 154, 154, 155, 155, + 155, 155, 155, 156, 156, 156, 156, 156, 157, 157, + 158, 158, 159, 159, 160, 160, 161, 161, 162, 162, + 163, 163, 164, 164, 165, 165, 166, 166, 167, 167, + 168, 168, 138, 138, 169, 169, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 105, 105, + 171, 171, 172, 172, 173, 173, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 124, 185, 185, 184, 184, 132, 132, 186, 186, + 187, 187, 189, 189, 188, 190, 193, 191, 191, 194, + 192, 192, 125, 126, 126, 127, 127, 174, 174, 174, + 174, 174, 174, 174, 175, 175, 175, 175, 176, 176, + 176, 176, 177, 177, 178, 180, 195, 195, 198, 198, + 196, 196, 199, 197, 179, 179, 179, 181, 181, 182, + 182, 182, 200, 201, 183, 183, 131, 142, 205, 205, + 202, 202, 203, 203, 206, 108, 207, 207, 106, 106, + 204, 204, 136, 136, 208}; const short QDeclarativeJSGrammar::rhs [] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, @@ -212,71 +212,71 @@ const short QDeclarativeJSGrammar::goto_default [] = { 185, 199, 181, 184, 198, 206, 0}; const short QDeclarativeJSGrammar::action_index [] = { - 350, 1271, 2492, 2492, 2395, 999, 52, 93, 137, -101, - 104, 72, 66, 177, -101, 285, 80, -101, -101, 641, - 71, 130, 167, 178, -101, -101, -101, 431, 321, 1271, - -101, -101, -101, 393, -101, 2201, 2007, 1271, 1271, 1271, - -101, 811, 1271, -101, -101, -101, 1271, 1271, -101, -101, - -101, -101, -101, 1271, -101, 1271, 1271, -101, 1271, 1271, - 87, 188, -101, -101, 1271, 1271, 1271, -101, -101, -101, - 179, 1271, 263, 1271, 1271, 1271, 1271, 456, 1271, 1271, - 1271, 1271, 1271, 1271, 321, 1271, 1271, 1271, 128, 114, - 120, 193, 181, 172, 321, 321, 446, 395, 405, 1271, - -8, 1271, 76, 2104, 1271, 1271, -101, -101, -101, -101, - -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, - -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, - -101, -101, -101, -101, -101, -101, -101, -101, -101, -101, - 110, 1271, -101, -101, 68, 38, -101, 1271, -101, -101, - 1271, -101, -101, -101, -101, -101, -101, -101, -101, -101, - -101, -101, -101, -101, 1271, 32, 1271, 1271, 85, 83, - 1271, -101, 2104, 1271, 1271, -101, 108, -101, 53, -101, - -101, 64, -101, 393, 89, 62, -101, 297, -101, 63, - 2492, -101, -101, -101, -101, -101, 154, -101, -101, 47, - -101, -101, -101, -101, -101, -101, 2492, -101, -101, 461, - -101, 470, 74, 2395, 59, 393, 92, 67, 2686, 152, - 1271, -101, 65, 43, 1271, 41, -101, 39, 34, -101, - -101, 393, -101, -101, -101, -101, -101, -101, 86, -101, - -101, -101, -101, 90, -101, -101, -101, -101, -101, -101, - -11, 50, 1271, 103, 82, -101, -101, 1455, -101, 84, - 44, 5, -101, 267, 70, 33, 575, 79, 69, 471, - 235, 393, 1271, 275, 1271, 1271, 1271, 1271, 305, 1271, - 1271, 1271, 1271, 1271, 229, 201, 225, 202, 321, 355, - 374, 380, 1271, 35, 1271, 81, 1271, -101, 641, 1271, - -101, 1271, 61, 1, 1271, 29, 2395, -101, 1271, 133, - 2395, -101, 1271, 73, 1271, 1271, 99, 97, 1271, -101, - 51, 153, 60, -101, -101, 1271, -101, 393, 1271, -101, - 56, 1271, -25, 2395, -101, 1271, 129, 2395, -101, -35, - 309, -56, -31, 2492, -39, -101, 2395, -101, 1271, 245, - 2395, -5, 2395, -101, 6, 0, -33, -101, -101, 2395, - -43, 543, 7, 488, 112, 1271, 2395, -1, -27, 453, - 8, -18, 630, 14, 16, -101, 1365, -101, 12, -19, - 3, 1271, 58, -30, 1271, -2, 1271, -29, -36, 1271, - -101, 2298, 18, -101, -101, -101, -101, -101, -101, 1271, - -101, -101, -101, -101, 223, -101, 1271, -10, -101, 2395, - -101, 95, -101, -101, 2395, -101, 1271, 107, 20, -101, - 40, -101, 46, 100, 1271, -101, 55, 57, -101, 28, - -101, 2395, -101, 118, 2395, -101, 161, -101, -101, 126, - 2395, 37, -101, -12, -4, -101, 393, -34, -6, -101, - -101, -101, -101, 1271, 98, 2395, -101, 1271, 116, 2395, - -101, 19, -101, 186, -101, -101, 1271, -101, -101, 303, - -101, -101, -101, 119, 1638, -101, -101, 1821, -101, -101, - 1914, -101, -101, -101, -101, -101, -101, 123, -101, -101, - -101, -101, -101, -101, -101, -101, 2492, -101, -101, -101, - 94, -26, 819, 158, -28, 4, -101, -101, 210, -101, - 203, -101, -101, -101, 393, 230, -101, 1545, -101, -101, - -101, -101, -101, -101, 234, 2, 393, 232, 17, 393, - 163, -101, 10, -101, 908, 125, -101, 13, 908, -101, - -101, 1090, -101, -101, -101, 1181, -101, -101, 214, -101, - 1545, -101, 262, 9, -101, -101, 180, 318, 30, 1545, - -101, 238, -101, 236, -101, 26, -32, 315, 183, 288, - -101, 77, -101, -101, -101, 1728, 908, 291, 2589, 2007, - -3, -101, 443, 25, 497, 88, 1271, 2395, 24, 11, - 384, 36, 27, 702, 48, 49, -101, 1365, -101, 54, - 31, 45, 1271, 58, 15, 1271, 42, 1271, 23, 22, - 122, -101, -101, 21, -101, -101, 730, -101, 254, -70, - 908, -101, -101, 138, 393, -101, 143, -101, 134, -101, - -101, 268, -101, -101, 124, -101, -101, -101, -101, -101, - -101, + 360, 1286, 2520, 2520, 2422, 1011, 52, 96, 132, -102, + 104, 69, 66, 177, -102, 283, 80, -102, -102, 649, + 71, 120, 160, 169, -102, -102, -102, 444, 325, 1286, + -102, -102, -102, 324, -102, 2226, 2030, 1286, 1286, 1286, + -102, 801, 1286, -102, -102, -102, 1286, 1286, -102, -102, + -102, -102, -102, 1286, -102, 1286, 1286, -102, 1286, 1286, + 87, 190, -102, -102, 1286, 1286, 1286, -102, -102, -102, + 187, 1286, 251, 1286, 1286, 1286, 1286, 471, 1286, 1286, + 1286, 1286, 1286, 1286, 325, 1286, 1286, 1286, 128, 113, + 127, 182, 168, 159, 325, 325, 454, 406, 416, 1286, + -7, 1286, 76, 2128, 1286, 1286, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, + 107, 1286, -102, -102, 68, 44, -102, 1286, -102, -102, + 1286, -102, -102, -102, -102, -102, -102, -102, -102, -102, + -102, -102, -102, -102, 1286, 32, 1286, 1286, 88, 86, + 1286, -102, 2128, 1286, 1286, -102, 103, -102, 56, -102, + -102, 65, -102, 398, 89, 63, -102, 274, -102, 62, + 2520, -102, -102, -102, -102, -102, 248, -102, -102, 47, + -102, -102, -102, -102, -102, -102, 2520, -102, -102, 467, + -102, 470, 73, 2422, 53, 398, 91, 67, 2716, 154, + 1286, -102, 64, 43, 1286, 41, -102, 39, 34, -102, + -102, 398, -102, -102, -102, -102, -102, -102, 82, -102, + -102, -102, -102, 90, -102, -102, -102, -102, -102, -102, + -8, 51, 1286, 100, 77, -102, -102, 1472, -102, 84, + 38, 5, -102, 266, 70, 33, 555, 79, 74, 477, + 234, 320, 1286, 281, 1286, 1286, 1286, 1286, 311, 1286, + 1286, 1286, 1286, 1286, 230, 189, 213, 208, 325, 371, + 386, 396, 1286, 35, 1286, 81, 1286, -102, 649, 1286, + -102, 1286, 60, 1, 1286, 31, 2422, -102, 1286, 140, + 2422, -102, 1286, 72, 1286, 1286, 97, 93, 1286, -102, + 50, 149, 61, -102, -102, 1286, -102, 310, 1286, -102, + 58, 1286, -25, 2422, -102, 1286, 125, 2422, -102, -35, + 292, -56, -31, 2520, -39, -102, 2422, -102, 1286, 141, + 2422, -5, 2422, -102, 6, 0, -33, -102, -102, 2422, + -43, 550, 7, 478, 115, 1286, 2422, -1, -27, 451, + 8, -18, 627, 14, 16, -102, 1381, -102, 12, -19, + 3, 1286, 59, -30, 1286, -2, 1286, -29, -36, 1286, + -102, 2324, 18, -102, -102, -102, -102, -102, -102, 1286, + -102, -102, -102, -102, 203, -102, 1286, -10, -102, 2422, + -102, 94, -102, -102, 2422, -102, 1286, 102, 20, -102, + 40, -102, 46, 99, 1286, -102, 55, 57, -102, 28, + -102, 2422, -102, 114, 2422, -102, 161, -102, -102, 121, + 2422, 37, -102, -12, -4, -102, 398, -34, -6, -102, + -102, -102, -102, 1286, 98, 2422, -102, 1286, 105, 2422, + -102, 19, -102, 181, -102, -102, 1286, -102, -102, 288, + -102, -102, -102, 110, 1657, -102, -102, 1842, -102, -102, + 1936, -102, -102, -102, -102, -102, -102, 122, -102, -102, + -102, -102, -102, -102, -102, -102, 2520, -102, -102, -102, + 92, -26, 829, 142, -28, 4, -102, -102, 191, -102, + 202, -102, -102, -102, 398, 218, -102, 1563, -102, -102, + -102, -102, -102, -102, 237, 2, 368, 207, 17, 398, + 205, -102, 10, -102, 919, 124, -102, 13, 919, -102, + -102, 1103, -102, -102, -102, 1195, -102, -102, 214, -102, + 1563, -102, 271, 9, -102, -102, 174, 307, 30, 1563, + -102, 228, -102, 212, -102, 26, -32, 301, 179, 265, + -102, 75, -102, -102, -102, 1748, 919, 280, 2618, 2030, + -3, -102, 459, 25, 486, 85, 1286, 2422, 24, 11, + 378, 36, 27, 711, 48, 49, -102, 1381, -102, 54, + 29, 45, 1286, 59, 15, 1286, 42, 1286, 23, 22, + 117, -102, -102, 21, -102, -102, 739, -102, 201, -70, + 919, -102, -102, 116, 398, -102, 143, -102, 129, -102, + -102, 252, -102, -102, 126, -102, -102, -102, -102, -102, + -102, -107, 25, -75, 27, 30, 272, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -42, @@ -351,252 +351,245 @@ const short QDeclarativeJSGrammar::action_info [] = { 541, -110, -129, 561, 568, 333, 466, 559, 556, 527, 510, 529, 541, 346, 534, 424, 541, 257, 440, -126, 408, 424, -121, 420, 541, -118, -100, 444, 457, 453, - 424, -99, 304, 348, 431, -123, 251, 416, 325, 141, - 457, 101, 414, 164, 440, 453, 147, 71, 296, 416, - 99, 312, 272, 430, 294, 272, 252, 164, 141, 306, - 170, 335, 292, 640, 301, 257, 190, 187, 149, 346, - 183, 312, 236, 348, 318, 71, 141, 0, 0, 172, - 427, 141, 0, 179, 294, 141, 141, 331, 141, 314, - 99, 292, 189, 315, 141, 434, 141, 477, 173, 62, - 538, 141, 443, 538, 0, 249, 248, 141, 573, 572, - 63, 141, 616, 256, 255, 101, 444, 242, 241, 249, - 248, 247, 246, 172, 58, 428, 413, 412, 455, 409, - 58, 327, 141, 254, 177, 59, 142, 418, 58, 141, - 532, 59, 173, 249, 248, 478, 459, 58, 611, 59, - 166, 539, 172, 488, 167, 636, 635, 525, 59, 337, - 64, 64, 103, 310, 469, 630, 629, 85, 0, 86, - 64, 173, 0, 174, 633, 632, 85, 0, 86, 511, - 87, 104, 511, 105, 328, 235, 234, 575, 85, 87, - 86, 550, 438, 437, 533, 531, 85, 85, 86, 86, - 0, 87, 511, 513, 631, 65, 65, 517, 172, 87, - 87, 66, 66, 541, 512, 65, 0, 470, 468, 172, - 85, 66, 86, 141, 85, 513, 86, 173, 513, 406, - 85, 511, 86, 87, 0, 511, 512, 87, 173, 512, - 406, 0, 0, 87, 563, 551, 549, 172, 513, 0, - 0, 73, 74, 0, 0, 274, 275, 0, 0, 512, - 0, 518, 516, 274, 275, -87, 173, 34, 174, 564, - 562, 626, 576, 73, 74, 350, 172, 513, 75, 76, - 0, 513, 276, 277, 0, 627, 625, 34, 512, 0, - 276, 277, 512, 0, -87, 173, 34, 174, 279, 280, - 75, 76, 34, 0, 48, 50, 49, 281, 34, 0, - 282, 0, 283, 0, 34, 624, 85, 34, 86, 0, - 0, 0, 0, 0, 48, 50, 49, 0, 0, 87, - 45, 0, 0, 48, 50, 49, 0, 0, 0, 48, - 50, 49, 0, 0, 0, 48, 50, 49, 279, 280, - 45, 48, 50, 49, 48, 50, 49, 281, 0, 45, - 282, 0, 283, 0, 0, 45, 0, 279, 280, 0, - 0, 45, 0, 279, 280, 0, 281, 45, 0, 282, - 45, 283, 281, 34, 0, 282, 0, 283, 78, 79, - -341, 0, 34, 0, 0, 0, 80, 81, 78, 79, - 82, 0, 83, 0, 0, 0, 80, 81, 0, 0, - 82, 0, 83, 6, 5, 4, 1, 3, 2, 0, - 48, 50, 49, 0, 78, 79, 0, 0, 0, 48, - 50, 49, 80, 81, 0, 0, 82, 0, 83, 78, - 79, 0, 34, 0, 0, 0, 45, 80, 81, 78, - 79, 82, 34, 83, 0, 45, 0, 80, 81, -341, - 34, 82, 0, 83, 279, 280, 0, 0, 0, 34, - 0, 0, 0, 281, 240, 239, 282, 0, 283, 48, - 50, 49, 0, 0, 0, 0, 0, 34, 0, 48, - 50, 49, 240, 239, 0, 0, 34, 48, 50, 49, - 0, 245, 244, 0, 0, 45, 48, 50, 49, 0, - 0, 0, 0, 0, 0, 45, 0, 0, 0, 245, - 244, 0, 0, 45, 48, 50, 49, 0, 245, 244, - 0, 0, 45, 48, 50, 49, 0, 0, 0, 0, - 0, 0, 34, 0, 0, 0, 0, 0, 151, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 152, 45, - 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, - 0, 154, 0, 155, 240, 239, 308, 0, 0, 48, - 50, 49, 0, 0, 156, 0, 157, 62, 0, 0, + 424, -99, 304, 348, 431, 416, -123, 325, 141, 251, + 457, 414, 101, 164, 440, 453, 147, 71, 296, 416, + 99, 312, 272, 430, 294, 272, 292, 252, 141, 257, + 164, 306, 335, 170, 301, 190, 640, 187, 346, 312, + 318, 183, 236, 348, 149, 71, 141, 172, 141, 427, + 141, 141, 0, 141, 294, 141, 179, 99, 477, 331, + 292, 434, 141, 189, 314, 538, 173, 443, 315, 62, + 141, 172, 538, 141, 249, 248, 573, 572, 256, 255, + 63, 444, 616, 242, 241, 101, 249, 248, 141, 141, + 173, 247, 246, 58, 428, 413, 412, 327, 455, 177, + 254, 409, 418, 142, 59, 459, 478, 58, 58, 141, + 166, 525, 58, 611, 167, 172, 249, 248, 59, 59, + 539, 64, 488, 59, 85, 337, 86, 636, 635, 469, + 630, 629, 103, 85, 173, 86, 174, 87, 575, 64, + 310, 350, 64, 511, 633, 632, 87, 85, 511, 86, + 328, 104, 532, 105, 85, 0, 86, 513, 172, 0, + 87, 550, 438, 437, 541, 517, 65, 87, 512, 0, + 0, 511, 66, 85, 631, 86, 511, 173, 85, 406, + 86, 511, 470, 468, 65, 0, 87, 65, 626, 513, + 66, 87, 172, 66, 513, 85, 141, 86, 0, 85, + 512, 86, 627, 625, 563, 512, 533, 531, 87, 73, + 74, 173, 87, 406, 0, 551, 549, 513, 0, 518, + 516, 34, 513, 576, 274, 275, 172, 513, 512, 564, + 562, 0, 624, 512, 34, 172, 75, 76, 512, 274, + 275, 73, 74, 34, -87, 173, 0, 174, 0, 235, + 234, 276, 277, -87, 173, 0, 174, 34, 48, 50, + 49, 34, 0, 0, 0, 0, 276, 277, 75, 76, + 34, 48, 50, 49, 279, 280, 34, 0, 0, 34, + 48, 50, 49, 281, 45, 0, 282, 0, 283, 34, + 85, 0, 86, 34, 48, 50, 49, 45, 48, 50, + 49, 0, 0, 87, 0, 0, 45, 48, 50, 49, + 0, 0, 0, 48, 50, 49, 48, 50, 49, 0, + 45, 0, 0, 0, 45, 0, 48, 50, 49, 0, + 48, 50, 49, 45, 279, 280, 0, 34, 0, 45, + 0, 0, 45, 281, 0, 0, 282, 34, 283, 279, + 280, 0, 45, 0, -341, 0, 45, 0, 281, 279, + 280, 282, 0, 283, 0, 0, 0, 34, 281, 78, + 79, 282, 0, 283, 48, 50, 49, 80, 81, 78, + 79, 82, 0, 83, 48, 50, 49, 80, 81, 0, + 0, 82, 0, 83, 6, 5, 4, 1, 3, 2, + 45, 0, 0, 0, 48, 50, 49, 78, 79, 0, + 45, 0, 0, 0, 0, 80, 81, 78, 79, 82, + 34, 83, 0, 0, 0, 80, 81, -341, 34, 82, + 45, 83, 0, 0, 78, 79, 34, 0, 0, 34, + 279, 280, 80, 81, 0, 0, 82, 34, 83, 281, + 0, 0, 282, 0, 283, 34, 0, 48, 50, 49, + 240, 239, 0, 0, 0, 48, 50, 49, 240, 239, + 0, 245, 244, 48, 50, 49, 48, 50, 49, 245, + 244, 0, 0, 45, 48, 50, 49, 245, 244, 0, + 0, 45, 48, 50, 49, 0, 0, 0, 151, 45, + 0, 0, 45, 0, 0, 0, 0, 0, 152, 0, + 45, 0, 153, 0, 0, 0, 0, 0, 45, 34, + 0, 154, 0, 155, 0, 0, 308, 0, 0, 0, + 0, 0, 0, 0, 156, 0, 157, 62, 0, 0, 0, 0, 0, 0, 158, 0, 0, 159, 63, 0, - 0, 0, 0, 160, 0, 45, 0, 0, 0, 161, - 0, 0, 30, 31, 151, 0, 0, 0, 0, 0, - 0, 0, 33, 0, 152, 162, 0, 0, 153, 34, - 0, 0, 0, 35, 36, 0, 37, 154, 0, 155, - 0, 0, 0, 41, 0, 0, 0, 44, 0, 0, - 156, 0, 157, 62, 0, 0, 0, 0, 0, 0, - 158, 0, 0, 159, 63, 51, 48, 50, 49, 160, - 52, 0, 0, 0, 0, 161, 0, 0, 0, 0, - 0, 43, 54, 32, 30, 31, 0, 40, 0, 0, - 0, 162, 45, 0, 33, 0, 0, 0, 0, 0, - 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, - 0, 0, 30, 31, 0, 41, 0, 0, 0, 44, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, - 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, - 49, 0, 52, 502, 0, 0, 0, 44, 0, 0, - 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, - 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, - 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, - 0, 0, 45, 30, 31, 0, 0, 0, 0, 0, - 0, 30, 31, 33, 0, 0, 0, 0, 0, 0, - 34, 33, 0, 0, 35, 36, 0, 37, 34, 0, - 0, 0, 35, 36, 41, 37, 0, 0, 44, 0, - 0, 0, 502, 0, 0, 0, 44, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, - 0, 52, 0, 0, 51, 48, 50, 49, 0, 52, + 0, 240, 239, 160, 0, 0, 48, 50, 49, 161, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 162, 0, 0, 0, 30, + 31, 0, 45, 0, 0, 0, 0, 0, 0, 33, + 0, 0, 151, 0, 0, 0, 34, 0, 0, 0, + 35, 36, 152, 37, 0, 0, 153, 0, 0, 0, + 41, 0, 0, 0, 44, 154, 0, 155, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, + 157, 62, 51, 48, 50, 49, 0, 52, 158, 0, + 0, 159, 63, 0, 0, 0, 0, 160, 43, 54, + 32, 0, 0, 161, 40, 0, 0, 0, 0, 45, + 0, 0, 0, 30, 31, 0, 0, 0, 0, 162, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, + 0, 30, 31, 0, 41, 0, 0, 0, 44, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, + 0, 52, 502, 0, 0, 0, 44, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, - 43, 54, 32, 45, 0, 0, 40, 0, 0, 0, - 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, - 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, - 0, 502, 0, 0, 0, 44, 0, 0, 0, 0, + 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, + 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, + 43, 54, 32, 33, 0, 0, 40, 0, 0, 0, + 34, 45, 0, 0, 35, 36, 0, 37, 0, 0, + 0, 30, 31, 0, 41, 0, 0, 0, 44, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, + 0, 52, 502, 0, 0, 0, 44, 0, 0, 0, + 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, + 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, - 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 501, + 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, - 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 502, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 51, 503, 505, 504, 0, 52, - 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, - 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, + 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, - 501, 0, 30, 31, 0, 0, 0, 0, 0, 0, - 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, - 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, - 0, 0, 0, 502, 0, 0, 0, 44, 0, 0, - 0, 0, 0, 0, 0, 543, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 51, 503, 505, 504, 0, - 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, - 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, - 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 501, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 502, 0, 0, 0, 44, 0, - 0, 0, 0, 0, 0, 0, 546, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 503, 505, 504, 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, - 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, - 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, - 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, - 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, - 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, - 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, - 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, - 0, 0, -119, 0, 0, 0, 29, 30, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 0, 0, 501, 0, 30, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, + 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, + 0, 0, 0, 0, 0, 0, 502, 0, 0, 0, + 44, 0, 0, 0, 0, 0, 0, 0, 543, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 51, 503, + 505, 504, 0, 52, 0, 0, 0, 0, 226, 0, + 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, + 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 501, 0, 30, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, - 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, - 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, - 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, + 0, 37, 0, 0, 0, 0, 0, 0, 502, 0, + 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, + 546, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 51, 503, 505, 504, 0, 52, 0, 0, 0, 0, + 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, - 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, - 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, - 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, + 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, + 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, + 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, - 271, 56, 0, 0, 0, 0, 43, 54, 32, 0, - 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, - 0, 0, 0, 0, 34, 217, 0, 0, 218, 36, - 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, - 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, - 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, - 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, - 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, - 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 483, 0, 0, 29, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, - 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, - 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, - 0, 47, 0, 0, 486, 0, 0, 0, 0, 0, - 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, - 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, - 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 29, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 34, 217, 0, - 0, 578, 579, 0, 37, 0, 0, 0, 38, 0, - 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, - 0, 47, 0, 0, 0, 0, 0, 0, 0, 221, - 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, - 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, - 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 475, + 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, + 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, + 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, - 0, 0, 46, 0, 47, 0, 0, 481, 0, 0, + 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 483, 0, 0, 29, 30, 31, 0, 0, - 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, - 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, - 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, - 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, - 484, 0, 0, 0, 0, 0, 0, 0, 0, 51, - 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, - 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, - 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, - 0, 0, 0, 0, 0, 475, 0, 0, 29, 30, + 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, + 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, + 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, + 49, 0, 52, 0, 53, 0, 55, 271, 56, 0, + 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, + 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, + 0, 0, 34, 217, 0, 0, 218, 36, 0, 37, + 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, + 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, + 0, 0, 0, 0, 221, 0, 0, 0, 51, 48, + 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, + 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, + 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 483, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, - 47, 0, 0, 476, 0, 0, 0, 0, 0, 0, + 47, 0, 0, 486, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, - 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, - 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, - 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, - 0, 0, 0, 34, 123, 124, 125, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, - 48, 50, 49, 130, 131, 132, 0, 134, 135, 136, - 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, - 128, 0, 0, 0, 0, 0, 45, 0, 0, 0, - 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, - 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, - 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, - 393, 123, 124, 125, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 126, 0, 0, 0, 394, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 0, 0, 0, 0, 0, 398, 395, 397, 0, - 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, - 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 0, 0, 34, 217, 0, + 0, 578, 579, 0, 37, 0, 0, 0, 38, 0, + 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, + 0, 47, 0, 0, 0, 0, 0, 0, 0, 221, + 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, + 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, + 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 475, 0, 0, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, + 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, + 0, 0, 0, 46, 0, 47, 0, 0, 481, 0, + 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, + 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, + 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, + 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 483, 0, 0, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, + 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, + 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, + 0, 0, 484, 0, 0, 0, 0, 0, 0, 0, + 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, + 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, + 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 475, 0, + 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, + 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, + 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, + 0, 46, 0, 47, 0, 0, 476, 0, 0, 0, + 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, + 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, + 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, + 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, - 122, 0, 0, 0, 0, 0, 0, 393, 123, 124, + 122, 0, 0, 0, 0, 0, 0, 34, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 126, 0, 0, 0, 394, 0, 0, 0, 0, - 0, 0, 0, 396, 0, 0, 0, 129, 0, 0, - 0, 0, 0, 398, 395, 397, 0, 130, 131, 132, + 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, + 0, 0, 0, 0, 48, 50, 49, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, - 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, - 0, 0, 0, 0, 0, 0, 214, 33, 0, 0, - 0, 0, 0, 0, 216, 217, 0, 0, 218, 36, - 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, - 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, - 0, 0, 0, 0, 220, 0, 221, 0, 0, 0, - 51, 219, 222, 49, 223, 52, 224, 53, 225, 55, - 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, - 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, + 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, + 0, 0, 0, 0, 0, 393, 123, 124, 125, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, + 0, 0, 0, 394, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, + 0, 398, 395, 397, 0, 130, 131, 132, 0, 134, + 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, + 112, 114, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, + 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, + 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, + 0, 0, 0, 393, 123, 124, 125, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, + 0, 394, 0, 0, 0, 0, 0, 0, 0, 396, + 0, 0, 0, 129, 0, 0, 0, 0, 0, 398, + 395, 397, 0, 130, 131, 132, 0, 134, 135, 136, + 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, + 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, 0, 0, 0, - 0, 0, 0, 214, 215, 0, 0, 0, 0, 0, + 0, 0, 0, 214, 33, 0, 0, 0, 0, 0, 0, 216, 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, @@ -604,16 +597,26 @@ const short QDeclarativeJSGrammar::action_info [] = { 49, 223, 52, 224, 53, 225, 55, 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 582, 110, 111, 0, 0, 584, 115, - 586, 30, 31, 587, 0, 118, 0, 0, 0, 120, - 589, 590, 0, 0, 0, 0, 0, 0, 591, 592, - 124, 125, 218, 36, 0, 37, 0, 0, 0, 38, - 0, 39, 593, 42, 0, 0, 595, 0, 0, 0, - 46, 0, 47, 0, 0, 0, 0, 0, 597, 0, - 221, 0, 0, 0, 599, 596, 598, 49, 600, 601, - 602, 53, 604, 605, 606, 607, 608, 609, 0, 0, - 594, 603, 588, 583, 585, 128, 40, 0, 0, 0, - 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 209, 0, 0, 0, 0, 211, + 0, 29, 30, 31, 213, 0, 0, 0, 0, 0, + 0, 214, 215, 0, 0, 0, 0, 0, 0, 216, + 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, + 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, + 0, 46, 0, 47, 0, 0, 0, 0, 0, 220, + 0, 221, 0, 0, 0, 51, 219, 222, 49, 223, + 52, 224, 53, 225, 55, 226, 56, 227, 228, 0, + 0, 43, 54, 32, 210, 212, 0, 40, 0, 0, + 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 582, 110, 111, 0, 0, 584, 115, 586, + 30, 31, 587, 0, 118, 0, 0, 0, 120, 589, + 590, 0, 0, 0, 0, 0, 0, 591, 592, 124, + 125, 218, 36, 0, 37, 0, 0, 0, 38, 0, + 39, 593, 42, 0, 0, 595, 0, 0, 0, 46, + 0, 47, 0, 0, 0, 0, 0, 597, 0, 221, + 0, 0, 0, 599, 596, 598, 49, 600, 601, 602, + 53, 604, 605, 606, 607, 608, 609, 0, 0, 594, + 603, 588, 583, 585, 128, 40, 0, 0, 0, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 361, 110, 111, 0, 0, 363, 115, 365, 30, 31, 366, 0, 118, 0, 0, 0, 120, 368, 369, 0, 0, 0, 0, 0, 0, 370, 371, 124, 125, 218, @@ -623,7 +626,7 @@ const short QDeclarativeJSGrammar::action_info [] = { 0, 378, 375, 377, 49, 379, 380, 381, 53, 383, 384, 385, 386, 387, 388, 0, 0, 373, 382, 367, 362, 364, 128, 40, 0, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 567, 169, 558, 570, 574, 515, 569, 557, 309, 548, 461, 528, 311, 530, 417, 555, 307, 188, 415, 358, @@ -681,201 +684,166 @@ const short QDeclarativeJSGrammar::action_check [] = { 33, 7, 7, 29, 8, 60, 17, 7, 66, 37, 66, 24, 33, 7, 34, 5, 33, 36, 33, 7, 60, 5, 7, 33, 33, 7, 7, 20, 36, 36, - 5, 7, 61, 36, 7, 7, 77, 36, 17, 8, - 36, 79, 7, 2, 33, 36, 8, 1, 8, 36, - 48, 2, 1, 55, 79, 1, 36, 2, 8, 60, - 7, 31, 48, 0, 61, 36, 33, 8, 60, 7, - 36, 2, 55, 36, 7, 1, 8, -1, -1, 15, - 10, 8, -1, 60, 79, 8, 8, 61, 8, 50, - 48, 48, 60, 54, 8, 7, 8, 8, 34, 42, - 8, 8, 6, 8, -1, 61, 62, 8, 61, 62, - 53, 8, 90, 61, 62, 79, 20, 61, 62, 61, - 62, 61, 62, 15, 40, 55, 61, 62, 60, 7, - 40, 8, 8, 60, 56, 51, 56, 60, 40, 8, - 7, 51, 34, 61, 62, 56, 60, 40, 56, 51, - 50, 56, 15, 60, 54, 61, 62, 29, 51, 60, - 12, 12, 15, 60, 8, 61, 62, 25, -1, 27, - 12, 34, -1, 36, 61, 62, 25, -1, 27, 29, - 38, 34, 29, 36, 61, 61, 62, 7, 25, 38, - 27, 7, 61, 62, 61, 62, 25, 25, 27, 27, - -1, 38, 29, 75, 91, 57, 57, 7, 15, 38, - 38, 63, 63, 33, 86, 57, -1, 61, 62, 15, - 25, 63, 27, 8, 25, 75, 27, 34, 75, 36, - 25, 29, 27, 38, -1, 29, 86, 38, 34, 86, - 36, -1, -1, 38, 36, 61, 62, 15, 75, -1, - -1, 18, 19, -1, -1, 18, 19, -1, -1, 86, - -1, 61, 62, 18, 19, 33, 34, 29, 36, 61, - 62, 47, 92, 18, 19, 60, 15, 75, 45, 46, - -1, 75, 45, 46, -1, 61, 62, 29, 86, -1, - 45, 46, 86, -1, 33, 34, 29, 36, 23, 24, - 45, 46, 29, -1, 66, 67, 68, 32, 29, -1, - 35, -1, 37, -1, 29, 91, 25, 29, 27, -1, - -1, -1, -1, -1, 66, 67, 68, -1, -1, 38, - 92, -1, -1, 66, 67, 68, -1, -1, -1, 66, - 67, 68, -1, -1, -1, 66, 67, 68, 23, 24, - 92, 66, 67, 68, 66, 67, 68, 32, -1, 92, - 35, -1, 37, -1, -1, 92, -1, 23, 24, -1, - -1, 92, -1, 23, 24, -1, 32, 92, -1, 35, - 92, 37, 32, 29, -1, 35, -1, 37, 23, 24, - 36, -1, 29, -1, -1, -1, 31, 32, 23, 24, - 35, -1, 37, -1, -1, -1, 31, 32, -1, -1, - 35, -1, 37, 93, 94, 95, 96, 97, 98, -1, - 66, 67, 68, -1, 23, 24, -1, -1, -1, 66, - 67, 68, 31, 32, -1, -1, 35, -1, 37, 23, - 24, -1, 29, -1, -1, -1, 92, 31, 32, 23, - 24, 35, 29, 37, -1, 92, -1, 31, 32, 36, - 29, 35, -1, 37, 23, 24, -1, -1, -1, 29, - -1, -1, -1, 32, 61, 62, 35, -1, 37, 66, - 67, 68, -1, -1, -1, -1, -1, 29, -1, 66, - 67, 68, 61, 62, -1, -1, 29, 66, 67, 68, - -1, 61, 62, -1, -1, 92, 66, 67, 68, -1, - -1, -1, -1, -1, -1, 92, -1, -1, -1, 61, - 62, -1, -1, 92, 66, 67, 68, -1, 61, 62, - -1, -1, 92, 66, 67, 68, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, -1, -1, 3, -1, - 92, -1, -1, -1, -1, -1, -1, -1, 13, 92, - -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, - -1, 26, -1, 28, 61, 62, 31, -1, -1, 66, - 67, 68, -1, -1, 39, -1, 41, 42, -1, -1, + 5, 7, 61, 36, 7, 36, 7, 17, 8, 77, + 36, 7, 79, 2, 33, 36, 8, 1, 8, 36, + 48, 2, 1, 55, 79, 1, 48, 36, 8, 36, + 2, 60, 31, 7, 61, 33, 0, 8, 7, 2, + 7, 36, 55, 36, 60, 1, 8, 15, 8, 10, + 8, 8, -1, 8, 79, 8, 60, 48, 8, 61, + 48, 7, 8, 60, 50, 8, 34, 6, 54, 42, + 8, 15, 8, 8, 61, 62, 61, 62, 61, 62, + 53, 20, 90, 61, 62, 79, 61, 62, 8, 8, + 34, 61, 62, 40, 55, 61, 62, 8, 60, 56, + 60, 7, 60, 56, 51, 60, 56, 40, 40, 8, + 50, 29, 40, 56, 54, 15, 61, 62, 51, 51, + 56, 12, 60, 51, 25, 60, 27, 61, 62, 8, + 61, 62, 15, 25, 34, 27, 36, 38, 7, 12, + 60, 60, 12, 29, 61, 62, 38, 25, 29, 27, + 61, 34, 7, 36, 25, -1, 27, 75, 15, -1, + 38, 7, 61, 62, 33, 7, 57, 38, 86, -1, + -1, 29, 63, 25, 91, 27, 29, 34, 25, 36, + 27, 29, 61, 62, 57, -1, 38, 57, 47, 75, + 63, 38, 15, 63, 75, 25, 8, 27, -1, 25, + 86, 27, 61, 62, 36, 86, 61, 62, 38, 18, + 19, 34, 38, 36, -1, 61, 62, 75, -1, 61, + 62, 29, 75, 92, 18, 19, 15, 75, 86, 61, + 62, -1, 91, 86, 29, 15, 45, 46, 86, 18, + 19, 18, 19, 29, 33, 34, -1, 36, -1, 61, + 62, 45, 46, 33, 34, -1, 36, 29, 66, 67, + 68, 29, -1, -1, -1, -1, 45, 46, 45, 46, + 29, 66, 67, 68, 23, 24, 29, -1, -1, 29, + 66, 67, 68, 32, 92, -1, 35, -1, 37, 29, + 25, -1, 27, 29, 66, 67, 68, 92, 66, 67, + 68, -1, -1, 38, -1, -1, 92, 66, 67, 68, + -1, -1, -1, 66, 67, 68, 66, 67, 68, -1, + 92, -1, -1, -1, 92, -1, 66, 67, 68, -1, + 66, 67, 68, 92, 23, 24, -1, 29, -1, 92, + -1, -1, 92, 32, -1, -1, 35, 29, 37, 23, + 24, -1, 92, -1, 36, -1, 92, -1, 32, 23, + 24, 35, -1, 37, -1, -1, -1, 29, 32, 23, + 24, 35, -1, 37, 66, 67, 68, 31, 32, 23, + 24, 35, -1, 37, 66, 67, 68, 31, 32, -1, + -1, 35, -1, 37, 94, 95, 96, 97, 98, 99, + 92, -1, -1, -1, 66, 67, 68, 23, 24, -1, + 92, -1, -1, -1, -1, 31, 32, 23, 24, 35, + 29, 37, -1, -1, -1, 31, 32, 36, 29, 35, + 92, 37, -1, -1, 23, 24, 29, -1, -1, 29, + 23, 24, 31, 32, -1, -1, 35, 29, 37, 32, + -1, -1, 35, -1, 37, 29, -1, 66, 67, 68, + 61, 62, -1, -1, -1, 66, 67, 68, 61, 62, + -1, 61, 62, 66, 67, 68, 66, 67, 68, 61, + 62, -1, -1, 92, 66, 67, 68, 61, 62, -1, + -1, 92, 66, 67, 68, -1, -1, -1, 3, 92, + -1, -1, 92, -1, -1, -1, -1, -1, 13, -1, + 92, -1, 17, -1, -1, -1, -1, -1, 92, 29, + -1, 26, -1, 28, -1, -1, 31, -1, -1, -1, + -1, -1, -1, -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, 52, 53, -1, - -1, -1, -1, 58, -1, 92, -1, -1, -1, 64, - -1, -1, 12, 13, 3, -1, -1, -1, -1, -1, - -1, -1, 22, -1, 13, 80, -1, -1, 17, 29, - -1, -1, -1, 33, 34, -1, 36, 26, -1, 28, - -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, - 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, - 49, -1, -1, 52, 53, 65, 66, 67, 68, 58, - 70, -1, -1, -1, -1, 64, -1, -1, -1, -1, - -1, 81, 82, 83, 12, 13, -1, 87, -1, -1, - -1, 80, 92, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, - -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, - -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, - 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, - -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, - 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, - -1, -1, 92, 12, 13, -1, -1, -1, -1, -1, - -1, 12, 13, 22, -1, -1, -1, -1, -1, -1, - 29, 22, -1, -1, 33, 34, -1, 36, 29, -1, - -1, -1, 33, 34, 43, 36, -1, -1, 47, -1, - -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, - -1, 70, -1, -1, 65, 66, 67, 68, -1, 70, + -1, 61, 62, 58, -1, -1, 66, 67, 68, 64, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 80, -1, -1, -1, 12, + 13, -1, 92, -1, -1, -1, -1, -1, -1, 22, + -1, -1, 3, -1, -1, -1, 29, -1, -1, -1, + 33, 34, 13, 36, -1, -1, 17, -1, -1, -1, + 43, -1, -1, -1, 47, 26, -1, 28, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, + 41, 42, 65, 66, 67, 68, -1, 70, 49, -1, + -1, 52, 53, -1, -1, -1, -1, 58, 81, 82, + 83, -1, -1, 64, 87, -1, -1, -1, -1, 92, + -1, -1, -1, 12, 13, -1, -1, -1, -1, 80, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, + -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, + -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, - 81, 82, 83, 92, -1, -1, 87, -1, -1, -1, - -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, - -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, - -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, + -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, + -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, + 81, 82, 83, 22, -1, -1, 87, -1, -1, -1, + 29, 92, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, + -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, + -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, - 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, - 92, -1, -1, -1, -1, -1, -1, -1, -1, 10, + 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, + -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, - -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, - 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, - 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, - -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, - -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, - -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, - -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, - 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, - -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, - -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, - -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, - -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, - 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, - -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, - -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, - -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, - -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, - -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, - -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, + -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, + -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, + 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, + 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, + -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, + 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, - -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, - -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, + -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, + -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, + 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, + 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, - -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, - -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, - 75, 76, -1, -1, -1, -1, 81, 82, 83, -1, - -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, - -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, - -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, - -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, - -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, - -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, - -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, - -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, - 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, - 92, -1, -1, -1, -1, -1, -1, -1, -1, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, - 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, - 92, -1, -1, -1, -1, -1, -1, -1, -1, 8, + -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, + 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, - -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, + -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, - -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, - -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, - -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, - 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, - 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, - -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, + -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, 72, -1, 74, 75, 76, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, + -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, + 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, + -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, + 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, + -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, + 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, @@ -885,45 +853,73 @@ const short QDeclarativeJSGrammar::action_check [] = { -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, - -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, - 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, - 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, - 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, - 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, - 86, -1, -1, -1, -1, -1, 92, -1, -1, -1, - -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, - 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, - -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, - 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 59, -1, -1, -1, -1, -1, 65, 66, 67, -1, - 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, - -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, + -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, + 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, + 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, + 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, + -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, + 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, + -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, + -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, + -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, - -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, - -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, + -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, + -1, -1, -1, -1, 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, - -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, - -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, - -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, - -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, - -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, - -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, - 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, + 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, + 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, + -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, + -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, + 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, + 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, + -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, + 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, + 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, + 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, @@ -934,16 +930,26 @@ const short QDeclarativeJSGrammar::action_check [] = { 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, - -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, - 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, - 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, - 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, - -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, - 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, - 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, - 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, - -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, + -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, + -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, + 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, + -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, + -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, + -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, + 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, + 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, + 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, + -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, + 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, + 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, @@ -953,7 +959,7 @@ const short QDeclarativeJSGrammar::action_check [] = { -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, 92, -1, - -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 26, 36, 15, 15, 15, 15, 26, 26, 3, 15, 15, 26, 2, 15, 3, 19, 2, 15, 2, 2, diff --git a/src/declarative/qml/parser/qdeclarativejsgrammar_p.h b/src/declarative/qml/parser/qdeclarativejsgrammar_p.h index a093bc25d9..0dae476372 100644 --- a/src/declarative/qml/parser/qdeclarativejsgrammar_p.h +++ b/src/declarative/qml/parser/qdeclarativejsgrammar_p.h @@ -63,8 +63,8 @@ class QDeclarativeJSGrammar public: enum VariousConstants { EOF_SYMBOL = 0, - REDUCE_HERE = 100, - SHIFT_THERE = 99, + REDUCE_HERE = 101, + SHIFT_THERE = 100, T_AND = 1, T_AND_AND = 2, T_AND_EQ = 3, @@ -89,13 +89,14 @@ public: T_EQ = 17, T_EQ_EQ = 18, T_EQ_EQ_EQ = 19, + T_ERROR = 93, T_FALSE = 83, - T_FEED_JS_EXPRESSION = 96, - T_FEED_JS_PROGRAM = 98, - T_FEED_JS_SOURCE_ELEMENT = 97, - T_FEED_JS_STATEMENT = 95, - T_FEED_UI_OBJECT_MEMBER = 94, - T_FEED_UI_PROGRAM = 93, + T_FEED_JS_EXPRESSION = 97, + T_FEED_JS_PROGRAM = 99, + T_FEED_JS_SOURCE_ELEMENT = 98, + T_FEED_JS_STATEMENT = 96, + T_FEED_UI_OBJECT_MEMBER = 95, + T_FEED_UI_PROGRAM = 94, T_FINALLY = 20, T_FOR = 21, T_FUNCTION = 22, @@ -167,12 +168,12 @@ public: ACCEPT_STATE = 640, RULE_COUNT = 345, STATE_COUNT = 641, - TERMINAL_COUNT = 101, + TERMINAL_COUNT = 102, NON_TERMINAL_COUNT = 107, GOTO_INDEX_OFFSET = 641, - GOTO_INFO_OFFSET = 2787, - GOTO_CHECK_OFFSET = 2787 + GOTO_INFO_OFFSET = 2818, + GOTO_CHECK_OFFSET = 2818 }; static const char *const spell []; diff --git a/src/declarative/qml/parser/qdeclarativejskeywords_p.h b/src/declarative/qml/parser/qdeclarativejskeywords_p.h new file mode 100644 index 0000000000..26e0def859 --- /dev/null +++ b/src/declarative/qml/parser/qdeclarativejskeywords_p.h @@ -0,0 +1,860 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEJSKEYWORDS_P_H +#define QDECLARATIVEJSKEYWORDS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +static inline int classify2(const QChar *s) { + if (s[0].unicode() == 'a') { + if (s[1].unicode() == 's') { + return Lexer::T_AS; + } + } + else if (s[0].unicode() == 'd') { + if (s[1].unicode() == 'o') { + return Lexer::T_DO; + } + } + else if (s[0].unicode() == 'i') { + if (s[1].unicode() == 'f') { + return Lexer::T_IF; + } + else if (s[1].unicode() == 'n') { + return Lexer::T_IN; + } + } + else if (s[0].unicode() == 'o') { + if (s[1].unicode() == 'n') { + return Lexer::T_ON; + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify3(const QChar *s) { + if (s[0].unicode() == 'f') { + if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'r') { + return Lexer::T_FOR; + } + } + } + else if (s[0].unicode() == 'i') { + if (s[1].unicode() == 'n') { + if (s[2].unicode() == 't') { + return Lexer::T_INT; + } + } + } + else if (s[0].unicode() == 'n') { + if (s[1].unicode() == 'e') { + if (s[2].unicode() == 'w') { + return Lexer::T_NEW; + } + } + } + else if (s[0].unicode() == 't') { + if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'y') { + return Lexer::T_TRY; + } + } + } + else if (s[0].unicode() == 'v') { + if (s[1].unicode() == 'a') { + if (s[2].unicode() == 'r') { + return Lexer::T_VAR; + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify4(const QChar *s) { + if (s[0].unicode() == 'b') { + if (s[1].unicode() == 'y') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'e') { + return Lexer::T_BYTE; + } + } + } + } + else if (s[0].unicode() == 'c') { + if (s[1].unicode() == 'a') { + if (s[2].unicode() == 's') { + if (s[3].unicode() == 'e') { + return Lexer::T_CASE; + } + } + } + else if (s[1].unicode() == 'h') { + if (s[2].unicode() == 'a') { + if (s[3].unicode() == 'r') { + return Lexer::T_CHAR; + } + } + } + } + else if (s[0].unicode() == 'e') { + if (s[1].unicode() == 'l') { + if (s[2].unicode() == 's') { + if (s[3].unicode() == 'e') { + return Lexer::T_ELSE; + } + } + } + else if (s[1].unicode() == 'n') { + if (s[2].unicode() == 'u') { + if (s[3].unicode() == 'm') { + return Lexer::T_ENUM; + } + } + } + } + else if (s[0].unicode() == 'g') { + if (s[1].unicode() == 'o') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'o') { + return Lexer::T_GOTO; + } + } + } + } + else if (s[0].unicode() == 'l') { + if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'n') { + if (s[3].unicode() == 'g') { + return Lexer::T_LONG; + } + } + } + } + else if (s[0].unicode() == 'n') { + if (s[1].unicode() == 'u') { + if (s[2].unicode() == 'l') { + if (s[3].unicode() == 'l') { + return Lexer::T_NULL; + } + } + } + } + else if (s[0].unicode() == 't') { + if (s[1].unicode() == 'h') { + if (s[2].unicode() == 'i') { + if (s[3].unicode() == 's') { + return Lexer::T_THIS; + } + } + } + else if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'u') { + if (s[3].unicode() == 'e') { + return Lexer::T_TRUE; + } + } + } + } + else if (s[0].unicode() == 'v') { + if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'i') { + if (s[3].unicode() == 'd') { + return Lexer::T_VOID; + } + } + } + } + else if (s[0].unicode() == 'w') { + if (s[1].unicode() == 'i') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'h') { + return Lexer::T_WITH; + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify5(const QChar *s) { + if (s[0].unicode() == 'b') { + if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'e') { + if (s[3].unicode() == 'a') { + if (s[4].unicode() == 'k') { + return Lexer::T_BREAK; + } + } + } + } + } + else if (s[0].unicode() == 'c') { + if (s[1].unicode() == 'a') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'c') { + if (s[4].unicode() == 'h') { + return Lexer::T_CATCH; + } + } + } + } + else if (s[1].unicode() == 'l') { + if (s[2].unicode() == 'a') { + if (s[3].unicode() == 's') { + if (s[4].unicode() == 's') { + return Lexer::T_CLASS; + } + } + } + } + else if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'n') { + if (s[3].unicode() == 's') { + if (s[4].unicode() == 't') { + return Lexer::T_CONST; + } + } + } + } + } + else if (s[0].unicode() == 'f') { + if (s[1].unicode() == 'a') { + if (s[2].unicode() == 'l') { + if (s[3].unicode() == 's') { + if (s[4].unicode() == 'e') { + return Lexer::T_FALSE; + } + } + } + } + else if (s[1].unicode() == 'i') { + if (s[2].unicode() == 'n') { + if (s[3].unicode() == 'a') { + if (s[4].unicode() == 'l') { + return Lexer::T_FINAL; + } + } + } + } + else if (s[1].unicode() == 'l') { + if (s[2].unicode() == 'o') { + if (s[3].unicode() == 'a') { + if (s[4].unicode() == 't') { + return Lexer::T_FLOAT; + } + } + } + } + } + else if (s[0].unicode() == 's') { + if (s[1].unicode() == 'h') { + if (s[2].unicode() == 'o') { + if (s[3].unicode() == 'r') { + if (s[4].unicode() == 't') { + return Lexer::T_SHORT; + } + } + } + } + else if (s[1].unicode() == 'u') { + if (s[2].unicode() == 'p') { + if (s[3].unicode() == 'e') { + if (s[4].unicode() == 'r') { + return Lexer::T_SUPER; + } + } + } + } + } + else if (s[0].unicode() == 't') { + if (s[1].unicode() == 'h') { + if (s[2].unicode() == 'r') { + if (s[3].unicode() == 'o') { + if (s[4].unicode() == 'w') { + return Lexer::T_THROW; + } + } + } + } + } + else if (s[0].unicode() == 'w') { + if (s[1].unicode() == 'h') { + if (s[2].unicode() == 'i') { + if (s[3].unicode() == 'l') { + if (s[4].unicode() == 'e') { + return Lexer::T_WHILE; + } + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify6(const QChar *s) { + if (s[0].unicode() == 'd') { + if (s[1].unicode() == 'e') { + if (s[2].unicode() == 'l') { + if (s[3].unicode() == 'e') { + if (s[4].unicode() == 't') { + if (s[5].unicode() == 'e') { + return Lexer::T_DELETE; + } + } + } + } + } + else if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'u') { + if (s[3].unicode() == 'b') { + if (s[4].unicode() == 'l') { + if (s[5].unicode() == 'e') { + return Lexer::T_DOUBLE; + } + } + } + } + } + } + else if (s[0].unicode() == 'e') { + if (s[1].unicode() == 'x') { + if (s[2].unicode() == 'p') { + if (s[3].unicode() == 'o') { + if (s[4].unicode() == 'r') { + if (s[5].unicode() == 't') { + return Lexer::T_EXPORT; + } + } + } + } + } + } + else if (s[0].unicode() == 'i') { + if (s[1].unicode() == 'm') { + if (s[2].unicode() == 'p') { + if (s[3].unicode() == 'o') { + if (s[4].unicode() == 'r') { + if (s[5].unicode() == 't') { + return Lexer::T_IMPORT; + } + } + } + } + } + } + else if (s[0].unicode() == 'n') { + if (s[1].unicode() == 'a') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'i') { + if (s[4].unicode() == 'v') { + if (s[5].unicode() == 'e') { + return Lexer::T_NATIVE; + } + } + } + } + } + } + else if (s[0].unicode() == 'p') { + if (s[1].unicode() == 'u') { + if (s[2].unicode() == 'b') { + if (s[3].unicode() == 'l') { + if (s[4].unicode() == 'i') { + if (s[5].unicode() == 'c') { + return Lexer::T_PUBLIC; + } + } + } + } + } + } + else if (s[0].unicode() == 'r') { + if (s[1].unicode() == 'e') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'u') { + if (s[4].unicode() == 'r') { + if (s[5].unicode() == 'n') { + return Lexer::T_RETURN; + } + } + } + } + } + } + else if (s[0].unicode() == 's') { + if (s[1].unicode() == 'i') { + if (s[2].unicode() == 'g') { + if (s[3].unicode() == 'n') { + if (s[4].unicode() == 'a') { + if (s[5].unicode() == 'l') { + return Lexer::T_SIGNAL; + } + } + } + } + } + else if (s[1].unicode() == 't') { + if (s[2].unicode() == 'a') { + if (s[3].unicode() == 't') { + if (s[4].unicode() == 'i') { + if (s[5].unicode() == 'c') { + return Lexer::T_STATIC; + } + } + } + } + } + else if (s[1].unicode() == 'w') { + if (s[2].unicode() == 'i') { + if (s[3].unicode() == 't') { + if (s[4].unicode() == 'c') { + if (s[5].unicode() == 'h') { + return Lexer::T_SWITCH; + } + } + } + } + } + } + else if (s[0].unicode() == 't') { + if (s[1].unicode() == 'h') { + if (s[2].unicode() == 'r') { + if (s[3].unicode() == 'o') { + if (s[4].unicode() == 'w') { + if (s[5].unicode() == 's') { + return Lexer::T_THROWS; + } + } + } + } + } + else if (s[1].unicode() == 'y') { + if (s[2].unicode() == 'p') { + if (s[3].unicode() == 'e') { + if (s[4].unicode() == 'o') { + if (s[5].unicode() == 'f') { + return Lexer::T_TYPEOF; + } + } + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify7(const QChar *s) { + if (s[0].unicode() == 'b') { + if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'o') { + if (s[3].unicode() == 'l') { + if (s[4].unicode() == 'e') { + if (s[5].unicode() == 'a') { + if (s[6].unicode() == 'n') { + return Lexer::T_BOOLEAN; + } + } + } + } + } + } + } + else if (s[0].unicode() == 'd') { + if (s[1].unicode() == 'e') { + if (s[2].unicode() == 'f') { + if (s[3].unicode() == 'a') { + if (s[4].unicode() == 'u') { + if (s[5].unicode() == 'l') { + if (s[6].unicode() == 't') { + return Lexer::T_DEFAULT; + } + } + } + } + } + } + } + else if (s[0].unicode() == 'e') { + if (s[1].unicode() == 'x') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'e') { + if (s[4].unicode() == 'n') { + if (s[5].unicode() == 'd') { + if (s[6].unicode() == 's') { + return Lexer::T_EXTENDS; + } + } + } + } + } + } + } + else if (s[0].unicode() == 'f') { + if (s[1].unicode() == 'i') { + if (s[2].unicode() == 'n') { + if (s[3].unicode() == 'a') { + if (s[4].unicode() == 'l') { + if (s[5].unicode() == 'l') { + if (s[6].unicode() == 'y') { + return Lexer::T_FINALLY; + } + } + } + } + } + } + } + else if (s[0].unicode() == 'p') { + if (s[1].unicode() == 'a') { + if (s[2].unicode() == 'c') { + if (s[3].unicode() == 'k') { + if (s[4].unicode() == 'a') { + if (s[5].unicode() == 'g') { + if (s[6].unicode() == 'e') { + return Lexer::T_PACKAGE; + } + } + } + } + } + } + else if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'i') { + if (s[3].unicode() == 'v') { + if (s[4].unicode() == 'a') { + if (s[5].unicode() == 't') { + if (s[6].unicode() == 'e') { + return Lexer::T_PRIVATE; + } + } + } + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify8(const QChar *s) { + if (s[0].unicode() == 'a') { + if (s[1].unicode() == 'b') { + if (s[2].unicode() == 's') { + if (s[3].unicode() == 't') { + if (s[4].unicode() == 'r') { + if (s[5].unicode() == 'a') { + if (s[6].unicode() == 'c') { + if (s[7].unicode() == 't') { + return Lexer::T_ABSTRACT; + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 'c') { + if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'n') { + if (s[3].unicode() == 't') { + if (s[4].unicode() == 'i') { + if (s[5].unicode() == 'n') { + if (s[6].unicode() == 'u') { + if (s[7].unicode() == 'e') { + return Lexer::T_CONTINUE; + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 'd') { + if (s[1].unicode() == 'e') { + if (s[2].unicode() == 'b') { + if (s[3].unicode() == 'u') { + if (s[4].unicode() == 'g') { + if (s[5].unicode() == 'g') { + if (s[6].unicode() == 'e') { + if (s[7].unicode() == 'r') { + return Lexer::T_DEBUGGER; + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 'f') { + if (s[1].unicode() == 'u') { + if (s[2].unicode() == 'n') { + if (s[3].unicode() == 'c') { + if (s[4].unicode() == 't') { + if (s[5].unicode() == 'i') { + if (s[6].unicode() == 'o') { + if (s[7].unicode() == 'n') { + return Lexer::T_FUNCTION; + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 'p') { + if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'o') { + if (s[3].unicode() == 'p') { + if (s[4].unicode() == 'e') { + if (s[5].unicode() == 'r') { + if (s[6].unicode() == 't') { + if (s[7].unicode() == 'y') { + return Lexer::T_PROPERTY; + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 'r') { + if (s[1].unicode() == 'e') { + if (s[2].unicode() == 'a') { + if (s[3].unicode() == 'd') { + if (s[4].unicode() == 'o') { + if (s[5].unicode() == 'n') { + if (s[6].unicode() == 'l') { + if (s[7].unicode() == 'y') { + return Lexer::T_READONLY; + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 'v') { + if (s[1].unicode() == 'o') { + if (s[2].unicode() == 'l') { + if (s[3].unicode() == 'a') { + if (s[4].unicode() == 't') { + if (s[5].unicode() == 'i') { + if (s[6].unicode() == 'l') { + if (s[7].unicode() == 'e') { + return Lexer::T_VOLATILE; + } + } + } + } + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify9(const QChar *s) { + if (s[0].unicode() == 'i') { + if (s[1].unicode() == 'n') { + if (s[2].unicode() == 't') { + if (s[3].unicode() == 'e') { + if (s[4].unicode() == 'r') { + if (s[5].unicode() == 'f') { + if (s[6].unicode() == 'a') { + if (s[7].unicode() == 'c') { + if (s[8].unicode() == 'e') { + return Lexer::T_INTERFACE; + } + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 'p') { + if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'o') { + if (s[3].unicode() == 't') { + if (s[4].unicode() == 'e') { + if (s[5].unicode() == 'c') { + if (s[6].unicode() == 't') { + if (s[7].unicode() == 'e') { + if (s[8].unicode() == 'd') { + return Lexer::T_PROTECTED; + } + } + } + } + } + } + } + } + } + else if (s[0].unicode() == 't') { + if (s[1].unicode() == 'r') { + if (s[2].unicode() == 'a') { + if (s[3].unicode() == 'n') { + if (s[4].unicode() == 's') { + if (s[5].unicode() == 'i') { + if (s[6].unicode() == 'e') { + if (s[7].unicode() == 'n') { + if (s[8].unicode() == 't') { + return Lexer::T_TRANSIENT; + } + } + } + } + } + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify10(const QChar *s) { + if (s[0].unicode() == 'i') { + if (s[1].unicode() == 'm') { + if (s[2].unicode() == 'p') { + if (s[3].unicode() == 'l') { + if (s[4].unicode() == 'e') { + if (s[5].unicode() == 'm') { + if (s[6].unicode() == 'e') { + if (s[7].unicode() == 'n') { + if (s[8].unicode() == 't') { + if (s[9].unicode() == 's') { + return Lexer::T_IMPLEMENTS; + } + } + } + } + } + } + } + } + } + else if (s[1].unicode() == 'n') { + if (s[2].unicode() == 's') { + if (s[3].unicode() == 't') { + if (s[4].unicode() == 'a') { + if (s[5].unicode() == 'n') { + if (s[6].unicode() == 'c') { + if (s[7].unicode() == 'e') { + if (s[8].unicode() == 'o') { + if (s[9].unicode() == 'f') { + return Lexer::T_INSTANCEOF; + } + } + } + } + } + } + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +static inline int classify12(const QChar *s) { + if (s[0].unicode() == 's') { + if (s[1].unicode() == 'y') { + if (s[2].unicode() == 'n') { + if (s[3].unicode() == 'c') { + if (s[4].unicode() == 'h') { + if (s[5].unicode() == 'r') { + if (s[6].unicode() == 'o') { + if (s[7].unicode() == 'n') { + if (s[8].unicode() == 'i') { + if (s[9].unicode() == 'z') { + if (s[10].unicode() == 'e') { + if (s[11].unicode() == 'd') { + return Lexer::T_SYNCHRONIZED; + } + } + } + } + } + } + } + } + } + } + } + } + return Lexer::T_IDENTIFIER; +} + +int Lexer::classify(const QChar *s, int n) { + switch (n) { + case 2: return classify2(s); + case 3: return classify3(s); + case 4: return classify4(s); + case 5: return classify5(s); + case 6: return classify6(s); + case 7: return classify7(s); + case 8: return classify8(s); + case 9: return classify9(s); + case 10: return classify10(s); + case 12: return classify12(s); + default: return Lexer::T_IDENTIFIER; + } // switch +} + +#endif // QDECLARATIVEJSKEYWORDS_P_H diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index 4d68f289bc..d466140949 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -39,1220 +39,1005 @@ ** ****************************************************************************/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include "qdeclarativejslexer_p.h" - -#include "qdeclarativejsglobal_p.h" #include "qdeclarativejsengine_p.h" -#include "qdeclarativejsgrammar_p.h" - -#include <QtCore/qcoreapplication.h> +#include "qdeclarativejsmemorypool_p.h" -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> +#include <private/qdeclarativeutils_p.h> +#include <QtCore/QCoreApplication> +#include <QtCore/QVarLengthArray> +#include <QtCore/QDebug> QT_BEGIN_NAMESPACE Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); QT_END_NAMESPACE -QT_QML_BEGIN_NAMESPACE +using namespace QDeclarativeJS; -#define shiftWindowsLineBreak() \ - do { \ - if (((current == '\r') && (next1 == '\n')) \ - || ((current == '\n') && (next1 == '\r'))) { \ - shift(1); \ - } \ - } \ - while (0) +enum RegExpFlag { + Global = 0x01, + IgnoreCase = 0x02, + Multiline = 0x04 +}; -namespace QDeclarativeJS { -extern double integerFromString(const char *buf, int size, int radix); +static int flagFromChar(const QChar &ch) +{ + switch (ch.unicode()) { + case 'g': return Global; + case 'i': return IgnoreCase; + case 'm': return Multiline; + } + return 0; } -using namespace QDeclarativeJS; +static unsigned char convertHex(ushort c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'a' && c <= 'f') + return (c - 'a' + 10); + else + return (c - 'A' + 10); +} -Lexer::Lexer(Engine *eng, bool tokenizeComments) - : driver(eng), - yylineno(0), - done(false), - size8(128), size16(128), - pos8(0), pos16(0), - terminator(false), - restrKeyword(false), - delimited(false), - stackToken(-1), - state(Start), - pos(0), - code(0), length(0), - yycolumn(0), - startpos(0), - startlineno(0), startcolumn(0), - bol(true), - current(0), next1(0), next2(0), next3(0), - err(NoError), - wantRx(false), - check_reserved(true), - parenthesesState(IgnoreParentheses), - parenthesesCount(0), - prohibitAutomaticSemicolon(false), - tokenizeComments(tokenizeComments) +static QChar convertHex(QChar c1, QChar c2) { - if (driver) driver->setLexer(this); - // allocate space for read buffers - buffer8 = new char[size8]; - buffer16 = new QChar[size16]; - pattern = 0; - flags = 0; + return QChar((convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); +} +static QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4) +{ + return QChar((convertHex(c3.unicode()) << 4) + convertHex(c4.unicode()), + (convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); } -Lexer::~Lexer() +Lexer::Lexer(Engine *engine) + : _engine(engine) + , _codePtr(0) + , _lastLinePtr(0) + , _tokenLinePtr(0) + , _tokenStartPtr(0) + , _char(QLatin1Char('\n')) + , _errorCode(NoError) + , _currentLineNumber(0) + , _tokenValue(0) + , _parenthesesState(IgnoreParentheses) + , _parenthesesCount(0) + , _stackToken(-1) + , _patternFlags(0) + , _tokenLength(0) + , _tokenLine(0) + , _validTokenText(false) + , _prohibitAutomaticSemicolon(false) + , _restrictedKeyword(false) + , _terminator(false) + , _delimited(false) { - delete [] buffer8; - delete [] buffer16; + if (engine) + engine->setLexer(this); } -void Lexer::setCode(const QString &c, int lineno) +QString Lexer::code() const { - errmsg.clear(); - yylineno = lineno; - yycolumn = 1; - restrKeyword = false; - delimited = false; - stackToken = -1; - pos = 0; - code = c.unicode(); - length = c.length(); - bol = true; - - // read first characters - current = (length > 0) ? code[0].unicode() : 0; - next1 = (length > 1) ? code[1].unicode() : 0; - next2 = (length > 2) ? code[2].unicode() : 0; - next3 = (length > 3) ? code[3].unicode() : 0; + return _code; } -void Lexer::shift(uint p) +void Lexer::setCode(const QString &code, int lineno) { - while (p--) { - ++pos; - ++yycolumn; - current = next1; - next1 = next2; - next2 = next3; - next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0; - } + if (_engine) + _engine->setCode(code); + + _code = code; + _tokenText.clear(); + _tokenText.reserve(1024); + _errorMessage.clear(); + _tokenSpell = QStringRef(); + + _codePtr = code.unicode(); + _lastLinePtr = _codePtr; + _tokenLinePtr = _codePtr; + _tokenStartPtr = _codePtr; + + _char = QLatin1Char('\n'); + _errorCode = NoError; + + _currentLineNumber = lineno; + _tokenValue = 0; + + // parentheses state + _parenthesesState = IgnoreParentheses; + _parenthesesCount = 0; + + _stackToken = -1; + + _patternFlags = 0; + _tokenLength = 0; + _tokenLine = lineno; + + _validTokenText = false; + _prohibitAutomaticSemicolon = false; + _restrictedKeyword = false; + _terminator = false; + _delimited = false; } -void Lexer::setDone(State s) +void Lexer::scanChar() { - state = s; - done = true; + _char = *_codePtr++; + + if (_char == QLatin1Char('\n')) { + _lastLinePtr = _codePtr; // points to the first character after the newline + ++_currentLineNumber; + } } -int Lexer::findReservedWord(const QChar *c, int size) const +int Lexer::lex() { - switch (size) { - case 2: { - if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')) - return QDeclarativeJSGrammar::T_DO; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f')) - return QDeclarativeJSGrammar::T_IF; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')) - return QDeclarativeJSGrammar::T_IN; - else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s')) - return QDeclarativeJSGrammar::T_AS; - else if (c[0] == QLatin1Char('o') && c[1] == QLatin1Char('n')) - return QDeclarativeJSGrammar::T_ON; - } break; - - case 3: { - if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r')) - return QDeclarativeJSGrammar::T_FOR; - else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w')) - return QDeclarativeJSGrammar::T_NEW; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y')) - return QDeclarativeJSGrammar::T_TRY; - else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r')) - return QDeclarativeJSGrammar::T_VAR; - else if (check_reserved) { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 4: { - if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_CASE; - else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_ELSE; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s')) - return QDeclarativeJSGrammar::T_THIS; - else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d')) - return QDeclarativeJSGrammar::T_VOID; - else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h')) - return QDeclarativeJSGrammar::T_WITH; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_TRUE; - else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l')) - return QDeclarativeJSGrammar::T_NULL; - else if (check_reserved) { - if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n') - && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 5: { - if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('k')) - return QDeclarativeJSGrammar::T_BREAK; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c') - && c[4] == QLatin1Char('h')) - return QDeclarativeJSGrammar::T_CATCH; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('w')) - return QDeclarativeJSGrammar::T_THROW; - else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_WHILE; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s') - && c[4] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_CONST; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s') - && c[4] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_FALSE; - else if (check_reserved) { - if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r') - && c[4] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('r')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('l')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s') - && c[4] == QLatin1Char('s')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 6: { - if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_DELETE; - else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n')) - return QDeclarativeJSGrammar::T_RETURN; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h')) - return QDeclarativeJSGrammar::T_SWITCH; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f')) - return QDeclarativeJSGrammar::T_TYPEOF; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_IMPORT; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l')) - return QDeclarativeJSGrammar::T_SIGNAL; - else if (check_reserved) { - if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b') - && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) - return QDeclarativeJSGrammar::T_PUBLIC; - else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i') - && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') - && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') - && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 7: { - if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l') - && c[6] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_DEFAULT; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l') - && c[6] == QLatin1Char('y')) - return QDeclarativeJSGrammar::T_FINALLY; - else if (check_reserved) { - if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a') - && c[6] == QLatin1Char('n')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d') - && c[6] == QLatin1Char('s')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a') - && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g') - && c[6] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t') - && c[6] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 8: { - if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n') - && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_CONTINUE; - else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') - && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') - && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')) - return QDeclarativeJSGrammar::T_FUNCTION; - else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u') - && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g') - && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r')) - return QDeclarativeJSGrammar::T_DEBUGGER; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r') - && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y')) - return QDeclarativeJSGrammar::T_PROPERTY; - else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('d') - && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('n') - && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('y')) - return QDeclarativeJSGrammar::T_READONLY; - else if (check_reserved) { - if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a') - && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') - && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a') - && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') - && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 9: { - if (check_reserved) { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') - && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') - && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f') - && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c') - && c[8] == QLatin1Char('e')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n') - && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i') - && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') - && c[8] == QLatin1Char('t')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') - && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c') - && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e') - && c[8] == QLatin1Char('d')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 10: { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') - && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') - && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n') - && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e') - && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f')) - return QDeclarativeJSGrammar::T_INSTANCEOF; - else if (check_reserved) { - if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') - && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l') - && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m') - && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') - && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; - } - } break; - - case 12: { - if (check_reserved) { - if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y') - && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') - && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r') - && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n') - && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z') - && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d')) - return QDeclarativeJSGrammar::T_RESERVED_WORD; + _tokenSpell = QStringRef(); + int token = scanToken(); + _tokenLength = _codePtr - _tokenStartPtr - 1; + + _delimited = false; + _restrictedKeyword = false; + + // update the flags + switch (token) { + case T_LBRACE: + case T_SEMICOLON: + _delimited = true; + break; + + case T_IF: + case T_FOR: + case T_WHILE: + case T_WITH: + _parenthesesState = CountParentheses; + _parenthesesCount = 0; + break; + + case T_DO: + _parenthesesState = BalancedParentheses; + break; + + case T_CONTINUE: + case T_BREAK: + case T_RETURN: + case T_THROW: + _restrictedKeyword = true; + break; + } // switch + + // update the parentheses state + switch (_parenthesesState) { + case IgnoreParentheses: + break; + + case CountParentheses: + if (token == T_RPAREN) { + --_parenthesesCount; + if (_parenthesesCount == 0) + _parenthesesState = BalancedParentheses; + } else if (token == T_LPAREN) { + ++_parenthesesCount; } - } break; + break; + case BalancedParentheses: + _parenthesesState = IgnoreParentheses; + break; } // switch - return -1; + return token; } -int Lexer::lex() +bool Lexer::isUnicodeEscapeSequence(const QChar *chars) +{ + if (isHexDigit(chars[0]) && isHexDigit(chars[1]) && isHexDigit(chars[2]) && isHexDigit(chars[3])) + return true; + + return false; +} + +QChar Lexer::decodeUnicodeEscapeCharacter(bool *ok) +{ + if (_char == QLatin1Char('u') && isUnicodeEscapeSequence(&_codePtr[0])) { + scanChar(); // skip u + + const QChar c1 = _char; + scanChar(); + + const QChar c2 = _char; + scanChar(); + + const QChar c3 = _char; + scanChar(); + + const QChar c4 = _char; + scanChar(); + + if (ok) + *ok = true; + + return convertUnicode(c1, c2, c3, c4); + } + + *ok = false; + return QChar(); +} + +int Lexer::scanToken() { - int token = 0; - state = Start; - ushort stringType = 0; // either single or double quotes - bool multiLineString = false; - pos8 = pos16 = 0; - done = false; - terminator = false; - - // did we push a token on the stack previously ? - // (after an automatic semicolon insertion) - if (stackToken >= 0) { - setDone(Other); - token = stackToken; - stackToken = -1; + if (_stackToken != -1) { + int tk = _stackToken; + _stackToken = -1; + return tk; } - bool identifierWithEscapedUnicode = false; - - while (!done) { - switch (state) { - case Start: - if (isWhiteSpace()) { - // do nothing - } else if (current == '/' && next1 == '/') { - recordStartPos(); - shift(1); - state = InSingleLineComment; - } else if (current == '/' && next1 == '*') { - recordStartPos(); - shift(1); - state = InMultiLineComment; - } else if (current == 0) { - syncProhibitAutomaticSemicolon(); - if (!terminator && !delimited && !prohibitAutomaticSemicolon) { - // automatic semicolon insertion if program incomplete - token = QDeclarativeJSGrammar::T_SEMICOLON; - stackToken = 0; - setDone(Other); - } else { - setDone(Eof); - } - } else if (isLineTerminator()) { - if (restrKeyword) { - // automatic semicolon insertion - recordStartPos(); - token = QDeclarativeJSGrammar::T_SEMICOLON; - setDone(Other); - } else { - shiftWindowsLineBreak(); - yylineno++; - yycolumn = 0; - bol = true; - terminator = true; - syncProhibitAutomaticSemicolon(); - } - } else if (current == '"' || current == '\'') { - recordStartPos(); - state = InString; - multiLineString = false; - stringType = current; - } else if (current == '\\' && next1 == 'u') { - identifierWithEscapedUnicode = true; - recordStartPos(); - - shift(2); // skip the unicode escape prefix `\u' - - if (isHexDigit(current) && isHexDigit(next1) && - isHexDigit(next2) && isHexDigit(next3)) { - record16(convertUnicode(current, next1, next2, next3)); - shift(3); - state = InIdentifier; - } else { - setDone(Bad); - err = IllegalUnicodeEscapeSequence; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence"); - break; - } + _terminator = false; + +again: + _validTokenText = false; + _tokenLinePtr = _lastLinePtr; - } else if (isIdentLetter(current)) { - identifierWithEscapedUnicode = false; - recordStartPos(); - record16(current); - state = InIdentifier; - } else if (current == '0') { - recordStartPos(); - record8(current); - state = InNum0; - } else if (isDecimalDigit(current)) { - recordStartPos(); - record8(current); - state = InNum; - } else if (current == '.' && isDecimalDigit(next1)) { - recordStartPos(); - record8(current); - state = InDecimal; + while (QDeclarativeUtils::isSpace(_char)) { + if (_char == QLatin1Char('\n')) { + _tokenLinePtr = _codePtr; + + if (_restrictedKeyword) { + // automatic semicolon insertion + _tokenLine = _currentLineNumber; + _tokenStartPtr = _codePtr - 1; // ### TODO: insert it before the optional \r sequence. + return T_SEMICOLON; } else { - recordStartPos(); - token = matchPunctuator(current, next1, next2, next3); - if (token != -1) { - if (terminator && !delimited && !prohibitAutomaticSemicolon - && (token == QDeclarativeJSGrammar::T_PLUS_PLUS - || token == QDeclarativeJSGrammar::T_MINUS_MINUS)) { - // automatic semicolon insertion - stackToken = token; - token = QDeclarativeJSGrammar::T_SEMICOLON; - } - setDone(Other); - } - else { - setDone(Bad); - err = IllegalCharacter; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal character"); + _terminator = true; + syncProhibitAutomaticSemicolon(); + } + } + + scanChar(); + } + + _tokenStartPtr = _codePtr - 1; + _tokenLine = _currentLineNumber; + + if (_char.isNull()) + return EOF_SYMBOL; + + const QChar ch = _char; + scanChar(); + + switch (ch.unicode()) { + case '~': return T_TILDE; + case '}': return T_RBRACE; + + case '|': + if (_char == QLatin1Char('|')) { + scanChar(); + return T_OR_OR; + } else if (_char == QLatin1Char('=')) { + scanChar(); + return T_OR_EQ; + } + return T_OR; + + case '{': return T_LBRACE; + + case '^': + if (_char == QLatin1Char('=')) { + scanChar(); + return T_XOR_EQ; + } + return T_XOR; + + case ']': return T_RBRACKET; + case '[': return T_LBRACKET; + case '?': return T_QUESTION; + + case '>': + if (_char == QLatin1Char('>')) { + scanChar(); + if (_char == QLatin1Char('>')) { + scanChar(); + if (_char == QLatin1Char('=')) { + scanChar(); + return T_GT_GT_GT_EQ; } + return T_GT_GT_GT; + } else if (_char == QLatin1Char('=')) { + scanChar(); + return T_GT_GT_EQ; } - break; - case InString: - if (current == stringType) { - shift(1); - setDone(String); - } else if (isLineTerminator()) { - multiLineString = true; - record16(current); - } else if (current == 0 || isLineTerminator()) { - setDone(Bad); - err = UnclosedStringLiteral; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed string at end of line"); - } else if (current == '\\') { - state = InEscapeSequence; - } else { - record16(current); + return T_GT_GT; + } else if (_char == QLatin1Char('=')) { + scanChar(); + return T_GE; + } + return T_GT; + + case '=': + if (_char == QLatin1Char('=')) { + scanChar(); + if (_char == QLatin1Char('=')) { + scanChar(); + return T_EQ_EQ_EQ; } - break; - // Escape Sequences inside of strings - case InEscapeSequence: - if (isOctalDigit(current)) { - if (current >= '0' && current <= '3' && - isOctalDigit(next1) && isOctalDigit(next2)) { - record16(convertOctal(current, next1, next2)); - shift(2); - state = InString; - } else if (isOctalDigit(current) && - isOctalDigit(next1)) { - record16(convertOctal('0', current, next1)); - shift(1); - state = InString; - } else if (isOctalDigit(current)) { - record16(convertOctal('0', '0', current)); - state = InString; - } else { - setDone(Bad); - err = IllegalEscapeSequence; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal escape sequence"); - } - } else if (current == 'x') - state = InHexEscape; - else if (current == 'u') - state = InUnicodeEscape; - else { - if (isLineTerminator()) { - shiftWindowsLineBreak(); - yylineno++; - yycolumn = 0; - bol = true; + return T_EQ_EQ; + } + return T_EQ; + + case '<': + if (_char == QLatin1Char('=')) { + scanChar(); + return T_LE; + } else if (_char == QLatin1Char('<')) { + scanChar(); + if (_char == QLatin1Char('=')) { + scanChar(); + return T_LT_LT_EQ; + } + return T_LT_LT; + } + return T_LT; + + case ';': return T_SEMICOLON; + case ':': return T_COLON; + + case '/': + if (_char == QLatin1Char('*')) { + scanChar(); + while (!_char.isNull()) { + if (_char == QLatin1Char('*')) { + scanChar(); + if (_char == QLatin1Char('/')) { + scanChar(); + + if (_engine) { + _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4, + tokenStartLine(), tokenStartColumn() + 2); + } + + goto again; + } } else { - record16(singleEscape(current)); + scanChar(); } - state = InString; - } - break; - case InHexEscape: - if (isHexDigit(current) && isHexDigit(next1)) { - state = InString; - record16(QLatin1Char(convertHex(current, next1))); - shift(1); - } else if (current == stringType) { - record16(QLatin1Char('x')); - shift(1); - setDone(String); - } else { - record16(QLatin1Char('x')); - record16(current); - state = InString; } - break; - case InUnicodeEscape: - if (isHexDigit(current) && isHexDigit(next1) && - isHexDigit(next2) && isHexDigit(next3)) { - record16(convertUnicode(current, next1, next2, next3)); - shift(3); - state = InString; - } else if (current == stringType) { - record16(QLatin1Char('u')); - shift(1); - setDone(String); - } else { - setDone(Bad); - err = IllegalUnicodeEscapeSequence; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence"); + } else if (_char == QLatin1Char('/')) { + while (!_char.isNull() && _char != QLatin1Char('\n')) { + scanChar(); } - break; - case InSingleLineComment: - if (isLineTerminator()) { - shiftWindowsLineBreak(); - yylineno++; - yycolumn = 0; - terminator = true; - bol = true; - if (restrKeyword) { - token = QDeclarativeJSGrammar::T_SEMICOLON; - setDone(Other); - } else - state = Start; - if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2); - } else if (current == 0) { - if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2); - setDone(Eof); + if (_engine) { + _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2, + tokenStartLine(), tokenStartColumn() + 2); } + goto again; + } if (_char == QLatin1Char('=')) { + scanChar(); + return T_DIVIDE_EQ; + } + return T_DIVIDE_; - break; - case InMultiLineComment: - if (current == 0) { - setDone(Bad); - err = UnclosedComment; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Unclosed comment at end of file"); - if (driver) driver->addComment(startpos+2, tokenLength()-2, startlineno, startcolumn+2); - } else if (isLineTerminator()) { - shiftWindowsLineBreak(); - yylineno++; - } else if (current == '*' && next1 == '/') { - state = Start; - shift(1); - if (driver) driver->addComment(startpos+2, tokenLength()-3, startlineno, startcolumn+2); + case '.': + if (QDeclarativeUtils::isDigit(_char)) { + QVarLengthArray<char,32> chars; + + chars.append(ch.unicode()); // append the `.' + + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); + scanChar(); } - break; - case InIdentifier: - if (isIdentLetter(current) || isDecimalDigit(current)) { - record16(current); - break; - } else if (current == '\\' && next1 == 'u') { - identifierWithEscapedUnicode = true; - shift(2); // skip the unicode escape prefix `\u' - - if (isHexDigit(current) && isHexDigit(next1) && - isHexDigit(next2) && isHexDigit(next3)) { - record16(convertUnicode(current, next1, next2, next3)); - shift(3); - break; - } else { - setDone(Bad); - err = IllegalUnicodeEscapeSequence; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence"); - break; + if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { + if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && + QDeclarativeUtils::isDigit(_codePtr[1]))) { + + chars.append(_char.unicode()); + scanChar(); // consume `e' + + if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { + chars.append(_char.unicode()); + scanChar(); // consume the sign + } + + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); + scanChar(); + } } } - setDone(Identifier); - break; - case InNum0: - if (current == 'x' || current == 'X') { - record8(current); - state = InHex; - } else if (current == '.') { - record8(current); - state = InDecimal; - } else if (current == 'e' || current == 'E') { - record8(current); - state = InExponentIndicator; - } else if (isOctalDigit(current)) { - record8(current); - state = InOctal; - } else if (isDecimalDigit(current)) { - record8(current); - state = InDecimal; - } else { - setDone(Number); - } - break; - case InHex: - if (isHexDigit(current)) - record8(current); - else - setDone(Hex); - break; - case InOctal: - if (isOctalDigit(current)) { - record8(current); - } else if (isDecimalDigit(current)) { - record8(current); - state = InDecimal; - } else { - setDone(Octal); + + chars.append('\0'); + + const char *begin = chars.constData(); + const char *end = 0; + bool ok = false; + + _tokenValue = qstrtod(begin, &end, &ok); + + if (end - begin != chars.size() - 1) { + _errorCode = IllegalExponentIndicator; + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number"); + return T_ERROR; } - break; - case InNum: - if (isDecimalDigit(current)) { - record8(current); - } else if (current == '.') { - record8(current); - state = InDecimal; - } else if (current == 'e' || current == 'E') { - record8(current); - state = InExponentIndicator; - } else { - setDone(Number); + + return T_NUMERIC_LITERAL; + } + return T_DOT; + + case '-': + if (_char == QLatin1Char('=')) { + scanChar(); + return T_MINUS_EQ; + } else if (_char == QLatin1Char('-')) { + scanChar(); + + if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) { + _stackToken = T_PLUS_PLUS; + return T_SEMICOLON; } - break; - case InDecimal: - if (isDecimalDigit(current)) { - record8(current); - } else if (current == 'e' || current == 'E') { - record8(current); - state = InExponentIndicator; - } else { - setDone(Number); + + return T_MINUS_MINUS; + } + return T_MINUS; + + case ',': return T_COMMA; + + case '+': + if (_char == QLatin1Char('=')) { + scanChar(); + return T_PLUS_EQ; + } else if (_char == QLatin1Char('+')) { + scanChar(); + + if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) { + _stackToken = T_PLUS_PLUS; + return T_SEMICOLON; } - break; - case InExponentIndicator: - if (current == '+' || current == '-') { - record8(current); - } else if (isDecimalDigit(current)) { - record8(current); - state = InExponent; - } else { - setDone(Bad); - err = IllegalExponentIndicator; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number"); + + return T_PLUS_PLUS; + } + return T_PLUS; + + case '*': + if (_char == QLatin1Char('=')) { + scanChar(); + return T_STAR_EQ; + } + return T_STAR; + + case ')': return T_RPAREN; + case '(': return T_LPAREN; + + case '&': + if (_char == QLatin1Char('=')) { + scanChar(); + return T_AND_EQ; + } else if (_char == QLatin1Char('&')) { + scanChar(); + return T_AND_AND; + } + return T_AND; + + case '%': + if (_char == QLatin1Char('=')) { + scanChar(); + return T_REMAINDER_EQ; + } + return T_REMAINDER; + + case '!': + if (_char == QLatin1Char('=')) { + scanChar(); + if (_char == QLatin1Char('=')) { + scanChar(); + return T_NOT_EQ_EQ; } - break; - case InExponent: - if (isDecimalDigit(current)) { - record8(current); - } else { - setDone(Number); + return T_NOT_EQ; + } + return T_NOT; + + case '\'': + case '"': { + const QChar quote = ch; + _validTokenText = true; + + bool multilineStringLiteral = false; + + const QChar *startCode = _codePtr; + + if (_engine) { + while (!_char.isNull()) { + if (_char == QLatin1Char('\n') || _char == QLatin1Char('\\')) { + break; + } else if (_char == quote) { + _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode); + scanChar(); + + return T_STRING_LITERAL; + } + scanChar(); } - break; - default: - Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement"); } - // move on to the next character - if (!done) - shift(1); - if (state != Start && state != InSingleLineComment) - bol = false; - } + _tokenText.resize(0); + startCode--; + while (startCode != _codePtr - 1) + _tokenText += *startCode++; + + while (! _char.isNull()) { + if (_char == QLatin1Char('\n')) { + multilineStringLiteral = true; + _tokenText += _char; + scanChar(); + } else if (_char == quote) { + scanChar(); + + if (_engine) + _tokenSpell = _engine->newStringRef(_tokenText); + + return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL; + } else if (_char == QLatin1Char('\\')) { + scanChar(); + + QChar u; + bool ok = false; + + switch (_char.unicode()) { + // unicode escape sequence + case 'u': + u = decodeUnicodeEscapeCharacter(&ok); + if (! ok) + u = _char; + break; - // no identifiers allowed directly after numeric literal, e.g. "3in" is bad - if ((state == Number || state == Octal || state == Hex) - && isIdentLetter(current)) { - state = Bad; - err = IllegalIdentifier; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Identifier cannot start with numeric literal"); - } + // hex escape sequence + case 'x': + case 'X': + if (isHexDigit(_codePtr[0]) && isHexDigit(_codePtr[1])) { + scanChar(); - // terminate string - buffer8[pos8] = '\0'; - - double dval = 0; - if (state == Number) { - dval = qstrtod(buffer8, 0, 0); - } else if (state == Hex) { // scan hex numbers - dval = integerFromString(buffer8, pos8, 16); - state = Number; - } else if (state == Octal) { // scan octal number - dval = integerFromString(buffer8, pos8, 8); - state = Number; - } + const QChar c1 = _char; + scanChar(); - restrKeyword = false; - delimited = false; + const QChar c2 = _char; + scanChar(); - switch (parenthesesState) { - case IgnoreParentheses: - break; - case CountParentheses: - if (token == QDeclarativeJSGrammar::T_RPAREN) { - --parenthesesCount; - if (parenthesesCount == 0) - parenthesesState = BalancedParentheses; - } else if (token == QDeclarativeJSGrammar::T_LPAREN) { - ++parenthesesCount; + u = convertHex(c1, c2); + } else { + u = _char; + } + break; + + // single character escape sequence + case '\\': u = QLatin1Char('\''); scanChar(); break; + case '\'': u = QLatin1Char('\''); scanChar(); break; + case '\"': u = QLatin1Char('\"'); scanChar(); break; + case 'b': u = QLatin1Char('\b'); scanChar(); break; + case 'f': u = QLatin1Char('\f'); scanChar(); break; + case 'n': u = QLatin1Char('\n'); scanChar(); break; + case 'r': u = QLatin1Char('\r'); scanChar(); break; + case 't': u = QLatin1Char('\t'); scanChar(); break; + case 'v': u = QLatin1Char('\v'); scanChar(); break; + + case '0': + if (! _codePtr[1].isDigit()) { + scanChar(); + u = QLatin1Char('\0'); + } else { + // ### parse deprecated octal escape sequence ? + u = _char; + } + break; + + case '\r': + while (_char == QLatin1Char('\r')) + scanChar(); + + if (_char == QLatin1Char('\n')) { + u = _char; + scanChar(); + } else { + u = QLatin1Char('\n'); + } + + break; + + case '\n': + u = _char; + scanChar(); + break; + + default: + // non escape character + u = _char; + scanChar(); + } + + _tokenText += u; + } else { + _tokenText += _char; + scanChar(); + } } - break; - case BalancedParentheses: - parenthesesState = IgnoreParentheses; - break; + + _errorCode = UnclosedStringLiteral; + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Unclosed string at end of line"); + return T_ERROR; } - switch (state) { - case Eof: - return 0; - case Other: - if (token == QDeclarativeJSGrammar::T_RBRACE || token == QDeclarativeJSGrammar::T_SEMICOLON) - delimited = true; - return token; - case Identifier: - token = -1; - if (! identifierWithEscapedUnicode) - token = findReservedWord(buffer16, pos16); - - if (token < 0) { - /* TODO: close leak on parse error. same holds true for String */ - if (driver) - qsyylval.ustr = driver->intern(buffer16, pos16); - else - qsyylval.ustr = 0; - return QDeclarativeJSGrammar::T_IDENTIFIER; - } - if (token == QDeclarativeJSGrammar::T_CONTINUE || token == QDeclarativeJSGrammar::T_BREAK - || token == QDeclarativeJSGrammar::T_RETURN || token == QDeclarativeJSGrammar::T_THROW) { - restrKeyword = true; - } else if (token == QDeclarativeJSGrammar::T_IF || token == QDeclarativeJSGrammar::T_FOR - || token == QDeclarativeJSGrammar::T_WHILE || token == QDeclarativeJSGrammar::T_WITH) { - parenthesesState = CountParentheses; - parenthesesCount = 0; - } else if (token == QDeclarativeJSGrammar::T_DO) { - parenthesesState = BalancedParentheses; - } - return token; - case String: - if (driver) - qsyylval.ustr = driver->intern(buffer16, pos16); - else - qsyylval.ustr = 0; - return multiLineString?QDeclarativeJSGrammar::T_MULTILINE_STRING_LITERAL:QDeclarativeJSGrammar::T_STRING_LITERAL; - case Number: - qsyylval.dval = dval; - return QDeclarativeJSGrammar::T_NUMERIC_LITERAL; - case Bad: - return -1; default: - Q_ASSERT(!"unhandled numeration value in switch"); - return -1; - } -} + if (QDeclarativeUtils::isLetter(ch) || ch == QLatin1Char('$') || ch == QLatin1Char('_') || (ch == QLatin1Char('\\') && _char == QLatin1Char('u'))) { + bool identifierWithEscapeChars = false; + if (ch == QLatin1Char('\\')) { + identifierWithEscapeChars = true; + _tokenText.resize(0); + bool ok = false; + _tokenText += decodeUnicodeEscapeCharacter(&ok); + _validTokenText = true; + if (! ok) { + _errorCode = IllegalUnicodeEscapeSequence; + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence"); + return T_ERROR; + } + } + while (true) { + if (QDeclarativeUtils::isLetterOrNumber(_char) || _char == QLatin1Char('$') || _char == QLatin1Char('_')) { + if (identifierWithEscapeChars) + _tokenText += _char; + + scanChar(); + } else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) { + if (! identifierWithEscapeChars) { + identifierWithEscapeChars = true; + _tokenText.resize(0); + _tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1); + _validTokenText = true; + } -bool Lexer::isWhiteSpace() const -{ - return (current == ' ' || current == '\t' || - current == 0x0b || current == 0x0c); -} + scanChar(); // skip '\\' + bool ok = false; + _tokenText += decodeUnicodeEscapeCharacter(&ok); + if (! ok) { + _errorCode = IllegalUnicodeEscapeSequence; + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence"); + return T_ERROR; + } + } else { + _tokenLength = _codePtr - _tokenStartPtr - 1; -bool Lexer::isLineTerminator() const -{ - return (current == '\n' || current == '\r'); -} + int kind = T_IDENTIFIER; -bool Lexer::isIdentLetter(ushort c) -{ - // ASCII-biased, since all reserved words are ASCII, aand hence the - // bulk of content to be parsed. - if ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || c == '$' - || c == '_') - return true; - if (c < 128) - return false; - return QChar(c).isLetterOrNumber(); -} + if (! identifierWithEscapeChars) + kind = classify(_tokenStartPtr, _tokenLength); -bool Lexer::isDecimalDigit(ushort c) -{ - return (c >= '0' && c <= '9'); -} + if (_engine) { + if (kind == T_IDENTIFIER && identifierWithEscapeChars) + _tokenSpell = _engine->newStringRef(_tokenText); + else + _tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength); + } -bool Lexer::isHexDigit(ushort c) const -{ - return ((c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f') - || (c >= 'A' && c <= 'F')); -} + return kind; + } + } + } else if (QDeclarativeUtils::isDigit(ch)) { + if (ch != QLatin1Char('0')) { + double integer = ch.unicode() - '0'; + + QChar n = _char; + const QChar *code = _codePtr; + while (QDeclarativeUtils::isDigit(n)) { + integer = integer * 10 + (n.unicode() - '0'); + n = *code++; + } -bool Lexer::isOctalDigit(ushort c) const -{ - return (c >= '0' && c <= '7'); -} + if (n != QLatin1Char('.') && n != QLatin1Char('e') && n != QLatin1Char('E')) { + if (code != _codePtr) { + _codePtr = code - 1; + scanChar(); + } + _tokenValue = integer; + return T_NUMERIC_LITERAL; + } + } -int Lexer::matchPunctuator(ushort c1, ushort c2, - ushort c3, ushort c4) -{ - if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { - shift(4); - return QDeclarativeJSGrammar::T_GT_GT_GT_EQ; - } else if (c1 == '=' && c2 == '=' && c3 == '=') { - shift(3); - return QDeclarativeJSGrammar::T_EQ_EQ_EQ; - } else if (c1 == '!' && c2 == '=' && c3 == '=') { - shift(3); - return QDeclarativeJSGrammar::T_NOT_EQ_EQ; - } else if (c1 == '>' && c2 == '>' && c3 == '>') { - shift(3); - return QDeclarativeJSGrammar::T_GT_GT_GT; - } else if (c1 == '<' && c2 == '<' && c3 == '=') { - shift(3); - return QDeclarativeJSGrammar::T_LT_LT_EQ; - } else if (c1 == '>' && c2 == '>' && c3 == '=') { - shift(3); - return QDeclarativeJSGrammar::T_GT_GT_EQ; - } else if (c1 == '<' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_LE; - } else if (c1 == '>' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_GE; - } else if (c1 == '!' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_NOT_EQ; - } else if (c1 == '+' && c2 == '+') { - shift(2); - return QDeclarativeJSGrammar::T_PLUS_PLUS; - } else if (c1 == '-' && c2 == '-') { - shift(2); - return QDeclarativeJSGrammar::T_MINUS_MINUS; - } else if (c1 == '=' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_EQ_EQ; - } else if (c1 == '+' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_PLUS_EQ; - } else if (c1 == '-' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_MINUS_EQ; - } else if (c1 == '*' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_STAR_EQ; - } else if (c1 == '/' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_DIVIDE_EQ; - } else if (c1 == '&' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_AND_EQ; - } else if (c1 == '^' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_XOR_EQ; - } else if (c1 == '%' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_REMAINDER_EQ; - } else if (c1 == '|' && c2 == '=') { - shift(2); - return QDeclarativeJSGrammar::T_OR_EQ; - } else if (c1 == '<' && c2 == '<') { - shift(2); - return QDeclarativeJSGrammar::T_LT_LT; - } else if (c1 == '>' && c2 == '>') { - shift(2); - return QDeclarativeJSGrammar::T_GT_GT; - } else if (c1 == '&' && c2 == '&') { - shift(2); - return QDeclarativeJSGrammar::T_AND_AND; - } else if (c1 == '|' && c2 == '|') { - shift(2); - return QDeclarativeJSGrammar::T_OR_OR; - } + QVarLengthArray<char,32> chars; + chars.append(ch.unicode()); - switch(c1) { - case '=': shift(1); return QDeclarativeJSGrammar::T_EQ; - case '>': shift(1); return QDeclarativeJSGrammar::T_GT; - case '<': shift(1); return QDeclarativeJSGrammar::T_LT; - case ',': shift(1); return QDeclarativeJSGrammar::T_COMMA; - case '!': shift(1); return QDeclarativeJSGrammar::T_NOT; - case '~': shift(1); return QDeclarativeJSGrammar::T_TILDE; - case '?': shift(1); return QDeclarativeJSGrammar::T_QUESTION; - case ':': shift(1); return QDeclarativeJSGrammar::T_COLON; - case '.': shift(1); return QDeclarativeJSGrammar::T_DOT; - case '+': shift(1); return QDeclarativeJSGrammar::T_PLUS; - case '-': shift(1); return QDeclarativeJSGrammar::T_MINUS; - case '*': shift(1); return QDeclarativeJSGrammar::T_STAR; - case '/': shift(1); return QDeclarativeJSGrammar::T_DIVIDE_; - case '&': shift(1); return QDeclarativeJSGrammar::T_AND; - case '|': shift(1); return QDeclarativeJSGrammar::T_OR; - case '^': shift(1); return QDeclarativeJSGrammar::T_XOR; - case '%': shift(1); return QDeclarativeJSGrammar::T_REMAINDER; - case '(': shift(1); return QDeclarativeJSGrammar::T_LPAREN; - case ')': shift(1); return QDeclarativeJSGrammar::T_RPAREN; - case '{': shift(1); return QDeclarativeJSGrammar::T_LBRACE; - case '}': shift(1); return QDeclarativeJSGrammar::T_RBRACE; - case '[': shift(1); return QDeclarativeJSGrammar::T_LBRACKET; - case ']': shift(1); return QDeclarativeJSGrammar::T_RBRACKET; - case ';': shift(1); return QDeclarativeJSGrammar::T_SEMICOLON; - - default: return -1; - } -} + if (ch == QLatin1Char('0') && (_char == QLatin1Char('x') || _char == QLatin1Char('X'))) { + // parse hex integer literal -ushort Lexer::singleEscape(ushort c) const -{ - switch(c) { - case 'b': - return 0x08; - case 't': - return 0x09; - case 'n': - return 0x0A; - case 'v': - return 0x0B; - case 'f': - return 0x0C; - case 'r': - return 0x0D; - case '"': - return 0x22; - case '\'': - return 0x27; - case '\\': - return 0x5C; - default: - return c; - } -} + chars.append(_char.unicode()); + scanChar(); // consume `x' -ushort Lexer::convertOctal(ushort c1, ushort c2, - ushort c3) const -{ - return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); -} + while (isHexDigit(_char)) { + chars.append(_char.unicode()); + scanChar(); + } -unsigned char Lexer::convertHex(ushort c) -{ - if (c >= '0' && c <= '9') - return (c - '0'); - else if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - else - return (c - 'A' + 10); -} + _tokenValue = integerFromString(chars.constData(), chars.size(), 16); + return T_NUMERIC_LITERAL; + } -unsigned char Lexer::convertHex(ushort c1, ushort c2) -{ - return ((convertHex(c1) << 4) + convertHex(c2)); -} + // decimal integer literal + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); + scanChar(); // consume the digit + } -QChar Lexer::convertUnicode(ushort c1, ushort c2, - ushort c3, ushort c4) -{ - return QChar((convertHex(c3) << 4) + convertHex(c4), - (convertHex(c1) << 4) + convertHex(c2)); -} + if (_char == QLatin1Char('.')) { + chars.append(_char.unicode()); + scanChar(); // consume `.' -void Lexer::record8(ushort c) -{ - Q_ASSERT(c <= 0xff); - - // enlarge buffer if full - if (pos8 >= size8 - 1) { - char *tmp = new char[2 * size8]; - memcpy(tmp, buffer8, size8 * sizeof(char)); - delete [] buffer8; - buffer8 = tmp; - size8 *= 2; - } + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); + scanChar(); + } - buffer8[pos8++] = (char) c; -} + if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { + if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && + QDeclarativeUtils::isDigit(_codePtr[1]))) { -void Lexer::record16(QChar c) -{ - // enlarge buffer if full - if (pos16 >= size16 - 1) { - QChar *tmp = new QChar[2 * size16]; - memcpy(tmp, buffer16, size16 * sizeof(QChar)); - delete [] buffer16; - buffer16 = tmp; - size16 *= 2; - } + chars.append(_char.unicode()); + scanChar(); // consume `e' - buffer16[pos16++] = c; -} + if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { + chars.append(_char.unicode()); + scanChar(); // consume the sign + } -void Lexer::recordStartPos() -{ - startpos = pos; - startlineno = yylineno; - startcolumn = yycolumn; + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); + scanChar(); + } + } + } + } else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { + if (QDeclarativeUtils::isDigit(_codePtr[0]) || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && + QDeclarativeUtils::isDigit(_codePtr[1]))) { + + chars.append(_char.unicode()); + scanChar(); // consume `e' + + if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { + chars.append(_char.unicode()); + scanChar(); // consume the sign + } + + while (QDeclarativeUtils::isDigit(_char)) { + chars.append(_char.unicode()); + scanChar(); + } + } + } + + chars.append('\0'); + + const char *begin = chars.constData(); + const char *end = 0; + bool ok = false; + + _tokenValue = qstrtod(begin, &end, &ok); + + if (end - begin != chars.size() - 1) { + _errorCode = IllegalExponentIndicator; + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Illegal syntax for exponential number"); + return T_ERROR; + } + + return T_NUMERIC_LITERAL; + } + + break; + } + + return T_ERROR; } bool Lexer::scanRegExp(RegExpBodyPrefix prefix) { - pos16 = 0; - pattern = 0; + _tokenText.resize(0); + _validTokenText = true; + _patternFlags = 0; if (prefix == EqualPrefix) - record16(QLatin1Char('=')); + _tokenText += QLatin1Char('='); while (true) { - switch (current) { - + switch (_char.unicode()) { case 0: // eof case '\n': case '\r': // line terminator - errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression literal"); + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression literal"); return false; case '/': - shift(1); - - if (driver) // create the pattern - pattern = driver->intern(buffer16, pos16); + scanChar(); // scan the flags - pos16 = 0; - flags = 0; - while (isIdentLetter(current)) { - int flag = Ecma::RegExp::flagFromChar(current); + _patternFlags = 0; + while (isIdentLetter(_char)) { + int flag = flagFromChar(_char); if (flag == 0) { - errmsg = QCoreApplication::translate("QDeclarativeParser", "Invalid regular expression flag '%0'") - .arg(QChar(current)); + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Invalid regular expression flag '%0'") + .arg(QChar(_char)); return false; } - flags |= flag; - record16(current); - shift(1); + _patternFlags |= flag; + scanChar(); } + + _tokenLength = _codePtr - _tokenStartPtr - 1; return true; case '\\': // regular expression backslash sequence - record16(current); - shift(1); + _tokenText += _char; + scanChar(); - if (! current || isLineTerminator()) { - errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence"); + if (_char.isNull() || isLineTerminator()) { + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence"); return false; } - record16(current); - shift(1); + _tokenText += _char; + scanChar(); break; case '[': // regular expression class - record16(current); - shift(1); + _tokenText += _char; + scanChar(); - while (current && ! isLineTerminator()) { - if (current == ']') + while (! _char.isNull() && ! isLineTerminator()) { + if (_char == QLatin1Char(']')) break; - else if (current == '\\') { + else if (_char == QLatin1Char('\\')) { // regular expression backslash sequence - record16(current); - shift(1); + _tokenText += _char; + scanChar(); - if (! current || isLineTerminator()) { - errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence"); + if (_char.isNull() || isLineTerminator()) { + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence"); return false; } - record16(current); - shift(1); + _tokenText += _char; + scanChar(); } else { - record16(current); - shift(1); + _tokenText += _char; + scanChar(); } } - if (current != ']') { - errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression class"); + if (_char != QLatin1Char(']')) { + _errorMessage = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression class"); return false; } - record16(current); - shift(1); // skip ] + _tokenText += _char; + scanChar(); // skip ] break; default: - record16(current); - shift(1); + _tokenText += _char; + scanChar(); } // switch } // while return false; } +bool Lexer::isLineTerminator() const +{ + return (_char == QLatin1Char('\n') || _char == QLatin1Char('\r')); +} + +bool Lexer::isIdentLetter(QChar ch) +{ + // ASCII-biased, since all reserved words are ASCII, aand hence the + // bulk of content to be parsed. + if ((ch >= QLatin1Char('a') && ch <= QLatin1Char('z')) + || (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z')) + || ch == QLatin1Char('$') + || ch == QLatin1Char('_')) + return true; + if (ch.unicode() < 128) + return false; + return ch.isLetterOrNumber(); +} + +bool Lexer::isDecimalDigit(ushort c) +{ + return (c >= '0' && c <= '9'); +} + +bool Lexer::isHexDigit(QChar c) +{ + return ((c >= QLatin1Char('0') && c <= QLatin1Char('9')) + || (c >= QLatin1Char('a') && c <= QLatin1Char('f')) + || (c >= QLatin1Char('A') && c <= QLatin1Char('F'))); +} + +bool Lexer::isOctalDigit(ushort c) +{ + return (c >= '0' && c <= '7'); +} + +int Lexer::tokenOffset() const +{ + return _tokenStartPtr - _code.unicode(); +} + +int Lexer::tokenLength() const +{ + return _tokenLength; +} + +int Lexer::tokenStartLine() const +{ + return _tokenLine; +} + +int Lexer::tokenStartColumn() const +{ + return _tokenStartPtr - _tokenLinePtr + 1; +} + +int Lexer::tokenEndLine() const +{ + return _currentLineNumber; +} + +int Lexer::tokenEndColumn() const +{ + return _codePtr - _lastLinePtr; +} + +QStringRef Lexer::tokenSpell() const +{ + return _tokenSpell; +} + +double Lexer::tokenValue() const +{ + return _tokenValue; +} + +QString Lexer::tokenText() const +{ + if (_validTokenText) + return _tokenText; + + return QString(_tokenStartPtr, _tokenLength); +} + +Lexer::Error Lexer::errorCode() const +{ + return _errorCode; +} + +QString Lexer::errorMessage() const +{ + return _errorMessage; +} + void Lexer::syncProhibitAutomaticSemicolon() { - if (parenthesesState == BalancedParentheses) { + if (_parenthesesState == BalancedParentheses) { // we have seen something like "if (foo)", which means we should // never insert an automatic semicolon at this point, since it would // then be expanded into an empty statement (ECMA-262 7.9.1) - prohibitAutomaticSemicolon = true; - parenthesesState = IgnoreParentheses; + _prohibitAutomaticSemicolon = true; + _parenthesesState = IgnoreParentheses; } else { - prohibitAutomaticSemicolon = false; + _prohibitAutomaticSemicolon = false; } } -QT_QML_END_NAMESPACE - +bool Lexer::prevTerminator() const +{ + return _terminator; +} +#include "qdeclarativejskeywords_p.h" diff --git a/src/declarative/qml/parser/qdeclarativejslexer_p.h b/src/declarative/qml/parser/qdeclarativejslexer_p.h index 5147df17e4..1852894b58 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer_p.h +++ b/src/declarative/qml/parser/qdeclarativejslexer_p.h @@ -54,7 +54,7 @@ // #include "qdeclarativejsglobal_p.h" - +#include "qdeclarativejsgrammar_p.h" #include <QtCore/QString> QT_QML_BEGIN_NAMESPACE @@ -62,55 +62,41 @@ QT_QML_BEGIN_NAMESPACE namespace QDeclarativeJS { class Engine; -class NameId; -class QML_PARSER_EXPORT Lexer +class QML_PARSER_EXPORT Lexer: public QDeclarativeJSGrammar { public: - Lexer(Engine *eng, bool tokenizeComments = false); - ~Lexer(); - - void setCode(const QString &c, int lineno); - int lex(); - - int currentLineNo() const { return yylineno; } - int currentColumnNo() const { return yycolumn; } - - int tokenOffset() const { return startpos; } - int tokenLength() const { return pos - startpos; } - - int startLineNo() const { return startlineno; } - int startColumnNo() const { return startcolumn; } - - int endLineNo() const { return currentLineNo(); } - int endColumnNo() const - { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; } - - bool prevTerminator() const { return terminator; } - - enum State { Start, - Identifier, - InIdentifier, - InSingleLineComment, - InMultiLineComment, - InNum, - InNum0, - InHex, - InOctal, - InDecimal, - InExponentIndicator, - InExponent, - Hex, - Octal, - Number, - String, - Eof, - InString, - InEscapeSequence, - InHexEscape, - InUnicodeEscape, - Other, - Bad }; + enum { + T_ABSTRACT = T_RESERVED_WORD, + T_BOOLEAN = T_RESERVED_WORD, + T_BYTE = T_RESERVED_WORD, + T_CHAR = T_RESERVED_WORD, + T_CLASS = T_RESERVED_WORD, + T_DOUBLE = T_RESERVED_WORD, + T_ENUM = T_RESERVED_WORD, + T_EXPORT = T_RESERVED_WORD, + T_EXTENDS = T_RESERVED_WORD, + T_FINAL = T_RESERVED_WORD, + T_FLOAT = T_RESERVED_WORD, + T_GOTO = T_RESERVED_WORD, + T_IMPLEMENTS = T_RESERVED_WORD, + T_INT = T_RESERVED_WORD, + T_INTERFACE = T_RESERVED_WORD, + T_LET = T_RESERVED_WORD, + T_LONG = T_RESERVED_WORD, + T_NATIVE = T_RESERVED_WORD, + T_PACKAGE = T_RESERVED_WORD, + T_PRIVATE = T_RESERVED_WORD, + T_PROTECTED = T_RESERVED_WORD, + T_SHORT = T_RESERVED_WORD, + T_STATIC = T_RESERVED_WORD, + T_SUPER = T_RESERVED_WORD, + T_SYNCHRONIZED = T_RESERVED_WORD, + T_THROWS = T_RESERVED_WORD, + T_TRANSIENT = T_RESERVED_WORD, + T_VOLATILE = T_RESERVED_WORD, + T_YIELD = T_RESERVED_WORD + }; enum Error { NoError, @@ -123,127 +109,102 @@ public: IllegalIdentifier }; - enum ParenthesesState { - IgnoreParentheses, - CountParentheses, - BalancedParentheses - }; - enum RegExpBodyPrefix { NoPrefix, EqualPrefix }; +public: + Lexer(Engine *engine); + + QString code() const; + void setCode(const QString &code, int lineno); + + int lex(); + bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); - NameId *pattern; - int flags; + int regExpFlags() const { return _patternFlags; } + QString regExpPattern() const { return _tokenText; } + + int tokenOffset() const; + int tokenLength() const; - State lexerState() const - { return state; } + int tokenStartLine() const; + int tokenStartColumn() const; - QString errorMessage() const - { return errmsg; } - void setErrorMessage(const QString &err) - { errmsg = err; } - void setErrorMessage(const char *err) - { setErrorMessage(QString::fromLatin1(err)); } + int tokenEndLine() const; + int tokenEndColumn() const; - Error error() const - { return err; } - void clearError() - { err = NoError; } + QStringRef tokenSpell() const; + double tokenValue() const; + QString tokenText() const; + + Error errorCode() const; + QString errorMessage() const; + + bool prevTerminator() const; + + enum ParenthesesState { + IgnoreParentheses, + CountParentheses, + BalancedParentheses + }; private: - Engine *driver; - int yylineno; - bool done; - char *buffer8; - QChar *buffer16; - uint size8, size16; - uint pos8, pos16; - bool terminator; - bool restrKeyword; - // encountered delimiter like "'" and "}" on last run - bool delimited; - int stackToken; - - State state; - void setDone(State s); - uint pos; - void shift(uint p); - int lookupKeyword(const char *); - - bool isWhiteSpace() const; + inline void scanChar(); + int scanToken(); + + int classify(const QChar *s, int n); + bool isLineTerminator() const; - bool isHexDigit(ushort c) const; - bool isOctalDigit(ushort c) const; - - int matchPunctuator(ushort c1, ushort c2, - ushort c3, ushort c4); - ushort singleEscape(ushort c) const; - ushort convertOctal(ushort c1, ushort c2, - ushort c3) const; -public: - static unsigned char convertHex(ushort c1); - static unsigned char convertHex(ushort c1, ushort c2); - static QChar convertUnicode(ushort c1, ushort c2, - ushort c3, ushort c4); - static bool isIdentLetter(ushort c); + static bool isIdentLetter(QChar c); static bool isDecimalDigit(ushort c); + static bool isHexDigit(QChar c); + static bool isOctalDigit(ushort c); + static bool isUnicodeEscapeSequence(const QChar *chars); - inline int ival() const { return qsyylval.ival; } - inline double dval() const { return qsyylval.dval; } - inline NameId *ustr() const { return qsyylval.ustr; } - - const QChar *characterBuffer() const { return buffer16; } - int characterCount() const { return pos16; } + void syncProhibitAutomaticSemicolon(); + QChar decodeUnicodeEscapeCharacter(bool *ok); private: - void record8(ushort c); - void record16(QChar c); - void recordStartPos(); + Engine *_engine; - int findReservedWord(const QChar *buffer, int size) const; + QString _code; + QString _tokenText; + QString _errorMessage; + QStringRef _tokenSpell; - void syncProhibitAutomaticSemicolon(); + const QChar *_codePtr; + const QChar *_lastLinePtr; + const QChar *_tokenLinePtr; + const QChar *_tokenStartPtr; - const QChar *code; - uint length; - int yycolumn; - int startpos; - int startlineno; - int startcolumn; - int bol; // begin of line - - union { - int ival; - double dval; - NameId *ustr; - } qsyylval; - - // current and following unicode characters - ushort current, next1, next2, next3; - - struct keyword { - const char *name; - int token; - }; + QChar _char; + Error _errorCode; + + int _currentLineNumber; + double _tokenValue; + + // parentheses state + ParenthesesState _parenthesesState; + int _parenthesesCount; - QString errmsg; - Error err; + int _stackToken; - bool wantRx; - bool check_reserved; + int _patternFlags; + int _tokenLength; + int _tokenLine; - ParenthesesState parenthesesState; - int parenthesesCount; - bool prohibitAutomaticSemicolon; - bool tokenizeComments; + bool _validTokenText; + bool _prohibitAutomaticSemicolon; + bool _restrictedKeyword; + bool _terminator; + bool _delimited; }; -} // namespace QDeclarativeJS +} // end of namespace QDeclarativeJS QT_QML_END_NAMESPACE -#endif +#endif // LEXER_H diff --git a/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h b/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h index 8d61dbe714..043331d9e8 100644 --- a/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h +++ b/src/declarative/qml/parser/qdeclarativejsmemorypool_p.h @@ -57,8 +57,9 @@ #include <QtCore/qglobal.h> #include <QtCore/qshareddata.h> +#include <QtCore/qdebug.h> -#include <string.h> +#include <cstring> QT_QML_BEGIN_NAMESPACE @@ -66,64 +67,103 @@ namespace QDeclarativeJS { class QML_PARSER_EXPORT MemoryPool : public QSharedData { + MemoryPool(const MemoryPool &other); + void operator =(const MemoryPool &other); + public: - enum { maxBlockCount = -1 }; - enum { defaultBlockSize = 1 << 12 }; - - MemoryPool() { - m_blockIndex = maxBlockCount; - m_currentIndex = 0; - m_storage = 0; - m_currentBlock = 0; - m_currentBlockSize = 0; + MemoryPool() + : _blocks(0), + _allocatedBlocks(0), + _blockCount(-1), + _ptr(0), + _end(0) + { } + + ~MemoryPool() + { + if (_blocks) { + for (int i = 0; i < _allocatedBlocks; ++i) { + if (char *b = _blocks[i]) + qFree(b); + } + + qFree(_blocks); + } } - virtual ~MemoryPool() { - for (int index = 0; index < m_blockIndex + 1; ++index) - qFree(m_storage[index]); + inline void *allocate(size_t size) + { + size = (size + 7) & ~7; + if (_ptr && (_ptr + size < _end)) { + void *addr = _ptr; + _ptr += size; + return addr; + } + return allocate_helper(size); + } - qFree(m_storage); + void reset() + { + _blockCount = -1; + _ptr = _end = 0; } - char *allocate(int bytes) { - bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment) - if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) { - ++m_blockIndex; - m_currentBlockSize = defaultBlockSize << m_blockIndex; +private: + void *allocate_helper(size_t size) + { + Q_ASSERT(size < BLOCK_SIZE); + + if (++_blockCount == _allocatedBlocks) { + if (! _allocatedBlocks) + _allocatedBlocks = DEFAULT_BLOCK_COUNT; + else + _allocatedBlocks *= 2; - m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex))); - m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize)); - ::memset(m_currentBlock, 0, m_currentBlockSize); + _blocks = (char **) qRealloc(_blocks, sizeof(char *) * _allocatedBlocks); - m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned - Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize); + for (int index = _blockCount; index < _allocatedBlocks; ++index) + _blocks[index] = 0; } - char *p = reinterpret_cast<char *> - (m_currentBlock + m_currentIndex); + char *&block = _blocks[_blockCount]; - m_currentIndex += bytes; + if (! block) + block = (char *) qMalloc(BLOCK_SIZE); - return p; - } + _ptr = block; + _end = _ptr + BLOCK_SIZE; - int bytesAllocated() const { - int bytes = 0; - for (int index = 0; index < m_blockIndex; ++index) - bytes += (defaultBlockSize << index); - bytes += m_currentIndex; - return bytes; + void *addr = _ptr; + _ptr += size; + return addr; } private: - int m_blockIndex; - int m_currentIndex; - char *m_currentBlock; - int m_currentBlockSize; - char **m_storage; + char **_blocks; + int _allocatedBlocks; + int _blockCount; + char *_ptr; + char *_end; + + enum + { + BLOCK_SIZE = 8 * 1024, + DEFAULT_BLOCK_COUNT = 8 + }; +}; -private: - Q_DISABLE_COPY(MemoryPool) +class QML_PARSER_EXPORT Managed +{ + Managed(const Managed &other); + void operator = (const Managed &other); + +public: + Managed() {} + ~Managed() {} + + void *operator new(size_t size, MemoryPool *pool) { return pool->allocate(size); } + void operator delete(void *) {} + void operator delete(void *, MemoryPool *) {} }; } // namespace QDeclarativeJS diff --git a/src/declarative/qml/parser/qdeclarativejsnodepool_p.h b/src/declarative/qml/parser/qdeclarativejsnodepool_p.h deleted file mode 100644 index 401500c57c..0000000000 --- a/src/declarative/qml/parser/qdeclarativejsnodepool_p.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVEJSNODEPOOL_P_H -#define QDECLARATIVEJSNODEPOOL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qdeclarativejsglobal_p.h" -#include "qdeclarativejsmemorypool_p.h" - -#include <QtCore/QHash> -#include <QtCore/QString> - -QT_QML_BEGIN_NAMESPACE - -namespace QDeclarativeJS { - -namespace AST { -class Node; -} // namespace AST - -class Code; -class CompilationUnit; -class Engine; - -template <typename NodeType> -inline NodeType *makeAstNode(MemoryPool *storage) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(); - return node; -} - -template <typename NodeType, typename Arg1> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1); - return node; -} - -template <typename NodeType, typename Arg1, typename Arg2> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2); - return node; -} - -template <typename NodeType, typename Arg1, typename Arg2, typename Arg3> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3); - return node; -} - -template <typename NodeType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4); - return node; -} - -class QML_PARSER_EXPORT NodePool : public MemoryPool -{ -public: - NodePool(const QString &fileName, Engine *engine); - virtual ~NodePool(); - - Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation); - - inline QString fileName() const { return m_fileName; } - inline Engine *engine() const { return m_engine; } -#ifndef J_SCRIPT_NO_EVENT_NOTIFY - inline qint64 id() const { return m_id; } -#endif - -private: - QHash<AST::Node*, Code*> m_codeCache; - QString m_fileName; - Engine *m_engine; -#ifndef J_SCRIPT_NO_EVENT_NOTIFY - qint64 m_id; -#endif - -private: - Q_DISABLE_COPY(NodePool) -}; - -} // namespace QDeclarativeJS - -QT_QML_END_NAMESPACE - -#endif diff --git a/src/declarative/qml/parser/qdeclarativejsparser.cpp b/src/declarative/qml/parser/qdeclarativejsparser.cpp index 01132e5362..546cfdd100 100644 --- a/src/declarative/qml/parser/qdeclarativejsparser.cpp +++ b/src/declarative/qml/parser/qdeclarativejsparser.cpp @@ -47,7 +47,7 @@ #include "qdeclarativejsengine_p.h" #include "qdeclarativejslexer_p.h" #include "qdeclarativejsast_p.h" -#include "qdeclarativejsnodepool_p.h" +#include "qdeclarativejsmemorypool_p.h" @@ -73,6 +73,7 @@ void Parser::reallocateStack() sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int))); location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); + string_stack = reinterpret_cast<QStringRef*> (qRealloc(string_stack, stack_size * sizeof(QStringRef))); } inline static bool automatic(Engine *driver, int token) @@ -85,11 +86,13 @@ inline static bool automatic(Engine *driver, int token) Parser::Parser(Engine *engine): driver(engine), + pool(engine->pool()), tos(0), stack_size(0), sym_stack(0), state_stack(0), location_stack(0), + string_stack(0), first_token(0), last_token(0) { @@ -101,6 +104,7 @@ Parser::~Parser() qFree(sym_stack); qFree(state_stack); qFree(location_stack); + qFree(string_stack); } } @@ -109,14 +113,14 @@ static inline AST::SourceLocation location(Lexer *lexer) AST::SourceLocation loc; loc.offset = lexer->tokenOffset(); loc.length = lexer->tokenLength(); - loc.startLine = lexer->startLineNo(); - loc.startColumn = lexer->startColumnNo(); + loc.startLine = lexer->tokenStartLine(); + loc.startColumn = lexer->tokenStartColumn(); return loc; } AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { - QVarLengthArray<NameId *, 4> nameIds; + QVarLengthArray<QStringRef, 4> nameIds; QVarLengthArray<AST::SourceLocation, 4> locations; AST::ExpressionNode *it = expr; @@ -127,12 +131,12 @@ AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) } if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) { - AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name); + AST::UiQualifiedId *q = new (pool) AST::UiQualifiedId(idExpr->name); q->identifierToken = idExpr->identifierToken; AST::UiQualifiedId *currentId = q; for (int i = nameIds.size() - 1; i != -1; --i) { - currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]); + currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); currentId->identifierToken = locations[i]; } @@ -168,11 +172,13 @@ bool Parser::parse(int startToken) if (first_token == last_token) { yytoken = lexer->lex(); - yylval = lexer->dval(); + yylval = lexer->tokenValue(); + yytokenspell = lexer->tokenSpell(); yylloc = location(lexer); } else { yytoken = first_token->token; yylval = first_token->dval; + yytokenspell = first_token->spell; yylloc = first_token->loc; ++first_token; } @@ -183,6 +189,7 @@ bool Parser::parse(int startToken) if (action != ACCEPT_STATE) { yytoken = -1; sym(1).dval = yylval; + stringRef(1) = yytokenspell; loc(1) = yylloc; } else { --tos; @@ -225,7 +232,7 @@ case 5: { } break; case 6: { - sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList, + sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); } break; @@ -234,12 +241,11 @@ case 8: { } break; case 9: { - sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport); + sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImport); } break; case 10: { - sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), - sym(1).UiImportList, sym(2).UiImport); + sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImportList, sym(2).UiImport); } break; case 13: { @@ -255,14 +261,14 @@ case 17: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->asToken = loc(3); sym(1).UiImport->importIdToken = loc(4); - sym(1).UiImport->importId = sym(4).sval; + sym(1).UiImport->importId = stringRef(4); sym(1).UiImport->semicolonToken = loc(5); } break; case 19: { sym(1).UiImport->asToken = loc(2); sym(1).UiImport->importIdToken = loc(3); - sym(1).UiImport->importId = sym(3).sval; + sym(1).UiImport->importId = stringRef(3); sym(1).UiImport->semicolonToken = loc(4); } break; @@ -270,10 +276,10 @@ case 20: { AST::UiImport *node = 0; if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { - node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value); + node = new (pool) AST::UiImport(importIdLiteral->value); node->fileNameToken = loc(2); } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { - node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId); + node = new (pool) AST::UiImport(qualifiedId); node->fileNameToken = loc(2); } @@ -294,52 +300,52 @@ case 21: { } break; case 22: { - sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; case 23: { - sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; case 24: { - AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(), + AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList( sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; case 25: { - sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember); + sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); } break; case 26: { - AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), + AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList( sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; } break; case 27: { - AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0); + AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; } break; case 28: { - AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish()); + AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 29: { - AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId, + AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); sym(1).Node = node; } break; case 31: { - AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), + AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding( sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); @@ -348,14 +354,14 @@ case 31: { } break; case 32: { - AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); sym(1).Node = node; } break; case 33: { - AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); node->hasOnToken = true; @@ -364,19 +370,12 @@ case 33: { case 38: { - AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), + AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding( sym(1).UiQualifiedId, sym(3).Statement); node->colonToken = loc(2); sym(1).Node = node; } break; -case 39: - -case 40: { - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); - break; -} - case 42: { sym(1).Node = 0; } break; @@ -386,20 +385,20 @@ case 43: { } break; case 44: { - AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval); + AST::UiParameterList *node = new (pool) AST::UiParameterList(stringRef(1), stringRef(2)); node->identifierToken = loc(2); sym(1).Node = node; } break; case 45: { - AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); + AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, stringRef(3), stringRef(4)); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; case 47: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); @@ -410,7 +409,7 @@ case 47: { } break; case 49: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); @@ -420,8 +419,8 @@ case 49: { } break; case 51: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval); - node->typeModifier = sym(2).sval; + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); + node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); @@ -431,7 +430,7 @@ case 51: { } break; case 53: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); @@ -440,7 +439,7 @@ case 53: { } break; case 55: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); @@ -451,7 +450,7 @@ case 55: { } break; case 56: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval, + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3), sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); @@ -461,7 +460,7 @@ case 56: { } break; case 57: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); @@ -473,7 +472,7 @@ case 57: { } break; case 58: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); @@ -485,19 +484,19 @@ case 58: { } break; case 59: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval); - node->typeModifier = sym(2).sval; + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); + node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); // insert a fake ';' before ':' - AST::UiQualifiedId *propertyName = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), sym(6).sval); + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); propertyName->identifierToken = loc(6); propertyName->next = 0; - AST::UiArrayBinding *binding = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), + AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding( propertyName, sym(9).UiArrayMemberList->finish()); binding->colonToken = loc(7); binding->lbracketToken = loc(8); @@ -509,17 +508,17 @@ case 59: { } break; case 60: { - AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); // insert a fake ';' before ':' - AST::UiQualifiedId *propertyName = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), sym(3).sval); + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); propertyName->identifierToken = loc(3); propertyName->next = 0; - AST::UiObjectBinding *binding = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); binding->colonToken = loc(4); @@ -529,75 +528,51 @@ case 60: { } break; case 61: { - sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; case 62: { - sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; -case 64: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_PROPERTY]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} - -case 65: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_SIGNAL]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} - -case 66: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_READONLY]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} - -case 67: { - QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_ON]); - sym(1).sval = driver->intern(s.constData(), s.length()); - break; -} - case 68: { - AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool()); + AST::ThisExpression *node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; case 69: { - AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval); + AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; case 70: { - AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool()); + AST::NullExpression *node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; case 71: { - AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool()); + AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; case 72: { - AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool()); + AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; case 73: { - AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval); + AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; case 74: case 75: { - AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval); + AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; @@ -611,7 +586,8 @@ case 76: { loc(1).length = lexer->tokenLength(); - AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( + driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; @@ -625,34 +601,35 @@ case 77: { loc(1).length = lexer->tokenLength(); - AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( + driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; case 78: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0); + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; case 79: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish()); + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; case 80: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ()); + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; case 81: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); node->commaToken = loc(3); @@ -661,7 +638,7 @@ case 81: { } break; case 82: { - AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); @@ -672,17 +649,17 @@ case 82: { case 83: { AST::ObjectLiteral *node = 0; if (sym(2).Node) - node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); else - node = makeAstNode<AST::ObjectLiteral> (driver->nodePool()); + node = new (pool) AST::ObjectLiteral(); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 84: { - AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); node->rbraceToken = loc(4); @@ -690,7 +667,7 @@ case 84: { } break; case 85: { - AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression); + AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; @@ -717,48 +694,48 @@ case 86: { } break; case 87: { - sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); + sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; case 88: { - sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); + sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; case 89: { - AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, + AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 90: { - AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), + AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 91: { - AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); + AST::Elision *node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; case 92: { - AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); + AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; case 93: { - AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; case 94: { - AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); @@ -766,116 +743,51 @@ case 94: { } break; case 95: { - AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 96: case 97: { - AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 98: { - AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); + AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 99: { - AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); + AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 100: { - AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 101: - -case 102: - -case 103: - -case 104: - -case 105: - -case 106: - -case 107: - -case 108: - -case 109: - -case 110: - -case 111: - -case 112: - -case 113: - -case 114: - -case 115: - -case 116: - -case 117: - -case 118: - -case 119: - -case 120: - -case 121: - -case 122: - -case 123: - -case 124: - -case 125: - -case 126: - -case 127: - -case 128: - -case 129: - -case 130: - -case 131: -{ - sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); -} break; - case 136: { - AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 137: { - AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; case 138: { - AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); + AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); node->rparenToken = loc(5); @@ -883,34 +795,34 @@ case 138: { } break; case 140: { - AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression); + AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; case 141: { - AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 142: { - AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 143: { - AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 144: { - AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; @@ -925,342 +837,342 @@ case 146: { } break; case 147: { - sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression); + sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; case 148: { - AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); + AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 152: { - AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression); + AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; case 153: { - AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression); + AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; case 155: { - AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression); + AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; case 156: { - AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression); + AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; case 157: { - AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression); + AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; case 158: { - AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression); + AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; case 159: { - AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression); + AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; case 160: { - AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression); + AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; case 161: { - AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression); + AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; case 162: { - AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression); + AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; case 163: { - AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression); + AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; case 165: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 166: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 167: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 169: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 170: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 172: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 173: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 174: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 176: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 177: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 178: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 179: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 180: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 181: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 183: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 184: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 185: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 186: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 187: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 189: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 190: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 191: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 192: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 194: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 195: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 196: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 197: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 199: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 201: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 203: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 205: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 207: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 209: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 211: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 213: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 215: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 217: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 219: { - AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); @@ -1268,7 +1180,7 @@ case 219: { } break; case 221: { - AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); @@ -1276,14 +1188,14 @@ case 221: { } break; case 223: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 225: { - AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; @@ -1338,7 +1250,7 @@ case 237: { } break; case 239: { - AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; @@ -1348,7 +1260,7 @@ case 240: { } break; case 243: { - AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; @@ -1358,18 +1270,18 @@ case 244: { } break; case 261: { - AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList); + AST::Block *node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 262: { - sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement); + sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; case 263: { - sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement); + sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; case 264: { @@ -1381,7 +1293,7 @@ case 265: { } break; case 267: { - AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(), + AST::VariableStatement *node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); node->semicolonToken = loc(3); @@ -1397,32 +1309,32 @@ case 269: { } break; case 270: { - sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; case 271: { - AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), + AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; case 272: { - sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; case 273: { - sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; case 274: { - AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; case 275: { - AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; @@ -1446,28 +1358,28 @@ case 280: { } break; case 282: { - AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool()); + AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; case 284: { - AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); + AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 285: { - AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); + AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); - node->elseToken = loc(5); + node->elseToken = loc(6); sym(1).Node = node; } break; case 286: { - AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -1475,7 +1387,7 @@ case 286: { } break; case 288: { - AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression); + AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); node->lparenToken = loc(4); @@ -1485,7 +1397,7 @@ case 288: { } break; case 289: { - AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -1493,7 +1405,7 @@ case 289: { } break; case 290: { - AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression, + AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); node->lparenToken = loc(2); @@ -1504,7 +1416,7 @@ case 290: { } break; case 291: { - AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(), + AST::LocalForStatement *node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); node->forToken = loc(1); @@ -1517,7 +1429,7 @@ case 291: { } break; case 292: { - AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression, + AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); node->lparenToken = loc(2); @@ -1527,7 +1439,7 @@ case 292: { } break; case 293: { - AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(), + AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); node->lparenToken = loc(2); @@ -1538,14 +1450,14 @@ case 293: { } break; case 295: { - AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool()); + AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 297: { - AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval); + AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); @@ -1553,14 +1465,14 @@ case 297: { } break; case 299: { - AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool()); + AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 301: { - AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval); + AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); @@ -1568,14 +1480,14 @@ case 301: { } break; case 303: { - AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression); + AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 304: { - AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -1583,7 +1495,7 @@ case 304: { } break; case 305: { - AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); + AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); @@ -1591,25 +1503,25 @@ case 305: { } break; case 306: { - AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses); + AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 307: { - AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); + AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; case 308: { - sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause); + sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; case 309: { - sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); + sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; case 310: { @@ -1621,60 +1533,60 @@ case 311: { } break; case 312: { - AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList); + AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; case 313: { - AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList); + AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 314: case 315: { - AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); + AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 316: { - AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement); + AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 318: { - AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression); + AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 319: { - AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch); + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; case 320: { - AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally); + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; case 321: { - AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); + AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; case 322: { - AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block); + AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); node->identifierToken = loc(3); @@ -1683,20 +1595,20 @@ case 322: { } break; case 323: { - AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block); + AST::Finally *node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; case 325: { - AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool()); + AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 326: { - AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); node->lparenToken = loc(3); @@ -1707,9 +1619,9 @@ case 326: { } break; case 327: { - AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); - if (sym(2).sval) + if (! stringRef(2).isNull()) node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); @@ -1719,13 +1631,13 @@ case 327: { } break; case 328: { - AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval); + AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; case 329: { - AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); + AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; @@ -1744,31 +1656,31 @@ case 332: { } break; case 334: { - sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ()); + sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; case 335: { - sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ()); + sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; case 336: { - sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement); + sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; case 337: { - sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); + sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; case 338: { - sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement); + sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; case 339: { - sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration); + sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; case 340: { - sym(1).sval = 0; + stringRef(1) = QStringRef(); } break; case 342: { @@ -1788,6 +1700,7 @@ case 342: { SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; + tk.spell = yytokenspell; tk.loc = yylloc; yylloc = yyprevlloc; @@ -1813,11 +1726,13 @@ case 342: { token_buffer[0].token = yytoken; token_buffer[0].dval = yylval; + token_buffer[0].spell = yytokenspell; token_buffer[0].loc = yylloc; - token_buffer[1].token = yytoken = lexer->lex(); - token_buffer[1].dval = yylval = lexer->dval(); - token_buffer[1].loc = yylloc = location(lexer); + token_buffer[1].token = yytoken = lexer->lex(); + token_buffer[1].dval = yylval = lexer->tokenValue(); + token_buffer[1].spell = yytokenspell = lexer->tokenSpell(); + token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { QString msg; diff --git a/src/declarative/qml/parser/qdeclarativejsparser_p.h b/src/declarative/qml/parser/qdeclarativejsparser_p.h index 0cbd76adfc..d94b3df2ec 100644 --- a/src/declarative/qml/parser/qdeclarativejsparser_p.h +++ b/src/declarative/qml/parser/qdeclarativejsparser_p.h @@ -72,7 +72,6 @@ QT_QML_BEGIN_NAMESPACE namespace QDeclarativeJS { class Engine; -class NameId; class QML_PARSER_EXPORT Parser: protected QDeclarativeJSGrammar { @@ -80,7 +79,6 @@ public: union Value { int ival; double dval; - NameId *sval; AST::ArgumentList *ArgumentList; AST::CaseBlock *CaseBlock; AST::CaseClause *CaseClause; @@ -196,6 +194,9 @@ protected: inline Value &sym(int index) { return sym_stack [tos + index - 1]; } + inline QStringRef &stringRef(int index) + { return string_stack [tos + index - 1]; } + inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } @@ -203,11 +204,13 @@ protected: protected: Engine *driver; + MemoryPool *pool; int tos; int stack_size; Value *sym_stack; int *state_stack; AST::SourceLocation *location_stack; + QStringRef *string_stack; AST::Node *program; @@ -218,9 +221,11 @@ protected: int token; double dval; AST::SourceLocation loc; + QStringRef spell; }; double yylval; + QStringRef yytokenspell; AST::SourceLocation yylloc; AST::SourceLocation yyprevlloc; diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 311ecd31ca..a0eb98d366 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -420,33 +420,35 @@ Q_DECLARATIVE_EXPORT void qmlRegisterBaseTypes(const char *uri, int versionMajor Installing a module API into a uri allows developers to provide arbitrary functionality (methods and properties) in a namespace that doesn't necessarily contain elements. - A module API may be either a QObject or a QScriptValue. Only one module API provider + A module API may be either a QObject or a QJSValue. Only one module API provider may be registered into any given namespace (combination of \a uri, \a majorVersion and \a minorVersion). - This function should be used to register a module API provider function which returns a QScriptValue as a module API. + This function should be used to register a module API provider function which returns a QJSValue as a module API. + + \e NOTE: QJSValue module API properties will \e not trigger binding re-evaluation if changed. Usage: \code // first, define the module API provider function (callback). - static QScriptValue *example_qscriptvalue_module_api_provider(QDeclarativeEngine *engine, QScriptEngine *scriptEngine) + static QJSValue *example_qjsvalue_module_api_provider(QDeclarativeEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) static int seedValue = 5; - QScriptValue example = scriptEngine->newObject(); + QJSValue example = scriptEngine->newObject(); example.setProperty("someProperty", seedValue++); return example; } // second, register the module API provider with QML by calling this function in an initialization function. ... - qmlRegisterModuleApi("Qt.example.qscriptvalueApi", 1, 0, example_qscriptvalue_module_api_provider); + qmlRegisterModuleApi("Qt.example.qjsvalueApi", 1, 0, example_qjsvalue_module_api_provider); ... \endcode In order to use the registered module API in QML, you must import the module API. \qml import QtQuick 2.0 - import Qt.example.qscriptvalueApi 1.0 as ExampleApi + import Qt.example.qjsvalueApi 1.0 as ExampleApi Item { id: root property int someValue: ExampleApi.someProperty @@ -474,7 +476,7 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi Installing a module API into a uri allows developers to provide arbitrary functionality (methods and properties) in a namespace that doesn't necessarily contain elements. - A module API may be either a QObject or a QScriptValue. Only one module API provider + A module API may be either a QObject or a QJSValue. Only one module API provider may be registered into any given namespace (combination of \a uri, \a majorVersion and \a minorVersion). This function should be used to register a module API provider function which returns a QObject as a module API. @@ -507,7 +509,7 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi }; // second, define the module API provider function (callback). - static QObject *example_qobject_module_api_provider(QDeclarativeEngine *engine, QScriptEngine *scriptEngine) + static QObject *example_qobject_module_api_provider(QDeclarativeEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 069744153a..d817990d7b 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -235,7 +235,7 @@ QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeCont QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(ctxt); - QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(obj)); + QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(ctxt->engine()); QDeclarativeCompiledData *cdata = 0; QDeclarativeTypeData *typeData = 0; if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index da7c3fea7b..c59dd78d53 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -100,6 +100,7 @@ int QDeclarativeCompiledData::indexForUrl(const QUrl &data) QDeclarativeCompiledData::QDeclarativeCompiledData(QDeclarativeEngine *engine) : QDeclarativeCleanup(engine), importCache(0), root(0), rootPropertyCache(0) { + bytecode.reserve(1024); } QDeclarativeCompiledData::~QDeclarativeCompiledData() @@ -202,10 +203,9 @@ int QDeclarativeCompiledData::addInstruction(const QDeclarativeInstruction &inst { int ptrOffset = bytecode.size(); int size = instr.size(); - bytecode.resize(bytecode.size() + size); - char *data = bytecode.data() + ptrOffset; - qMemCopy(data, &instr, size); - + if (bytecode.capacity() <= bytecode.size() + size) + bytecode.reserve(bytecode.size() + size + 512); + bytecode.append(reinterpret_cast<const char *>(&instr), size); return ptrOffset; } diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 7cc8422ddd..79094b7e0e 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -41,11 +41,10 @@ #include "private/qdeclarativecompiler_p.h" -#include "private/qdeclarativeparser_p.h" -#include "private/qdeclarativescriptparser_p.h" #include "qdeclarativepropertyvaluesource.h" #include "qdeclarativecomponent.h" #include "private/qmetaobjectbuilder_p.h" +#include "private/qfastmetabuilder_p.h" #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativeengine_p.h" #include "qdeclarativeengine.h" @@ -61,9 +60,9 @@ #include "private/qdeclarativerewrite_p.h" #include "qdeclarativescriptstring.h" #include "private/qdeclarativeglobal_p.h" -#include "private/qdeclarativescriptparser_p.h" #include "private/qdeclarativebinding_p.h" #include "private/qdeclarativev4compiler_p.h" +#include "private/qdeclarativeutils_p.h" #include <QColor> #include <QDebug> @@ -79,14 +78,22 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP); DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATS); -using namespace QDeclarativeParser; +using namespace QDeclarativeScript; +using namespace QDeclarativeCompilerTypes; + +static QString id_string(QLatin1String("id")); +static QString on_string(QLatin1String("on")); +static QString Changed_string(QLatin1String("Changed")); +static QString Component_string(QLatin1String("Component")); /*! Instantiate a new QDeclarativeCompiler. */ -QDeclarativeCompiler::QDeclarativeCompiler() -: output(0), engine(0), unitRoot(0), unit(0) +QDeclarativeCompiler::QDeclarativeCompiler(QDeclarativePool *pool) +: pool(pool), output(0), engine(0), unitRoot(0), unit(0), componentStats(0) { + if (compilerStatDump()) + componentStats = pool->New<ComponentStats>(); } /*! @@ -113,9 +120,14 @@ QList<QDeclarativeError> QDeclarativeCompiler::errors() const Attached property names are those that start with a capital letter. */ -bool QDeclarativeCompiler::isAttachedPropertyName(const QByteArray &name) +bool QDeclarativeCompiler::isAttachedPropertyName(const QString &name) +{ + return isAttachedPropertyName(QHashedStringRef(&name)); +} + +bool QDeclarativeCompiler::isAttachedPropertyName(const QHashedStringRef &name) { - return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z'; + return !name.isEmpty() && QDeclarativeUtils::isUpper(name.at(0)); } /*! @@ -129,15 +141,20 @@ bool QDeclarativeCompiler::isAttachedPropertyName(const QByteArray &name) character codes in property names, for simplicity and performance reasons QML only supports letters, numbers and underscores. */ -bool QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name) +bool QDeclarativeCompiler::isSignalPropertyName(const QString &name) +{ + return isSignalPropertyName(QStringRef(&name)); +} + +bool QDeclarativeCompiler::isSignalPropertyName(const QHashedStringRef &name) { if (name.length() < 3) return false; - if (!name.startsWith("on")) return false; - int ns = name.size(); + if (!name.startsWith(on_string)) return false; + int ns = name.length(); for (int i = 2; i < ns; ++i) { - char curr = name.at(i); - if (curr == '_') continue; - if (curr >= 'A' && curr <= 'Z') return true; + const QChar curr = name.at(i); + if (curr.unicode() == '_') continue; + if (QDeclarativeUtils::isUpper(curr)) return true; return false; } return false; // consists solely of underscores - invalid. @@ -155,7 +172,7 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name) For example: \code - COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(QString::fromUtf8(property->name))); + COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(property->name)); \endcode */ #define COMPILE_EXCEPTION(token, desc) \ @@ -187,27 +204,33 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name) This test corresponds to action taken by genLiteralAssignment(). Any change made here, must have a corresponding action in genLiteralAssigment(). */ -bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, - QDeclarativeParser::Value *v) +bool QDeclarativeCompiler::testLiteralAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Value *v) { - QString string = v->value.asString(); + const QDeclarativeScript::Variant &value = v->value; - if (!prop.isWritable()) - COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); + if (!prop->core.isWritable()) + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); - if (prop.isEnumType()) { - int value; - if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toUtf8().constData()); + if (prop->core.isEnum()) { + QMetaProperty p = prop->parent->metaObject()->property(prop->index); + int enumValue; + if (p.isFlagType()) { + enumValue = p.enumerator().keysToValue(value.asString().toUtf8().constData()); } else - value = prop.enumerator().keyToValue(string.toUtf8().constData()); - if (value == -1) + enumValue = p.enumerator().keyToValue(value.asString().toUtf8().constData()); + + if (enumValue == -1) COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration")); + + v->value = QDeclarativeScript::Variant((double)enumValue); return true; } - int type = prop.userType(); + + int type = prop->type; + switch(type) { - case -1: + case QMetaType::QVariant: break; case QVariant::String: if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected")); @@ -249,7 +272,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::Color: { bool ok; - QDeclarativeStringConverters::colorFromString(string, &ok); + QDeclarativeStringConverters::colorFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected")); } break; @@ -257,21 +280,21 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::Date: { bool ok; - QDeclarativeStringConverters::dateFromString(string, &ok); + QDeclarativeStringConverters::dateFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected")); } break; case QVariant::Time: { bool ok; - QDeclarativeStringConverters::timeFromString(string, &ok); + QDeclarativeStringConverters::timeFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected")); } break; case QVariant::DateTime: { bool ok; - QDeclarativeStringConverters::dateTimeFromString(string, &ok); + QDeclarativeStringConverters::dateTimeFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected")); } break; @@ -280,7 +303,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::PointF: { bool ok; - QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok); + QPointF point = QDeclarativeStringConverters::pointFFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected")); } break; @@ -288,7 +311,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::SizeF: { bool ok; - QSizeF size = QDeclarativeStringConverters::sizeFFromString(string, &ok); + QSizeF size = QDeclarativeStringConverters::sizeFFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected")); } break; @@ -296,7 +319,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::RectF: { bool ok; - QRectF rect = QDeclarativeStringConverters::rectFFromString(string, &ok); + QRectF rect = QDeclarativeStringConverters::rectFFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected")); } break; @@ -308,24 +331,22 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case QVariant::Vector3D: { bool ok; - QDeclarativeStringConverters::vector3DFromString(string, &ok); + QDeclarativeStringConverters::vector3DFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected")); } break; case QVariant::Vector4D: { bool ok; - QDeclarativeStringConverters::vector4DFromString(string, &ok); + QDeclarativeStringConverters::vector4DFromString(value.asString(), &ok); if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected")); } break; default: { - int t = prop.userType(); - QDeclarativeMetaType::StringConverter converter = - QDeclarativeMetaType::customStringConverter(t); + QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type); if (!converter) - COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type())))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName((QVariant::Type)type)))); } break; } @@ -338,140 +359,132 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, Any literal assignment that is approved in testLiteralAssignment() must have a corresponding action in this method. */ -void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, - QDeclarativeParser::Value *v) +void QDeclarativeCompiler::genLiteralAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Value *v) { QDeclarativeInstruction instr; - if (prop.isEnumType()) { - int value; - if (v->value.isNumber()) { - // Preresolved enum - value = (int)v->value.asNumber(); - } else { - // Must be a string - if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(v->value.asString().toUtf8().constData()); - } else - value = prop.enumerator().keyToValue(v->value.asString().toUtf8().constData()); - } + + if (prop->core.isEnum()) { + Q_ASSERT(v->value.isNumber()); + // Preresolved value + int value = (int)v->value.asNumber(); instr.setType(QDeclarativeInstruction::StoreInteger); - instr.storeInteger.propertyIndex = prop.propertyIndex(); + instr.storeInteger.propertyIndex = prop->index; instr.storeInteger.value = value; output->addInstruction(instr); return; } - QString string = v->value.asString(); - - int type = prop.userType(); + int type = prop->type; switch(type) { - case -1: + case QMetaType::QVariant: { if (v->value.isNumber()) { double n = v->value.asNumber(); if (double(int(n)) == n) { instr.setType(QDeclarativeInstruction::StoreVariantInteger); - instr.storeInteger.propertyIndex = prop.propertyIndex(); + instr.storeInteger.propertyIndex = prop->index; instr.storeInteger.value = int(n); } else { instr.setType(QDeclarativeInstruction::StoreVariantDouble); - instr.storeDouble.propertyIndex = prop.propertyIndex(); + instr.storeDouble.propertyIndex = prop->index; instr.storeDouble.value = n; } } else if(v->value.isBoolean()) { instr.setType(QDeclarativeInstruction::StoreVariantBool); - instr.storeBool.propertyIndex = prop.propertyIndex(); + instr.storeBool.propertyIndex = prop->index; instr.storeBool.value = v->value.asBoolean(); } else { instr.setType(QDeclarativeInstruction::StoreVariant); - instr.storeString.propertyIndex = prop.propertyIndex(); - instr.storeString.value = output->indexForString(string); + instr.storeString.propertyIndex = prop->index; + instr.storeString.value = output->indexForString(v->value.asString()); } } break; case QVariant::String: { instr.setType(QDeclarativeInstruction::StoreString); - instr.storeString.propertyIndex = prop.propertyIndex(); - instr.storeString.value = output->indexForString(string); + instr.storeString.propertyIndex = prop->index; + instr.storeString.value = output->indexForString(v->value.asString()); } break; case QVariant::ByteArray: { instr.setType(QDeclarativeInstruction::StoreByteArray); - instr.storeByteArray.propertyIndex = prop.propertyIndex(); - instr.storeByteArray.value = output->indexForByteArray(string.toLatin1()); + instr.storeByteArray.propertyIndex = prop->index; + instr.storeByteArray.value = output->indexForByteArray(v->value.asString().toLatin1()); } break; case QVariant::Url: { instr.setType(QDeclarativeInstruction::StoreUrl); + QString string = v->value.asString(); QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string)); - instr.storeUrl.propertyIndex = prop.propertyIndex(); + instr.storeUrl.propertyIndex = prop->index; instr.storeUrl.value = output->indexForUrl(u); } break; case QVariant::UInt: { instr.setType(QDeclarativeInstruction::StoreInteger); - instr.storeInteger.propertyIndex = prop.propertyIndex(); + instr.storeInteger.propertyIndex = prop->index; instr.storeInteger.value = uint(v->value.asNumber()); } break; case QVariant::Int: { instr.setType(QDeclarativeInstruction::StoreInteger); - instr.storeInteger.propertyIndex = prop.propertyIndex(); + instr.storeInteger.propertyIndex = prop->index; instr.storeInteger.value = int(v->value.asNumber()); } break; case QMetaType::Float: { instr.setType(QDeclarativeInstruction::StoreFloat); - instr.storeFloat.propertyIndex = prop.propertyIndex(); + instr.storeFloat.propertyIndex = prop->index; instr.storeFloat.value = float(v->value.asNumber()); } break; case QVariant::Double: { instr.setType(QDeclarativeInstruction::StoreDouble); - instr.storeDouble.propertyIndex = prop.propertyIndex(); + instr.storeDouble.propertyIndex = prop->index; instr.storeDouble.value = v->value.asNumber(); } break; case QVariant::Color: { - QColor c = QDeclarativeStringConverters::colorFromString(string); + QColor c = QDeclarativeStringConverters::colorFromString(v->value.asString()); instr.setType(QDeclarativeInstruction::StoreColor); - instr.storeColor.propertyIndex = prop.propertyIndex(); + instr.storeColor.propertyIndex = prop->index; instr.storeColor.value = c.rgba(); } break; #ifndef QT_NO_DATESTRING case QVariant::Date: { - QDate d = QDeclarativeStringConverters::dateFromString(string); + QDate d = QDeclarativeStringConverters::dateFromString(v->value.asString()); instr.setType(QDeclarativeInstruction::StoreDate); - instr.storeDate.propertyIndex = prop.propertyIndex(); + instr.storeDate.propertyIndex = prop->index; instr.storeDate.value = d.toJulianDay(); } break; case QVariant::Time: { - QTime time = QDeclarativeStringConverters::timeFromString(string); + QTime time = QDeclarativeStringConverters::timeFromString(v->value.asString()); instr.setType(QDeclarativeInstruction::StoreTime); - instr.storeTime.propertyIndex = prop.propertyIndex(); + instr.storeTime.propertyIndex = prop->index; Q_ASSERT(sizeof(instr.storeTime.time) == sizeof(QTime)); ::memcpy(&instr.storeTime.time, &time, sizeof(QTime)); } break; case QVariant::DateTime: { - QDateTime dateTime = QDeclarativeStringConverters::dateTimeFromString(string); + QDateTime dateTime = QDeclarativeStringConverters::dateTimeFromString(v->value.asString()); QTime time = dateTime.time(); instr.setType(QDeclarativeInstruction::StoreDateTime); - instr.storeDateTime.propertyIndex = prop.propertyIndex(); + instr.storeDateTime.propertyIndex = prop->index; instr.storeDateTime.date = dateTime.date().toJulianDay(); Q_ASSERT(sizeof(instr.storeDateTime.time) == sizeof(QTime)); ::memcpy(&instr.storeDateTime.time, &time, sizeof(QTime)); @@ -481,9 +494,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Point: { bool ok; - QPoint point = QDeclarativeStringConverters::pointFFromString(string, &ok).toPoint(); + QPoint point = QDeclarativeStringConverters::pointFFromString(v->value.asString(), &ok).toPoint(); instr.setType(QDeclarativeInstruction::StorePoint); - instr.storePoint.propertyIndex = prop.propertyIndex(); + instr.storePoint.propertyIndex = prop->index; instr.storePoint.point.xp = point.x(); instr.storePoint.point.yp = point.y(); } @@ -491,9 +504,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::PointF: { bool ok; - QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok); + QPointF point = QDeclarativeStringConverters::pointFFromString(v->value.asString(), &ok); instr.setType(QDeclarativeInstruction::StorePointF); - instr.storePointF.propertyIndex = prop.propertyIndex(); + instr.storePointF.propertyIndex = prop->index; instr.storePointF.point.xp = point.x(); instr.storePointF.point.yp = point.y(); } @@ -501,9 +514,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Size: { bool ok; - QSize size = QDeclarativeStringConverters::sizeFFromString(string, &ok).toSize(); + QSize size = QDeclarativeStringConverters::sizeFFromString(v->value.asString(), &ok).toSize(); instr.setType(QDeclarativeInstruction::StoreSize); - instr.storeSize.propertyIndex = prop.propertyIndex(); + instr.storeSize.propertyIndex = prop->index; instr.storeSize.size.wd = size.width(); instr.storeSize.size.ht = size.height(); } @@ -511,9 +524,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::SizeF: { bool ok; - QSizeF size = QDeclarativeStringConverters::sizeFFromString(string, &ok); + QSizeF size = QDeclarativeStringConverters::sizeFFromString(v->value.asString(), &ok); instr.setType(QDeclarativeInstruction::StoreSizeF); - instr.storeSizeF.propertyIndex = prop.propertyIndex(); + instr.storeSizeF.propertyIndex = prop->index; instr.storeSizeF.size.wd = size.width(); instr.storeSizeF.size.ht = size.height(); } @@ -521,9 +534,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Rect: { bool ok; - QRect rect = QDeclarativeStringConverters::rectFFromString(string, &ok).toRect(); + QRect rect = QDeclarativeStringConverters::rectFFromString(v->value.asString(), &ok).toRect(); instr.setType(QDeclarativeInstruction::StoreRect); - instr.storeRect.propertyIndex = prop.propertyIndex(); + instr.storeRect.propertyIndex = prop->index; instr.storeRect.rect.x1 = rect.left(); instr.storeRect.rect.y1 = rect.top(); instr.storeRect.rect.x2 = rect.right(); @@ -533,9 +546,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::RectF: { bool ok; - QRectF rect = QDeclarativeStringConverters::rectFFromString(string, &ok); + QRectF rect = QDeclarativeStringConverters::rectFFromString(v->value.asString(), &ok); instr.setType(QDeclarativeInstruction::StoreRectF); - instr.storeRectF.propertyIndex = prop.propertyIndex(); + instr.storeRectF.propertyIndex = prop->index; instr.storeRectF.rect.xp = rect.left(); instr.storeRectF.rect.yp = rect.top(); instr.storeRectF.rect.w = rect.width(); @@ -546,16 +559,16 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, { bool b = v->value.asBoolean(); instr.setType(QDeclarativeInstruction::StoreBool); - instr.storeBool.propertyIndex = prop.propertyIndex(); + instr.storeBool.propertyIndex = prop->index; instr.storeBool.value = b; } break; case QVariant::Vector3D: { bool ok; - QVector3D vector = QDeclarativeStringConverters::vector3DFromString(string, &ok); + QVector3D vector = QDeclarativeStringConverters::vector3DFromString(v->value.asString(), &ok); instr.setType(QDeclarativeInstruction::StoreVector3D); - instr.storeVector3D.propertyIndex = prop.propertyIndex(); + instr.storeVector3D.propertyIndex = prop->index; instr.storeVector3D.vector.xp = vector.x(); instr.storeVector3D.vector.yp = vector.y(); instr.storeVector3D.vector.zp = vector.z(); @@ -564,9 +577,9 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, case QVariant::Vector4D: { bool ok; - QVector4D vector = QDeclarativeStringConverters::vector4DFromString(string, &ok); + QVector4D vector = QDeclarativeStringConverters::vector4DFromString(v->value.asString(), &ok); instr.setType(QDeclarativeInstruction::StoreVector4D); - instr.storeVector4D.propertyIndex = prop.propertyIndex(); + instr.storeVector4D.propertyIndex = prop->index; instr.storeVector4D.vector.xp = vector.x(); instr.storeVector4D.vector.yp = vector.y(); instr.storeVector4D.vector.zp = vector.z(); @@ -575,11 +588,10 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, break; default: { - int t = prop.userType(); instr.setType(QDeclarativeInstruction::AssignCustomType); - instr.assignCustomType.propertyIndex = prop.propertyIndex(); - instr.assignCustomType.primitive = output->indexForString(string); - instr.assignCustomType.type = t; + instr.assignCustomType.propertyIndex = prop->index; + instr.assignCustomType.primitive = output->indexForString(v->value.asString()); + instr.assignCustomType.type = type; } break; } @@ -594,7 +606,7 @@ void QDeclarativeCompiler::reset(QDeclarativeCompiledData *data) data->types.clear(); data->primitives.clear(); data->datas.clear(); - data->bytecode.clear(); + data->bytecode.resize(0); } /*! @@ -621,13 +633,13 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, // Compile types const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); - QList<QDeclarativeScriptParser::TypeReference *> referencedTypes = unit->parser().referencedTypes(); + QList<QDeclarativeScript::TypeReference *> referencedTypes = unit->parser().referencedTypes(); for (int ii = 0; ii < resolvedTypes.count(); ++ii) { QDeclarativeCompiledData::TypeReference ref; const QDeclarativeTypeData::TypeReference &tref = resolvedTypes.at(ii); - QDeclarativeScriptParser::TypeReference *parserRef = referencedTypes.at(ii); + QDeclarativeScript::TypeReference *parserRef = referencedTypes.at(ii); if (tref.type) { ref.type = tref.type; @@ -652,11 +664,11 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, } else if (tref.typeData) { ref.component = tref.typeData->compiledData(); } - ref.className = parserRef->name.toUtf8(); + ref.className = parserRef->name; out->types << ref; } - QDeclarativeParser::Object *root = unit->parser().tree(); + QDeclarativeScript::Object *root = unit->parser().tree(); Q_ASSERT(root); this->engine = engine; @@ -668,15 +680,14 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, if (!isError()) { if (compilerDump()) out->dumpInstructions(); - if (compilerStatDump()) + if (componentStats) dumpStats(); Q_ASSERT(out->rootPropertyCache); } else { reset(out); } - compileState = ComponentCompileState(); - savedCompileStates.clear(); + compileState = 0; output = 0; this->engine = 0; this->enginePrivate = 0; @@ -686,10 +697,13 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, return !isError(); } -void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) +void QDeclarativeCompiler::compileTree(QDeclarativeScript::Object *tree) { - compileState.root = tree; - componentStat.lineNumber = tree->location.start.line; + compileState = pool->New<ComponentCompileState>(); + + compileState->root = tree; + if (componentStats) + componentStats->componentStat.lineNumber = tree->location.start.line; // Build global import scripts QStringList importedScriptIndexes; @@ -720,21 +734,21 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) QDeclarativeInstruction init; init.setType(QDeclarativeInstruction::Init); - init.init.bindingsSize = compileState.bindings.count(); - init.init.parserStatusSize = compileState.parserStatusCount; + init.init.bindingsSize = compileState->bindings.count(); + init.init.parserStatusSize = compileState->parserStatusCount; init.init.contextCache = genContextCache(); - if (compileState.compiledBindingData.isEmpty()) + if (compileState->compiledBindingData.isEmpty()) init.init.compiledBinding = -1; else - init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData); + init.init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData); output->addInstruction(init); - if (!compileState.v8BindingProgram.isEmpty()) { + if (!compileState->v8BindingProgram.isEmpty()) { QDeclarativeInstruction bindings; bindings.setType(QDeclarativeInstruction::InitV8Bindings); - bindings.initV8Bindings.program = output->indexForString(compileState.v8BindingProgram); - bindings.initV8Bindings.programIndex = compileState.v8BindingProgramIndex; - bindings.initV8Bindings.line = compileState.v8BindingProgramLine; + bindings.initV8Bindings.program = output->indexForString(compileState->v8BindingProgram); + bindings.initV8Bindings.programIndex = compileState->v8BindingProgramIndex; + bindings.initV8Bindings.line = compileState->v8BindingProgramLine; output->addInstruction(bindings); } @@ -760,25 +774,27 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree) enginePrivate->registerCompositeType(output); } -static bool ValuePtrLessThan(const QDeclarativeParser::Value *t1, const QDeclarativeParser::Value *t2) +static bool QStringList_contains(const QStringList &list, const QHashedStringRef &string) { - return t1->location.start.line < t2->location.start.line || - (t1->location.start.line == t2->location.start.line && - t1->location.start.column < t2->location.start.column); + for (int ii = 0; ii < list.count(); ++ii) + if (string == list.at(ii)) + return true; + + return false; } -bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const BindingContext &ctxt) +bool QDeclarativeCompiler::buildObject(QDeclarativeScript::Object *obj, const BindingContext &ctxt) { - componentStat.objects++; + if (componentStats) + componentStats->componentStat.objects++; Q_ASSERT (obj->type != -1); const QDeclarativeCompiledData::TypeReference &tr = output->types.at(obj->type); obj->metatype = tr.metaObject(); - if (tr.type) + if (tr.type) obj->typeName = tr.type->qmlTypeName(); - obj->className = tr.className; // This object is a "Component" element if (tr.type && obj->metatype == &QDeclarativeComponent::staticMetaObject) { @@ -799,7 +815,7 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi Q_ASSERT(type); obj->parserStatusCast = type->parserStatusCast(); if (obj->parserStatusCast != -1) - compileState.parserStatusCount++; + compileState->parserStatusCount++; // Check if this is a custom parser type. Custom parser types allow // assignments to non-existent properties. These assignments are then @@ -814,8 +830,8 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi // Must do id property first. This is to ensure that the id given to any // id reference created matches the order in which the objects are // instantiated - foreach(Property *prop, obj->properties) { - if (prop->name == "id") { + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { + if (prop->name() == id_string) { COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); break; } @@ -825,34 +841,75 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi Property *defaultProperty = 0; Property *skipProperty = 0; if (obj->defaultProperty) { - const QMetaObject *metaObject = obj->metaObject(); - Q_ASSERT(metaObject); - QMetaProperty p = QDeclarativeMetaType::defaultProperty(metaObject); - if (p.name()) { - Property *explicitProperty = obj->getProperty(p.name(), false); - if (explicitProperty && !explicitProperty->value) { - skipProperty = explicitProperty; - - defaultProperty = new Property; - defaultProperty->parent = obj; - defaultProperty->isDefault = true; - defaultProperty->location = obj->defaultProperty->location; - defaultProperty->listValueRange = obj->defaultProperty->listValueRange; - - defaultProperty->values = obj->defaultProperty->values; - defaultProperty->values += explicitProperty->values; - foreach(QDeclarativeParser::Value *value, defaultProperty->values) - value->addref(); - qSort(defaultProperty->values.begin(), defaultProperty->values.end(), ValuePtrLessThan); + defaultProperty = obj->defaultProperty; + + Property *explicitProperty = 0; + + const QMetaObject *mo = obj->metatype; + int idx = mo->indexOfClassInfo("DefaultProperty"); + if (idx != -1) { + QMetaClassInfo info = mo->classInfo(idx); + const char *p = info.value(); + if (p) { + int plen = 0; + char ord = 0; + while (char c = p[plen++]) { ord |= c; }; + --plen; + + if (ord & 0x80) { + // Utf8 - unoptimal, but seldom hit + QString *s = pool->NewString(QString::fromUtf8(p, plen)); + QHashedStringRef r(*s); + + if (obj->propertiesHashField.test(r.hash())) { + for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) { + if (ep->name() == r) { + explicitProperty = ep; + break; + } + } + } + + if (!explicitProperty) + defaultProperty->setName(r); - } else { - defaultProperty = obj->defaultProperty; - defaultProperty->addref(); + } else { + QHashedCStringRef r(p, plen); + + if (obj->propertiesHashField.test(r.hash())) { + for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) { + if (ep->name() == r) { + explicitProperty = ep; + break; + } + } + } + + if (!explicitProperty) { + // Set the default property name + QChar *buffer = pool->NewRawArray<QChar>(r.length()); + r.writeUtf16(buffer); + defaultProperty->setName(QHashedStringRef(buffer, r.length(), r.hash())); + } + } } - } else { - defaultProperty = obj->defaultProperty; - defaultProperty->addref(); } + + if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) { + + skipProperty = explicitProperty; // We merge the values into defaultProperty + + // Find the correct insertion point + Value *insertPos = 0; + + for (Value *v = defaultProperty->values.first(); v; v = Property::ValueList::next(v)) { + if (!(v->location.start < explicitProperty->values.first()->location.start)) + break; + insertPos = v; + } + + defaultProperty->values.insertAfter(insertPos, explicitProperty->values); + } } QDeclarativeCustomParser *cp = 0; @@ -860,39 +917,38 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi cp = output->types.at(obj->type).type->customParser(); // Build all explicit properties specified - foreach(Property *prop, obj->properties) { + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { if (prop == skipProperty) continue; - if (prop->name == "id") + if (prop->name() == id_string) continue; bool canDefer = false; if (isCustomParser) { - if (doesPropertyExist(prop, obj) && + if (doesPropertyExist(prop, obj) && (!(cp->flags() & QDeclarativeCustomParser::AcceptsAttachedProperties) || - !isAttachedPropertyName(prop->name))) { - int ids = compileState.ids.count(); + !isAttachedPropertyName(prop->name()))) { + int ids = compileState->ids.count(); COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); - canDefer = ids == compileState.ids.count(); - } else if (isSignalPropertyName(prop->name) && + canDefer = ids == compileState->ids.count(); + } else if (isSignalPropertyName(prop->name()) && (cp->flags() & QDeclarativeCustomParser::AcceptsSignalHandlers)) { COMPILE_CHECK(buildSignal(prop,obj,objCtxt)); } else { customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop); } } else { - if (isSignalPropertyName(prop->name)) { + if (isSignalPropertyName(prop->name())) { COMPILE_CHECK(buildSignal(prop,obj,objCtxt)); } else { - int ids = compileState.ids.count(); + int ids = compileState->ids.count(); COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); - canDefer = ids == compileState.ids.count(); + canDefer = ids == compileState->ids.count(); } } - if (canDefer && !deferredList.isEmpty() && - deferredList.contains(QString::fromUtf8(prop->name))) + if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name())) prop->isDeferred = true; } @@ -904,26 +960,22 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi bool canDefer = false; if (isCustomParser) { if (doesPropertyExist(prop, obj)) { - int ids = compileState.ids.count(); + int ids = compileState->ids.count(); COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); - canDefer = ids == compileState.ids.count(); + canDefer = ids == compileState->ids.count(); } else { customProps << QDeclarativeCustomParserNodePrivate::fromProperty(prop); } } else { - int ids = compileState.ids.count(); + int ids = compileState->ids.count(); COMPILE_CHECK(buildProperty(prop, obj, objCtxt)); - canDefer = ids == compileState.ids.count(); + canDefer = ids == compileState->ids.count(); } - if (canDefer && !deferredList.isEmpty() && - deferredList.contains(QString::fromUtf8(prop->name))) + if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name())) prop->isDeferred = true; } - if (defaultProperty) - defaultProperty->release(); - // Compile custom parser parts if (isCustomParser && !customProps.isEmpty()) { cp->clearErrors(); @@ -941,7 +993,7 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi return true; } -void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) +void QDeclarativeCompiler::genObject(QDeclarativeScript::Object *obj) { QDeclarativeCompiledData::TypeReference &tr = output->types[obj->type]; if (tr.type && obj->metatype == &QDeclarativeComponent::staticMetaObject) { @@ -951,7 +1003,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) // Create the object if (obj->custom.isEmpty() && output->types.at(obj->type).type && - !output->types.at(obj->type).type->isExtendedType() && obj != compileState.root) { + !output->types.at(obj->type).type->isExtendedType() && obj != compileState->root) { QDeclarativeInstruction create; create.setType(QDeclarativeInstruction::CreateSimpleObject); @@ -1039,23 +1091,24 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) genObjectBody(obj); } -void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) +void QDeclarativeCompiler::genObjectBody(QDeclarativeScript::Object *obj) { - typedef QPair<Property *, int> PropPair; - foreach(const PropPair &prop, obj->scriptStringProperties) { - const QString &script = prop.first->values.at(0)->value.asScript(); + for (Property *prop = obj->scriptStringProperties.first(); prop; prop = Object::PropertyList::next(prop)) { + Q_ASSERT(prop->scriptStringScope != -1); + const QString &script = prop->values.first()->value.asScript(); QDeclarativeInstruction ss; ss.setType(QDeclarativeInstruction::StoreScriptString); - ss.storeScriptString.propertyIndex = prop.first->index; + ss.storeScriptString.propertyIndex = prop->index; ss.storeScriptString.value = output->indexForString(script); - ss.storeScriptString.scope = prop.second; - ss.storeScriptString.bindingId = rewriteBinding(script, prop.first->name); - ss.storeScriptString.line = prop.first->location.start.line; + ss.storeScriptString.scope = prop->scriptStringScope; +// ss.storeScriptString.bindingId = rewriteBinding(script, prop->name()); + ss.storeScriptString.bindingId = rewriteBinding(script, QString()); // XXX + ss.storeScriptString.line = prop->location.start.line; output->addInstruction(ss); } bool seenDefer = false; - foreach(Property *prop, obj->valueProperties) { + for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) { if (prop->isDeferred) { seenDefer = true; continue; @@ -1072,13 +1125,13 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) QDeclarativeInstruction init; init.setType(QDeclarativeInstruction::Init); - init.init.bindingsSize = compileState.bindings.count(); // XXX - bigger than necessary - init.init.parserStatusSize = compileState.parserStatusCount; // XXX - bigger than necessary + init.init.bindingsSize = compileState->bindings.count(); // XXX - bigger than necessary + init.init.parserStatusSize = compileState->parserStatusCount; // XXX - bigger than necessary init.init.contextCache = -1; init.init.compiledBinding = -1; output->addInstruction(init); - foreach(Property *prop, obj->valueProperties) { + for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) { if (!prop->isDeferred) continue; genValueProperty(prop, obj); @@ -1091,9 +1144,9 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) output->instruction(deferIdx)->defer.deferCount = output->nextInstructionIndex() - nextInstructionIndex; } - foreach(Property *prop, obj->signalProperties) { + for (Property *prop = obj->signalProperties.first(); prop; prop = Object::PropertyList::next(prop)) { - QDeclarativeParser::Value *v = prop->values.at(0); + QDeclarativeScript::Value *v = prop->values.first(); if (v->type == Value::SignalObject) { @@ -1102,21 +1155,18 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) QDeclarativeInstruction assign; assign.setType(QDeclarativeInstruction::AssignSignalObject); assign.assignSignalObject.line = v->location.start.line; - assign.assignSignalObject.signal = - output->indexForByteArray(prop->name); + assign.assignSignalObject.signal = output->indexForString(prop->name().toString()); output->addInstruction(assign); } else if (v->type == Value::SignalExpression) { - BindingContext ctxt = compileState.signalExpressions.value(v); - QDeclarativeInstruction store; store.setType(QDeclarativeInstruction::StoreSignal); store.storeSignal.signalIndex = prop->index; store.storeSignal.value = output->indexForString(v->value.asScript().trimmed()); - store.storeSignal.context = ctxt.stack; - store.storeSignal.name = output->indexForByteArray(prop->name); + store.storeSignal.context = v->signalExpressionContextStack; + store.storeSignal.name = output->indexForByteArray(prop->name().toUtf8()); store.storeSignal.line = v->location.start.line; output->addInstruction(store); @@ -1124,7 +1174,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) } - foreach(Property *prop, obj->attachedProperties) { + for (Property *prop = obj->attachedProperties.first(); prop; prop = Object::PropertyList::next(prop)) { QDeclarativeInstruction fetch; fetch.setType(QDeclarativeInstruction::FetchAttached); fetch.fetchAttached.id = prop->index; @@ -1138,7 +1188,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) output->addInstruction(pop); } - foreach(Property *prop, obj->groupedProperties) { + for (Property *prop = obj->groupedProperties.first(); prop; prop = Object::PropertyList::next(prop)) { QDeclarativeInstruction fetch; fetch.setType(QDeclarativeInstruction::FetchObject); fetch.fetch.property = prop->index; @@ -1161,25 +1211,25 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) output->addInstruction(pop); } - foreach(Property *prop, obj->valueTypeProperties) { + for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) { if (!prop->isAlias) genValueTypeProperty(obj, prop); } - foreach(Property *prop, obj->valueProperties) { + for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) { if (prop->isDeferred) continue; if (prop->isAlias) genValueProperty(prop, obj); } - foreach(Property *prop, obj->valueTypeProperties) { + for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) { if (prop->isAlias) genValueTypeProperty(obj, prop); } } -void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj,QDeclarativeParser::Property *prop) +void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeScript::Object *obj,QDeclarativeScript::Property *prop) { QDeclarativeInstruction fetch; fetch.setType(QDeclarativeInstruction::FetchValueType); @@ -1190,7 +1240,7 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj, if (obj->type == -1 || output->types.at(obj->type).component) { // We only have to do this if this is a composite type. If it is a builtin // type it can't possibly already have bindings that need to be cleared. - foreach(Property *vprop, prop->value->valueProperties) { + for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) { if (!vprop->values.isEmpty()) { Q_ASSERT(vprop->index >= 0 && vprop->index < 32); fetch.fetchValue.bindingSkipList |= (1 << vprop->index); @@ -1200,7 +1250,7 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj, output->addInstruction(fetch); - foreach(Property *vprop, prop->value->valueProperties) { + for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) { genPropertyAssignment(vprop, prop->value, prop); } @@ -1212,9 +1262,9 @@ void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj, output->addInstruction(pop); } -void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) +void QDeclarativeCompiler::genComponent(QDeclarativeScript::Object *obj) { - QDeclarativeParser::Object *root = obj->defaultProperty->values.at(0)->object; + QDeclarativeScript::Object *root = obj->defaultProperty->values.first()->object; Q_ASSERT(root); QDeclarativeInstruction create; @@ -1225,26 +1275,26 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) int createInstruction = output->addInstruction(create); int nextInstructionIndex = output->nextInstructionIndex(); - ComponentCompileState oldCompileState = compileState; + ComponentCompileState *oldCompileState = compileState; compileState = componentState(root); QDeclarativeInstruction init; init.setType(QDeclarativeInstruction::Init); - init.init.bindingsSize = compileState.bindings.count(); - init.init.parserStatusSize = compileState.parserStatusCount; + init.init.bindingsSize = compileState->bindings.count(); + init.init.parserStatusSize = compileState->parserStatusCount; init.init.contextCache = genContextCache(); - if (compileState.compiledBindingData.isEmpty()) + if (compileState->compiledBindingData.isEmpty()) init.init.compiledBinding = -1; else - init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData); + init.init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData); output->addInstruction(init); - if (!compileState.v8BindingProgram.isEmpty()) { + if (!compileState->v8BindingProgram.isEmpty()) { QDeclarativeInstruction bindings; bindings.setType(QDeclarativeInstruction::InitV8Bindings); - bindings.initV8Bindings.program = output->indexForString(compileState.v8BindingProgram); - bindings.initV8Bindings.programIndex = compileState.v8BindingProgramIndex; - bindings.initV8Bindings.line = compileState.v8BindingProgramLine; + bindings.initV8Bindings.program = output->indexForString(compileState->v8BindingProgram); + bindings.initV8Bindings.programIndex = compileState->v8BindingProgramIndex; + bindings.initV8Bindings.line = compileState->v8BindingProgramLine; output->addInstruction(bindings); } @@ -1277,7 +1327,7 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) } } -bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildComponent(QDeclarativeScript::Object *obj, const BindingContext &ctxt) { // The special "Component" element can only have the id property and a @@ -1285,21 +1335,21 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, // Find, check and set the "id" property (if any) Property *idProp = 0; - if (obj->properties.count() > 1 || - (obj->properties.count() == 1 && obj->properties.begin().key() != "id")) - COMPILE_EXCEPTION(*obj->properties.begin(), tr("Component elements may not contain properties other than id")); + if (obj->properties.isMany() || + (obj->properties.isOne() && obj->properties.first()->name() != id_string)) + COMPILE_EXCEPTION(obj->properties.first(), tr("Component elements may not contain properties other than id")); - if (obj->properties.count()) - idProp = *obj->properties.begin(); + if (!obj->properties.isEmpty()) + idProp = obj->properties.first(); if (idProp) { - if (idProp->value || idProp->values.count() > 1 || idProp->values.at(0)->object) + if (idProp->value || idProp->values.isMany() || idProp->values.first()->object) COMPILE_EXCEPTION(idProp, tr("Invalid component id specification")); COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive())) QString idVal = idProp->values.first()->primitive(); - if (compileState.ids.contains(idVal)) + if (compileState->ids.value(idVal)) COMPILE_EXCEPTION(idProp, tr("id is not unique")); obj->id = idVal; @@ -1308,8 +1358,8 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, // Check the Component tree is well formed if (obj->defaultProperty && - (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 || - (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object))) + (obj->defaultProperty->value || obj->defaultProperty->values.isMany() || + (obj->defaultProperty->values.isOne() && !obj->defaultProperty->values.first()->object))) COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); if (!obj->dynamicProperties.isEmpty()) @@ -1319,8 +1369,8 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, if (!obj->dynamicSlots.isEmpty()) COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions.")); - QDeclarativeParser::Object *root = 0; - if (obj->defaultProperty && obj->defaultProperty->values.count()) + QDeclarativeScript::Object *root = 0; + if (obj->defaultProperty && !obj->defaultProperty->values.isEmpty()) root = obj->defaultProperty->values.first()->object; if (!root) @@ -1332,26 +1382,34 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, return true; } -bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeScript::Object *obj, const BindingContext &ctxt) { - ComponentCompileState oldComponentCompileState = compileState; - ComponentStat oldComponentStat = componentStat; + ComponentCompileState *oldComponentCompileState = compileState; + compileState = pool->New<ComponentCompileState>(); + compileState->root = obj; + compileState->nested = true; + + if (componentStats) { + ComponentStat oldComponentStat = componentStats->componentStat; - compileState = ComponentCompileState(); - compileState.root = obj; - compileState.nested = true; + componentStats->componentStat = ComponentStat(); + componentStats->componentStat.lineNumber = obj->location.start.line; - componentStat = ComponentStat(); - componentStat.lineNumber = obj->location.start.line; + if (obj) + COMPILE_CHECK(buildObject(obj, ctxt)); - if (obj) - COMPILE_CHECK(buildObject(obj, ctxt)); + COMPILE_CHECK(completeComponentBuild()); - COMPILE_CHECK(completeComponentBuild()); + componentStats->componentStat = oldComponentStat; + } else { + if (obj) + COMPILE_CHECK(buildObject(obj, ctxt)); + + COMPILE_CHECK(completeComponentBuild()); + } compileState = oldComponentCompileState; - componentStat = oldComponentStat; return true; } @@ -1360,15 +1418,15 @@ bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeParser::Object *ob // Build a sub-object. A sub-object is one that was not created directly by // QML - such as a grouped property object, or an attached object. Sub-object's // can't have an id, involve a custom parser, have attached properties etc. -bool QDeclarativeCompiler::buildSubObject(QDeclarativeParser::Object *obj, const BindingContext &ctxt) +bool QDeclarativeCompiler::buildSubObject(QDeclarativeScript::Object *obj, const BindingContext &ctxt) { Q_ASSERT(obj->metatype); Q_ASSERT(!obj->defaultProperty); Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding // sub-context - foreach(Property *prop, obj->properties) { - if (isSignalPropertyName(prop->name)) { + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { + if (isSignalPropertyName(prop->name())) { COMPILE_CHECK(buildSignal(prop, obj, ctxt)); } else { COMPILE_CHECK(buildProperty(prop, obj, ctxt)); @@ -1380,49 +1438,51 @@ bool QDeclarativeCompiler::buildSubObject(QDeclarativeParser::Object *obj, const int QDeclarativeCompiler::componentTypeRef() { - QDeclarativeType *t = QDeclarativeMetaType::qmlType("QtQuick/Component",2,0); + QDeclarativeType *t = QDeclarativeMetaType::qmlType(QLatin1String("QtQuick/Component"),2,0); for (int ii = output->types.count() - 1; ii >= 0; --ii) { if (output->types.at(ii).type == t) return ii; } QDeclarativeCompiledData::TypeReference ref; - ref.className = "Component"; + ref.className = Component_string; ref.type = t; output->types << ref; return output->types.count() - 1; } -bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildSignal(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj, const BindingContext &ctxt) { Q_ASSERT(obj->metaObject()); - QByteArray name = prop->name; - Q_ASSERT(name.startsWith("on")); - name = name.mid(2); + const QHashedStringRef &propName = prop->name(); + + Q_ASSERT(propName.startsWith(on_string)); + QString name = propName.mid(2, -1).toString(); // Note that the property name could start with any alpha or '_' or '$' character, // so we need to do the lower-casing of the first alpha character. for (int firstAlphaIndex = 0; firstAlphaIndex < name.size(); ++firstAlphaIndex) { - if (name[firstAlphaIndex] >= 'A' && name[firstAlphaIndex] <= 'Z') { - name[firstAlphaIndex] = name[firstAlphaIndex] - 'A' + 'a'; + if (QDeclarativeUtils::isUpper(name.at(firstAlphaIndex))) { + name[firstAlphaIndex] = name.at(firstAlphaIndex).toLower(); break; } } bool notInRevision = false; - int sigIdx = indexOfSignal(obj, name, ¬InRevision); - if (sigIdx == -1) { + QDeclarativePropertyCache::Data *sig = signal(obj, QStringRef(&name), ¬InRevision); + + if (sig == 0) { - if (notInRevision && -1 == indexOfProperty(obj, prop->name, 0)) { + if (notInRevision && 0 == property(obj, propName, 0)) { Q_ASSERT(obj->type != -1); const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); if (type.type) { - COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion)); } else { - COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString())); } } @@ -1432,26 +1492,28 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl } else { - if (prop->value || prop->values.count() != 1) + if (prop->value || !prop->values.isOne()) COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment")); - prop->index = sigIdx; + prop->index = sig->coreIndex; + prop->core = *sig; + obj->addSignalProperty(prop); - if (prop->values.at(0)->object) { - COMPILE_CHECK(buildObject(prop->values.at(0)->object, ctxt)); - prop->values.at(0)->type = Value::SignalObject; + if (prop->values.first()->object) { + COMPILE_CHECK(buildObject(prop->values.first()->object, ctxt)); + prop->values.first()->type = Value::SignalObject; } else { - prop->values.at(0)->type = Value::SignalExpression; + prop->values.first()->type = Value::SignalExpression; - if (!prop->values.at(0)->value.isScript()) + if (!prop->values.first()->value.isScript()) COMPILE_EXCEPTION(prop, tr("Cannot assign a value to a signal (expecting a script to be run)")); - QString script = prop->values.at(0)->value.asScript().trimmed(); + QString script = prop->values.first()->value.asScript().trimmed(); if (script.isEmpty()) COMPILE_EXCEPTION(prop, tr("Empty signal assignment")); - compileState.signalExpressions.insert(prop->values.at(0), ctxt); + prop->values.first()->signalExpressionContextStack = ctxt.stack; } } @@ -1462,37 +1524,28 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl /*! Returns true if (value) property \a prop exists on obj, false otherwise. */ -bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj) +bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj) { - if(isAttachedPropertyName(prop->name) || prop->name == "id") + if (prop->name().isEmpty()) + return false; + if(isAttachedPropertyName(prop->name()) || prop->name() == id_string) return true; - const QMetaObject *mo = obj->metaObject(); - if (mo) { - if (prop->isDefault) { - QMetaProperty p = QDeclarativeMetaType::defaultProperty(mo); - return p.name() != 0; - } else { - int idx = indexOfProperty(obj, prop->name); - return idx != -1 && mo->property(idx).isScriptable(); - } - } - - return false; + return property(obj, prop->name()) != 0; } -bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - const BindingContext &ctxt) +bool QDeclarativeCompiler::buildProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + const BindingContext &ctxt) { - if (prop->isEmpty()) + if (prop->isEmpty()) COMPILE_EXCEPTION(prop, tr("Empty property assignment")); const QMetaObject *metaObject = obj->metaObject(); Q_ASSERT(metaObject); - if (isAttachedPropertyName(prop->name)) { + if (isAttachedPropertyName(prop->name())) { // Setup attached property data if (ctxt.isSubContext()) { @@ -1504,7 +1557,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, QDeclarativeType *type = 0; QDeclarativeImportedNamespace *typeNamespace = 0; - unit->imports().resolveType(prop->name, &type, 0, 0, 0, &typeNamespace); + unit->imports().resolveType(prop->name().toString(), &type, 0, 0, 0, &typeNamespace); if (typeNamespace) { COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, @@ -1522,44 +1575,35 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, prop->value->metatype = type->attachedPropertiesType(); } else { // Setup regular property data - QMetaProperty p; - - if (prop->isDefault) { - p = QDeclarativeMetaType::defaultProperty(metaObject); + bool notInRevision = false; + QDeclarativePropertyCache::Data *d = + prop->name().isEmpty()?0:property(obj, prop->name(), ¬InRevision); - if (p.name()) { - prop->index = p.propertyIndex(); - prop->name = p.name(); - } - - } else { - bool notInRevision = false; - prop->index = indexOfProperty(obj, prop->name, ¬InRevision); - if (prop->index == -1 && notInRevision) { - const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); - const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); - if (type.type) { - COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); - } else { - COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name))); - } - } - - if (prop->index != -1) { - p = metaObject->property(prop->index); - Q_ASSERT(p.name()); - - if (!p.isScriptable()) { - prop->index = -1; - p = QMetaProperty(); - } + if (d == 0 && notInRevision) { + const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); + const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); + if (type.type) { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion)); + } else { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString())); } + } else if (d) { + prop->index = d->coreIndex; + prop->core = *d; + } else if (prop->isDefault) { + QMetaProperty p = QDeclarativeMetaType::defaultProperty(metaObject); + QDeclarativePropertyCache::Data defaultPropertyData; + defaultPropertyData.load(p, engine); + if (p.name()) + prop->setName(p.name()); + prop->core = defaultPropertyData; + prop->index = prop->core.coreIndex; } // We can't error here as the "id" property does not require a // successful index resolution - if (p.name()) - prop->type = p.userType(); + if (prop->index != -1) + prop->type = prop->core.propType; // Check if this is an alias if (prop->index != -1 && @@ -1576,17 +1620,17 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, prop->parent->setBindingBit(prop->index); } - if (!prop->isDefault && prop->name == "id" && !ctxt.isSubContext()) { + if (!prop->isDefault && prop->name() == id_string && !ctxt.isSubContext()) { // The magic "id" behavior doesn't apply when "id" is resolved as a // default property or to sub-objects (which are always in binding // sub-contexts) COMPILE_CHECK(buildIdProperty(prop, obj)); if (prop->type == QVariant::String && - prop->values.at(0)->value.isString()) + prop->values.first()->value.isString()) COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt)); - } else if (isAttachedPropertyName(prop->name)) { + } else if (isAttachedPropertyName(prop->name())) { COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt)); @@ -1595,14 +1639,14 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, if (prop->isDefault) { COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existent default property")); } else { - COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString())); } } else if (prop->value) { COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt)); - } else if (enginePrivate->isList(prop->type)) { + } else if (prop->core.isQList()) { COMPILE_CHECK(buildListProperty(prop, obj, ctxt)); @@ -1620,22 +1664,22 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, } bool QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeImportedNamespace *ns, - QDeclarativeParser::Property *nsProp, - QDeclarativeParser::Object *obj, + QDeclarativeScript::Property *nsProp, + QDeclarativeScript::Object *obj, const BindingContext &ctxt) { if (!nsProp->value) COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace")); - foreach (Property *prop, nsProp->value->properties) { + for (Property *prop = nsProp->value->properties.first(); prop; prop = nsProp->value->properties.next(prop)) { - if (!isAttachedPropertyName(prop->name)) + if (!isAttachedPropertyName(prop->name())) COMPILE_EXCEPTION(prop, tr("Not an attached property name")); // Setup attached property data QDeclarativeType *type = 0; - unit->imports().resolveType(ns, prop->name, &type, 0, 0, 0); + unit->imports().resolveType(ns, prop->name().toString(), &type, 0, 0, 0); if (!type || !type->attachedPropertiesType()) COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); @@ -1653,18 +1697,18 @@ bool QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeImportedNamespac return true; } -void QDeclarativeCompiler::genValueProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj) +void QDeclarativeCompiler::genValueProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj) { - if (enginePrivate->isList(prop->type)) { + if (prop->core.isQList()) { genListProperty(prop, obj); } else { genPropertyAssignment(prop, obj); } } -void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj) +void QDeclarativeCompiler::genListProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj) { int listType = enginePrivate->listType(prop->type); @@ -1675,8 +1719,7 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, fetch.fetchQmlList.type = listType; output->addInstruction(fetch); - for (int ii = 0; ii < prop->values.count(); ++ii) { - QDeclarativeParser::Value *v = prop->values.at(ii); + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { if (v->type == Value::CreatedObject) { @@ -1705,12 +1748,11 @@ void QDeclarativeCompiler::genListProperty(QDeclarativeParser::Property *prop, output->addInstruction(pop); } -void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Property *valueTypeProperty) +void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Property *valueTypeProperty) { - for (int ii = 0; ii < prop->values.count(); ++ii) { - QDeclarativeParser::Value *v = prop->values.at(ii); + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { Q_ASSERT(v->type == Value::CreatedObject || v->type == Value::PropertyBinding || @@ -1728,7 +1770,7 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p store.storeObject.propertyIndex = prop->index; output->addInstruction(store); - } else if (prop->type == -1) { + } else if (prop->type == QMetaType::QVariant) { QDeclarativeInstruction store; store.setType(QDeclarativeInstruction::StoreVariantObject); @@ -1751,16 +1793,13 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p } else if (v->type == Value::Literal) { - QMetaProperty mp = obj->metaObject()->property(prop->index); - genLiteralAssignment(mp, v); + genLiteralAssignment(prop, v); } } - for (int ii = 0; ii < prop->onValues.count(); ++ii) { - - QDeclarativeParser::Value *v = prop->onValues.at(ii); + for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) { Q_ASSERT(v->type == Value::ValueSource || v->type == Value::ValueInterceptor); @@ -1801,23 +1840,23 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p } } -bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj) +bool QDeclarativeCompiler::buildIdProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj) { if (prop->value || - prop->values.count() > 1 || - prop->values.at(0)->object) + prop->values.isMany() || + prop->values.first()->object) COMPILE_EXCEPTION(prop, tr("Invalid use of id property")); - QDeclarativeParser::Value *idValue = prop->values.at(0); + QDeclarativeScript::Value *idValue = prop->values.first(); QString val = idValue->primitive(); COMPILE_CHECK(checkValidId(idValue, val)); - if (compileState.ids.contains(val)) + if (compileState->ids.value(val)) COMPILE_EXCEPTION(prop, tr("id is not unique")); - prop->values.at(0)->type = Value::Id; + prop->values.first()->type = Value::Id; obj->id = val; addId(val, obj); @@ -1825,35 +1864,37 @@ bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop, return true; } -void QDeclarativeCompiler::addId(const QString &id, QDeclarativeParser::Object *obj) +void QDeclarativeCompiler::addId(const QString &id, QDeclarativeScript::Object *obj) { - Q_ASSERT(!compileState.ids.contains(id)); + Q_ASSERT(!compileState->ids.value(id)); Q_ASSERT(obj->id == id); - obj->idIndex = compileState.ids.count(); - compileState.ids.insert(id, obj); - compileState.idIndexes.insert(obj->idIndex, obj); + obj->idIndex = compileState->ids.count(); + compileState->ids.append(obj); } -void QDeclarativeCompiler::addBindingReference(const BindingReference &ref) +void QDeclarativeCompiler::addBindingReference(BindingReference *ref) { - Q_ASSERT(ref.value && !compileState.bindings.contains(ref.value)); - compileState.bindings.insert(ref.value, ref); + Q_ASSERT(ref->value && !ref->value->bindingReference); + ref->value->bindingReference = ref; + compileState->bindings.prepend(ref); } void QDeclarativeCompiler::saveComponentState() { - Q_ASSERT(compileState.root); - Q_ASSERT(!savedCompileStates.contains(compileState.root)); + Q_ASSERT(compileState->root); + Q_ASSERT(compileState->root->componentCompileState == 0); + + compileState->root->componentCompileState = compileState; - savedCompileStates.insert(compileState.root, compileState); - savedComponentStats.append(componentStat); + if (componentStats) + componentStats->savedComponentStats.append(componentStats->componentStat); } -QDeclarativeCompiler::ComponentCompileState -QDeclarativeCompiler::componentState(QDeclarativeParser::Object *obj) +QDeclarativeCompilerTypes::ComponentCompileState * +QDeclarativeCompiler::componentState(QDeclarativeScript::Object *obj) { - Q_ASSERT(savedCompileStates.contains(obj)); - return savedCompileStates.value(obj); + Q_ASSERT(obj->componentCompileState); + return obj->componentCompileState; } // Build attached property object. In this example, @@ -1861,8 +1902,8 @@ QDeclarativeCompiler::componentState(QDeclarativeParser::Object *obj) // GridView.row: 10 // } // GridView is an attached property object. -bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, const BindingContext &ctxt) { Q_ASSERT(prop->value); @@ -1882,32 +1923,33 @@ bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeParser::Property *p // font.family: "Helvetica" // } // font is a nested property. pointSize and family are not. -bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, const BindingContext &ctxt) { Q_ASSERT(prop->type != 0); Q_ASSERT(prop->index != -1); if (QDeclarativeValueTypeFactory::isValueType(prop->type)) { - if (prop->type >= 0 /* QVariant == -1 */ && enginePrivate->valueTypes[prop->type]) { + if (prop->type >= 0 && enginePrivate->valueTypes[prop->type]) { - if (prop->values.count()) { - if (prop->values.at(0)->location < prop->value->location) { + if (!prop->values.isEmpty()) { + if (prop->values.first()->location < prop->value->location) { COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value")); } else { - COMPILE_EXCEPTION(prop->values.at(0), tr( "Property has already been assigned a value")); + COMPILE_EXCEPTION(prop->values.first(), tr( "Property has already been assigned a value")); } } if (!obj->metaObject()->property(prop->index).isWritable()) { - COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); } if (prop->isAlias) { - foreach (Property *vtProp, prop->value->properties) + for (Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) { vtProp->isAlias = true; + } } COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type], @@ -1923,8 +1965,8 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr if (!prop->value->metatype) COMPILE_EXCEPTION(prop, tr("Invalid grouped property access")); - if (prop->values.count()) - COMPILE_EXCEPTION(prop->values.at(0), tr( "Cannot assign a value directly to a grouped property")); + if (!prop->values.isEmpty()) + COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign a value directly to a grouped property")); obj->addGroupedProperty(prop); @@ -1935,32 +1977,32 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr } bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Object *baseObj, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Object *baseObj, const BindingContext &ctxt) { if (obj->defaultProperty) COMPILE_EXCEPTION(obj, tr("Invalid property use")); obj->metatype = type->metaObject(); - foreach (Property *prop, obj->properties) { - int idx = type->metaObject()->indexOfProperty(prop->name.constData()); - if (idx == -1) - COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); - QMetaProperty p = type->metaObject()->property(idx); - if (!p.isScriptable()) - COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); - prop->index = idx; - prop->type = p.userType(); + for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) { + + QDeclarativePropertyCache::Data *d = property(obj, prop->name()); + if (d == 0) + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString())); + + prop->index = d->coreIndex; + prop->type = d->propType; + prop->core = *d; prop->isValueTypeSubProperty = true; if (prop->value) COMPILE_EXCEPTION(prop, tr("Property assignment expected")); - if (prop->values.count() > 1) { + if (prop->values.isMany()) { COMPILE_EXCEPTION(prop, tr("Single property assignment expected")); - } else if (prop->values.count()) { - QDeclarativeParser::Value *value = prop->values.at(0); + } else if (!prop->values.isEmpty()) { + QDeclarativeScript::Value *value = prop->values.first(); if (value->object) { COMPILE_EXCEPTION(prop, tr("Unexpected object assignment")); @@ -1969,27 +2011,30 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, //optimization for <Type>.<EnumValue> enum assignments bool isEnumAssignment = false; - COMPILE_CHECK(testQualifiedEnumAssignment(p, obj, value, &isEnumAssignment)); + + if (prop->core.isEnum()) + COMPILE_CHECK(testQualifiedEnumAssignment(obj->metatype->property(prop->index), obj, + value, &isEnumAssignment)); + if (isEnumAssignment) { value->type = Value::Literal; } else { - BindingReference reference; - reference.expression = value->value; - reference.property = prop; - reference.value = value; - reference.bindingContext = ctxt; - reference.bindingContext.owner++; + BindingReference *reference = pool->New<BindingReference>(); + reference->expression = value->value; + reference->property = prop; + reference->value = value; + reference->bindingContext = ctxt; + reference->bindingContext.owner++; addBindingReference(reference); value->type = Value::PropertyBinding; } } else { - COMPILE_CHECK(testLiteralAssignment(p, value)); + COMPILE_CHECK(testLiteralAssignment(prop, value)); value->type = Value::Literal; } } - for (int ii = 0; ii < prop->onValues.count(); ++ii) { - QDeclarativeParser::Value *v = prop->onValues.at(ii); + for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) { Q_ASSERT(v->object); COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt)); @@ -2004,11 +2049,11 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, // Build assignments to QML lists. QML lists are properties of type // QDeclarativeListProperty<T>. List properties can accept a list of // objects, or a single binding. -bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildListProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, const BindingContext &ctxt) { - Q_ASSERT(enginePrivate->isList(prop->type)); + Q_ASSERT(prop->core.isQList()); int t = prop->type; @@ -2018,8 +2063,7 @@ bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop, bool listTypeIsInterface = QDeclarativeMetaType::isInterface(listType); bool assignedBinding = false; - for (int ii = 0; ii < prop->values.count(); ++ii) { - QDeclarativeParser::Value *v = prop->values.at(ii); + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { if (v->object) { v->type = Value::CreatedObject; COMPILE_CHECK(buildObject(v->object, ctxt)); @@ -2048,33 +2092,33 @@ bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop, } // Compiles an assignment to a QDeclarativeScriptString property -bool QDeclarativeCompiler::buildScriptStringProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildScriptStringProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, const BindingContext &ctxt) { - if (prop->values.count() > 1) - COMPILE_EXCEPTION(prop->values.at(1), tr( "Cannot assign multiple values to a script property")); + if (prop->values.isMany()) + COMPILE_EXCEPTION(prop->values.first()->nextValue, tr( "Cannot assign multiple values to a script property")); - if (prop->values.at(0)->object) - COMPILE_EXCEPTION(prop->values.at(0), tr( "Invalid property assignment: script expected")); + if (prop->values.first()->object) + COMPILE_EXCEPTION(prop->values.first(), tr( "Invalid property assignment: script expected")); - obj->addScriptStringProperty(prop, ctxt.stack); + prop->scriptStringScope = ctxt.stack; + obj->addScriptStringProperty(prop); return true; } // Compile regular property assignments of the form "property: <value>" -bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, +bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, const BindingContext &ctxt) { obj->addValueProperty(prop); - if (prop->values.count() > 1) - COMPILE_EXCEPTION(prop->values.at(0), tr( "Cannot assign multiple values to a singular property") ); + if (prop->values.isMany()) + COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a singular property") ); - for (int ii = 0; ii < prop->values.count(); ++ii) { - QDeclarativeParser::Value *v = prop->values.at(ii); + for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) { if (v->object) { COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt)); @@ -2086,9 +2130,7 @@ bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property } } - for (int ii = 0; ii < prop->onValues.count(); ++ii) { - QDeclarativeParser::Value *v = prop->onValues.at(ii); - + for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) { Q_ASSERT(v->object); COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt)); } @@ -2097,16 +2139,16 @@ bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property } // Compile assigning a single object instance to a regular property -bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Value *v, +bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Value *v, const BindingContext &ctxt) { Q_ASSERT(prop->index != -1); Q_ASSERT(v->object->type != -1); if (!obj->metaObject()->property(prop->index).isWritable()) - COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); if (QDeclarativeMetaType::isInterface(prop->type)) { @@ -2115,7 +2157,7 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro v->type = Value::CreatedObject; - } else if (prop->type == -1) { + } else if (prop->type == QMetaType::QVariant) { // Assigning an object to a QVariant COMPILE_CHECK(buildObject(v->object, ctxt)); @@ -2152,13 +2194,13 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro v->type = Value::CreatedObject; } else if (propertyMetaObject == &QDeclarativeComponent::staticMetaObject) { // Automatic "Component" insertion - QDeclarativeParser::Object *root = v->object; - QDeclarativeParser::Object *component = new QDeclarativeParser::Object; + QDeclarativeScript::Object *root = v->object; + QDeclarativeScript::Object *component = pool->New<Object>(); component->type = componentTypeRef(); component->typeName = "Qt/Component"; component->metatype = &QDeclarativeComponent::staticMetaObject; component->location = root->location; - QDeclarativeParser::Value *componentValue = new QDeclarativeParser::Value; + QDeclarativeScript::Value *componentValue = pool->New<Value>(); componentValue->object = root; component->getDefaultProperty()->addValue(componentValue); v->object = component; @@ -2177,17 +2219,17 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro // Item { // NumberAnimation on x { } // } -bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Object *baseObj, - QDeclarativeParser::Value *v, +bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Object *baseObj, + QDeclarativeScript::Value *v, const BindingContext &ctxt) { Q_ASSERT(prop->index != -1); Q_ASSERT(v->object->type != -1); if (!obj->metaObject()->property(prop->index).isWritable()) - COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); // Normally buildObject() will set this up, but we need the static @@ -2214,28 +2256,31 @@ bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeParser::Propert buildDynamicMeta(baseObj, ForceCreation); v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; } else { - COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(QString::fromUtf8(v->object->typeName)).arg(QString::fromUtf8(prop->name.constData()))); + COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(QString::fromUtf8(v->object->typeName)).arg(prop->name().toString())); } return true; } // Compile assigning a literal or binding to a regular property -bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Value *v, - const BindingContext &ctxt) +bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Value *v, + const BindingContext &ctxt) { Q_ASSERT(prop->index != -1); if (v->value.isScript()) { //optimization for <Type>.<EnumValue> enum assignments - bool isEnumAssignment = false; - COMPILE_CHECK(testQualifiedEnumAssignment(obj->metaObject()->property(prop->index), obj, v, &isEnumAssignment)); - if (isEnumAssignment) { - v->type = Value::Literal; - return true; + if (prop->core.isEnum()) { + bool isEnumAssignment = false; + COMPILE_CHECK(testQualifiedEnumAssignment(obj->metaObject()->property(prop->index), obj, + v, &isEnumAssignment)); + if (isEnumAssignment) { + v->type = Value::Literal; + return true; + } } COMPILE_CHECK(buildBinding(v, prop, ctxt)); @@ -2244,7 +2289,7 @@ bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeParser::Pr } else { - COMPILE_CHECK(testLiteralAssignment(obj->metaObject()->property(prop->index), v)); + COMPILE_CHECK(testLiteralAssignment(prop, v)); v->type = Value::Literal; } @@ -2253,9 +2298,9 @@ bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeParser::Pr } bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Value *v, - bool *isAssignment) + QDeclarativeScript::Object *obj, + QDeclarativeScript::Value *v, + bool *isAssignment) { *isAssignment = false; if (!prop.isEnumType()) @@ -2265,7 +2310,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); QString string = v->value.asString(); - if (!string.at(0).isUpper()) + if (!QDeclarativeUtils::isUpper(string.at(0))) return true; QStringList parts = string.split(QLatin1Char('.')); @@ -2274,7 +2319,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop QString typeName = parts.at(0); QDeclarativeType *type = 0; - unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); + unit->imports().resolveType(typeName, &type, 0, 0, 0, 0); //handle enums on value types (where obj->typeName is empty) QByteArray objTypeName = obj->typeName; @@ -2312,7 +2357,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop return true; v->type = Value::Literal; - v->value = QDeclarativeParser::Variant((double)value); + v->value = QDeclarativeScript::Variant((double)value); *isAssignment = true; return true; @@ -2331,7 +2376,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const if (dot > 0) { const QByteArray &scope = script.left(dot); QDeclarativeType *type = 0; - unit->imports().resolveType(scope, &type, 0, 0, 0, 0); + unit->imports().resolveType(QString::fromUtf8(script.left(dot)), &type, 0, 0, 0, 0); if (!type && scope != "Qt") return -1; const QMetaObject *mo = type ? type->metaObject() : StaticQtMetaObject::get(); @@ -2349,7 +2394,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) const { QDeclarativeType *qmltype = 0; - if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0, 0)) + if (!unit->imports().resolveType(QString::fromUtf8(name), &qmltype, 0, 0, 0, 0)) return 0; if (!qmltype) return 0; @@ -2358,10 +2403,10 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) con // similar to logic of completeComponentBuild, but also sticks data // into primitives at the end -int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteArray& name) +int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QString& name) { QDeclarativeRewrite::RewriteBinding rewriteBinding; - rewriteBinding.setName('$' + name.mid(name.lastIndexOf('.') + 1)); + rewriteBinding.setName(QLatin1Char('$') + name.mid(name.lastIndexOf('.') + 1)); QString rewrite = rewriteBinding(expression, 0, 0); @@ -2369,16 +2414,20 @@ int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteA } // Ensures that the dynamic meta specification on obj is valid -bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) +bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeScript::Object *obj) { - QSet<QByteArray> propNames; - QSet<QByteArray> methodNames; bool seenDefaultProperty = false; + // We use a coarse grain, 31 bit hash to check if there are duplicates. + // Calculating the hash for the names is not a waste as we have to test + // them against the illegalNames set anyway. + QHashField propNames; + QHashField methodNames; + // Check properties - for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { - const QDeclarativeParser::Object::DynamicProperty &prop = - obj->dynamicProperties.at(ii); + int dpCount = obj->dynamicProperties.count(); + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + const QDeclarativeScript::Object::DynamicProperty &prop = *p; if (prop.isDefaultProperty) { if (seenDefaultProperty) @@ -2386,60 +2435,75 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) seenDefaultProperty = true; } - if (propNames.contains(prop.name)) - COMPILE_EXCEPTION(&prop, tr("Duplicate property name")); + if (propNames.testAndSet(prop.name.hash())) { + for (Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p; + p2 = obj->dynamicProperties.next(p2)) { + if (p2->name == prop.name) + COMPILE_EXCEPTION(&prop, tr("Duplicate property name")); + } + } - QString propName = QString::fromUtf8(prop.name); - if (propName.at(0).isUpper()) + if (QDeclarativeUtils::isUpper(prop.name.at(0))) COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter")); - if (enginePrivate->v8engine()->illegalNames().contains(propName)) + if (enginePrivate->v8engine()->illegalNames().contains(prop.name)) COMPILE_EXCEPTION(&prop, tr("Illegal property name")); - - propNames.insert(prop.name); } - for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { - const QDeclarativeParser::Object::DynamicSignal &currSig = obj->dynamicSignals.at(ii); - QByteArray name = currSig.name; - if (methodNames.contains(name)) - COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name")); - QString nameStr = QString::fromUtf8(name); - if (nameStr.at(0).isUpper()) + for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) { + const QDeclarativeScript::Object::DynamicSignal &currSig = *s; + + if (methodNames.testAndSet(currSig.name.hash())) { + for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s; + s2 = obj->dynamicSignals.next(s2)) { + if (s2->name == currSig.name) + COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name")); + } + } + + if (currSig.name.at(0).isUpper()) COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter")); - if (enginePrivate->v8engine()->illegalNames().contains(nameStr)) + if (enginePrivate->v8engine()->illegalNames().contains(currSig.name)) COMPILE_EXCEPTION(&currSig, tr("Illegal signal name")); - methodNames.insert(name); - } - for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { - const QDeclarativeParser::Object::DynamicSlot &currSlot = obj->dynamicSlots.at(ii); - QByteArray name = currSlot.name; - if (methodNames.contains(name)) - COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); - QString nameStr = QString::fromUtf8(name); - if (nameStr.at(0).isUpper()) + } + + for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) { + const QDeclarativeScript::Object::DynamicSlot &currSlot = *s; + + if (methodNames.testAndSet(currSlot.name.hash())) { + for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2; + s2 = obj->dynamicSignals.next(s2)) { + if (s2->name == currSlot.name) + COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); + } + for (Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s; + s2 = obj->dynamicSlots.next(s2)) { + if (s2->name == currSlot.name) + COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name")); + } + } + + if (currSlot.name.at(0).isUpper()) COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter")); - if (enginePrivate->v8engine()->illegalNames().contains(nameStr)) + if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name)) COMPILE_EXCEPTION(&currSlot, tr("Illegal method name")); - methodNames.insert(name); } return true; } -bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeParser::Object *obj) +bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeScript::Object *obj) { - for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { - const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { - if (!p.defaultValue || p.type == Object::DynamicProperty::Alias) + if (!p->defaultValue || p->type == Object::DynamicProperty::Alias) continue; Property *property = 0; - if (p.isDefaultProperty) { + if (p->isDefaultProperty) { property = obj->getDefaultProperty(); } else { - property = obj->getProperty(p.name); + property = obj->getProperty(p->name); if (!property->values.isEmpty()) COMPILE_EXCEPTION(property, tr("Property value set multiple times")); } @@ -2447,18 +2511,14 @@ bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeParser::Object if (property->value) COMPILE_EXCEPTION(property, tr("Invalid property nesting")); - for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) { - QDeclarativeParser::Value *v = p.defaultValue->values.at(ii); - v->addref(); - property->values.append(v); - } + property->values.append(p->defaultValue->values); } return true; } Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter) -bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, DynamicMetaMode mode) +bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeScript::Object *obj, DynamicMetaMode mode) { Q_ASSERT(obj); Q_ASSERT(obj->metatype); @@ -2469,61 +2529,121 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn obj->dynamicSlots.isEmpty()) return true; - QByteArray dynamicData(sizeof(QDeclarativeVMEMetaData), (char)0); + bool resolveAlias = (mode == ResolveAliases); + + const Object::DynamicProperty *defaultProperty = 0; + int aliasCount = 0; + + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + + if (p->type == Object::DynamicProperty::Alias) + aliasCount++; + + if (p->isDefaultProperty && + (resolveAlias || p->type != Object::DynamicProperty::Alias)) + defaultProperty = p; + + if (!resolveAlias) { + // No point doing this for both the alias and non alias cases + QDeclarativePropertyCache::Data *d = property(obj, p->name); + if (d && d->isFinal()) + COMPILE_EXCEPTION(p, tr("Cannot override FINAL property")); + } + } + + bool buildData = resolveAlias || aliasCount == 0; + + QByteArray dynamicData; + if (buildData) { + typedef QDeclarativeVMEMetaData VMD; + + dynamicData = QByteArray(sizeof(QDeclarativeVMEMetaData) + + (obj->dynamicProperties.count() - aliasCount) * sizeof(VMD::PropertyData) + + obj->dynamicSlots.count() * sizeof(VMD::MethodData) + + aliasCount * sizeof(VMD::AliasData), 0); + } + + int uniqueClassId = classIndexCounter()->fetchAndAddRelaxed(1); QByteArray newClassName = obj->metatype->className(); newClassName.append("_QML_"); - int idx = classIndexCounter()->fetchAndAddRelaxed(1); - newClassName.append(QByteArray::number(idx)); - if (compileState.root == obj && !compileState.nested) { + newClassName.append(QByteArray::number(uniqueClassId)); + + if (compileState->root == obj && !compileState->nested) { QString path = output->url.path(); int lastSlash = path.lastIndexOf(QLatin1Char('/')); if (lastSlash > -1) { QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5); - if (!nameBase.isEmpty() && nameBase.at(0).isUpper()) - newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(idx); + if (!nameBase.isEmpty() && QDeclarativeUtils::isUpper(nameBase.at(0))) + newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(uniqueClassId); } } - QMetaObjectBuilder builder; - builder.setClassName(newClassName); - builder.setFlags(QMetaObjectBuilder::DynamicMetaObject); + QFastMetaBuilder builder; + QFastMetaBuilder::StringRef classNameRef = builder.init(newClassName.length(), + obj->dynamicProperties.count() - (resolveAlias?0:aliasCount), + obj->dynamicSlots.count(), + obj->dynamicSignals.count() + obj->dynamicProperties.count(), + defaultProperty?1:0); + + struct TypeData { + Object::DynamicProperty::Type dtype; + int metaType; + const char *cppType; + } builtinTypes[] = { + { Object::DynamicProperty::Variant, 0, "QVariant" }, + { Object::DynamicProperty::Int, QMetaType::Int, "int" }, + { Object::DynamicProperty::Bool, QMetaType::Bool, "bool" }, + { Object::DynamicProperty::Real, QMetaType::Double, "double" }, + { Object::DynamicProperty::String, QMetaType::QString, "QString" }, + { Object::DynamicProperty::Url, QMetaType::QUrl, "QUrl" }, + { Object::DynamicProperty::Color, QMetaType::QColor, "QColor" }, + { Object::DynamicProperty::Time, QMetaType::QTime, "QTime" }, + { Object::DynamicProperty::Date, QMetaType::QDate, "QDate" }, + { Object::DynamicProperty::DateTime, QMetaType::QDateTime, "QDateTime" }, + }; + static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData); + QFastMetaBuilder::StringRef typeRefs[builtinTypeCount]; + + // Reserve dynamic properties + if (obj->dynamicProperties.count()) { + typedef QDeclarativeVMEMetaData VMD; + + int effectivePropertyIndex = 0; + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + + // Reserve space for name + p->nameRef = builder.newString(p->name.utf8length()); + + int propertyType = 0; + bool readonly = false; + QFastMetaBuilder::StringRef typeRef; + + if (p->type == Object::DynamicProperty::Alias) { + continue; + } else if (p->type < builtinTypeCount) { + Q_ASSERT(builtinTypes[p->type].dtype == p->type); + propertyType = builtinTypes[p->type].metaType; + if (typeRefs[p->type].isEmpty()) + typeRefs[p->type] = builder.newString(strlen(builtinTypes[p->type].cppType)); + typeRef = typeRefs[p->type]; + if (p->type == Object::DynamicProperty::Variant) + propertyType = -1; - bool hasAlias = false; - for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { - const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); + } else { + Q_ASSERT(p->type == Object::DynamicProperty::CustomList || + p->type == Object::DynamicProperty::Custom); - int propIdx = obj->metaObject()->indexOfProperty(p.name.constData()); - if (-1 != propIdx) { - QMetaProperty prop = obj->metaObject()->property(propIdx); - if (prop.isFinal()) - COMPILE_EXCEPTION(&p, tr("Cannot override FINAL property")); - } + // XXX don't double resolve this in the case of an alias run - if (p.isDefaultProperty && - (p.type != Object::DynamicProperty::Alias || - mode == ResolveAliases)) - builder.addClassInfo("DefaultProperty", p.name); - - QByteArray type; - int propertyType = 0; - bool readonly = false; - switch(p.type) { - case Object::DynamicProperty::Alias: - hasAlias = true; - continue; - break; - case Object::DynamicProperty::CustomList: - case Object::DynamicProperty::Custom: - { QByteArray customTypeName; QDeclarativeType *qmltype = 0; - QUrl url; - if (!unit->imports().resolveType(p.customType, &qmltype, &url, 0, 0, 0)) - COMPILE_EXCEPTION(&p, tr("Invalid property type")); + QString url; + if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0)) + COMPILE_EXCEPTION(p, tr("Invalid property type")); if (!qmltype) { - QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(url); + QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(QUrl(url)); Q_ASSERT(tdata); Q_ASSERT(tdata->isComplete()); @@ -2535,146 +2655,217 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn customTypeName = qmltype->typeName(); } - if (p.type == Object::DynamicProperty::Custom) { - type = customTypeName + '*'; + if (p->type == Object::DynamicProperty::Custom) { + customTypeName += '*'; propertyType = QMetaType::QObjectStar; } else { readonly = true; - type = "QDeclarativeListProperty<"; - type.append(customTypeName); - type.append(">"); + customTypeName = QByteArray("QDeclarativeListProperty<") + customTypeName + QByteArray(">"); propertyType = qMetaTypeId<QDeclarativeListProperty<QObject> >(); } + + p->resolvedCustomTypeName = pool->NewByteArray(customTypeName); + p->typeRef = builder.newString(customTypeName.length()); + typeRef = p->typeRef; } - break; - case Object::DynamicProperty::Variant: - propertyType = -1; - type = "QVariant"; - break; - case Object::DynamicProperty::Int: - propertyType = QVariant::Int; - type = "int"; - break; - case Object::DynamicProperty::Bool: - propertyType = QVariant::Bool; - type = "bool"; - break; - case Object::DynamicProperty::Real: - propertyType = QVariant::Double; - type = "double"; - break; - case Object::DynamicProperty::String: - propertyType = QVariant::String; - type = "QString"; - break; - case Object::DynamicProperty::Url: - propertyType = QVariant::Url; - type = "QUrl"; - break; - case Object::DynamicProperty::Color: - propertyType = QVariant::Color; - type = "QColor"; - break; - case Object::DynamicProperty::Time: - propertyType = QVariant::Time; - type = "QTime"; - break; - case Object::DynamicProperty::Date: - propertyType = QVariant::Date; - type = "QDate"; - break; - case Object::DynamicProperty::DateTime: - propertyType = QVariant::DateTime; - type = "QDateTime"; - break; - } - ((QDeclarativeVMEMetaData *)dynamicData.data())->propertyCount++; - QDeclarativeVMEMetaData::PropertyData propertyData = { propertyType }; - dynamicData.append((char *)&propertyData, sizeof(propertyData)); + if (buildData) { + VMD *vmd = (QDeclarativeVMEMetaData *)dynamicData.data(); + vmd->propertyCount++; + (vmd->propertyData() + effectivePropertyIndex)->propertyType = propertyType; + } - builder.addSignal(p.name + "Changed()"); - QMetaPropertyBuilder propBuilder = - builder.addProperty(p.name, type, builder.methodCount() - 1); - propBuilder.setWritable(!readonly); - } + if (p->type < builtinTypeCount) + builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, (QMetaType::Type)propertyType, + readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, + effectivePropertyIndex); + else + builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, + readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, + effectivePropertyIndex); - for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { - const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); + p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()")); + builder.setSignal(effectivePropertyIndex, p->changedSignatureRef); - if (p.type == Object::DynamicProperty::Alias) { - if (mode == ResolveAliases) { - ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++; - COMPILE_CHECK(compileAlias(builder, dynamicData, obj, p)); - } else { - // Need a fake signal so that the metaobject remains consistent across - // the resolve and non-resolve alias runs - builder.addSignal(p.name + "Changed()"); + effectivePropertyIndex++; + } + + if (aliasCount) { + int aliasIndex = 0; + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { + if (p->type == Object::DynamicProperty::Alias) { + if (resolveAlias) { + Q_ASSERT(buildData); + ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++; + COMPILE_CHECK(compileAlias(builder, dynamicData, obj, effectivePropertyIndex, + aliasIndex, *p)); + } + // Even if we aren't resolving the alias, we need a fake signal so that the + // metaobject remains consistent across the resolve and non-resolve alias runs + p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()")); + builder.setSignal(effectivePropertyIndex, p->changedSignatureRef); + effectivePropertyIndex++; + aliasIndex++; + } } } } - for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { - const Object::DynamicSignal &s = obj->dynamicSignals.at(ii); - QByteArray sig(s.name + '('); - for (int jj = 0; jj < s.parameterTypes.count(); ++jj) { - if (jj) sig.append(','); - sig.append(s.parameterTypes.at(jj)); - } - sig.append(')'); - QMetaMethodBuilder b = builder.addSignal(sig); - b.setParameterNames(s.parameterNames); - ((QDeclarativeVMEMetaData *)dynamicData.data())->signalCount++; + // Reserve default property + QFastMetaBuilder::StringRef defPropRef; + if (defaultProperty) { + defPropRef = builder.newString(strlen("DefaultProperty")); + builder.setClassInfo(0, defPropRef, defaultProperty->nameRef); + } + + // Reserve dynamic signals + int signalIndex = 0; + for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) { + + int paramCount = s->parameterNames.count(); + + int signatureSize = s->name.utf8length() + 2 /* paren */; + int namesSize = 0; + if (paramCount) signatureSize += s->parameterTypesLength() + (paramCount - 1) /* commas */; + if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1) /* commas */; + + s->signatureRef = builder.newString(signatureSize); + if (namesSize) s->parameterNamesRef = builder.newString(namesSize); + + if (buildData) + ((QDeclarativeVMEMetaData *)dynamicData.data())->signalCount++; + + builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->signatureRef, s->parameterNamesRef); + ++signalIndex; } - QStringList funcScripts; + // Reserve dynamic slots + if (obj->dynamicSlots.count()) { + + // Allocate QVariant string + if (typeRefs[0].isEmpty()) + typeRefs[0] = builder.newString(strlen(builtinTypes[0].cppType)); + + typedef QDeclarativeVMEMetaData VMD; + + int methodIndex = 0; + for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) { + int paramCount = s->parameterNames.count(); - for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { - Object::DynamicSlot &s = obj->dynamicSlots[ii]; - QByteArray sig(s.name + '('); - QString funcScript(QLatin1String("(function ") + s.name + QLatin1Char('(')); + int signatureSize = s->name.utf8length() + 2 /* paren */; + int namesSize = 0; + if (paramCount) signatureSize += (paramCount * strlen("QVariant") + (paramCount - 1)); + if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */); - for (int jj = 0; jj < s.parameterNames.count(); ++jj) { - if (jj) { - sig.append(','); - funcScript.append(QLatin1Char(',')); + s->signatureRef = builder.newString(signatureSize); + if (namesSize) s->parameterNamesRef = builder.newString(namesSize); + + builder.setMethod(methodIndex, s->signatureRef, s->parameterNamesRef, typeRefs[0]); + + if (buildData) { + QString funcScript; + funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ + + namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */); + funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('('); + for (int jj = 0; jj < paramCount; ++jj) { + if (jj) funcScript.append(QLatin1Char(',')); + funcScript.append(QLatin1String(s->parameterNames.at(jj))); + } + funcScript += QLatin1Char(')') + s->body + QLatin1Char(')'); + + VMD::MethodData methodData = { s->parameterNames.count(), 0, + funcScript.length(), + s->location.start.line }; + + VMD *vmd = (QDeclarativeVMEMetaData *)dynamicData.data(); + vmd->methodCount++; + + VMD::MethodData &md = *(vmd->methodData() + methodIndex); + md = methodData; + md.bodyOffset = dynamicData.size(); + + dynamicData.append((const char *)funcScript.constData(), + (funcScript.length() * sizeof(QChar))); } - funcScript.append(QLatin1String(s.parameterNames.at(jj))); - sig.append("QVariant"); + + methodIndex++; } - sig.append(')'); - funcScript.append(QLatin1Char(')')); - funcScript.append(s.body); - funcScript.append(QLatin1Char(')')); - funcScripts << funcScript; + } - QMetaMethodBuilder b = builder.addSlot(sig); - b.setReturnType("QVariant"); - b.setParameterNames(s.parameterNames); + // Now allocate used builtin types + for (int ii = 0; ii < builtinTypeCount; ++ii) { + if (!typeRefs[ii].isEmpty()) + typeRefs[ii].load(builtinTypes[ii].cppType); + } - ((QDeclarativeVMEMetaData *)dynamicData.data())->methodCount++; - QDeclarativeVMEMetaData::MethodData methodData = - { s.parameterNames.count(), 0, funcScript.length(), s.location.start.line }; + // Now allocate properties + for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) { - dynamicData.append((char *)&methodData, sizeof(methodData)); - } + char *d = p->changedSignatureRef.data(); + p->name.writeUtf8(d); + strcpy(d + p->name.utf8length(), "Changed()"); - for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { - const QString &funcScript = funcScripts.at(ii); - QDeclarativeVMEMetaData::MethodData *data = - ((QDeclarativeVMEMetaData *)dynamicData.data())->methodData() + ii; + if (p->type == Object::DynamicProperty::Alias && !resolveAlias) + continue; + + p->nameRef.load(p->name); - data->bodyOffset = dynamicData.size(); + if (p->type >= builtinTypeCount) { + Q_ASSERT(p->resolvedCustomTypeName); + p->typeRef.load(*p->resolvedCustomTypeName); + } + } - dynamicData.append((const char *)funcScript.constData(), - (funcScript.length() * sizeof(QChar))); + // Allocate default property if necessary + if (defaultProperty) + strcpy(defPropRef.data(), "DefaultProperty"); + + // Now allocate signals + for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) { + + char *d = s->signatureRef.data(); + char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data(); + s->name.writeUtf8(d); d += s->name.utf8length(); + *d++ = '('; + + for (int jj = 0; jj < s->parameterNames.count(); ++jj) { + if (jj != 0) { *d++ = ','; *d2++ = ','; } + strcpy(d, s->parameterTypes.at(jj).constData()); + d += s->parameterTypes.at(jj).length(); + s->parameterNames.at(jj).writeUtf8(d2); + d2 += s->parameterNames.at(jj).utf8length(); + } + *d++ = ')'; + *d = 0; + if (d2) *d2 = 0; + } + + // Now allocate methods + for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) { + char *d = s->signatureRef.data(); + char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data(); + s->name.writeUtf8(d); d += s->name.utf8length(); + *d++ = '('; + for (int jj = 0; jj < s->parameterNames.count(); ++jj) { + if (jj != 0) { *d++ = ','; *d2++ = ','; } + strcpy(d, "QVariant"); + d += strlen("QVariant"); + strcpy(d2, s->parameterNames.at(jj).constData()); + d2 += s->parameterNames.at(jj).length(); + } + *d++ = ')'; + *d = 0; + if (d2) *d2 = 0; } - obj->metadata = builder.toRelocatableData(); - builder.fromRelocatableData(&obj->extObject, obj->metatype, obj->metadata); + // Now allocate class name + classNameRef.load(newClassName); - if (mode == IgnoreAliases && hasAlias) - compileState.aliasingObjects << obj; + obj->metadata = builder.toData(); + builder.fromData(&obj->extObject, obj->metatype, obj->metadata); + + if (mode == IgnoreAliases && aliasCount) + compileState->aliasingObjects.append(obj); obj->synthdata = dynamicData; @@ -2694,23 +2885,23 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn return true; } -bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QString &val) +bool QDeclarativeCompiler::checkValidId(QDeclarativeScript::Value *v, const QString &val) { if (val.isEmpty()) COMPILE_EXCEPTION(v, tr( "Invalid empty ID")); - if (val.at(0).isLetter() && !val.at(0).isLower()) + QChar ch = val.at(0); + if (QDeclarativeUtils::isLetter(ch) && !QDeclarativeUtils::isLower(ch)) COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter")); QChar u(QLatin1Char('_')); - for (int ii = 0; ii < val.count(); ++ii) { + if (!QDeclarativeUtils::isLetter(ch) && ch != u) + COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore")); - if (ii == 0 && !val.at(ii).isLetter() && val.at(ii) != u) { - COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore")); - } else if (ii != 0 && !val.at(ii).isLetterOrNumber() && val.at(ii) != u) { + for (int ii = 1; ii < val.count(); ++ii) { + ch = val.at(ii); + if (!QDeclarativeUtils::isLetterOrNumber(ch) && ch != u) COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores")); - } - } if (enginePrivate->v8engine()->illegalNames().contains(val)) @@ -2725,7 +2916,7 @@ static QStringList astNodeToStringList(QDeclarativeJS::AST::Node *node) { if (node->kind == QDeclarativeJS::AST::Node::Kind_IdentifierExpression) { QString name = - static_cast<QDeclarativeJS::AST::IdentifierExpression *>(node)->name->asString(); + static_cast<QDeclarativeJS::AST::IdentifierExpression *>(node)->name.toString(); return QStringList() << name; } else if (node->kind == QDeclarativeJS::AST::Node::Kind_FieldMemberExpression) { QDeclarativeJS::AST::FieldMemberExpression *expr = static_cast<QDeclarativeJS::AST::FieldMemberExpression *>(node); @@ -2733,26 +2924,27 @@ static QStringList astNodeToStringList(QDeclarativeJS::AST::Node *node) QStringList rv = astNodeToStringList(expr->base); if (rv.isEmpty()) return rv; - rv.append(expr->name->asString()); + rv.append(expr->name.toString()); return rv; } return QStringList(); } -bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, +bool QDeclarativeCompiler::compileAlias(QFastMetaBuilder &builder, QByteArray &data, - QDeclarativeParser::Object *obj, - const Object::DynamicProperty &prop) + QDeclarativeScript::Object *obj, + int propIndex, int aliasIndex, + Object::DynamicProperty &prop) { if (!prop.defaultValue) COMPILE_EXCEPTION(obj, tr("No property alias location")); - if (prop.defaultValue->values.count() != 1 || - prop.defaultValue->values.at(0)->object || - !prop.defaultValue->values.at(0)->value.isScript()) + if (!prop.defaultValue->values.isOne() || + prop.defaultValue->values.first()->object || + !prop.defaultValue->values.first()->value.isScript()) COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); - QDeclarativeJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST(); + QDeclarativeJS::AST::Node *node = prop.defaultValue->values.first()->value.asAST(); if (!node) COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen? @@ -2761,19 +2953,19 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, if (alias.count() < 1 || alias.count() > 3) COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>")); - if (!compileState.ids.contains(alias.at(0))) + QDeclarativeScript::Object *idObject = compileState->ids.value(alias.at(0)); + if (!idObject) COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0))); - QDeclarativeParser::Object *idObject = compileState.ids[alias.at(0)]; - QByteArray typeName; int propIdx = -1; int flags = 0; + int type = 0; bool writable = false; bool resettable = false; if (alias.count() == 2 || alias.count() == 3) { - propIdx = indexOfProperty(idObject, alias.at(1).toUtf8()); + propIdx = indexOfProperty(idObject, alias.at(1)); if (-1 == propIdx) { COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); @@ -2788,6 +2980,9 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, writable = aliasProperty.isWritable(); resettable = aliasProperty.isResettable(); + if (aliasProperty.type() < QVariant::UserType) + type = aliasProperty.type(); + if (alias.count() == 3) { QDeclarativeValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()]; if (!valueType) @@ -2802,6 +2997,11 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, aliasProperty = valueType->metaObject()->property(valueTypeIndex); propIdx |= (valueTypeIndex << 16); + + // update the property type + type = aliasProperty.type(); + if (type >= QVariant::UserType) + type = 0; } if (aliasProperty.isEnumType()) @@ -2823,49 +3023,59 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, if (typeName.endsWith('*')) flags |= QML_ALIAS_FLAG_PTR; - data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex)); - data.append((const char *)&propIdx, sizeof(propIdx)); - data.append((const char *)&flags, sizeof(flags)); + QDeclarativeVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags }; + + typedef QDeclarativeVMEMetaData VMD; + VMD *vmd = (QDeclarativeVMEMetaData *)data.data(); + *(vmd->aliasData() + aliasIndex) = aliasData; + + prop.nameRef = builder.newString(prop.name.utf8length()); + prop.resolvedCustomTypeName = pool->NewByteArray(typeName); + prop.typeRef = builder.newString(typeName.length()); + + int propertyFlags = 0; + if (writable) + propertyFlags |= QFastMetaBuilder::Writable; + if (resettable) + propertyFlags |= QFastMetaBuilder::Resettable; + + builder.setProperty(propIndex, prop.nameRef, prop.typeRef, (QMetaType::Type)type, + (QFastMetaBuilder::PropertyFlag)propertyFlags, + propIndex); - builder.addSignal(prop.name + "Changed()"); - QMetaPropertyBuilder propBuilder = - builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1); - propBuilder.setWritable(writable); - propBuilder.setResettable(resettable); return true; } -bool QDeclarativeCompiler::buildBinding(QDeclarativeParser::Value *value, - QDeclarativeParser::Property *prop, - const BindingContext &ctxt) +bool QDeclarativeCompiler::buildBinding(QDeclarativeScript::Value *value, + QDeclarativeScript::Property *prop, + const BindingContext &ctxt) { Q_ASSERT(prop->index != -1); Q_ASSERT(prop->parent); Q_ASSERT(prop->parent->metaObject()); - QMetaProperty mp = prop->parent->metaObject()->property(prop->index); - if (!mp.isWritable() && !QDeclarativeMetaType::isList(prop->type)) - COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + if (!prop->core.isWritable() && !prop->core.isQList()) + COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString())); - BindingReference reference; - reference.expression = value->value; - reference.property = prop; - reference.value = value; - reference.bindingContext = ctxt; + BindingReference *reference = pool->New<BindingReference>(); + reference->expression = value->value; + reference->property = prop; + reference->value = value; + reference->bindingContext = ctxt; addBindingReference(reference); return true; } -void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *binding, - QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Property *valueTypeProperty) +void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *binding, + QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Property *valueTypeProperty) { Q_UNUSED(obj); - Q_ASSERT(compileState.bindings.contains(binding)); + Q_ASSERT(binding->bindingReference); - const BindingReference &ref = compileState.bindings.value(binding); + const BindingReference &ref = *binding->bindingReference; if (ref.dataType == BindingReference::V4) { QDeclarativeInstruction store; store.setType(QDeclarativeInstruction::StoreV4Binding); @@ -2921,22 +3131,20 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi int QDeclarativeCompiler::genContextCache() { - if (compileState.ids.count() == 0) + if (compileState->ids.count() == 0) return -1; QDeclarativeIntegerCache *cache = new QDeclarativeIntegerCache(); - - for (QHash<QString, QDeclarativeParser::Object *>::ConstIterator iter = compileState.ids.begin(); - iter != compileState.ids.end(); - ++iter) - cache->add(iter.key(), (*iter)->idIndex); + cache->reserve(compileState->ids.count()); + for (Object *o = compileState->ids.first(); o; o = compileState->ids.next(o)) + cache->add(o->id, o->idIndex); output->contextCaches.append(cache); return output->contextCaches.count() - 1; } -int QDeclarativeCompiler::genValueTypeData(QDeclarativeParser::Property *valueTypeProp, - QDeclarativeParser::Property *prop) +int QDeclarativeCompiler::genValueTypeData(QDeclarativeScript::Property *valueTypeProp, + QDeclarativeScript::Property *prop) { typedef QDeclarativePropertyPrivate QDPP; QByteArray data = QDPP::saveValueType(prop->parent->metaObject(), prop->index, @@ -2946,7 +3154,7 @@ int QDeclarativeCompiler::genValueTypeData(QDeclarativeParser::Property *valueTy return output->indexForByteArray(data); } -int QDeclarativeCompiler::genPropertyData(QDeclarativeParser::Property *prop) +int QDeclarativeCompiler::genPropertyData(QDeclarativeScript::Property *prop) { typedef QDeclarativePropertyPrivate QDPP; QByteArray data = QDPP::saveProperty(prop->parent->metaObject(), prop->index, engine); @@ -2956,27 +3164,25 @@ int QDeclarativeCompiler::genPropertyData(QDeclarativeParser::Property *prop) bool QDeclarativeCompiler::completeComponentBuild() { - componentStat.ids = compileState.ids.count(); + if (componentStats) + componentStats->componentStat.ids = compileState->ids.count(); - for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) { - QDeclarativeParser::Object *aliasObject = compileState.aliasingObjects.at(ii); + for (Object *aliasObject = compileState->aliasingObjects.first(); aliasObject; + aliasObject = compileState->aliasingObjects.next(aliasObject)) COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases)); - } - QDeclarativeV4Compiler::Expression expr; - expr.component = compileState.root; - expr.ids = compileState.ids; + QDeclarativeV4Compiler::Expression expr(unit->imports()); + expr.component = compileState->root; + expr.ids = &compileState->ids; expr.importCache = output->importCache; - expr.imports = unit->imports(); QDeclarativeV4Compiler bindingCompiler; QList<BindingReference*> sharedBindings; - for (QHash<QDeclarativeParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); - iter != compileState.bindings.end(); ++iter) { + for (BindingReference *b = compileState->bindings.first(); b; b = b->nextReference) { - BindingReference &binding = *iter; + BindingReference &binding = *b; // ### We don't currently optimize for bindings on alias's - because // of the solution to QTBUG-13719 @@ -2989,7 +3195,8 @@ bool QDeclarativeCompiler::completeComponentBuild() if (index != -1) { binding.dataType = BindingReference::V4; binding.compiledIndex = index; - componentStat.optimizedBindings.append(iter.key()->location); + if (componentStats) + componentStats->componentStat.optimizedBindings.append(b->value->location); continue; } } @@ -2998,19 +3205,20 @@ bool QDeclarativeCompiler::completeComponentBuild() QString expression = binding.expression.asScript(); QDeclarativeRewrite::RewriteBinding rewriteBinding; - rewriteBinding.setName('$'+binding.property->name); + rewriteBinding.setName(QLatin1Char('$')+binding.property->name().toString()); bool isSharable = false; binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable); if (isSharable && !binding.property->isAlias /* See above re alias */ && binding.property->type != qMetaTypeId<QDeclarativeBinding*>()) { binding.dataType = BindingReference::V8; - sharedBindings.append(&iter.value()); + sharedBindings.append(b); } else { binding.dataType = BindingReference::QtScript; } - componentStat.scriptBindings.append(iter.key()->location); + if (componentStats) + componentStats->componentStat.scriptBindings.append(b->value->location); } if (!sharedBindings.isEmpty()) { @@ -3029,7 +3237,7 @@ bool QDeclarativeCompiler::completeComponentBuild() QString functionArray(QLatin1String("[")); for (int ii = 0; ii < sharedBindings.count(); ++ii) { BindingReference *reference = sharedBindings.at(ii); - QDeclarativeParser::Value *value = reference->value; + QDeclarativeScript::Value *value = reference->value; const QString &expression = reference->rewrittenExpression; if (ii != 0) functionArray += QLatin1String(","); @@ -3044,14 +3252,14 @@ bool QDeclarativeCompiler::completeComponentBuild() } functionArray += QLatin1String("]"); - compileState.v8BindingProgram = functionArray; - compileState.v8BindingProgramLine = startLineNumber; - compileState.v8BindingProgramIndex = output->v8bindings.count(); + compileState->v8BindingProgram = functionArray; + compileState->v8BindingProgramLine = startLineNumber; + compileState->v8BindingProgramIndex = output->v8bindings.count(); output->v8bindings.append(v8::Persistent<v8::Array>()); } if (bindingCompiler.isValid()) - compileState.compiledBindingData = bindingCompiler.program(); + compileState->compiledBindingData = bindingCompiler.program(); saveComponentState(); @@ -3060,9 +3268,10 @@ bool QDeclarativeCompiler::completeComponentBuild() void QDeclarativeCompiler::dumpStats() { + Q_ASSERT(componentStats); qWarning().nospace() << "QML Document: " << output->url.toString(); - for (int ii = 0; ii < savedComponentStats.count(); ++ii) { - const ComponentStat &stat = savedComponentStats.at(ii); + for (int ii = 0; ii < componentStats->savedComponentStats.count(); ++ii) { + const ComponentStat &stat = componentStats->savedComponentStats.at(ii); qWarning().nospace() << " Component Line " << stat.lineNumber; qWarning().nospace() << " Total Objects: " << stat.objects; qWarning().nospace() << " IDs Used: " << stat.ids; @@ -3111,7 +3320,7 @@ void QDeclarativeCompiler::dumpStats() Returns true if from can be assigned to a (QObject) property of type to. */ -bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeParser::Object *from) +bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeScript::Object *from) { const QMetaObject *toMo = enginePrivate->rawMetaObjectForType(to); @@ -3125,7 +3334,20 @@ bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeParser::Object *from) return false; } -QDeclarativeType *QDeclarativeCompiler::toQmlType(QDeclarativeParser::Object *from) +/*! + Returns the element name, as written in the QML file, for o. +*/ +QString QDeclarativeCompiler::elementName(QDeclarativeScript::Object *o) +{ + Q_ASSERT(o); + if (o->type != -1) { + return output->types.at(o->type).className; + } else { + return QString(); + } +} + +QDeclarativeType *QDeclarativeCompiler::toQmlType(QDeclarativeScript::Object *from) { // ### Optimize const QMetaObject *mo = from->metatype; @@ -3137,7 +3359,7 @@ QDeclarativeType *QDeclarativeCompiler::toQmlType(QDeclarativeParser::Object *fr return type; } -QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeParser::Object *obj) +QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeScript::Object *obj) { const QMetaObject *mo = obj->metatype; @@ -3150,74 +3372,108 @@ QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeParser::Object return rv; } -// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName -int QDeclarativeCompiler::indexOfSignal(QDeclarativeParser::Object *object, const QByteArray &name, - bool *notInRevision) +QDeclarativePropertyCache::Data * +QDeclarativeCompiler::property(QDeclarativeScript::Object *object, int index) { - if (notInRevision) *notInRevision = false; + QDeclarativePropertyCache *cache = 0; + + if (object->synthCache) + cache = object->synthCache; + else if (object->type != -1) + cache = output->types[object->type].createPropertyCache(engine); + else + cache = QDeclarativeEnginePrivate::get(engine)->cache(object->metaObject()); - if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) { - // XXX fromUtf8 - QString strName(QString::fromUtf8(name)); - QDeclarativePropertyCache *cache = - object->synthCache?object->synthCache:output->types.at(object->type).propertyCache(); + return cache->property(index); +} - QDeclarativePropertyCache::Data *d = cache->property(strName); - if (notInRevision) *notInRevision = false; +QDeclarativePropertyCache::Data * +QDeclarativeCompiler::property(QDeclarativeScript::Object *object, const QHashedStringRef &name, bool *notInRevision) +{ + if (notInRevision) *notInRevision = false; - while (d && !(d->isFunction())) - d = cache->overrideData(d); + QDeclarativePropertyCache *cache = 0; - if (d && !cache->isAllowedInRevision(d)) { - if (notInRevision) *notInRevision = true; - return -1; - } else if (d) { - return d->coreIndex; - } + if (object->synthCache) + cache = object->synthCache; + else if (object->type != -1) + cache = output->types[object->type].createPropertyCache(engine); + else + cache = QDeclarativeEnginePrivate::get(engine)->cache(object->metaObject()); - if (name.endsWith("Changed")) { - QByteArray propName = name.mid(0, name.length() - 7); + QDeclarativePropertyCache::Data *d = cache->property(name); - int propIndex = indexOfProperty(object, propName, notInRevision); - if (propIndex != -1) { - d = cache->property(propIndex); - return d->notifyIndex; - } - } + // Find the first property + while (d && d->isFunction()) + d = cache->overrideData(d); - return -1; + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return 0; } else { - return QDeclarativePropertyPrivate::findSignalByName(object->metaObject(), name).methodIndex(); + return d; } - } -int QDeclarativeCompiler::indexOfProperty(QDeclarativeParser::Object *object, const QByteArray &name, - bool *notInRevision) +// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName +QDeclarativePropertyCache::Data * +QDeclarativeCompiler::signal(QDeclarativeScript::Object *object, const QHashedStringRef &name, bool *notInRevision) { if (notInRevision) *notInRevision = false; - if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) { - // XXX fromUtf8 - QString strName(QString::fromUtf8(name)); - QDeclarativePropertyCache *cache = - object->synthCache?object->synthCache:output->types.at(object->type).propertyCache(); + QDeclarativePropertyCache *cache = 0; - QDeclarativePropertyCache::Data *d = cache->property(strName); - // Find the first property - while (d && d->isFunction()) - d = cache->overrideData(d); + if (object->synthCache) + cache = object->synthCache; + else if (object->type != -1) + cache = output->types[object->type].createPropertyCache(engine); + else + cache = QDeclarativeEnginePrivate::get(engine)->cache(object->metaObject()); - if (d && !cache->isAllowedInRevision(d)) { - if (notInRevision) *notInRevision = true; - return -1; - } else { - return d?d->coreIndex:-1; - } - } else { - const QMetaObject *mo = object->metaObject(); - return mo->indexOfProperty(name.constData()); + + QDeclarativePropertyCache::Data *d = cache->property(name); + if (notInRevision) *notInRevision = false; + + while (d && !(d->isFunction())) + d = cache->overrideData(d); + + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return 0; + } else if (d) { + return d; + } + + if (name.endsWith(Changed_string)) { + QHashedStringRef propName = name.mid(0, name.length() - Changed_string.length()); + + d = property(object, propName, notInRevision); + if (d) + return cache->method(d->notifyIndex); } + + return 0; +} + +// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName +int QDeclarativeCompiler::indexOfSignal(QDeclarativeScript::Object *object, const QString &name, + bool *notInRevision) +{ + QDeclarativePropertyCache::Data *d = signal(object, QStringRef(&name), notInRevision); + return d?d->coreIndex:-1; +} + +int QDeclarativeCompiler::indexOfProperty(QDeclarativeScript::Object *object, const QString &name, + bool *notInRevision) +{ + return indexOfProperty(object, QStringRef(&name), notInRevision); +} + +int QDeclarativeCompiler::indexOfProperty(QDeclarativeScript::Object *object, const QHashedStringRef &name, + bool *notInRevision) +{ + QDeclarativePropertyCache::Data *d = property(object, name, notInRevision); + return d?d->coreIndex:-1; } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index a2b959a568..0e159a2cdf 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -57,7 +57,7 @@ #include "qdeclarativeerror.h" #include "private/qv8_p.h" #include "private/qdeclarativeinstruction_p.h" -#include "private/qdeclarativeparser_p.h" +#include "private/qdeclarativescript_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qbitfield_p.h" #include "private/qdeclarativepropertycache_p.h" @@ -91,7 +91,7 @@ public: TypeReference() : type(0), typePropertyCache(0), component(0) {} - QByteArray className; + QString className; QDeclarativeType *type; QDeclarativePropertyCache *typePropertyCache; QDeclarativeCompiledData *component; @@ -139,183 +139,237 @@ private: int indexForUrl(const QUrl &); }; +namespace QDeclarativeCompilerTypes { + struct BindingContext + { + BindingContext() + : stack(0), owner(0), object(0) {} + BindingContext(QDeclarativeScript::Object *o) + : stack(0), owner(0), object(o) {} + BindingContext incr() const { + BindingContext rv(object); + rv.stack = stack + 1; + return rv; + } + bool isSubContext() const { return stack != 0; } + int stack; + int owner; + QDeclarativeScript::Object *object; + }; + + struct BindingReference : public QDeclarativePool::Class + { + BindingReference() : nextReference(0) {} + + QDeclarativeScript::Variant expression; + QDeclarativeScript::Property *property; + QDeclarativeScript::Value *value; + + enum DataType { QtScript, V4, V8 }; + DataType dataType; + + int compiledIndex; + + QString rewrittenExpression; + BindingContext bindingContext; + + BindingReference *nextReference; + }; + + struct IdList : public QFieldList<QDeclarativeScript::Object, + &QDeclarativeScript::Object::nextIdObject> + { + QDeclarativeScript::Object *value(const QString &id) const { + for (QDeclarativeScript::Object *o = first(); o; o = next(o)) { + if (o->id == id) + return o; + } + return 0; + } + }; + + // Contains all the incremental compiler state about a component. As + // a single QML file can have multiple components defined, there may be + // more than one of these for each compile + struct ComponentCompileState : public QDeclarativePool::Class + { + ComponentCompileState() + : parserStatusCount(0), pushedProperties(0), nested(false), v8BindingProgramLine(-1), root(0) {} + + IdList ids; + int parserStatusCount; + int pushedProperties; + bool nested; + + QByteArray compiledBindingData; + QString v8BindingProgram; + int v8BindingProgramLine; + int v8BindingProgramIndex; + + typedef QDeclarativeCompilerTypes::BindingReference B; + typedef QFieldList<B, &B::nextReference> BindingReferenceList; + BindingReferenceList bindings; + typedef QDeclarativeScript::Object O; + typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList; + AliasingObjectsList aliasingObjects; + QDeclarativeScript::Object *root; + }; +}; + class QMetaObjectBuilder; class Q_AUTOTEST_EXPORT QDeclarativeCompiler { Q_DECLARE_TR_FUNCTIONS(QDeclarativeCompiler) public: - QDeclarativeCompiler(); + QDeclarativeCompiler(QDeclarativePool *); bool compile(QDeclarativeEngine *, QDeclarativeTypeData *, QDeclarativeCompiledData *); bool isError() const; QList<QDeclarativeError> errors() const; - static bool isAttachedPropertyName(const QByteArray &); - static bool isSignalPropertyName(const QByteArray &); + static bool isAttachedPropertyName(const QString &); + static bool isSignalPropertyName(const QString &); + static bool isAttachedPropertyName(const QHashedStringRef &); + static bool isSignalPropertyName(const QHashedStringRef &); int evaluateEnum(const QByteArray& script) const; // for QDeclarativeCustomParser::evaluateEnum const QMetaObject *resolveType(const QByteArray& name) const; // for QDeclarativeCustomParser::resolveType - int rewriteBinding(const QString& expression, const QByteArray& name); // for QDeclarativeCustomParser::rewriteBinding + int rewriteBinding(const QString& expression, const QString& name); // for QDeclarativeCustomParser::rewriteBinding private: static void reset(QDeclarativeCompiledData *); - struct BindingContext { - BindingContext() - : stack(0), owner(0), object(0) {} - BindingContext(QDeclarativeParser::Object *o) - : stack(0), owner(0), object(o) {} - BindingContext incr() const { - BindingContext rv(object); - rv.stack = stack + 1; - return rv; - } - bool isSubContext() const { return stack != 0; } - int stack; - int owner; - QDeclarativeParser::Object *object; - }; - - void compileTree(QDeclarativeParser::Object *tree); + void compileTree(QDeclarativeScript::Object *tree); - bool buildObject(QDeclarativeParser::Object *obj, const BindingContext &); - bool buildComponent(QDeclarativeParser::Object *obj, const BindingContext &); - bool buildSubObject(QDeclarativeParser::Object *obj, const BindingContext &); - bool buildSignal(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj, - const BindingContext &); - bool buildProperty(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj, - const BindingContext &); + bool buildObject(QDeclarativeScript::Object *obj, const QDeclarativeCompilerTypes::BindingContext &); + bool buildComponent(QDeclarativeScript::Object *obj, const QDeclarativeCompilerTypes::BindingContext &); + bool buildSubObject(QDeclarativeScript::Object *obj, const QDeclarativeCompilerTypes::BindingContext &); + bool buildSignal(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &); + bool buildProperty(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &); bool buildPropertyInNamespace(QDeclarativeImportedNamespace *ns, - QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - const BindingContext &); - bool buildIdProperty(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj); - bool buildAttachedProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - const BindingContext &ctxt); - bool buildGroupedProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - const BindingContext &ctxt); + QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &); + bool buildIdProperty(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj); + bool buildAttachedProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildGroupedProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &ctxt); bool buildValueTypeProperty(QObject *type, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Object *baseObj, - const BindingContext &ctxt); - bool buildListProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - const BindingContext &ctxt); - bool buildScriptStringProperty(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - const BindingContext &ctxt); - bool buildPropertyAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - const BindingContext &ctxt); - bool buildPropertyObjectAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Value *value, - const BindingContext &ctxt); - bool buildPropertyOnAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Object *baseObj, - QDeclarativeParser::Value *value, - const BindingContext &ctxt); - bool buildPropertyLiteralAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Value *value, - const BindingContext &ctxt); - bool doesPropertyExist(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj); - bool testLiteralAssignment(const QMetaProperty &prop, - QDeclarativeParser::Value *value); + QDeclarativeScript::Object *obj, + QDeclarativeScript::Object *baseObj, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildListProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildScriptStringProperty(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildPropertyAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildPropertyObjectAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Value *value, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildPropertyOnAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Object *baseObj, + QDeclarativeScript::Value *value, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildPropertyLiteralAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Value *value, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool doesPropertyExist(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj); + bool testLiteralAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Value *value); bool testQualifiedEnumAssignment(const QMetaProperty &prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Value *value, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Value *value, bool *isAssignment); enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation }; - bool mergeDynamicMetaProperties(QDeclarativeParser::Object *obj); - bool buildDynamicMeta(QDeclarativeParser::Object *obj, DynamicMetaMode mode); - bool checkDynamicMeta(QDeclarativeParser::Object *obj); - bool buildBinding(QDeclarativeParser::Value *, QDeclarativeParser::Property *prop, - const BindingContext &ctxt); - bool buildComponentFromRoot(QDeclarativeParser::Object *obj, const BindingContext &); - bool compileAlias(QMetaObjectBuilder &, + bool mergeDynamicMetaProperties(QDeclarativeScript::Object *obj); + bool buildDynamicMeta(QDeclarativeScript::Object *obj, DynamicMetaMode mode); + bool checkDynamicMeta(QDeclarativeScript::Object *obj); + bool buildBinding(QDeclarativeScript::Value *, QDeclarativeScript::Property *prop, + const QDeclarativeCompilerTypes::BindingContext &ctxt); + bool buildComponentFromRoot(QDeclarativeScript::Object *obj, const QDeclarativeCompilerTypes::BindingContext &); + bool compileAlias(QFastMetaBuilder &, QByteArray &data, - QDeclarativeParser::Object *obj, - const QDeclarativeParser::Object::DynamicProperty &); + QDeclarativeScript::Object *obj, + int propIndex, int aliasIndex, + QDeclarativeScript::Object::DynamicProperty &); bool completeComponentBuild(); - bool checkValidId(QDeclarativeParser::Value *, const QString &); - - - void genObject(QDeclarativeParser::Object *obj); - void genObjectBody(QDeclarativeParser::Object *obj); - void genValueTypeProperty(QDeclarativeParser::Object *obj,QDeclarativeParser::Property *); - void genComponent(QDeclarativeParser::Object *obj); - void genValueProperty(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj); - void genListProperty(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj); - void genPropertyAssignment(QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Property *valueTypeProperty = 0); - void genLiteralAssignment(const QMetaProperty &prop, - QDeclarativeParser::Value *value); - void genBindingAssignment(QDeclarativeParser::Value *binding, - QDeclarativeParser::Property *prop, - QDeclarativeParser::Object *obj, - QDeclarativeParser::Property *valueTypeProperty = 0); + bool checkValidId(QDeclarativeScript::Value *, const QString &); + + + void genObject(QDeclarativeScript::Object *obj); + void genObjectBody(QDeclarativeScript::Object *obj); + void genValueTypeProperty(QDeclarativeScript::Object *obj,QDeclarativeScript::Property *); + void genComponent(QDeclarativeScript::Object *obj); + void genValueProperty(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj); + void genListProperty(QDeclarativeScript::Property *prop, QDeclarativeScript::Object *obj); + void genPropertyAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Property *valueTypeProperty = 0); + void genLiteralAssignment(QDeclarativeScript::Property *prop, + QDeclarativeScript::Value *value); + void genBindingAssignment(QDeclarativeScript::Value *binding, + QDeclarativeScript::Property *prop, + QDeclarativeScript::Object *obj, + QDeclarativeScript::Property *valueTypeProperty = 0); int genContextCache(); - int genValueTypeData(QDeclarativeParser::Property *prop, QDeclarativeParser::Property *valueTypeProp); - int genPropertyData(QDeclarativeParser::Property *prop); + int genValueTypeData(QDeclarativeScript::Property *prop, QDeclarativeScript::Property *valueTypeProp); + int genPropertyData(QDeclarativeScript::Property *prop); int componentTypeRef(); - static QDeclarativeType *toQmlType(QDeclarativeParser::Object *from); - bool canCoerce(int to, QDeclarativeParser::Object *from); + static QDeclarativeType *toQmlType(QDeclarativeScript::Object *from); + bool canCoerce(int to, QDeclarativeScript::Object *from); - QStringList deferredProperties(QDeclarativeParser::Object *); - int indexOfProperty(QDeclarativeParser::Object *, const QByteArray &, bool *notInRevision = 0); - int indexOfSignal(QDeclarativeParser::Object *, const QByteArray &, bool *notInRevision = 0); + QString elementName(QDeclarativeScript::Object *); - void addId(const QString &, QDeclarativeParser::Object *); + QStringList deferredProperties(QDeclarativeScript::Object *); - void dumpStats(); + QDeclarativePropertyCache::Data *property(QDeclarativeScript::Object *, int); + QDeclarativePropertyCache::Data *property(QDeclarativeScript::Object *, const QHashedStringRef &, + bool *notInRevision = 0); + QDeclarativePropertyCache::Data *signal(QDeclarativeScript::Object *, const QHashedStringRef &, + bool *notInRevision = 0); + int indexOfProperty(QDeclarativeScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); + int indexOfProperty(QDeclarativeScript::Object *, const QString &, bool *notInRevision = 0); + int indexOfSignal(QDeclarativeScript::Object *, const QString &, bool *notInRevision = 0); - struct BindingReference { - QDeclarativeParser::Variant expression; - QDeclarativeParser::Property *property; - QDeclarativeParser::Value *value; + void addId(const QString &, QDeclarativeScript::Object *); - enum DataType { QtScript, V4, V8 }; - DataType dataType; + void dumpStats(); - int compiledIndex; + void addBindingReference(QDeclarativeCompilerTypes::BindingReference *); - QString rewrittenExpression; - BindingContext bindingContext; - }; - void addBindingReference(const BindingReference &); + QDeclarativeCompilerTypes::ComponentCompileState *compileState; - struct ComponentCompileState - { - ComponentCompileState() - : parserStatusCount(0), pushedProperties(0), nested(false), v8BindingProgramLine(-1), root(0) {} - QHash<QString, QDeclarativeParser::Object *> ids; - QHash<int, QDeclarativeParser::Object *> idIndexes; - int parserStatusCount; - int pushedProperties; - bool nested; + QDeclarativePool *pool; - QByteArray compiledBindingData; - QString v8BindingProgram; - int v8BindingProgramLine; - int v8BindingProgramIndex; + QDeclarativeCompilerTypes::ComponentCompileState *componentState(QDeclarativeScript::Object *); + void saveComponentState(); + + QList<QDeclarativeError> exceptions; + QDeclarativeCompiledData *output; + QDeclarativeEngine *engine; + QDeclarativeEnginePrivate *enginePrivate; + QDeclarativeScript::Object *unitRoot; + QDeclarativeTypeData *unit; - QHash<QDeclarativeParser::Value *, BindingReference> bindings; - QHash<QDeclarativeParser::Value *, BindingContext> signalExpressions; - QList<QDeclarativeParser::Object *> aliasingObjects; - QDeclarativeParser::Object *root; - }; - ComponentCompileState compileState; + // Compiler component statistics. Only collected if QML_COMPILER_STATS=1 struct ComponentStat { ComponentStat() : ids(0), objects(0) {} @@ -323,25 +377,18 @@ private: int lineNumber; int ids; - QList<QDeclarativeParser::LocationSpan> scriptBindings; - QList<QDeclarativeParser::LocationSpan> optimizedBindings; + QList<QDeclarativeScript::LocationSpan> scriptBindings; + QList<QDeclarativeScript::LocationSpan> optimizedBindings; int objects; }; - ComponentStat componentStat; - - void saveComponentState(); - - ComponentCompileState componentState(QDeclarativeParser::Object *); - QHash<QDeclarativeParser::Object *, ComponentCompileState> savedCompileStates; - QList<ComponentStat> savedComponentStats; - - QList<QDeclarativeError> exceptions; - QDeclarativeCompiledData *output; - QDeclarativeEngine *engine; - QDeclarativeEnginePrivate *enginePrivate; - QDeclarativeParser::Object *unitRoot; - QDeclarativeTypeData *unit; + struct ComponentStats : public QDeclarativePool::Class + { + ComponentStat componentStat; + QList<ComponentStat> savedComponentStats; + }; + ComponentStats *componentStats; }; + QT_END_NAMESPACE #endif // QDECLARATIVECOMPILER_P_H diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index ca7f3e0f74..eea94cef3e 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -51,7 +51,7 @@ #include "private/qdeclarativebinding_p.h" #include "private/qdeclarativebinding_p_p.h" #include "private/qdeclarativeglobal_p.h" -#include "private/qdeclarativescriptparser_p.h" +#include "private/qdeclarativescript_p.h" #include "private/qdeclarativedebugtrace_p.h" #include "private/qdeclarativeenginedebug_p.h" diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index 5f4072130a..9a068bbf8d 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -60,7 +60,7 @@ #include "private/qdeclarativetypenamecache_p.h" #include "private/qdeclarativenotifier_p.h" #include "qdeclarativelist.h" -#include "private/qdeclarativeparser_p.h" +#include "private/qdeclarativescript_p.h" #include <QtCore/qhash.h> #include <QtDeclarative/qjsvalue.h> diff --git a/src/declarative/qml/qdeclarativecustomparser.cpp b/src/declarative/qml/qdeclarativecustomparser.cpp index e80d911bb5..e806707a06 100644 --- a/src/declarative/qml/qdeclarativecustomparser.cpp +++ b/src/declarative/qml/qdeclarativecustomparser.cpp @@ -42,14 +42,13 @@ #include "private/qdeclarativecustomparser_p.h" #include "private/qdeclarativecustomparser_p_p.h" -#include "private/qdeclarativeparser_p.h" #include "private/qdeclarativecompiler_p.h" #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE -using namespace QDeclarativeParser; +using namespace QDeclarativeScript; /*! \class QDeclarativeCustomParser @@ -95,18 +94,13 @@ using namespace QDeclarativeParser; */ QDeclarativeCustomParserNode -QDeclarativeCustomParserNodePrivate::fromObject(QDeclarativeParser::Object *root) +QDeclarativeCustomParserNodePrivate::fromObject(QDeclarativeScript::Object *root) { QDeclarativeCustomParserNode rootNode; rootNode.d->name = root->typeName; rootNode.d->location = root->location.start; - for(QHash<QByteArray, Property *>::Iterator iter = root->properties.begin(); - iter != root->properties.end(); - ++iter) { - - Property *p = *iter; - + for (Property *p = root->properties.first(); p; p = root->properties.next(p)) { rootNode.d->properties << fromProperty(p); } @@ -117,11 +111,11 @@ QDeclarativeCustomParserNodePrivate::fromObject(QDeclarativeParser::Object *root } QDeclarativeCustomParserProperty -QDeclarativeCustomParserNodePrivate::fromProperty(QDeclarativeParser::Property *p) +QDeclarativeCustomParserNodePrivate::fromProperty(QDeclarativeScript::Property *p) { QDeclarativeCustomParserProperty prop; - prop.d->name = p->name; - prop.d->isList = (p->values.count() > 1); + prop.d->name = p->name().toUtf8(); + prop.d->isList = p->values.isMany(); prop.d->location = p->location.start; if (p->value) { @@ -130,9 +124,8 @@ QDeclarativeCustomParserNodePrivate::fromProperty(QDeclarativeParser::Property * for (int ii = 0; ii < props.count(); ++ii) prop.d->values << QVariant::fromValue(props.at(ii)); } else { - for(int ii = 0; ii < p->values.count(); ++ii) { - QDeclarativeParser::Value *v = p->values.at(ii); - v->type = QDeclarativeParser::Value::Literal; + for (QDeclarativeScript::Value *v = p->values.first(); v; v = p->values.next(v)) { + v->type = QDeclarativeScript::Value::Literal; if(v->object) { QDeclarativeCustomParserNode node = fromObject(v->object); @@ -181,7 +174,7 @@ QList<QDeclarativeCustomParserProperty> QDeclarativeCustomParserNode::properties return d->properties; } -QDeclarativeParser::Location QDeclarativeCustomParserNode::location() const +QDeclarativeScript::Location QDeclarativeCustomParserNode::location() const { return d->location; } @@ -221,7 +214,7 @@ bool QDeclarativeCustomParserProperty::isList() const return d->isList; } -QDeclarativeParser::Location QDeclarativeCustomParserProperty::location() const +QDeclarativeScript::Location QDeclarativeCustomParserProperty::location() const { return d->location; } diff --git a/src/declarative/qml/qdeclarativecustomparser_p.h b/src/declarative/qml/qdeclarativecustomparser_p.h index 31452836bd..47b3ee8f8e 100644 --- a/src/declarative/qml/qdeclarativecustomparser_p.h +++ b/src/declarative/qml/qdeclarativecustomparser_p.h @@ -55,7 +55,7 @@ #include "private/qdeclarativemetatype_p.h" #include "qdeclarativeerror.h" -#include "private/qdeclarativeparser_p.h" +#include "private/qdeclarativescript_p.h" #include "private/qdeclarativebinding_p.h" #include <QtCore/qbytearray.h> @@ -79,10 +79,10 @@ public: ~QDeclarativeCustomParserProperty(); QByteArray name() const; - QDeclarativeParser::Location location() const; + QDeclarativeScript::Location location() const; bool isList() const; - // Will be one of QDeclarativeParser::Variant, QDeclarativeCustomParserProperty or + // Will be one of QDeclarativeScript::Variant, QDeclarativeCustomParserProperty or // QDeclarativeCustomParserNode QList<QVariant> assignedValues() const; @@ -102,7 +102,7 @@ public: ~QDeclarativeCustomParserNode(); QByteArray name() const; - QDeclarativeParser::Location location() const; + QDeclarativeScript::Location location() const; QList<QDeclarativeCustomParserProperty> properties() const; @@ -147,7 +147,7 @@ protected: private: QList<QDeclarativeError> exceptions; QDeclarativeCompiler *compiler; - QDeclarativeParser::Object *object; + QDeclarativeScript::Object *object; Flags m_flags; friend class QDeclarativeCompiler; }; diff --git a/src/declarative/qml/qdeclarativecustomparser_p_p.h b/src/declarative/qml/qdeclarativecustomparser_p_p.h index 386dd96bb4..b11cb3432d 100644 --- a/src/declarative/qml/qdeclarativecustomparser_p_p.h +++ b/src/declarative/qml/qdeclarativecustomparser_p_p.h @@ -55,7 +55,7 @@ #include "private/qdeclarativecustomparser_p.h" -#include "private/qdeclarativeparser_p.h" +#include "private/qdeclarativescript_p.h" #include <QtCore/qglobal.h> @@ -66,10 +66,10 @@ class QDeclarativeCustomParserNodePrivate public: QByteArray name; QList<QDeclarativeCustomParserProperty> properties; - QDeclarativeParser::Location location; + QDeclarativeScript::Location location; - static QDeclarativeCustomParserNode fromObject(QDeclarativeParser::Object *); - static QDeclarativeCustomParserProperty fromProperty(QDeclarativeParser::Property *); + static QDeclarativeCustomParserNode fromObject(QDeclarativeScript::Object *); + static QDeclarativeCustomParserProperty fromProperty(QDeclarativeScript::Property *); }; class QDeclarativeCustomParserPropertyPrivate @@ -80,7 +80,7 @@ public: QByteArray name; bool isList; - QDeclarativeParser::Location location; + QDeclarativeScript::Location location; QList<QVariant> values; }; diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp index ba7aca038d..49cb40f654 100644 --- a/src/declarative/qml/qdeclarativedirparser.cpp +++ b/src/declarative/qml/qdeclarativedirparser.cpp @@ -41,8 +41,11 @@ #include "private/qdeclarativedirparser_p.h" #include "qdeclarativeerror.h" +#include <private/qdeclarativeglobal_p.h> +#include <private/qdeclarativeutils_p.h> #include <QtCore/QTextStream> +#include <QtCore/QFile> #include <QtCore/QtDebug> QT_BEGIN_NAMESPACE @@ -66,6 +69,16 @@ void QDeclarativeDirParser::setUrl(const QUrl &url) _url = url; } +QString QDeclarativeDirParser::fileSource() const +{ + return _filePathSouce; +} + +void QDeclarativeDirParser::setFileSource(const QString &filePath) +{ + _filePathSouce = filePath; +} + QString QDeclarativeDirParser::source() const { return _source; @@ -92,6 +105,23 @@ bool QDeclarativeDirParser::parse() _plugins.clear(); _components.clear(); + if (_source.isEmpty() && !_filePathSouce.isEmpty()) { + QFile file(_filePathSouce); + if (!QDeclarative_isFileCaseCorrect(_filePathSouce)) { + QDeclarativeError error; + error.setDescription(QString::fromUtf8("cannot load module \"$$URI$$\": File name case mismatch for \"%1\"").arg(_filePathSouce)); + _errors.prepend(error); + return false; + } else if (file.open(QFile::ReadOnly)) { + _source = QString::fromUtf8(file.readAll()); + } else { + QDeclarativeError error; + error.setDescription(QString::fromUtf8("module \"$$URI$$\" definition \"%1\" not readable").arg(_filePathSouce)); + _errors.prepend(error); + return false; + } + } + QTextStream stream(&_source); int lineNumber = 0; @@ -111,9 +141,9 @@ bool QDeclarativeDirParser::parse() while (index != length) { const QChar ch = line.at(index); - if (ch.isSpace()) { + if (QDeclarativeUtils::isSpace(ch)) { do { ++index; } - while (index != length && line.at(index).isSpace()); + while (index != length && QDeclarativeUtils::isSpace(line.at(index))); } else if (ch == QLatin1Char('#')) { // recognized a comment @@ -123,7 +153,7 @@ bool QDeclarativeDirParser::parse() const int start = index; do { ++index; } - while (index != length && !line.at(index).isSpace()); + while (index != length && !QDeclarativeUtils::isSpace(line.at(index))); const QString lexeme = line.mid(start, index - start); @@ -157,7 +187,7 @@ bool QDeclarativeDirParser::parse() QString::fromUtf8("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1)); continue; } - Component entry(sections[1], sections[2], -1, -1); + Component entry(sections[1].toUtf8(), sections[2], -1, -1); entry.internal = true; _components.append(entry); } else if (sections[0] == QLatin1String("typeinfo")) { @@ -173,7 +203,7 @@ bool QDeclarativeDirParser::parse() } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) - const Component entry(sections[0], sections[1], -1, -1); + const Component entry(sections[0].toUtf8(), sections[1], -1, -1); _components.append(entry); } else if (sectionCount == 3) { const QString &version = sections[1]; @@ -191,7 +221,7 @@ bool QDeclarativeDirParser::parse() const int minorVersion = version.mid(dotIndex + 1).toInt(&validVersionNumber); if (validVersionNumber) { - const Component entry(sections[0], sections[2], majorVersion, minorVersion); + const Component entry(sections[0].toUtf8(), sections[2], majorVersion, minorVersion); _components.append(entry); } @@ -224,9 +254,16 @@ bool QDeclarativeDirParser::hasError() const return false; } -QList<QDeclarativeError> QDeclarativeDirParser::errors() const +QList<QDeclarativeError> QDeclarativeDirParser::errors(const QString &uri) const { - return _errors; + QList<QDeclarativeError> errors = _errors; + for (int i = 0; i < errors.size(); ++i) { + QDeclarativeError &e = errors[i]; + QString description = e.description(); + description.replace(QLatin1String("$$URI$$"), uri); + e.setDescription(description); + } + return errors; } QList<QDeclarativeDirParser::Plugin> QDeclarativeDirParser::plugins() const diff --git a/src/declarative/qml/qdeclarativedirparser_p.h b/src/declarative/qml/qdeclarativedirparser_p.h index d40833ac45..8540747055 100644 --- a/src/declarative/qml/qdeclarativedirparser_p.h +++ b/src/declarative/qml/qdeclarativedirparser_p.h @@ -70,6 +70,9 @@ public: QUrl url() const; void setUrl(const QUrl &url); + QString fileSource() const; + void setFileSource(const QString &filePath); + QString source() const; void setSource(const QString &source); @@ -77,7 +80,7 @@ public: bool parse(); bool hasError() const; - QList<QDeclarativeError> errors() const; + QList<QDeclarativeError> errors(const QString &uri) const; struct Plugin { @@ -95,11 +98,11 @@ public: Component() : majorVersion(0), minorVersion(0), internal(false) {} - Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion) + Component(const QByteArray &typeName, const QString &fileName, int majorVersion, int minorVersion) : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion), internal(false) {} - QString typeName; + QByteArray typeName; QString fileName; int majorVersion; int minorVersion; @@ -129,6 +132,7 @@ private: QList<QDeclarativeError> _errors; QUrl _url; QString _source; + QString _filePathSouce; QList<Component> _components; QList<Plugin> _plugins; #ifdef QT_CREATOR diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 1906612e8a..051739be59 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1126,6 +1126,34 @@ QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url) return url.toLocalFile(); } + +static QString toLocalFile(const QString &url) +{ + if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive)) + return QString(); + + QString file = url.mid(7); + + //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt" + + // magic for drives on windows + if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':')) + file.remove(0, 1); + + return file; +} + +QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QString& url) +{ + if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) { + if (url.length() > 4) + return QLatin1Char(':') + url.mid(4); + return QString(); + } + + return toLocalFile(url); +} + void QDeclarativeEnginePrivate::sendQuit() { Q_Q(QDeclarativeEngine); @@ -1424,7 +1452,9 @@ QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObj return rv; } else { QDeclarativePropertyCache *super = cache(mo->superClass()); - QDeclarativePropertyCache *rv = super->copy(); + QDeclarativePropertyCache *rv = super->copy(mo->propertyCount() + mo->methodCount() - + mo->superClass()->propertyCount() - + mo->superClass()->methodCount()); rv->append(q, mo); propertyCache.insert(mo, rv); return rv; diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 6ff12189da..be4f714545 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -262,6 +262,7 @@ public: static QDeclarativeEngine *get(QDeclarativeEnginePrivate *p) { return p->q_func(); } static QString urlToLocalFileOrQrc(const QUrl& url); + static QString urlToLocalFileOrQrc(const QString& url); static void registerBaseTypes(const char *uri, int versionMajor, int versionMinor); static void defineModule(); diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index 8806996bd4..a24d46914c 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -242,7 +242,7 @@ QDeclarativeExpression::QDeclarativeExpression(const QDeclarativeScriptString &s } else { QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(script.context()); - QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(script.scopeObject())); + QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(script.context()->engine()); QDeclarativeCompiledData *cdata = 0; QDeclarativeTypeData *typeData = 0; if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { @@ -251,7 +251,7 @@ QDeclarativeExpression::QDeclarativeExpression(const QDeclarativeScriptString &s } if (cdata) - d->init(ctxtdata, cdata->primitives.at(id), cdata, script.scopeObject(), + d->init(ctxtdata, cdata->primitives.at(id), true, script.scopeObject(), cdata->name, script.d.data()->lineNumber); else defaultConstruction = true; diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index b2fa071f91..0c0719a710 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -65,30 +65,53 @@ static bool greaterThan(const QString &s1, const QString &s2) return s1 > s2; } +QString resolveLocalUrl(const QString &url, const QString &relative) +{ + if (relative.contains(QLatin1Char(':'))) { + // contains a host name + return QUrl(url).resolved(QUrl(relative)).toString(); + } else if (relative.isEmpty()) { + return url; + } else if (relative.at(0) == QLatin1Char('/') || !url.contains(QLatin1Char('/'))) { + return relative; + } else { + if (relative == QLatin1String(".")) + return url.left(url.lastIndexOf(QLatin1Char('/')) + 1); + else if (relative.startsWith(QLatin1String("./"))) + return url.left(url.lastIndexOf(QLatin1Char('/')) + 1) + relative.mid(2); + return url.left(url.lastIndexOf(QLatin1Char('/')) + 1) + relative; + } +} + + + typedef QMap<QString, QString> StringStringMap; Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri class QDeclarativeImportedNamespace { public: - QStringList uris; - QStringList urls; - QList<int> majversions; - QList<int> minversions; - QList<bool> isLibrary; - QList<QDeclarativeDirComponents> qmlDirComponents; - - - bool find_helper(int i, const QByteArray& type, int *vmajor, int *vminor, - QDeclarativeType** type_return, QUrl* url_return, - QUrl *base = 0, bool *typeRecursionDetected = 0); - bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, - QUrl* url_return, QUrl *base = 0, QList<QDeclarativeError> *errors = 0); + struct Data { + QString uri; + QString url; + int majversion; + int minversion; + bool isLibrary; + QDeclarativeDirComponents qmlDirComponents; + }; + QList<Data> imports; + + + bool find_helper(QDeclarativeTypeLoader *typeLoader, const Data &data, const QString& type, int *vmajor, int *vminor, + QDeclarativeType** type_return, QString* url_return, + QString *base = 0, bool *typeRecursionDetected = 0); + bool find(QDeclarativeTypeLoader *typeLoader, const QString& type, int *vmajor, int *vminor, QDeclarativeType** type_return, + QString* url_return, QString *base = 0, QList<QDeclarativeError> *errors = 0); }; class QDeclarativeImportsPrivate { public: - QDeclarativeImportsPrivate(); + QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader); ~QDeclarativeImportsPrivate(); bool importExtension(const QString &absoluteFilePath, const QString &uri, @@ -98,19 +121,21 @@ public: QString resolvedUri(const QString &dir_arg, QDeclarativeImportDatabase *database); bool add(const QDeclarativeDirComponents &qmldircomponentsnetwork, const QString& uri_arg, const QString& prefix, - int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, + int vmaj, int vmin, QDeclarativeScript::Import::Type importType, QDeclarativeImportDatabase *database, QList<QDeclarativeError> *errors); - bool find(const QByteArray& type, int *vmajor, int *vminor, - QDeclarativeType** type_return, QUrl* url_return, QList<QDeclarativeError> *errors); + bool find(const QString& type, int *vmajor, int *vminor, + QDeclarativeType** type_return, QString* url_return, QList<QDeclarativeError> *errors); QDeclarativeImportedNamespace *findNamespace(const QString& type); - QUrl base; + QUrl baseUrl; + QString base; int ref; QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded; QDeclarativeImportedNamespace unqualifiedset; QHash<QString,QDeclarativeImportedNamespace* > set; + QDeclarativeTypeLoader *typeLoader; }; /*! @@ -134,8 +159,8 @@ QDeclarativeImports::operator =(const QDeclarativeImports ©) return *this; } -QDeclarativeImports::QDeclarativeImports() -: d(new QDeclarativeImportsPrivate) +QDeclarativeImports::QDeclarativeImports(QDeclarativeTypeLoader *typeLoader) + : d(new QDeclarativeImportsPrivate(typeLoader)) { } @@ -150,7 +175,8 @@ QDeclarativeImports::~QDeclarativeImports() */ void QDeclarativeImports::setBaseUrl(const QUrl& url) { - d->base = url; + d->baseUrl = url; + d->base = url.toString(); } /*! @@ -158,25 +184,33 @@ void QDeclarativeImports::setBaseUrl(const QUrl& url) */ QUrl QDeclarativeImports::baseUrl() const { - return d->base; + return d->baseUrl; } -static QDeclarativeTypeNameCache * -cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespace &set, - QDeclarativeTypeNameCache *cache, bool importWasQualified) +void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const { - if (!cache) - cache = new QDeclarativeTypeNameCache(engine); - - QList<QDeclarativeType *> types = QDeclarativeMetaType::qmlTypes(); + const QDeclarativeImportedNamespace &set = d->unqualifiedset; - for (int ii = 0; ii < set.uris.count(); ++ii) { - QByteArray uri = set.uris.at(ii).toUtf8(); - int major = set.majversions.at(ii); - int minor = set.minversions.at(ii); + for (int ii = set.imports.count() - 1; ii >= 0; --ii) { + const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii); + QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(data.uri, data.majversion); + if (module) + cache->m_anonymousImports.append(QDeclarativeTypeModuleVersion(module, data.minversion)); + } - if (importWasQualified) { - QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(uri, major, minor); + for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.begin(); + iter != d->set.end(); + ++iter) { + + const QDeclarativeImportedNamespace &set = *iter.value(); + QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()]; + for (int ii = set.imports.count() - 1; ii >= 0; --ii) { + const QDeclarativeImportedNamespace::Data &data = set.imports.at(ii); + QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(data.uri, data.majversion); + if (module) + import.modules.append(QDeclarativeTypeModuleVersion(module, data.minversion)); + + QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(data.uri.toUtf8(), data.majversion, data.minversion); if (moduleApi.script || moduleApi.qobject) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QDeclarativeMetaType::ModuleApiInstance *a = ep->moduleApiInstances.value(moduleApi); @@ -186,46 +220,12 @@ cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespac a->qobjectCallback = moduleApi.qobject; ep->moduleApiInstances.insert(moduleApi, a); } - cache->setModuleApi(a); - } - } - - QByteArray base = uri + '/'; - - foreach (QDeclarativeType *type, types) { - if (type->qmlTypeName().startsWith(base) && - type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) && - (major < 0 || type->availableInVersion(major,minor))) - { - QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length())); - - cache->add(name, type); + import.moduleApi = a; } } } - return cache; -} - -void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const -{ - const QDeclarativeImportedNamespace &set = d->unqualifiedset; - - for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.begin(); - iter != d->set.end(); ++iter) { - QDeclarativeTypeNameCache::Data *d = cache->data(iter.key()); - if (d) { - if (!d->typeNamespace) - cacheForNamespace(engine, *(*iter), d->typeNamespace, true); - } else { - QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0, true); - cache->add(iter.key(), nc); - nc->release(); - } - } - - cacheForNamespace(engine, set, cache, false); } /*! @@ -242,11 +242,11 @@ void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDecla \sa addImport() */ -bool QDeclarativeImports::resolveType(const QByteArray& type, - QDeclarativeType** type_return, QUrl* url_return, int *vmaj, int *vmin, +bool QDeclarativeImports::resolveType(const QString& type, + QDeclarativeType** type_return, QString* url_return, int *vmaj, int *vmin, QDeclarativeImportedNamespace** ns_return, QList<QDeclarativeError> *errors) const { - QDeclarativeImportedNamespace* ns = d->findNamespace(QString::fromUtf8(type)); + QDeclarativeImportedNamespace* ns = d->findNamespace(type); if (ns) { if (ns_return) *ns_return = ns; @@ -281,25 +281,22 @@ bool QDeclarativeImports::resolveType(const QByteArray& type, If either return pointer is 0, the corresponding search is not done. */ -bool QDeclarativeImports::resolveType(QDeclarativeImportedNamespace* ns, const QByteArray& type, - QDeclarativeType** type_return, QUrl* url_return, +bool QDeclarativeImports::resolveType(QDeclarativeImportedNamespace* ns, const QString& type, + QDeclarativeType** type_return, QString* url_return, int *vmaj, int *vmin) const { - return ns->find(type,vmaj,vmin,type_return,url_return); + return ns->find(d->typeLoader,type,vmaj,vmin,type_return,url_return); } -bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, int *vmajor, int *vminor, - QDeclarativeType** type_return, QUrl* url_return, - QUrl *base, bool *typeRecursionDetected) +bool QDeclarativeImportedNamespace::find_helper(QDeclarativeTypeLoader *typeLoader, const Data &data, const QString& type, int *vmajor, int *vminor, + QDeclarativeType** type_return, QString* url_return, + QString *base, bool *typeRecursionDetected) { - int vmaj = majversions.at(i); - int vmin = minversions.at(i); + int vmaj = data.majversion; + int vmin = data.minversion; if (vmaj >= 0 && vmin >= 0) { - QByteArray qt = uris.at(i).toUtf8(); - qt += '/'; - qt += type; - + QString qt = data.uri + QLatin1Char('/') + type; QDeclarativeType *t = QDeclarativeMetaType::qmlType(qt,vmaj,vmin); if (t) { if (vmajor) *vmajor = vmaj; @@ -310,21 +307,18 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i } } - QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml")); - QDeclarativeDirComponents qmldircomponents = qmlDirComponents.at(i); - + const QDeclarativeDirComponents &qmldircomponents = data.qmlDirComponents; bool typeWasDeclaredInQmldir = false; if (!qmldircomponents.isEmpty()) { - const QString typeName = QString::fromUtf8(type); foreach (const QDeclarativeDirParser::Component &c, qmldircomponents) { - if (c.typeName == typeName) { + if (c.typeName == type) { typeWasDeclaredInQmldir = true; - // importing version -1 means import ALL versions if ((vmaj == -1) || (c.majorVersion == vmaj && vmin >= c.minorVersion)) { - QUrl candidate = url.resolved(QUrl(c.fileName)); + QString url(data.url + type + QLatin1String(".qml")); + QString candidate = resolveLocalUrl(url, c.fileName); if (c.internal && base) { - if (base->resolved(QUrl(c.fileName)) != candidate) + if (resolveLocalUrl(*base, c.fileName) != candidate) continue; // failed attempt to access an internal type } if (base && *base == candidate) { @@ -340,10 +334,11 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i } } - if (!typeWasDeclaredInQmldir && !isLibrary.at(i)) { + if (!typeWasDeclaredInQmldir && !data.isLibrary) { // XXX search non-files too! (eg. zip files, see QT-524) - QFileInfo f(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)); - if (f.exists()) { + QString url(data.url + type + QLatin1String(".qml")); + QString file = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); + if (!typeLoader->absoluteFilePath(file).isEmpty()) { if (base && *base == url) { // no recursion if (typeRecursionDetected) *typeRecursionDetected = true; @@ -357,8 +352,8 @@ bool QDeclarativeImportedNamespace::find_helper(int i, const QByteArray& type, i return false; } -QDeclarativeImportsPrivate::QDeclarativeImportsPrivate() -: ref(1) +QDeclarativeImportsPrivate::QDeclarativeImportsPrivate(QDeclarativeTypeLoader *loader) + : ref(1), typeLoader(loader) { } @@ -372,52 +367,30 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath QDeclarativeImportDatabase *database, QDeclarativeDirComponents* components, QList<QDeclarativeError> *errors) { - QFile file(absoluteFilePath); - QString filecontent; - if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { + const QDeclarativeDirParser *qmldirParser = typeLoader->qmlDirParser(absoluteFilePath); + if (qmldirParser->hasError()) { if (errors) { - QDeclarativeError error; - error.setDescription(QDeclarativeImportDatabase::tr("cannot load module \"%1\": File name case mismatch for \"%2\"").arg(uri).arg(absoluteFilePath)); - errors->prepend(error); - } - return false; - } else if (file.open(QFile::ReadOnly)) { - filecontent = QString::fromUtf8(file.readAll()); - if (qmlImportTrace()) - qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base.toString()) << "::importExtension: " - << "loaded " << absoluteFilePath; - } else { - if (errors) { - QDeclarativeError error; - error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath)); - errors->prepend(error); + const QList<QDeclarativeError> qmldirErrors = qmldirParser->errors(uri); + for (int i = 0; i < qmldirErrors.size(); ++i) + errors->prepend(qmldirErrors.at(i)); } return false; } - QDir dir = QFileInfo(file).dir(); - QUrl url = QUrl::fromLocalFile(absoluteFilePath); - - QDeclarativeDirParser qmldirParser; - qmldirParser.setSource(filecontent); - qmldirParser.setUrl(url); - // propagate any errors reported by the parser back up to the typeloader. - if (qmldirParser.parse()) { - if (errors) { - for (int i = 0; i < qmldirParser.errors().size(); ++i) { - errors->prepend(qmldirParser.errors().at(i)); - } - } - return false; - } + if (qmlImportTrace()) + qDebug().nospace() << "QDeclarativeImports(" << qPrintable(base) << "::importExtension: " + << "loaded " << absoluteFilePath; if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) { qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath); + QString qmldirPath = absoluteFilePath; + int slash = absoluteFilePath.lastIndexOf(QLatin1Char('/')); + if (slash > 0) + qmldirPath.truncate(slash); + foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser->plugins()) { - foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { - - QString resolvedFilePath = database->resolvePlugin(dir, plugin.path, plugin.name); + QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name); #if defined(QT_LIBINFIX) && defined(Q_OS_SYMBIAN) if (resolvedFilePath.isEmpty()) { // In case of libinfixed build, attempt to load libinfixed version, too. @@ -434,7 +407,7 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath QDeclarativeError poppedError = errors->takeFirst(); QDeclarativeError error; error.setDescription(QDeclarativeImportDatabase::tr("plugin cannot be loaded for module \"%1\": %2").arg(uri).arg(poppedError.description())); - error.setUrl(url); + error.setUrl(QUrl::fromLocalFile(absoluteFilePath)); errors->prepend(error); } return false; @@ -443,7 +416,7 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath if (errors) { QDeclarativeError error; error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name)); - error.setUrl(url); + error.setUrl(QUrl::fromLocalFile(absoluteFilePath)); errors->prepend(error); } return false; @@ -452,7 +425,7 @@ bool QDeclarativeImportsPrivate::importExtension(const QString &absoluteFilePath } if (components) - *components = qmldirParser.components(); + *components = qmldirParser->components(); return true; } @@ -490,9 +463,12 @@ QString QDeclarativeImportsPrivate::resolvedUri(const QString &dir_arg, QDeclara bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomponentsnetwork, const QString& uri_arg, const QString& prefix, int vmaj, int vmin, - QDeclarativeScriptParser::Import::Type importType, + QDeclarativeScript::Import::Type importType, QDeclarativeImportDatabase *database, QList<QDeclarativeError> *errors) { + static QLatin1String Slash_qmldir("/qmldir"); + static QLatin1Char Slash('/'); + QDeclarativeDirComponents qmldircomponents = qmldircomponentsnetwork; QString uri = uri_arg; QDeclarativeImportedNamespace *s; @@ -505,18 +481,18 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } QString url = uri; bool versionFound = false; - if (importType == QDeclarativeScriptParser::Import::Library) { + if (importType == QDeclarativeScript::Import::Library) { Q_ASSERT(vmaj >= 0 && vmin >= 0); // Versions are always specified for libraries - url.replace(QLatin1Char('.'), QLatin1Char('/')); + url.replace(QLatin1Char('.'), Slash); bool found = false; QString dir; - + QString qmldir; // step 1: search for extension with fully encoded version number foreach (const QString &p, database->fileImportPath) { - dir = p+QLatin1Char('/')+url; + dir = p+Slash+url; QFileInfo fi(dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir")); const QString absoluteFilePath = fi.absoluteFilePath(); @@ -534,7 +510,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp // step 2: search for extension with encoded version major foreach (const QString &p, database->fileImportPath) { - dir = p+QLatin1Char('/')+url; + dir = p+Slash+url; QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir")); const QString absoluteFilePath = fi.absoluteFilePath(); @@ -554,15 +530,14 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp // step 3: search for extension without version number foreach (const QString &p, database->fileImportPath) { - dir = p+QLatin1Char('/')+url; + dir = p+Slash+url; + qmldir = dir+Slash_qmldir; - QFileInfo fi(dir+QLatin1String("/qmldir")); - const QString absoluteFilePath = fi.absoluteFilePath(); - - if (fi.isFile()) { + QString absoluteFilePath = typeLoader->absoluteFilePath(qmldir); + if (!absoluteFilePath.isEmpty()) { found = true; - - url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1); + url = QLatin1String("file://") + absolutePath; uri = resolvedUri(dir, database); if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errors)) return false; @@ -571,15 +546,13 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } } - if (QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin)) { + if (QDeclarativeMetaType::isModule(uri, vmaj, vmin)) versionFound = true; - } if (!versionFound && qmldircomponents.isEmpty()) { if (errors) { - bool anyversion = QDeclarativeMetaType::isAnyModule(uri.toUtf8()); QDeclarativeError error; // we don't set the url or line or column as these will be set by the loader. - if (anyversion) + if (QDeclarativeMetaType::isAnyModule(uri)) error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin)); else error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg)); @@ -588,42 +561,39 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp return false; } } else { - - if (importType == QDeclarativeScriptParser::Import::File && qmldircomponents.isEmpty()) { - QUrl importUrl = base.resolved(QUrl(uri + QLatin1String("/qmldir"))); + if (importType == QDeclarativeScript::Import::File && qmldircomponents.isEmpty()) { + QString importUrl = resolveLocalUrl(base, uri + Slash_qmldir); QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl); if (!localFileOrQrc.isEmpty()) { - QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))); - QFileInfo dirinfo(dir); - if (dir.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) { + QString dir = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(resolveLocalUrl(base, uri)); + if (!typeLoader->directoryExists(dir)) { if (errors) { QDeclarativeError error; // we don't set the line or column as these will be set by the loader. error.setDescription(QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri_arg)); - error.setUrl(importUrl); + error.setUrl(QUrl(importUrl)); errors->prepend(error); } return false; // local import dirs must exist } - uri = resolvedUri(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))), database); - if (uri.endsWith(QLatin1Char('/'))) + uri = resolvedUri(dir, database); + if (uri.endsWith(Slash)) uri.chop(1); - if (QFile::exists(localFileOrQrc)) { + if (!typeLoader->absoluteFilePath(localFileOrQrc).isEmpty()) { if (!importExtension(localFileOrQrc,uri,database,&qmldircomponents,errors)) return false; } } else { if (prefix.isEmpty()) { // directory must at least exist for valid import - QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(base.resolved(QUrl(uri))); - QFileInfo dirinfo(localFileOrQrc); - if (localFileOrQrc.isEmpty() || !dirinfo.exists() || !dirinfo.isDir()) { + QString localFileOrQrc = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(resolveLocalUrl(base, uri)); + if (!typeLoader->directoryExists(localFileOrQrc)) { if (errors) { QDeclarativeError error; // we don't set the line or column as these will be set by the loader. if (localFileOrQrc.isEmpty()) error.setDescription(QDeclarativeImportDatabase::tr("import \"%1\" has no qmldir and no namespace").arg(uri)); else error.setDescription(QDeclarativeImportDatabase::tr("\"%1\": no such directory").arg(uri)); - error.setUrl(importUrl); + error.setUrl(QUrl(importUrl)); errors->prepend(error); } return false; @@ -632,9 +602,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } } - url = base.resolved(QUrl(url)).toString(); - if (url.endsWith(QLatin1Char('/'))) - url.chop(1); + url = resolveLocalUrl(base, url); } if (!versionFound && vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { @@ -657,22 +625,28 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } } - s->uris.prepend(uri); - s->urls.prepend(url); - s->majversions.prepend(vmaj); - s->minversions.prepend(vmin); - s->isLibrary.prepend(importType == QDeclarativeScriptParser::Import::Library); - s->qmlDirComponents.prepend(qmldircomponents); + if (!url.endsWith(Slash)) + url += Slash; + + QDeclarativeImportedNamespace::Data data; + data.uri = uri; + data.url = url; + data.majversion = vmaj; + data.minversion = vmin; + data.isLibrary = importType == QDeclarativeScript::Import::Library; + data.qmlDirComponents = qmldircomponents; + s->imports.prepend(data); + return true; } -bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, - QUrl* url_return, QList<QDeclarativeError> *errors) +bool QDeclarativeImportsPrivate::find(const QString& type, int *vmajor, int *vminor, QDeclarativeType** type_return, + QString* url_return, QList<QDeclarativeError> *errors) { QDeclarativeImportedNamespace *s = 0; - int slash = type.indexOf('/'); + int slash = type.indexOf(QLatin1Char('/')); if (slash >= 0) { - QString namespaceName = QString::fromUtf8(type.left(slash)); + QString namespaceName = type.left(slash); s = set.value(namespaceName); if (!s) { if (errors) { @@ -682,7 +656,7 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int * } return false; } - int nslash = type.indexOf('/',slash+1); + int nslash = type.indexOf(QLatin1Char('/'),slash+1); if (nslash > 0) { if (errors) { QDeclarativeError error; @@ -694,13 +668,13 @@ bool QDeclarativeImportsPrivate::find(const QByteArray& type, int *vmajor, int * } else { s = &unqualifiedset; } - QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower) + QString unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower) if (s) { - if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors)) + if (s->find(typeLoader,unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors)) return true; - if (s->urls.count() == 1 && !s->isLibrary[0] && url_return && s != &unqualifiedset) { + if (s->imports.count() == 1 && !s->imports.at(0).isLibrary && url_return && s != &unqualifiedset) { // qualified, and only 1 url - *url_return = QUrl(s->urls[0]+QLatin1Char('/')).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml"))); + *url_return = resolveLocalUrl(s->imports.at(0).url, unqualifiedtype + QLatin1String(".qml")); return true; } } @@ -713,21 +687,21 @@ QDeclarativeImportedNamespace *QDeclarativeImportsPrivate::findNamespace(const Q return set.value(type); } -bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, - QUrl* url_return, QUrl *base, QList<QDeclarativeError> *errors) +bool QDeclarativeImportedNamespace::find(QDeclarativeTypeLoader *typeLoader, const QString& type, int *vmajor, int *vminor, QDeclarativeType** type_return, + QString* url_return, QString *base, QList<QDeclarativeError> *errors) { bool typeRecursionDetected = false; - for (int i=0; i<urls.count(); ++i) { - if (find_helper(i, type, vmajor, vminor, type_return, url_return, base, &typeRecursionDetected)) { + for (int i=0; i<imports.count(); ++i) { + if (find_helper(typeLoader, imports.at(i), type, vmajor, vminor, type_return, url_return, base, &typeRecursionDetected)) { if (qmlCheckTypes()) { // check for type clashes - for (int j = i+1; j<urls.count(); ++j) { - if (find_helper(j, type, vmajor, vminor, 0, 0, base)) { + for (int j = i+1; j<imports.count(); ++j) { + if (find_helper(typeLoader, imports.at(j), type, vmajor, vminor, 0, 0, base)) { if (errors) { - QString u1 = urls.at(i); - QString u2 = urls.at(j); + QString u1 = imports.at(i).url; + QString u2 = imports.at(j).url; if (base) { - QString b = base->toString(); + QString b = *base; int slash = b.lastIndexOf(QLatin1Char('/')); if (slash >= 0) { b = b.left(slash+1); @@ -749,8 +723,8 @@ bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, in } else { error.setDescription(QDeclarativeImportDatabase::tr("is ambiguous. Found in %1 in version %2.%3 and %4.%5") .arg(u1) - .arg(majversions.at(i)).arg(minversions.at(i)) - .arg(majversions.at(j)).arg(minversions.at(j))); + .arg(imports.at(i).majversion).arg(imports.at(i).minversion) + .arg(imports.at(j).majversion).arg(imports.at(j).minversion)); } errors->prepend(error); } @@ -850,14 +824,14 @@ QDeclarativeImportDatabase::~QDeclarativeImportDatabase() */ bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb, const QString& uri, const QString& prefix, int vmaj, int vmin, - QDeclarativeScriptParser::Import::Type importType, + QDeclarativeScript::Import::Type importType, const QDeclarativeDirComponents &qmldircomponentsnetwork, QList<QDeclarativeError> *errors) { if (qmlImportTrace()) qDebug().nospace() << "QDeclarativeImports(" << qPrintable(baseUrl().toString()) << ")" << "::addImport: " << uri << " " << vmaj << '.' << vmin << " " - << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") + << (importType==QDeclarativeScript::Import::Library? "Library" : "File") << " as " << prefix; return d->add(qmldircomponentsnetwork, uri, prefix, vmaj, vmin, importType, importDb, errors); @@ -871,7 +845,8 @@ bool QDeclarativeImports::addImport(QDeclarativeImportDatabase *importDb, \a qmldirPath is the location of the qmldir file. */ -QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, +QString QDeclarativeImportDatabase::resolvePlugin(QDeclarativeTypeLoader *typeLoader, + const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName, const QStringList &suffixes, const QString &prefix) { @@ -883,37 +858,40 @@ QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const foreach (const QString &pluginPath, searchPaths) { QString resolvedPath; - if (pluginPath == QLatin1String(".")) { - if (qmldirPluginPathIsRelative) - resolvedPath = qmldirPath.absoluteFilePath(qmldirPluginPath); + if (qmldirPluginPathIsRelative && !qmldirPluginPath.isEmpty() && qmldirPluginPath != QLatin1String(".")) + resolvedPath = QDir::cleanPath(qmldirPath + QLatin1Char('/') + qmldirPluginPath); else - resolvedPath = qmldirPath.absolutePath(); + resolvedPath = qmldirPath; } else { - resolvedPath = pluginPath; + if (QDir::isRelativePath(pluginPath)) + resolvedPath = QDir::cleanPath(qmldirPath + QLatin1Char('/') + pluginPath); + else + resolvedPath = pluginPath; } // hack for resources, should probably go away if (resolvedPath.startsWith(QLatin1Char(':'))) resolvedPath = QCoreApplication::applicationDirPath(); - QDir dir(resolvedPath); + if (!resolvedPath.endsWith(QLatin1Char('/'))) + resolvedPath += QLatin1Char('/'); + foreach (const QString &suffix, suffixes) { QString pluginFileName = prefix; pluginFileName += baseName; pluginFileName += suffix; - QFileInfo fileInfo(dir, pluginFileName); - - if (fileInfo.exists()) - return fileInfo.absoluteFilePath(); + QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + pluginFileName); + if (!absolutePath.isEmpty()) + return absolutePath; } } if (qmlImportTrace()) qDebug() << "QDeclarativeImportDatabase::resolvePlugin: Could not resolve plugin" << baseName - << "in" << qmldirPath.absolutePath(); + << "in" << qmldirPath; return QString(); } @@ -935,18 +913,19 @@ QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const Version number on unix are ignored. */ -QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, +QString QDeclarativeImportDatabase::resolvePlugin(QDeclarativeTypeLoader *typeLoader, + const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName) { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, + return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() # ifdef QT_DEBUG << QLatin1String("d.dll") // try a qmake-style debug build first # endif << QLatin1String(".dll")); #elif defined(Q_OS_SYMBIAN) - return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, + return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() << QLatin1String(".dll") << QLatin1String(".qtplugin")); @@ -954,7 +933,7 @@ QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const # if defined(Q_OS_DARWIN) - return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, + return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() # ifdef QT_DEBUG << QLatin1String("_debug.dylib") // try a qmake-style debug build first @@ -988,7 +967,7 @@ QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const // Examples of valid library names: // libfoo.so - return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib")); + return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib")); # endif #endif @@ -1097,7 +1076,7 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt if (!QDeclarative_isFileCaseCorrect(absoluteFilePath)) { if (errors) { QDeclarativeError error; - error.setDescription(tr("File name case mismatch for \"%2\"").arg(absoluteFilePath)); + error.setDescription(tr("File name case mismatch for \"%1\"").arg(absoluteFilePath)); errors->prepend(error); } return false; @@ -1146,5 +1125,4 @@ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QSt #endif } - QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeimport_p.h b/src/declarative/qml/qdeclarativeimport_p.h index fe9404d9b2..c695a6b423 100644 --- a/src/declarative/qml/qdeclarativeimport_p.h +++ b/src/declarative/qml/qdeclarativeimport_p.h @@ -45,8 +45,9 @@ #include <QtCore/qurl.h> #include <QtCore/qcoreapplication.h> #include <QtCore/qset.h> +#include <QtCore/qstringlist.h> #include <private/qdeclarativedirparser_p.h> -#include <private/qdeclarativescriptparser_p.h> +#include <private/qdeclarativescript_p.h> #include <private/qdeclarativemetatype_p.h> // @@ -68,11 +69,12 @@ class QDir; class QDeclarativeImportedNamespace; class QDeclarativeImportsPrivate; class QDeclarativeImportDatabase; +class QDeclarativeTypeLoader; class QDeclarativeImports { public: - QDeclarativeImports(); + QDeclarativeImports(QDeclarativeTypeLoader *); QDeclarativeImports(const QDeclarativeImports &); ~QDeclarativeImports(); QDeclarativeImports &operator=(const QDeclarativeImports &); @@ -80,19 +82,19 @@ public: void setBaseUrl(const QUrl &url); QUrl baseUrl() const; - bool resolveType(const QByteArray& type, - QDeclarativeType** type_return, QUrl* url_return, + bool resolveType(const QString& type, + QDeclarativeType** type_return, QString* url_return, int *version_major, int *version_minor, QDeclarativeImportedNamespace** ns_return, QList<QDeclarativeError> *errors = 0) const; bool resolveType(QDeclarativeImportedNamespace*, - const QByteArray& type, - QDeclarativeType** type_return, QUrl* url_return, + const QString& type, + QDeclarativeType** type_return, QString* url_return, int *version_major, int *version_minor) const; bool addImport(QDeclarativeImportDatabase *, const QString& uri, const QString& prefix, int vmaj, int vmin, - QDeclarativeScriptParser::Import::Type importType, + QDeclarativeScript::Import::Type importType, const QDeclarativeDirComponents &qmldircomponentsnetwork, QList<QDeclarativeError> *errors); @@ -122,10 +124,12 @@ public: private: friend class QDeclarativeImportsPrivate; - QString resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, + QString resolvePlugin(QDeclarativeTypeLoader *typeLoader, + const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName, const QStringList &suffixes, const QString &prefix = QString()); - QString resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, + QString resolvePlugin(QDeclarativeTypeLoader *typeLoader, + const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName); diff --git a/src/declarative/qml/qdeclarativeintegercache.cpp b/src/declarative/qml/qdeclarativeintegercache.cpp index ef99c63086..16bf8d1dab 100644 --- a/src/declarative/qml/qdeclarativeintegercache.cpp +++ b/src/declarative/qml/qdeclarativeintegercache.cpp @@ -61,6 +61,11 @@ QString QDeclarativeIntegerCache::findId(int value) const return QString(); } +void QDeclarativeIntegerCache::reserve(int size) +{ + stringCache.reserve(size); +} + void QDeclarativeIntegerCache::add(const QString &id, int value) { Q_ASSERT(!stringCache.contains(id)); diff --git a/src/declarative/qml/qdeclarativeintegercache_p.h b/src/declarative/qml/qdeclarativeintegercache_p.h index a66457cede..1ac03ada66 100644 --- a/src/declarative/qml/qdeclarativeintegercache_p.h +++ b/src/declarative/qml/qdeclarativeintegercache_p.h @@ -68,6 +68,7 @@ public: inline int count() const; void add(const QString &, int); + void reserve(int); int value(const QString &); inline int value(const QHashedV8String &); diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index a989ae847b..091a561993 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -42,15 +42,18 @@ #include <QtDeclarative/qdeclarativeprivate.h> #include "private/qdeclarativemetatype_p.h" -#include "private/qdeclarativeproxymetaobject_p.h" -#include "private/qdeclarativecustomparser_p.h" -#include "private/qdeclarativeguard_p.h" +#include <private/qdeclarativeproxymetaobject_p.h> +#include <private/qdeclarativecustomparser_p.h> +#include <private/qdeclarativeguard_p.h> +#include <private/qhashedstring_p.h> #include <QtCore/qdebug.h> #include <QtCore/qstringlist.h> #include <QtCore/qmetaobject.h> #include <QtCore/qbitarray.h> #include <QtCore/qreadwritelock.h> +#include <QtCore/private/qmetaobject_p.h> + #include <qmetatype.h> #include <qobjectdefs.h> #include <qdatetime.h> @@ -93,41 +96,68 @@ struct QDeclarativeMetaTypeData QList<QDeclarativeType *> types; typedef QHash<int, QDeclarativeType *> Ids; Ids idToType; - typedef QHash<QByteArray, QDeclarativeType *> Names; + typedef QHash<QString, QDeclarativeType *> Names; Names nameToType; typedef QHash<const QMetaObject *, QDeclarativeType *> MetaObjects; MetaObjects metaObjectToType; typedef QHash<int, QDeclarativeMetaType::StringConverter> StringConverters; StringConverters stringConverters; + + struct VersionedUri { + VersionedUri() + : majorVersion(0) {} + VersionedUri(const QString &uri, int majorVersion) + : uri(uri), majorVersion(majorVersion) {} + bool operator==(const VersionedUri &other) const { + return other.majorVersion == majorVersion && other.uri == uri; + } + QString uri; + int majorVersion; + }; + typedef QHash<VersionedUri, QDeclarativeTypeModule *> TypeModules; + TypeModules uriToModule; + struct ModuleApiList { ModuleApiList() : sorted(true) {} QList<QDeclarativeMetaType::ModuleApi> moduleApis; bool sorted; }; - typedef QHash<QByteArray, ModuleApiList> ModuleApis; + typedef QHash<QString, ModuleApiList> ModuleApis; ModuleApis moduleApis; int moduleApiCount; - struct ModuleInfo { - ModuleInfo(int major, int minor) - : vmajor(major), vminor_min(minor), vminor_max(minor) {} - ModuleInfo(int major, int minor_min, int minor_max) - : vmajor(major), vminor_min(minor_min), vminor_max(minor_max) {} - int vmajor; - int vminor_min, vminor_max; - }; - typedef QHash<QPair<QByteArray,int>, ModuleInfo> ModuleInfoHash; - ModuleInfoHash modules; - QBitArray objects; QBitArray interfaces; QBitArray lists; QList<QDeclarativePrivate::AutoParentFunction> parentFunctions; }; + +class QDeclarativeTypeModulePrivate +{ +public: + QDeclarativeTypeModulePrivate() + : minMinorVersion(INT_MAX), maxMinorVersion(0) {} + + QDeclarativeMetaTypeData::VersionedUri uri; + + int minMinorVersion; + int maxMinorVersion; + + void add(QDeclarativeType *); + + QStringHash<QList<QDeclarativeType *> > typeHash; + QList<QDeclarativeType *> types; +}; + Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData) Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock) +static uint qHash(const QDeclarativeMetaTypeData::VersionedUri &v) +{ + return qHash(v.uri) ^ qHash(v.majorVersion); +} + QDeclarativeMetaTypeData::QDeclarativeMetaTypeData() : moduleApiCount(0) { @@ -145,11 +175,13 @@ public: QDeclarativeTypePrivate(); void init() const; + void initEnums() const; bool m_isInterface : 1; const char *m_iid; - QByteArray m_module; + QString m_module; QByteArray m_name; + QString m_elementName; int m_version_maj; int m_version_min; int m_typeId; int m_listId; @@ -173,8 +205,10 @@ public: int m_index; QDeclarativeCustomParser *m_customParser; mutable volatile bool m_isSetup:1; - mutable bool m_haveSuperType : 1; + mutable volatile bool m_isEnumSetup:1; + mutable bool m_haveSuperType:1; mutable QList<QDeclarativeProxyMetaObject::ProxyData> m_metaObjects; + mutable QStringHash<int> m_enums; static QHash<const QMetaObject *, int> m_attachedPropertyIds; }; @@ -186,7 +220,7 @@ QDeclarativeTypePrivate::QDeclarativeTypePrivate() m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), - m_isSetup(false), m_haveSuperType(false) + m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false) { } @@ -212,7 +246,7 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe if (type.uri) name += '/'; name += type.elementName; - d->m_module = type.uri; + d->m_module = QString::fromUtf8(type.uri); d->m_name = name; d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; @@ -251,7 +285,7 @@ QDeclarativeType::~QDeclarativeType() delete d; } -QByteArray QDeclarativeType::module() const +QString QDeclarativeType::module() const { return d->m_module; } @@ -268,11 +302,13 @@ int QDeclarativeType::minorVersion() const bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const { + Q_ASSERT(vmajor >= 0 && vminor >= 0); return vmajor == d->m_version_maj && vminor >= d->m_version_min; } -bool QDeclarativeType::availableInVersion(const QByteArray &module, int vmajor, int vminor) const +bool QDeclarativeType::availableInVersion(const QString &module, int vmajor, int vminor) const { + Q_ASSERT(vmajor >= 0 && vminor >= 0); return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min; } @@ -364,6 +400,24 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, } } +static bool isPropertyRevisioned(const QMetaObject *mo, int index) +{ + int i = index; + i -= mo->propertyOffset(); + if (i < 0 && mo->d.superdata) + return isPropertyRevisioned(mo->d.superdata, index); + + const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data); + if (i >= 0 && i < mop->propertyCount) { + int handle = mop->propertyData + 3*i; + int flags = mo->d.data[handle + 2]; + + return (flags & Revisioned); + } + + return false; +} + void QDeclarativeTypePrivate::init() const { if (m_isSetup) return; @@ -417,7 +471,7 @@ void QDeclarativeTypePrivate::init() const mo = m_metaObjects.first().metaObject; for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) { - if (mo->property(ii).revision() != 0) + if (isPropertyRevisioned(mo, ii)) m_containsRevisionedAttributes = true; } @@ -431,6 +485,27 @@ void QDeclarativeTypePrivate::init() const lock.unlock(); } +void QDeclarativeTypePrivate::initEnums() const +{ + if (m_isEnumSetup) return; + + init(); + + QWriteLocker lock(metaTypeDataLock()); + if (m_isEnumSetup) return; + + const QMetaObject *metaObject = m_baseMetaObject; + for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) { + + QMetaEnum e = metaObject->enumerator(ii); + + for (int jj = 0; jj < e.keyCount(); ++jj) + m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); + } + + m_isEnumSetup = true; +} + QByteArray QDeclarativeType::typeName() const { if (d->m_baseMetaObject) @@ -439,7 +514,17 @@ QByteArray QDeclarativeType::typeName() const return QByteArray(); } -QByteArray QDeclarativeType::qmlTypeName() const +const QString &QDeclarativeType::elementName() const +{ + if (d->m_elementName.isEmpty()) { + QByteArray n = qmlTypeName(); + int idx = n.lastIndexOf('/'); + d->m_elementName = QString::fromUtf8(n.mid(idx + 1)); + } + return d->m_elementName; +} + +const QByteArray &QDeclarativeType::qmlTypeName() const { return d->m_name; } @@ -591,6 +676,164 @@ int QDeclarativeType::index() const return d->m_index; } +int QDeclarativeType::enumValue(const QHashedStringRef &name) const +{ + d->initEnums(); + + int *rv = d->m_enums.value(name); + return rv?*rv:-1; +} + +int QDeclarativeType::enumValue(const QHashedV8String &name) const +{ + d->initEnums(); + + int *rv = d->m_enums.value(name); + return rv?*rv:-1; +} + +QDeclarativeTypeModule::QDeclarativeTypeModule() +: d(new QDeclarativeTypeModulePrivate) +{ +} + +QDeclarativeTypeModule::~QDeclarativeTypeModule() +{ + delete d; d = 0; +} + +QString QDeclarativeTypeModule::module() const +{ + return d->uri.uri; +} + +int QDeclarativeTypeModule::majorVersion() const +{ + return d->uri.majorVersion; +} + +int QDeclarativeTypeModule::minimumMinorVersion() const +{ + return d->minMinorVersion; +} + +int QDeclarativeTypeModule::maximumMinorVersion() const +{ + return d->maxMinorVersion; +} + +void QDeclarativeTypeModulePrivate::add(QDeclarativeType *type) +{ + types << type; + + minMinorVersion = qMin(minMinorVersion, type->minorVersion()); + maxMinorVersion = qMax(maxMinorVersion, type->minorVersion()); + + QList<QDeclarativeType *> &list = typeHash[type->elementName()]; + for (int ii = 0; ii < list.count(); ++ii) { + if (list.at(ii)->minorVersion() < type->minorVersion()) { + list.insert(ii, type); + return; + } + } + list.append(type); +} + +QList<QDeclarativeType *> QDeclarativeTypeModule::types() +{ + QList<QDeclarativeType *> rv; + QReadLocker lock(metaTypeDataLock()); + rv = d->types; + return rv; +} + +QList<QDeclarativeType *> QDeclarativeTypeModule::type(const QString &name) +{ + QReadLocker lock(metaTypeDataLock()); + QList<QDeclarativeType *> rv; + for (int ii = 0; ii < d->types.count(); ++ii) { + if (d->types.at(ii)->elementName() == name) + rv << d->types.at(ii); + } + return rv; +} + +QDeclarativeType *QDeclarativeTypeModule::type(const QHashedStringRef &name, int minor) +{ + QReadLocker lock(metaTypeDataLock()); + + QList<QDeclarativeType *> *types = d->typeHash.value(name); + if (!types) return 0; + + for (int ii = 0; ii < types->count(); ++ii) + if (types->at(ii)->minorVersion() <= minor) + return types->at(ii); + + return 0; +} + +QDeclarativeType *QDeclarativeTypeModule::type(const QHashedV8String &name, int minor) +{ + QReadLocker lock(metaTypeDataLock()); + + QList<QDeclarativeType *> *types = d->typeHash.value(name); + if (!types) return 0; + + for (int ii = 0; ii < types->count(); ++ii) + if (types->at(ii)->minorVersion() <= minor) + return types->at(ii); + + return 0; +} + + +QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion() +: m_module(0), m_minor(0) +{ +} + +QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *module, int minor) +: m_module(module), m_minor(minor) +{ + Q_ASSERT(m_module); + Q_ASSERT(m_minor >= 0); +} + +QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &o) +: m_module(o.m_module), m_minor(o.m_minor) +{ +} + +QDeclarativeTypeModuleVersion &QDeclarativeTypeModuleVersion::operator=(const QDeclarativeTypeModuleVersion &o) +{ + m_module = o.m_module; + m_minor = o.m_minor; + return *this; +} + +QDeclarativeTypeModule *QDeclarativeTypeModuleVersion::module() const +{ + return m_module; +} + +int QDeclarativeTypeModuleVersion::minorVersion() const +{ + return m_minor; +} + +QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedStringRef &name) const +{ + if (m_module) return m_module->type(name, m_minor); + else return 0; +} + +QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedV8String &name) const +{ + if (m_module) return m_module->type(name, m_minor); + else return 0; +} + + int registerAutoParentFunction(QDeclarativePrivate::RegisterAutoParent &autoparent) { QWriteLocker lock(metaTypeDataLock()); @@ -618,7 +861,7 @@ int registerInterface(const QDeclarativePrivate::RegisterInterface &interface) data->idToType.insert(type->qListTypeId(), type); // XXX No insertMulti, so no multi-version interfaces? if (!type->qmlTypeName().isEmpty()) - data->nameToType.insert(type->qmlTypeName(), type); + data->nameToType.insert(QString::fromUtf8(type->qmlTypeName()), type); if (data->interfaces.size() <= interface.typeId) data->interfaces.resize(interface.typeId + 16); @@ -652,7 +895,7 @@ int registerType(const QDeclarativePrivate::RegisterType &type) if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype); if (!dtype->qmlTypeName().isEmpty()) - data->nameToType.insertMulti(dtype->qmlTypeName(), dtype); + data->nameToType.insertMulti(QString::fromUtf8(dtype->qmlTypeName()), dtype); data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype); @@ -664,21 +907,16 @@ int registerType(const QDeclarativePrivate::RegisterType &type) if (type.listId) data->lists.setBit(type.listId, true); if (type.uri) { - QByteArray mod(type.uri); - QPair<QByteArray,int> key(mod,type.versionMajor); - QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(key); - if (it == data->modules.end()) { - // New module - data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo(type.versionMajor,type.versionMinor)); - } else { - if ((*it).vminor_max < type.versionMinor) { - // Newer module - data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, (*it).vminor_min, type.versionMinor)); - } else if ((*it).vminor_min > type.versionMinor) { - // Older module - data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, type.versionMinor, (*it).vminor_min)); - } + QString mod = QString::fromUtf8(type.uri); + + QDeclarativeMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor); + QDeclarativeTypeModule *module = data->uriToModule.value(versionedUri); + if (!module) { + module = new QDeclarativeTypeModule; + module->d->uri = versionedUri; + data->uriToModule.insert(versionedUri, module); } + module->d->add(dtype); } return index; @@ -689,7 +927,7 @@ int registerModuleApi(const QDeclarativePrivate::RegisterModuleApi &api) QWriteLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); - QByteArray uri(api.uri); + QString uri = QString::fromUtf8(api.uri); QDeclarativeMetaType::ModuleApi import; import.major = api.versionMajor; import.minor = api.versionMinor; @@ -730,15 +968,18 @@ int QDeclarativePrivate::qmlregister(RegistrationType type, void *data) return -1; } -bool QDeclarativeMetaType::isAnyModule(const QByteArray &module) +/* + Returns true if a module \a uri of any version is installed. +*/ +bool QDeclarativeMetaType::isAnyModule(const QString &uri) { + QReadLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); - QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.begin(); - while (it != data->modules.end()) { - if (it.key().first == module) + for (QDeclarativeMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin(); + iter != data->uriToModule.end(); ++iter) { + if ((*iter)->module() == uri) return true; - ++it; } return false; @@ -751,27 +992,35 @@ bool QDeclarativeMetaType::isAnyModule(const QByteArray &module) So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10. */ -bool QDeclarativeMetaType::isModule(const QByteArray &module, int versionMajor, int versionMinor) +bool QDeclarativeMetaType::isModule(const QString &module, int versionMajor, int versionMinor) { + Q_ASSERT(versionMajor >= 0 && versionMinor >= 0); + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); // first, check Types - QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(QPair<QByteArray,int>(module,versionMajor)); - if (it != data->modules.end()) { - if (((*it).vminor_max >= versionMinor && (*it).vminor_min <= versionMinor)) - return true; - } + QDeclarativeTypeModule *tm = + data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(module, versionMajor)); + if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor) + return true; // then, check ModuleApis foreach (const QDeclarativeMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) { - if (mApi.major == versionMajor && mApi.minor == versionMinor) { + if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct? return true; - } } return false; } +QDeclarativeTypeModule *QDeclarativeMetaType::typeModule(const QString &uri, int majorVersion) +{ + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); + return data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(uri, majorVersion)); +} + QList<QDeclarativePrivate::AutoParentFunction> QDeclarativeMetaType::parentFunctions() { QReadLocker lock(metaTypeDataLock()); @@ -785,7 +1034,7 @@ static bool operator<(const QDeclarativeMetaType::ModuleApi &lhs, const QDeclara } QDeclarativeMetaType::ModuleApi -QDeclarativeMetaType::moduleApi(const QByteArray &uri, int versionMajor, int versionMinor) +QDeclarativeMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor) { QReadLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); @@ -1001,17 +1250,20 @@ QDeclarativeMetaType::StringConverter QDeclarativeMetaType::customStringConverte Returns the type (if any) of URI-qualified named \a name in version specified by \a version_major and \a version_minor. */ -QDeclarativeType *QDeclarativeMetaType::qmlType(const QByteArray &name, int version_major, int version_minor) +QDeclarativeType *QDeclarativeMetaType::qmlType(const QString &name, int version_major, int version_minor) { + Q_ASSERT(version_major >= 0 && version_minor >= 0); QReadLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); - QList<QDeclarativeType*> types = data->nameToType.values(name); - foreach (QDeclarativeType *t, types) { + QDeclarativeMetaTypeData::Names::ConstIterator it = data->nameToType.find(name); + while (it != data->nameToType.end()) { // XXX version_major<0 just a kludge for QDeclarativePropertyPrivate::initProperty - if (version_major<0 || t->availableInVersion(version_major,version_minor)) - return t; + if (it.key() == name && (version_major<0 || (*it)->availableInVersion(version_major,version_minor))) + return (*it); + ++it; } + return 0; } @@ -1032,8 +1284,9 @@ QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject) by \a version_major and \a version_minor in module specified by \a uri. Returns null if no type is registered. */ -QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor) +QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor) { + Q_ASSERT(version_major >= 0 && version_minor >= 0); QReadLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); @@ -1067,7 +1320,7 @@ QDeclarativeType *QDeclarativeMetaType::qmlType(int userType) /*! Returns the list of registered QML type names. */ -QList<QByteArray> QDeclarativeMetaType::qmlTypeNames() +QList<QString> QDeclarativeMetaType::qmlTypeNames() { QReadLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 429aa7a98f..2a6ce20bbb 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -66,6 +66,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeType; class QDeclarativeCustomParser; class QDeclarativeTypePrivate; +class QDeclarativeTypeModule; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeMetaType { @@ -73,12 +74,12 @@ public: static bool canCopy(int type); static bool copy(int type, void *data, const void *copy = 0); - static QList<QByteArray> qmlTypeNames(); + static QList<QString> qmlTypeNames(); static QList<QDeclarativeType*> qmlTypes(); - static QDeclarativeType *qmlType(const QByteArray &, int, int); + static QDeclarativeType *qmlType(const QString &, int, int); static QDeclarativeType *qmlType(const QMetaObject *); - static QDeclarativeType *qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor); + static QDeclarativeType *qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor); static QDeclarativeType *qmlType(int); static QMetaProperty defaultProperty(const QMetaObject *); @@ -104,8 +105,9 @@ public: static void registerCustomStringConverter(int, StringConverter); static StringConverter customStringConverter(int); - static bool isAnyModule(const QByteArray &module); - static bool isModule(const QByteArray &module, int versionMajor, int versionMinor); + static bool isAnyModule(const QString &uri); + static bool isModule(const QString &module, int versionMajor, int versionMinor); + static QDeclarativeTypeModule *typeModule(const QString &uri, int majorVersion); static QList<QDeclarativePrivate::AutoParentFunction> parentFunctions(); @@ -126,21 +128,24 @@ public: QJSValue (*script)(QDeclarativeEngine *, QJSEngine *); QObject *(*qobject)(QDeclarativeEngine *, QJSEngine *); }; - static ModuleApi moduleApi(const QByteArray &, int, int); + static ModuleApi moduleApi(const QString &, int, int); }; +class QHashedStringRef; +class QHashedV8String; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeType { public: QByteArray typeName() const; - QByteArray qmlTypeName() const; + const QByteArray &qmlTypeName() const; + const QString &elementName() const; - QByteArray module() const; + QString module() const; int majorVersion() const; int minorVersion() const; bool availableInVersion(int vmajor, int vminor) const; - bool availableInVersion(const QByteArray &module, int vmajor, int vminor) const; + bool availableInVersion(const QString &module, int vmajor, int vminor) const; QObject *create() const; void create(QObject **, void **, size_t) const; @@ -176,6 +181,8 @@ public: int index() const; + int enumValue(const QHashedStringRef &) const; + int enumValue(const QHashedV8String &) const; private: QDeclarativeType *superType() const; friend class QDeclarativeTypePrivate; @@ -189,8 +196,49 @@ private: QDeclarativeTypePrivate *d; }; +class QDeclarativeTypeModulePrivate; +class QDeclarativeTypeModule +{ +public: + QString module() const; + int majorVersion() const; + + int minimumMinorVersion() const; + int maximumMinorVersion() const; + + QList<QDeclarativeType *> types(); + QList<QDeclarativeType *> type(const QString &); + + QDeclarativeType *type(const QHashedStringRef &, int); + QDeclarativeType *type(const QHashedV8String &, int); + +private: + friend int registerType(const QDeclarativePrivate::RegisterType &); + QDeclarativeTypeModule(); + ~QDeclarativeTypeModule(); + QDeclarativeTypeModulePrivate *d; +}; + +class QDeclarativeTypeModuleVersion +{ +public: + QDeclarativeTypeModuleVersion(); + QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *, int); + QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &); + QDeclarativeTypeModuleVersion &operator=(const QDeclarativeTypeModuleVersion &); + + QDeclarativeTypeModule *module() const; + int minorVersion() const; + + QDeclarativeType *type(const QHashedStringRef &) const; + QDeclarativeType *type(const QHashedV8String &) const; + +private: + QDeclarativeTypeModule *m_module; + int m_minor; +}; + QDeclarativeMetaType::ModuleApi::ModuleApi() -// : major(0), minor(0), script(0), qobject(0) { major = 0; minor = 0; diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp deleted file mode 100644 index a405022a71..0000000000 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qdeclarativeparser_p.h" - -#include "qdeclarativepropertyvaluesource.h" -#include "private/qdeclarativevme_p.h" -#include "qdeclarative.h" -#include "private/qdeclarativecomponent_p.h" -#include "qdeclarativecomponent.h" -#include "private/qmetaobjectbuilder_p.h" -#include "private/qdeclarativevmemetaobject_p.h" -#include "private/qdeclarativecompiler_p.h" -#include "parser/qdeclarativejsast_p.h" -#include "parser/qdeclarativejsengine_p.h" - -#include <QStack> -#include <QColor> -#include <QPointF> -#include <QSizeF> -#include <QRectF> -#include <QStringBuilder> -#include <QtDebug> - -QT_BEGIN_NAMESPACE - -using namespace QDeclarativeJS; -using namespace QDeclarativeParser; - -QDeclarativeParser::Object::Object() -: type(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1) -{ -} - -QDeclarativeParser::Object::~Object() -{ - if (defaultProperty) defaultProperty->release(); - if (synthCache) synthCache->release(); - foreach(Property *prop, properties) - prop->release(); - foreach(Property *prop, valueProperties) - prop->release(); - foreach(Property *prop, signalProperties) - prop->release(); - foreach(Property *prop, attachedProperties) - prop->release(); - foreach(Property *prop, groupedProperties) - prop->release(); - foreach(Property *prop, valueTypeProperties) - prop->release(); - typedef QPair<Property *, int> PropPair; - foreach(const PropPair &prop, scriptStringProperties) - prop.first->release(); - foreach(const DynamicProperty &prop, dynamicProperties) - if (prop.defaultValue) prop.defaultValue->release(); -} - -void Object::setBindingBit(int b) -{ - while (bindingBitmask.size() < 4 * (1 + b / 32)) - bindingBitmask.append(char(0)); - - quint32 *bits = (quint32 *)bindingBitmask.data(); - bits[b / 32] |= (1 << (b % 32)); -} - -const QMetaObject *Object::metaObject() const -{ - if (!metadata.isEmpty() && metatype) - return &extObject; - else - return metatype; -} - -QDeclarativeParser::Property *Object::getDefaultProperty() -{ - if (!defaultProperty) { - defaultProperty = new Property; - defaultProperty->parent = this; - } - return defaultProperty; -} - -void QDeclarativeParser::Object::addValueProperty(Property *p) -{ - p->addref(); - valueProperties << p; -} - -void QDeclarativeParser::Object::addSignalProperty(Property *p) -{ - p->addref(); - signalProperties << p; -} - -void QDeclarativeParser::Object::addAttachedProperty(Property *p) -{ - p->addref(); - attachedProperties << p; -} - -void QDeclarativeParser::Object::addGroupedProperty(Property *p) -{ - p->addref(); - groupedProperties << p; -} - -void QDeclarativeParser::Object::addValueTypeProperty(Property *p) -{ - p->addref(); - valueTypeProperties << p; -} - -void QDeclarativeParser::Object::addScriptStringProperty(Property *p, int stack) -{ - p->addref(); - scriptStringProperties << qMakePair(p, stack); -} - - -Property *QDeclarativeParser::Object::getProperty(const QByteArray &name, bool create) -{ - if (!properties.contains(name)) { - if (create) { - Property *property = new Property(name); - property->parent = this; - properties.insert(name, property); - } else { - return 0; - } - } - return properties[name]; -} - -QDeclarativeParser::Object::DynamicProperty::DynamicProperty() -: isDefaultProperty(false), type(Variant), defaultValue(0) -{ -} - -QDeclarativeParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o) -: isDefaultProperty(o.isDefaultProperty), - type(o.type), - customType(o.customType), - name(o.name), - defaultValue(o.defaultValue), - location(o.location) -{ -} - -QDeclarativeParser::Object::DynamicSignal::DynamicSignal() -{ -} - -QDeclarativeParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o) -: name(o.name), parameterTypes(o.parameterTypes), - parameterNames(o.parameterNames), location(o.location) -{ -} - -QDeclarativeParser::Object::DynamicSlot::DynamicSlot() -{ -} - -QDeclarativeParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o) -: name(o.name), body(o.body), parameterNames(o.parameterNames), location(o.location) -{ -} - -QDeclarativeParser::Property::Property() -: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false), - isValueTypeSubProperty(false), isAlias(false) -{ -} - -QDeclarativeParser::Property::Property(const QByteArray &n) -: parent(0), type(0), index(-1), value(0), name(n), isDefault(false), - isDeferred(false), isValueTypeSubProperty(false), isAlias(false) -{ -} - -QDeclarativeParser::Property::~Property() -{ - foreach(Value *value, values) - value->release(); - foreach(Value *value, onValues) - value->release(); - if (value) value->release(); -} - -QDeclarativeParser::Object *QDeclarativeParser::Property::getValue(const LocationSpan &l) -{ - if (!value) { value = new QDeclarativeParser::Object; value->location = l; } - return value; -} - -void QDeclarativeParser::Property::addValue(Value *v) -{ - values << v; -} - -void QDeclarativeParser::Property::addOnValue(Value *v) -{ - onValues << v; -} - -bool QDeclarativeParser::Property::isEmpty() const -{ - return !value && values.isEmpty() && onValues.isEmpty(); -} - -QDeclarativeParser::Value::Value() -: type(Unknown), object(0) -{ -} - -QDeclarativeParser::Value::~Value() -{ - if (object) object->release(); -} - -QDeclarativeParser::Variant::Variant() -: t(Invalid) {} - -QDeclarativeParser::Variant::Variant(const Variant &o) -: t(o.t), d(o.d), s(o.s) -{ -} - -QDeclarativeParser::Variant::Variant(bool v) -: t(Boolean), b(v) -{ -} - -QDeclarativeParser::Variant::Variant(double v, const QString &asWritten) -: t(Number), d(v), s(asWritten) -{ -} - -QDeclarativeParser::Variant::Variant(const QString &v) -: t(String), s(v) -{ -} - -QDeclarativeParser::Variant::Variant(const QString &v, QDeclarativeJS::AST::Node *n) -: t(Script), n(n), s(v) -{ -} - -QDeclarativeParser::Variant &QDeclarativeParser::Variant::operator=(const Variant &o) -{ - t = o.t; - d = o.d; - s = o.s; - return *this; -} - -QDeclarativeParser::Variant::Type QDeclarativeParser::Variant::type() const -{ - return t; -} - -bool QDeclarativeParser::Variant::asBoolean() const -{ - return b; -} - -QString QDeclarativeParser::Variant::asString() const -{ - return s; -} - -double QDeclarativeParser::Variant::asNumber() const -{ - return d; -} - -//reverse of Lexer::singleEscape() -QString escapedString(const QString &string) -{ - QString tmp = QLatin1String("\""); - for (int i = 0; i < string.length(); ++i) { - const QChar &c = string.at(i); - switch(c.unicode()) { - case 0x08: - tmp += QLatin1String("\\b"); - break; - case 0x09: - tmp += QLatin1String("\\t"); - break; - case 0x0A: - tmp += QLatin1String("\\n"); - break; - case 0x0B: - tmp += QLatin1String("\\v"); - break; - case 0x0C: - tmp += QLatin1String("\\f"); - break; - case 0x0D: - tmp += QLatin1String("\\r"); - break; - case 0x22: - tmp += QLatin1String("\\\""); - break; - case 0x27: - tmp += QLatin1String("\\\'"); - break; - case 0x5C: - tmp += QLatin1String("\\\\"); - break; - default: - tmp += c; - break; - } - } - tmp += QLatin1Char('\"'); - return tmp; -} - -QString QDeclarativeParser::Variant::asScript() const -{ - switch(type()) { - default: - case Invalid: - return QString(); - case Boolean: - return b?QLatin1String("true"):QLatin1String("false"); - case Number: - if (s.isEmpty()) - return QString::number(d); - else - return s; - case String: - return escapedString(s); - case Script: - return s; - } -} - -QDeclarativeJS::AST::Node *QDeclarativeParser::Variant::asAST() const -{ - if (type() == Script) - return n; - else - return 0; -} - -bool QDeclarativeParser::Variant::isStringList() const -{ - if (isString()) - return true; - - if (type() != Script || !n) - return false; - - AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n); - if (!array) - return false; - - AST::ElementList *elements = array->elements; - - while (elements) { - - if (!AST::cast<AST::StringLiteral *>(elements->expression)) - return false; - - elements = elements->next; - } - - return true; -} - -QStringList QDeclarativeParser::Variant::asStringList() const -{ - QStringList rv; - if (isString()) { - rv << asString(); - return rv; - } - - AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n); - if (!array) - return rv; - - AST::ElementList *elements = array->elements; - while (elements) { - - AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(elements->expression); - if (!string) - return QStringList(); - rv.append(string->value->asString()); - - elements = elements->next; - } - - return rv; -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h deleted file mode 100644 index 7080a8daee..0000000000 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ /dev/null @@ -1,375 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVEPARSER_P_H -#define QDECLARATIVEPARSER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qdeclarative.h" - -#include <QtCore/qbytearray.h> -#include <QtCore/qlist.h> -#include <QtCore/qurl.h> -#include <QtCore/qstring.h> -#include <QtCore/qstringlist.h> - -#include <private/qobject_p.h> -#include <private/qdeclarativerefcount_p.h> -#include <private/qdeclarativeglobal_p.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QDeclarativePropertyCache; -namespace QDeclarativeJS { namespace AST { class Node; } } - -/* - XXX - - These types are created (and owned) by the QDeclarativeScriptParser and consumed by the - QDeclarativeCompiler. During the compilation phase the compiler will update some of - the fields for its own use. - - The types are part of the generic sounding "QDeclarativeParser" namespace for legacy - reasons (there used to be more in this namespace) and will be cleaned up and - migrated into a more appropriate location eventually. -*/ -namespace QDeclarativeParser -{ - struct Location - { - Location() : line(-1), column(-1) {} - int line; - int column; - }; - - struct LocationRange - { - LocationRange() : offset(0), length(0) {} - quint32 offset; - quint32 length; - }; - - struct LocationSpan - { - Location start; - Location end; - LocationRange range; - - bool operator<(LocationSpan &o) const { - return (start.line < o.start.line) || - (start.line == o.start.line && start.column < o.start.column); - } - }; - - class Property; - class Object : public QDeclarativeRefCount - { - public: - Object(); - virtual ~Object(); - - // Type of the object. The integer is an index into the - // QDeclarativeCompiledData::types array, or -1 if the object is a property - // group. - int type; - - // The fully-qualified name of this type - QByteArray typeName; - // The class name - QByteArray className; - // The id assigned to the object (if any). Set by the QDeclarativeCompiler - QString id; - // The id index assigned to the object (if any). Set by the QDeclarativeCompiler - int idIndex; - // Custom parsed data - QByteArray custom; - // Bit mask of the properties assigned bindings - QByteArray bindingBitmask; - void setBindingBit(int); - // Returns the metaobject for this type, or 0 if not available. - // Internally selectd between the metatype and extObject variables - const QMetaObject *metaObject() const; - - // The compile time metaobject for this type - const QMetaObject *metatype; - // The synthesized metaobject, if QML added signals or properties to - // this type. Otherwise null - QAbstractDynamicMetaObject extObject; - QByteArray metadata; // Generated by compiler - QByteArray synthdata; // Generated by compiler - QDeclarativePropertyCache *synthCache; // Generated by compiler - - Property *getDefaultProperty(); - Property *getProperty(const QByteArray &name, bool create=true); - - Property *defaultProperty; - QHash<QByteArray, Property *> properties; - - // Output of the compilation phase (these properties continue to exist - // in either the defaultProperty or properties members too) - void addValueProperty(Property *); - void addSignalProperty(Property *); - void addAttachedProperty(Property *); - void addGroupedProperty(Property *); - void addValueTypeProperty(Property *); - void addScriptStringProperty(Property *, int = 0); - QList<Property *> valueProperties; - QList<Property *> signalProperties; - QList<Property *> attachedProperties; - QList<Property *> groupedProperties; - QList<Property *> valueTypeProperties; - QList<QPair<Property *, int> > scriptStringProperties; - - // Script blocks that were nested under this object - struct ScriptBlock { - enum Pragma { - None = 0x00000000, - Shared = 0x00000001 - }; - Q_DECLARE_FLAGS(Pragmas, Pragma) - - QString code; - QString file; - Pragmas pragmas; - }; - - // The bytes to cast instances by to get to the QDeclarativeParserStatus - // interface. -1 indicates the type doesn't support this interface. - // Set by the QDeclarativeCompiler. - int parserStatusCast; - - LocationSpan location; - - struct DynamicProperty { - DynamicProperty(); - DynamicProperty(const DynamicProperty &); - - enum Type { Variant, Int, Bool, Real, String, Url, Color, Time, Date, DateTime, Alias, Custom, CustomList }; - - bool isDefaultProperty; - Type type; - QByteArray customType; - QByteArray name; - QDeclarativeParser::Property *defaultValue; - LocationSpan location; - }; - struct DynamicSignal { - DynamicSignal(); - DynamicSignal(const DynamicSignal &); - - QByteArray name; - QList<QByteArray> parameterTypes; - QList<QByteArray> parameterNames; - LocationSpan location; - }; - struct DynamicSlot { - DynamicSlot(); - DynamicSlot(const DynamicSlot &); - - QByteArray name; - QString body; - QList<QByteArray> parameterNames; - LocationSpan location; - }; - - // The list of dynamic properties - QList<DynamicProperty> dynamicProperties; - // The list of dynamic signals - QList<DynamicSignal> dynamicSignals; - // The list of dynamic slots - QList<DynamicSlot> dynamicSlots; - }; - - class Q_DECLARATIVE_EXPORT Variant - { - public: - enum Type { - Invalid, - Boolean, - Number, - String, - Script - }; - - Variant(); - Variant(const Variant &); - Variant(bool); - Variant(double, const QString &asWritten=QString()); - Variant(const QString &); - Variant(const QString &, QDeclarativeJS::AST::Node *); - Variant &operator=(const Variant &); - - Type type() const; - - bool isBoolean() const { return type() == Boolean; } - bool isNumber() const { return type() == Number; } - bool isString() const { return type() == String; } - bool isScript() const { return type() == Script; } - bool isStringList() const; - - bool asBoolean() const; - QString asString() const; - double asNumber() const; - QString asScript() const; - QDeclarativeJS::AST::Node *asAST() const; - QStringList asStringList() const; - - private: - Type t; - union { - bool b; - double d; - QDeclarativeJS::AST::Node *n; - }; - QString s; - }; - - class Value : public QDeclarativeRefCount - { - public: - Value(); - virtual ~Value(); - - enum Type { - // The type of this value assignment is not yet known - Unknown, - // This is used as a literal property assignment - Literal, - // This is used as a property binding assignment - PropertyBinding, - // This is used as a QDeclarativePropertyValueSource assignment - ValueSource, - // This is used as a QDeclarativePropertyValueInterceptor assignment - ValueInterceptor, - // This is used as a property QObject assignment - CreatedObject, - // This is used as a signal object assignment - SignalObject, - // This is used as a signal expression assignment - SignalExpression, - // This is used as an id assignment only - Id - }; - Type type; - - // ### Temporary (for id only) - QString primitive() const { return value.isString() ? value.asString() : value.asScript(); } - - // Primitive value - Variant value; - // Object value - Object *object; - - LocationSpan location; - }; - - class Property : public QDeclarativeRefCount - { - public: - Property(); - Property(const QByteArray &n); - virtual ~Property(); - - // The Object to which this property is attached - Object *parent; - - Object *getValue(const LocationSpan &); - void addValue(Value *v); - void addOnValue(Value *v); - - // The QVariant::Type of the property, or 0 (QVariant::Invalid) if - // unknown. - int type; - // The metaobject index of this property, or -1 if unknown. - int index; - - // Returns true if this is an empty property - both value and values - // are unset. - bool isEmpty() const; - // The list of values assigned to this property. Content in values - // and value are mutually exclusive - QList<Value *> values; - // The list of values assigned to this property using the "on" syntax - QList<Value *> onValues; - // The accessed property. This is used to represent dot properties. - // Content in value and values are mutually exclusive. - Object *value; - // The property name - QByteArray name; - // True if this property was accessed as the default property. - bool isDefault; - // True if the setting of this property will be deferred. Set by the - // QDeclarativeCompiler - bool isDeferred; - // True if this property is a value-type pseudo-property - bool isValueTypeSubProperty; - // True if this property is a property alias. Set by the - // QDeclarativeCompiler - bool isAlias; - - LocationSpan location; - LocationRange listValueRange; - }; -} - -Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeParser::Object::ScriptBlock::Pragmas); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QDeclarativeParser::Variant) - -QT_END_HEADER - -#endif // QDECLARATIVEPARSER_P_H diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 3406109a28..60e785510a 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -235,63 +235,71 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name for (int ii = 0; ii < path.count() - 1; ++ii) { const QString &pathName = path.at(ii); - if (QDeclarativeTypeNameCache::Data *data = typeNameCache?typeNameCache->data(pathName):0) { - if (data->type) { - QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); - if (!func) return; // Not an attachable type - - currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject); - if (!currentObject) return; // Something is broken with the attachable type - } else { - Q_ASSERT(data->typeNamespace); - if ((ii + 1) == path.count()) return; // No type following the namespace + if (typeNameCache) { + QDeclarativeTypeNameCache::Result r = typeNameCache->query(pathName); + if (r.isValid()) { + if (r.type) { + QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(); + if (!func) return; // Not an attachable type + + currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject); + if (!currentObject) return; // Something is broken with the attachable type + } else if (r.importNamespace) { + if ((ii + 1) == path.count()) return; // No type following the namespace + + ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace); + if (!r.type) return; // Invalid type in namespace - ++ii; data = data->typeNamespace->data(path.at(ii)); - if (!data || !data->type) return; // Invalid type in namespace + QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(); + if (!func) return; // Not an attachable type - QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); - if (!func) return; // Not an attachable type + currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject); + if (!currentObject) return; // Something is broken with the attachable type - currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject); - if (!currentObject) return; // Something is broken with the attachable type + } else if (r.scriptIndex != -1) { + return; // Not a type + } else { + Q_ASSERT(!"Unreachable"); + } + continue; } - } else { - QDeclarativePropertyCache::Data local; - QDeclarativePropertyCache::Data *property = - QDeclarativePropertyCache::property(engine, obj, pathName, local); + } - if (!property) return; // Not a property - if (property->isFunction()) - return; // Not an object property + QDeclarativePropertyCache::Data local; + QDeclarativePropertyCache::Data *property = + QDeclarativePropertyCache::property(engine, obj, pathName, local); - if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) { - // We're now at a value type property. We can use a global valuetypes array as we - // never actually use the objects, just look up their properties. - QObject *typeObject = (*qmlValueTypes())[property->propType]; - if (!typeObject) return; // Not a value type + if (!property) return; // Not a property + if (property->isFunction()) + return; // Not an object property - int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); - if (idx == -1) return; // Value type property does not exist + if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) { + // We're now at a value type property. We can use a global valuetypes array as we + // never actually use the objects, just look up their properties. + QObject *typeObject = (*qmlValueTypes())[property->propType]; + if (!typeObject) return; // Not a value type - QMetaProperty vtProp = typeObject->metaObject()->property(idx); + int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); + if (idx == -1) return; // Value type property does not exist - object = currentObject; - core = *property; - valueType.flags = QDeclarativePropertyCache::Data::flagsForProperty(vtProp); - valueType.valueTypeCoreIdx = idx; - valueType.valueTypePropType = vtProp.userType(); + QMetaProperty vtProp = typeObject->metaObject()->property(idx); - return; - } else { - if (!property->isQObject()) - return; // Not an object property + object = currentObject; + core = *property; + valueType.flags = QDeclarativePropertyCache::Data::flagsForProperty(vtProp); + valueType.valueTypeCoreIdx = idx; + valueType.valueTypePropType = vtProp.userType(); - void *args[] = { ¤tObject, 0 }; - QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args); - if (!currentObject) return; // No value + return; + } else { + if (!property->isQObject()) + return; // Not an object property + + void *args[] = { ¤tObject, 0 }; + QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args); + if (!currentObject) return; // No value - } } } diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index d2148ad874..406e43fc21 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -241,12 +241,13 @@ QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObj QDeclarativePropertyCache::Data rv; { const QMetaObject *cmo = metaObject; + const QByteArray propertyName = property.toUtf8(); while (cmo) { - int idx = metaObject->indexOfProperty(property.toUtf8()); + int idx = cmo->indexOfProperty(propertyName); if (idx != -1) { - QMetaProperty p = metaObject->property(idx); + QMetaProperty p = cmo->property(idx); if (p.isScriptable()) { - rv.load(metaObject->property(idx)); + rv.load(p); return rv; } else { while (cmo && cmo->propertyOffset() >= idx) @@ -278,14 +279,14 @@ QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObj return rv; } -QDeclarativePropertyCache *QDeclarativePropertyCache::copy() +QDeclarativePropertyCache *QDeclarativePropertyCache::copy(int reserve) { QDeclarativePropertyCache *cache = new QDeclarativePropertyCache(engine); cache->parent = this; cache->parent->addref(); cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart; cache->methodIndexCacheStart = methodIndexCache.count() + methodIndexCacheStart; - cache->stringCache = stringCache; + cache->stringCache.copyAndReserve(stringCache, reserve); cache->allowedRevisionCache = allowedRevisionCache; // We specifically do *NOT* copy the constructor @@ -324,14 +325,13 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb // Extract method name const char *signature = m.signature(); const char *cptr = signature; - while (*cptr != '(') { Q_ASSERT(*cptr != 0); ++cptr; } - QString str = dynamicMetaObject?QString::fromUtf8(signature, cptr - signature): - QString::fromLatin1(signature, cptr - signature); - QHashedString methodName(str); + bool utf8 = false; + while (*cptr != '(') { Q_ASSERT(*cptr != 0); utf8 |= *cptr & 0x80; ++cptr; } Data *data = &methodIndexCache[ii - methodIndexCacheStart]; data->lazyLoad(m); + if (data->isSignal()) data->flags |= signalFlags; else @@ -342,15 +342,27 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb data->metaObjectOffset = allowedRevisionCache.count() - 1; - if (Data **old = stringCache.value(methodName)) { - // We only overload methods in the same class, exactly like C++ - if ((*old)->flags & Data::IsFunction && (*old)->coreIndex >= methodOffset) - data->relatedIndex = (*old)->coreIndex; - data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction); - data->overrideIndex = (*old)->coreIndex; + Data *old = 0; + + if (utf8) { + QHashedString methodName(QString::fromUtf8(signature, cptr - signature)); + if (Data **it = stringCache.value(methodName)) + old = *it; + stringCache.insert(methodName, data); + } else { + QHashedCStringRef methodName(signature, cptr - signature); + if (Data **it = stringCache.value(methodName)) + old = *it; + stringCache.insert(methodName, data); } - stringCache.insert(methodName, data); + if (old) { + // We only overload methods in the same class, exactly like C++ + if (old->flags & Data::IsFunction && old->coreIndex >= methodOffset) + data->relatedIndex = old->coreIndex; + data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); + data->overrideIndex = old->coreIndex; + } } int propCount = metaObject->propertyCount(); @@ -362,9 +374,10 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb if (!p.isScriptable()) continue; - QString str = dynamicMetaObject?QString::fromUtf8(p.name()): - QString::fromLatin1(p.name()); - QHashedString propName(str); + const char *str = p.name(); + bool utf8 = false; + const char *cptr = str; + while (*cptr != 0) { utf8 |= *cptr & 0x80; ++cptr; } Data *data = &propertyIndexCache[ii - propertyIndexCacheStart]; @@ -376,12 +389,24 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb data->metaObjectOffset = allowedRevisionCache.count() - 1; - if (Data **old = stringCache.value(propName)) { - data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction); - data->overrideIndex = (*old)->coreIndex; + Data *old = 0; + + if (utf8) { + QHashedString propName(QString::fromUtf8(str, cptr - str)); + if (Data **it = stringCache.value(propName)) + old = *it; + stringCache.insert(propName, data); + } else { + QHashedCStringRef propName(str, cptr - str); + if (Data **it = stringCache.value(propName)) + old = *it; + stringCache.insert(propName, data); } - stringCache.insert(propName, data); + if (old) { + data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); + data->overrideIndex = old->coreIndex; + } } } @@ -417,8 +442,12 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb Q_ASSERT(stringCache.isEmpty()); // Optimization to prevent unnecessary reallocation of lists - propertyIndexCache.reserve(metaObject->propertyCount()); - methodIndexCache.reserve(metaObject->methodCount()); + int pc = metaObject->propertyCount(); + int mc = metaObject->methodCount(); + propertyIndexCache.reserve(pc); + methodIndexCache.reserve(mc); + + stringCache.reserve(pc + mc); updateRecur(engine,metaObject); } @@ -452,6 +481,22 @@ QDeclarativePropertyCache::method(int index) const } QDeclarativePropertyCache::Data * +QDeclarativePropertyCache::property(const QHashedStringRef &str) const +{ + QDeclarativePropertyCache::Data **rv = stringCache.value(str); + if (rv && (*rv)->notFullyResolved()) resolve(*rv); + return rv?*rv:0; +} + +QDeclarativePropertyCache::Data * +QDeclarativePropertyCache::property(const QHashedCStringRef &str) const +{ + QDeclarativePropertyCache::Data **rv = stringCache.value(str); + if (rv && (*rv)->notFullyResolved()) resolve(*rv); + return rv?*rv:0; +} + +QDeclarativePropertyCache::Data * QDeclarativePropertyCache::property(const QString &str) const { QDeclarativePropertyCache::Data **rv = stringCache.value(str); diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index cdbd49388f..8a1da1929c 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -172,7 +172,7 @@ public: void update(QDeclarativeEngine *, const QMetaObject *); - QDeclarativePropertyCache *copy(); + QDeclarativePropertyCache *copy(int reserve = 0); void append(QDeclarativeEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags, Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags); void append(QDeclarativeEngine *, const QMetaObject *, int revision, Data::Flag propertyFlags = Data::NoFlags, @@ -181,6 +181,8 @@ public: static Data create(const QMetaObject *, const QString &); inline Data *property(const QHashedV8String &) const; + Data *property(const QHashedStringRef &) const; + Data *property(const QHashedCStringRef &) const; Data *property(const QString &) const; Data *property(int) const; Data *method(int) const; diff --git a/src/declarative/qml/qdeclarativerewrite.cpp b/src/declarative/qml/qdeclarativerewrite.cpp index bff296b00b..be399dd074 100644 --- a/src/declarative/qml/qdeclarativerewrite.cpp +++ b/src/declarative/qml/qdeclarativerewrite.cpp @@ -54,7 +54,6 @@ namespace QDeclarativeRewrite { bool SharedBindingTester::isSharable(const QString &code) { Engine engine; - NodePool pool(QString(), &engine); Lexer lexer(&engine); Parser parser(&engine); lexer.setCode(code, 0); @@ -75,7 +74,6 @@ bool SharedBindingTester::isSharable(AST::Node *node) QString RewriteBinding::operator()(const QString &code, bool *ok, bool *sharable) { Engine engine; - NodePool pool(QString(), &engine); Lexer lexer(&engine); Parser parser(&engine); lexer.setCode(code, 0); @@ -118,7 +116,7 @@ QString RewriteBinding::operator()(QDeclarativeJS::AST::Node *node, const QStrin unsigned startOfStatement = 0; unsigned endOfStatement = (expression ? expression->lastSourceLocation().end() : statement->lastSourceLocation().end()) - _position; - QString startString = QLatin1String("(function ") + QString::fromUtf8(_name) + QLatin1String("() { "); + QString startString = QLatin1String("(function ") + _name + QLatin1String("() { "); if (expression) startString += QLatin1String("return "); _writer->replace(startOfStatement, 0, startString); @@ -160,7 +158,7 @@ QString RewriteBinding::rewrite(QString code, unsigned position, unsigned startOfStatement = node->firstSourceLocation().begin() - _position; unsigned endOfStatement = node->lastSourceLocation().end() - _position; - _writer->replace(startOfStatement, 0, QLatin1String("(function ") + QString::fromUtf8(_name) + QLatin1String("() { ")); + _writer->replace(startOfStatement, 0, QLatin1String("(function ") + _name + QLatin1String("() { ")); _writer->replace(endOfStatement, 0, QLatin1String(" })")); if (rewriteDump()) { diff --git a/src/declarative/qml/qdeclarativerewrite_p.h b/src/declarative/qml/qdeclarativerewrite_p.h index 9f4030667c..c57e9956b0 100644 --- a/src/declarative/qml/qdeclarativerewrite_p.h +++ b/src/declarative/qml/qdeclarativerewrite_p.h @@ -56,7 +56,7 @@ #include "rewriter/textwriter_p.h" #include "parser/qdeclarativejslexer_p.h" #include "parser/qdeclarativejsparser_p.h" -#include "parser/qdeclarativejsnodepool_p.h" +#include "parser/qdeclarativejsmemorypool_p.h" QT_BEGIN_NAMESPACE @@ -79,14 +79,14 @@ class RewriteBinding: protected AST::Visitor { unsigned _position; TextWriter *_writer; - QByteArray _name; + QString _name; public: QString operator()(const QString &code, bool *ok = 0, bool *sharable = 0); QString operator()(QDeclarativeJS::AST::Node *node, const QString &code, bool *sharable = 0); //name of the function: used for the debugger - void setName(const QByteArray &name) { _name = name; } + void setName(const QString &name) { _name = name; } protected: using AST::Visitor::visit; diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescript.cpp index dcd12e287a..55a6b2b2cf 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescript.cpp @@ -39,13 +39,12 @@ ** ****************************************************************************/ -#include "private/qdeclarativescriptparser_p.h" +#include "private/qdeclarativescript_p.h" -#include "private/qdeclarativeparser_p.h" #include "parser/qdeclarativejsengine_p.h" #include "parser/qdeclarativejsparser_p.h" #include "parser/qdeclarativejslexer_p.h" -#include "parser/qdeclarativejsnodepool_p.h" +#include "parser/qdeclarativejsmemorypool_p.h" #include "parser/qdeclarativejsastvisitor_p.h" #include "parser/qdeclarativejsast_p.h" #include "private/qdeclarativerewrite_p.h" @@ -57,9 +56,399 @@ QT_BEGIN_NAMESPACE using namespace QDeclarativeJS; -using namespace QDeclarativeParser; +using namespace QDeclarativeScript; + +// +// Parser IR classes +// +QDeclarativeScript::Object::Object() +: type(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1), + componentCompileState(0), nextAliasingObject(0), nextIdObject(0) +{ +} + +QDeclarativeScript::Object::~Object() +{ + if (synthCache) synthCache->release(); +} + +void Object::setBindingBit(int b) +{ + while (bindingBitmask.size() < 4 * (1 + b / 32)) + bindingBitmask.append(char(0)); + + quint32 *bits = (quint32 *)bindingBitmask.data(); + bits[b / 32] |= (1 << (b % 32)); +} + +const QMetaObject *Object::metaObject() const +{ + if (!metadata.isEmpty() && metatype) + return &extObject; + else + return metatype; +} + +QDeclarativeScript::Property *Object::getDefaultProperty() +{ + if (!defaultProperty) { + defaultProperty = pool()->New<Property>(); + defaultProperty->parent = this; + } + return defaultProperty; +} + +void QDeclarativeScript::Object::addValueProperty(Property *p) +{ + valueProperties.append(p); +} + +void QDeclarativeScript::Object::addSignalProperty(Property *p) +{ + signalProperties.append(p); +} + +void QDeclarativeScript::Object::addAttachedProperty(Property *p) +{ + attachedProperties.append(p); +} + +void QDeclarativeScript::Object::addGroupedProperty(Property *p) +{ + groupedProperties.append(p); +} + +void QDeclarativeScript::Object::addValueTypeProperty(Property *p) +{ + valueTypeProperties.append(p); +} + +void QDeclarativeScript::Object::addScriptStringProperty(Property *p) +{ + scriptStringProperties.append(p); +} + +// This lookup is optimized for missing, and having to create a new property. +Property *QDeclarativeScript::Object::getProperty(const QHashedStringRef &name, bool create) +{ + if (create) { + quint32 h = name.hash(); + if (propertiesHashField.testAndSet(h)) { + for (Property *p = properties.first(); p; p = properties.next(p)) { + if (p->name() == name) + return p; + } + } + + Property *property = pool()->New<Property>(); + property->parent = this; + property->_name = name; + property->isDefault = false; + properties.prepend(property); + return property; + } else { + for (Property *p = properties.first(); p; p = properties.next(p)) { + if (p->name() == name) + return p; + } + } + + return 0; +} + +Property *QDeclarativeScript::Object::getProperty(const QStringRef &name, bool create) +{ + return getProperty(QHashedStringRef(name), create); +} + +Property *QDeclarativeScript::Object::getProperty(const QString &name, bool create) +{ + for (Property *p = properties.first(); p; p = properties.next(p)) { + if (p->name() == name) + return p; + } + + if (create) { + Property *property = pool()->New<Property>(); + property->parent = this; + property->_name = QStringRef(pool()->NewString(name)); + propertiesHashField.testAndSet(property->_name.hash()); + property->isDefault = false; + properties.prepend(property); + return property; + } else { + return 0; + } +} + +QDeclarativeScript::Object::DynamicProperty::DynamicProperty() +: isDefaultProperty(false), type(Variant), defaultValue(0), nextProperty(0), + resolvedCustomTypeName(0) +{ +} + +QDeclarativeScript::Object::DynamicSignal::DynamicSignal() +: nextSignal(0) +{ +} + +// Returns length in utf8 bytes +int QDeclarativeScript::Object::DynamicSignal::parameterTypesLength() const +{ + int rv = 0; + for (int ii = 0; ii < parameterTypes.count(); ++ii) + rv += parameterTypes.at(ii).length(); + return rv; +} + +// Returns length in utf8 bytes +int QDeclarativeScript::Object::DynamicSignal::parameterNamesLength() const +{ + int rv = 0; + for (int ii = 0; ii < parameterNames.count(); ++ii) + rv += parameterNames.at(ii).utf8length(); + return rv; +} + +QDeclarativeScript::Object::DynamicSlot::DynamicSlot() +: nextSlot(0) +{ +} + +int QDeclarativeScript::Object::DynamicSlot::parameterNamesLength() const +{ + int rv = 0; + for (int ii = 0; ii < parameterNames.count(); ++ii) + rv += parameterNames.at(ii).length(); + return rv; +} + +QDeclarativeScript::Property::Property() +: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false), + isValueTypeSubProperty(false), isAlias(false), scriptStringScope(-1), + nextMainProperty(0), nextProperty(0) +{ +} + +QDeclarativeScript::Object *QDeclarativeScript::Property::getValue(const LocationSpan &l) +{ + if (!value) { value = pool()->New<Object>(); value->location = l; } + return value; +} + +void QDeclarativeScript::Property::addValue(Value *v) +{ + values.append(v); +} + +void QDeclarativeScript::Property::addOnValue(Value *v) +{ + onValues.append(v); +} + +bool QDeclarativeScript::Property::isEmpty() const +{ + return !value && values.isEmpty() && onValues.isEmpty(); +} + +QDeclarativeScript::Value::Value() +: type(Unknown), object(0), bindingReference(0), signalExpressionContextStack(0), nextValue(0) +{ +} + +QDeclarativeScript::Variant::Variant() +: t(Invalid) +{ +} + +QDeclarativeScript::Variant::Variant(const Variant &o) +: t(o.t), d(o.d), asWritten(o.asWritten) +{ +} + +QDeclarativeScript::Variant::Variant(bool v) +: t(Boolean), b(v) +{ +} + +QDeclarativeScript::Variant::Variant(double v, const QStringRef &asWritten) +: t(Number), d(v), asWritten(asWritten) +{ +} + +QDeclarativeScript::Variant::Variant(QDeclarativeJS::AST::StringLiteral *v) +: t(String), l(v) +{ +} + +QDeclarativeScript::Variant::Variant(const QStringRef &asWritten, QDeclarativeJS::AST::Node *n) +: t(Script), n(n), asWritten(asWritten) +{ +} + +QDeclarativeScript::Variant &QDeclarativeScript::Variant::operator=(const Variant &o) +{ + t = o.t; + d = o.d; + asWritten = o.asWritten; + return *this; +} + +QDeclarativeScript::Variant::Type QDeclarativeScript::Variant::type() const +{ + return t; +} + +bool QDeclarativeScript::Variant::asBoolean() const +{ + return b; +} + +QString QDeclarativeScript::Variant::asString() const +{ + if (t == String) { + // XXX aakenned + return l->value.toString(); + } else { + return asWritten.toString(); + } +} + +double QDeclarativeScript::Variant::asNumber() const +{ + return d; +} + +//reverse of Lexer::singleEscape() +QString escapedString(const QString &string) +{ + QString tmp = QLatin1String("\""); + for (int i = 0; i < string.length(); ++i) { + const QChar &c = string.at(i); + switch(c.unicode()) { + case 0x08: + tmp += QLatin1String("\\b"); + break; + case 0x09: + tmp += QLatin1String("\\t"); + break; + case 0x0A: + tmp += QLatin1String("\\n"); + break; + case 0x0B: + tmp += QLatin1String("\\v"); + break; + case 0x0C: + tmp += QLatin1String("\\f"); + break; + case 0x0D: + tmp += QLatin1String("\\r"); + break; + case 0x22: + tmp += QLatin1String("\\\""); + break; + case 0x27: + tmp += QLatin1String("\\\'"); + break; + case 0x5C: + tmp += QLatin1String("\\\\"); + break; + default: + tmp += c; + break; + } + } + tmp += QLatin1Char('\"'); + return tmp; +} + +QString QDeclarativeScript::Variant::asScript() const +{ + switch(type()) { + default: + case Invalid: + return QString(); + case Boolean: + return b?QLatin1String("true"):QLatin1String("false"); + case Number: + if (asWritten.isEmpty()) + return QString::number(d); + else + return asWritten.toString(); + case String: + return escapedString(asString()); + case Script: + if (AST::IdentifierExpression *i = AST::cast<AST::IdentifierExpression *>(n)) { + // XXX aakenned + return i->name.toString(); + } else + return asWritten.toString(); + } +} + +QDeclarativeJS::AST::Node *QDeclarativeScript::Variant::asAST() const +{ + if (type() == Script) + return n; + else + return 0; +} + +bool QDeclarativeScript::Variant::isStringList() const +{ + if (isString()) + return true; + + if (type() != Script || !n) + return false; + + AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n); + if (!array) + return false; + + AST::ElementList *elements = array->elements; + + while (elements) { -void QDeclarativeScriptParser::Import::extractVersion(int *maj, int *min) const + if (!AST::cast<AST::StringLiteral *>(elements->expression)) + return false; + + elements = elements->next; + } + + return true; +} + +QStringList QDeclarativeScript::Variant::asStringList() const +{ + QStringList rv; + if (isString()) { + rv << asString(); + return rv; + } + + AST::ArrayLiteral *array = AST::cast<AST::ArrayLiteral *>(n); + if (!array) + return rv; + + AST::ElementList *elements = array->elements; + while (elements) { + + AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(elements->expression); + if (!string) + return QStringList(); + rv.append(string->value.toString()); + + elements = elements->next; + } + + return rv; +} + +// +// Actual parser classes +// +void QDeclarativeScript::Import::extractVersion(int *maj, int *min) const { *maj = -1; *min = -1; @@ -81,16 +470,16 @@ class ProcessAST: protected AST::Visitor { struct State { State() : object(0), property(0) {} - State(QDeclarativeParser::Object *o) : object(o), property(0) {} - State(QDeclarativeParser::Object *o, Property *p) : object(o), property(p) {} + State(QDeclarativeScript::Object *o) : object(o), property(0) {} + State(QDeclarativeScript::Object *o, Property *p) : object(o), property(p) {} - QDeclarativeParser::Object *object; + QDeclarativeScript::Object *object; Property *property; }; struct StateStack : public QStack<State> { - void pushObject(QDeclarativeParser::Object *obj) + void pushObject(QDeclarativeScript::Object *obj) { push(State(obj)); } @@ -100,12 +489,27 @@ class ProcessAST: protected AST::Visitor const State &state = top(); if (state.property) { State s(state.property->getValue(location), - state.property->getValue(location)->getProperty(name.toUtf8())); + state.property->getValue(location)->getProperty(name)); s.property->location = location; push(s); } else { - State s(state.object, - state.object->getProperty(name.toUtf8())); + State s(state.object, state.object->getProperty(name)); + + s.property->location = location; + push(s); + } + } + + void pushProperty(const QStringRef &name, const LocationSpan &location) + { + const State &state = top(); + if (state.property) { + State s(state.property->getValue(location), + state.property->getValue(location)->getProperty(name)); + s.property->location = location; + push(s); + } else { + State s(state.object, state.object->getProperty(name)); s.property->location = location; push(s); @@ -114,21 +518,21 @@ class ProcessAST: protected AST::Visitor }; public: - ProcessAST(QDeclarativeScriptParser *parser); + ProcessAST(QDeclarativeScript::Parser *parser); virtual ~ProcessAST(); void operator()(const QString &code, AST::Node *node); protected: - QDeclarativeParser::Object *defineObjectBinding(AST::UiQualifiedId *propertyName, bool onAssignment, + QDeclarativeScript::Object *defineObjectBinding(AST::UiQualifiedId *propertyName, bool onAssignment, const QString &objectType, AST::SourceLocation typeLocation, LocationSpan location, AST::UiObjectInitializer *initializer = 0); - QDeclarativeParser::Variant getVariant(AST::Statement *stmt); - QDeclarativeParser::Variant getVariant(AST::ExpressionNode *expr); + QDeclarativeScript::Variant getVariant(AST::Statement *stmt); + QDeclarativeScript::Variant getVariant(AST::ExpressionNode *expr); LocationSpan location(AST::SourceLocation start, AST::SourceLocation end); LocationSpan location(AST::UiQualifiedId *); @@ -151,18 +555,24 @@ protected: QString asString(AST::UiQualifiedId *node) const; const State state() const; - QDeclarativeParser::Object *currentObject() const; + QDeclarativeScript::Object *currentObject() const; Property *currentProperty() const; QString qualifiedNameId() const; QString textAt(const AST::SourceLocation &loc) const - { return _contents.mid(loc.offset, loc.length); } + { return _contents->mid(loc.offset, loc.length); } + QStringRef textRefAt(const AST::SourceLocation &loc) const + { return QStringRef(_contents, loc.offset, loc.length); } QString textAt(const AST::SourceLocation &first, const AST::SourceLocation &last) const - { return _contents.mid(first.offset, last.offset + last.length - first.offset); } + { return _contents->mid(first.offset, last.offset + last.length - first.offset); } + + QStringRef textRefAt(const AST::SourceLocation &first, + const AST::SourceLocation &last) const + { return QStringRef(_contents, first.offset, last.offset + last.length - first.offset); } QString asString(AST::ExpressionNode *expr) { @@ -172,6 +582,14 @@ protected: return textAt(expr->firstSourceLocation(), expr->lastSourceLocation()); } + QStringRef asStringRef(AST::ExpressionNode *expr) + { + if (! expr) + return QStringRef(); + + return textRefAt(expr->firstSourceLocation(), expr->lastSourceLocation()); + } + QString asString(AST::Statement *stmt) { if (! stmt) @@ -182,14 +600,22 @@ protected: return s; } + QStringRef asStringRef(AST::Statement *stmt) + { + if (! stmt) + return QStringRef(); + + return textRefAt(stmt->firstSourceLocation(), stmt->lastSourceLocation()); + } + private: - QDeclarativeScriptParser *_parser; + QDeclarativeScript::Parser *_parser; StateStack _stateStack; QStringList _scope; - QString _contents; + const QString *_contents; }; -ProcessAST::ProcessAST(QDeclarativeScriptParser *parser) +ProcessAST::ProcessAST(QDeclarativeScript::Parser *parser) : _parser(parser) { } @@ -200,7 +626,7 @@ ProcessAST::~ProcessAST() void ProcessAST::operator()(const QString &code, AST::Node *node) { - _contents = code; + _contents = &code; accept(node); } @@ -217,7 +643,7 @@ const ProcessAST::State ProcessAST::state() const return _stateStack.back(); } -QDeclarativeParser::Object *ProcessAST::currentObject() const +QDeclarativeScript::Object *ProcessAST::currentObject() const { return state().object; } @@ -237,7 +663,7 @@ QString ProcessAST::asString(AST::UiQualifiedId *node) const QString s; for (AST::UiQualifiedId *it = node; it; it = it->next) { - s.append(it->name->asString()); + s.append(it->name.toString()); if (it->next) s.append(QLatin1Char('.')); @@ -246,7 +672,7 @@ QString ProcessAST::asString(AST::UiQualifiedId *node) const return s; } -QDeclarativeParser::Object * +QDeclarativeScript::Object * ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, bool onAssignment, const QString &objectType, @@ -262,11 +688,11 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, int propertyCount = 0; for (AST::UiQualifiedId *name = propertyName; name; name = name->next){ ++propertyCount; - _stateStack.pushProperty(name->name->asString(), + _stateStack.pushProperty(name->name, this->location(name)); } - if (!onAssignment && propertyCount && currentProperty() && currentProperty()->values.count()) { + if (!onAssignment && propertyCount && currentProperty() && !currentProperty()->values.isEmpty()) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Property value set multiple times")); error.setLine(this->location(propertyName).start.line); @@ -303,9 +729,9 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, if (lastTypeDot >= 0) resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/')); - QDeclarativeParser::Object *obj = new QDeclarativeParser::Object; + QDeclarativeScript::Object *obj = _parser->_pool.New<QDeclarativeScript::Object>(); - QDeclarativeScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType); + QDeclarativeScript::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType); obj->type = typeRef->id; typeRef->refObjects.append(obj); @@ -319,7 +745,7 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, if (propertyCount) { Property *prop = currentProperty(); - QDeclarativeParser::Value *v = new QDeclarativeParser::Value; + QDeclarativeScript::Value *v = _parser->_pool.New<QDeclarativeScript::Value>(); v->object = obj; v->location = obj->location; if (onAssignment) @@ -336,7 +762,7 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, _parser->setTree(obj); } else { const State state = _stateStack.top(); - QDeclarativeParser::Value *v = new QDeclarativeParser::Value; + QDeclarativeScript::Value *v = _parser->_pool.New<QDeclarativeScript::Value>(); v->object = obj; v->location = obj->location; if (state.property) { @@ -390,18 +816,18 @@ bool ProcessAST::visit(AST::UiProgram *node) bool ProcessAST::visit(AST::UiImport *node) { QString uri; - QDeclarativeScriptParser::Import import; + QDeclarativeScript::Import import; - if (node->fileName) { - uri = node->fileName->asString(); + if (!node->fileName.isNull()) { + uri = node->fileName.toString(); if (uri.endsWith(QLatin1String(".js"))) { - import.type = QDeclarativeScriptParser::Import::Script; + import.type = QDeclarativeScript::Import::Script; } else { - import.type = QDeclarativeScriptParser::Import::File; + import.type = QDeclarativeScript::Import::File; } } else { - import.type = QDeclarativeScriptParser::Import::Library; + import.type = QDeclarativeScript::Import::Library; uri = asString(node->importUri); } @@ -409,8 +835,8 @@ bool ProcessAST::visit(AST::UiImport *node) AST::SourceLocation endLoc = node->semicolonToken; // Qualifier - if (node->importId) { - import.qualifier = node->importId->asString(); + if (!node->importId.isNull()) { + import.qualifier = node->importId.toString(); if (!import.qualifier.at(0).isUpper()) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Invalid import qualifier ID")); @@ -429,10 +855,10 @@ bool ProcessAST::visit(AST::UiImport *node) } // Check for script qualifier clashes - bool isScript = import.type == QDeclarativeScriptParser::Import::Script; + bool isScript = import.type == QDeclarativeScript::Import::Script; for (int ii = 0; ii < _parser->_imports.count(); ++ii) { - const QDeclarativeScriptParser::Import &other = _parser->_imports.at(ii); - bool otherIsScript = other.type == QDeclarativeScriptParser::Import::Script; + const QDeclarativeScript::Import &other = _parser->_imports.at(ii); + bool otherIsScript = other.type == QDeclarativeScript::Import::Script; if ((isScript || otherIsScript) && import.qualifier == other.qualifier) { QDeclarativeError error; @@ -444,7 +870,7 @@ bool ProcessAST::visit(AST::UiImport *node) } } - } else if (import.type == QDeclarativeScriptParser::Import::Script) { + } else if (import.type == QDeclarativeScript::Import::Script) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Script import requires a qualifier")); error.setLine(node->fileNameToken.startLine); @@ -455,7 +881,7 @@ bool ProcessAST::visit(AST::UiImport *node) if (node->versionToken.isValid()) { import.version = textAt(node->versionToken); - } else if (import.type == QDeclarativeScriptParser::Import::Library) { + } else if (import.type == QDeclarativeScript::Import::Library) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Library import requires a version")); error.setLine(node->importIdToken.startLine); @@ -475,46 +901,61 @@ bool ProcessAST::visit(AST::UiImport *node) bool ProcessAST::visit(AST::UiPublicMember *node) { - const struct TypeNameToType { + static const struct TypeNameToType { const char *name; + int nameLength; Object::DynamicProperty::Type type; const char *qtName; + int qtNameLength; } propTypeNameToTypes[] = { - { "int", Object::DynamicProperty::Int, "int" }, - { "bool", Object::DynamicProperty::Bool, "bool" }, - { "double", Object::DynamicProperty::Real, "double" }, - { "real", Object::DynamicProperty::Real, "qreal" }, - { "string", Object::DynamicProperty::String, "QString" }, - { "url", Object::DynamicProperty::Url, "QUrl" }, - { "color", Object::DynamicProperty::Color, "QColor" }, + { "int", strlen("int"), Object::DynamicProperty::Int, "int", strlen("int") }, + { "bool", strlen("bool"), Object::DynamicProperty::Bool, "bool", strlen("bool") }, + { "double", strlen("double"), Object::DynamicProperty::Real, "double", strlen("double") }, + { "real", strlen("real"), Object::DynamicProperty::Real, "qreal", strlen("qreal") }, + { "string", strlen("string"), Object::DynamicProperty::String, "QString", strlen("QString") }, + { "url", strlen("url"), Object::DynamicProperty::Url, "QUrl", strlen("QUrl") }, + { "color", strlen("color"), Object::DynamicProperty::Color, "QColor", strlen("QColor") }, // Internally QTime, QDate and QDateTime are all supported. // To be more consistent with JavaScript we expose only // QDateTime as it matches closely with the Date JS type. // We also call it "date" to match. - // { "time", Object::DynamicProperty::Time, "QTime" }, - // { "date", Object::DynamicProperty::Date, "QDate" }, - { "date", Object::DynamicProperty::DateTime, "QDateTime" }, - { "variant", Object::DynamicProperty::Variant, "QVariant" } + // { "time", strlen("time"), Object::DynamicProperty::Time, "QTime", strlen("QTime") }, + // { "date", strlen("date"), Object::DynamicProperty::Date, "QDate", strlen("QDate") }, + { "date", strlen("date"), Object::DynamicProperty::DateTime, "QDateTime", strlen("QDateTime") }, + { "variant", strlen("variant"), Object::DynamicProperty::Variant, "QVariant", strlen("QVariant") } }; - const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) / - sizeof(propTypeNameToTypes[0]); + static const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) / + sizeof(propTypeNameToTypes[0]); if(node->type == AST::UiPublicMember::Signal) { - const QString name = node->name->asString(); - - Object::DynamicSignal signal; - signal.name = name.toUtf8(); + Object::DynamicSignal *signal = _parser->_pool.New<Object::DynamicSignal>(); + signal->name = node->name; AST::UiParameterList *p = node->parameters; + int paramLength = 0; + while (p) { paramLength++; p = p->next; } + p = node->parameters; + + if (paramLength) { + signal->parameterTypes = _parser->_pool.NewRawList<QHashedCStringRef>(paramLength); + signal->parameterNames = _parser->_pool.NewRawList<QHashedStringRef>(paramLength); + } + + int index = 0; while (p) { - const QString memberType = p->type->asString(); - const char *qtType = 0; - for(int ii = 0; !qtType && ii < propTypeNameToTypesCount; ++ii) { - if(QLatin1String(propTypeNameToTypes[ii].name) == memberType) - qtType = propTypeNameToTypes[ii].qtName; + const QStringRef &memberType = p->type; + + const TypeNameToType *type = 0; + for(int typeIndex = 0; typeIndex < propTypeNameToTypesCount; ++typeIndex) { + const TypeNameToType *t = propTypeNameToTypes + typeIndex; + if (t->nameLength == memberType.length() && + QHashedString::compare(memberType.constData(), t->name, t->nameLength)) { + type = t; + break; + } } - if (!qtType) { + if (!type) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Expected parameter type")); error.setLine(node->typeToken.startLine); @@ -523,39 +964,43 @@ bool ProcessAST::visit(AST::UiPublicMember *node) return false; } - signal.parameterTypes << qtType; - signal.parameterNames << p->name->asString().toUtf8(); - p = p->finish(); + signal->parameterTypes[index] = QHashedCStringRef(type->qtName, type->qtNameLength); + signal->parameterNames[index] = QHashedStringRef(p->name); + p = p->next; + index++; } - signal.location = location(node->typeToken, node->semicolonToken); - _stateStack.top().object->dynamicSignals << signal; + signal->location = location(node->typeToken, node->semicolonToken); + _stateStack.top().object->dynamicSignals.append(signal); } else { - const QString memberType = node->memberType->asString(); - const QString name = node->name->asString(); + const QStringRef &memberType = node->memberType; + const QStringRef &name = node->name; bool typeFound = false; Object::DynamicProperty::Type type; - if (memberType == QLatin1String("alias")) { + if ((unsigned)memberType.length() == strlen("alias") && + QHashedString::compare(memberType.constData(), "alias", strlen("alias"))) { type = Object::DynamicProperty::Alias; typeFound = true; - } + } for(int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) { - if(QLatin1String(propTypeNameToTypes[ii].name) == memberType) { - type = propTypeNameToTypes[ii].type; + const TypeNameToType *t = propTypeNameToTypes + ii; + if (t->nameLength == memberType.length() && + QHashedString::compare(memberType.constData(), t->name, t->nameLength)) { + type = t->type; typeFound = true; } } if (!typeFound && memberType.at(0).isUpper()) { - QString typemodifier; - if(node->typeModifier) - typemodifier = node->typeModifier->asString(); - if (typemodifier.isEmpty()) { + const QStringRef &typeModifier = node->typeModifier; + + if (typeModifier.isEmpty()) { type = Object::DynamicProperty::Custom; - } else if(typemodifier == QLatin1String("list")) { + } else if((unsigned)typeModifier.length() == strlen("list") && + QHashedString::compare(typeModifier.constData(), "list", strlen("list"))) { type = Object::DynamicProperty::CustomList; } else { QDeclarativeError error; @@ -566,7 +1011,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node) return false; } typeFound = true; - } else if (node->typeModifier) { + } else if (!node->typeModifier.isNull()) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Unexpected property type modifier")); error.setLine(node->typeModifierToken.startLine); @@ -593,33 +1038,35 @@ bool ProcessAST::visit(AST::UiPublicMember *node) return false; } - Object::DynamicProperty property; - property.isDefaultProperty = node->isDefaultMember; - property.type = type; + + Object::DynamicProperty *property = _parser->_pool.New<Object::DynamicProperty>(); + property->isDefaultProperty = node->isDefaultMember; + property->type = type; if (type >= Object::DynamicProperty::Custom) { - QDeclarativeScriptParser::TypeReference *typeRef = - _parser->findOrCreateType(memberType); + QDeclarativeScript::TypeReference *typeRef = + _parser->findOrCreateType(memberType.toString()); typeRef->refObjects.append(_stateStack.top().object); + property->customType = memberType; } - property.customType = memberType.toUtf8(); - property.name = name.toUtf8(); - property.location = location(node->firstSourceLocation(), - node->lastSourceLocation()); + + property->name = QHashedStringRef(name); + property->location = location(node->firstSourceLocation(), + node->lastSourceLocation()); if (node->statement) { // default value - property.defaultValue = new Property; - property.defaultValue->parent = _stateStack.top().object; - property.defaultValue->location = + property->defaultValue = _parser->_pool.New<Property>(); + property->defaultValue->parent = _stateStack.top().object; + property->defaultValue->location = location(node->statement->firstSourceLocation(), node->statement->lastSourceLocation()); - QDeclarativeParser::Value *value = new QDeclarativeParser::Value; + QDeclarativeScript::Value *value = _parser->_pool.New<QDeclarativeScript::Value>(); value->location = location(node->statement->firstSourceLocation(), node->statement->lastSourceLocation()); value->value = getVariant(node->statement); - property.defaultValue->values << value; + property->defaultValue->values.append(value); } - _stateStack.top().object->dynamicProperties << property; + _stateStack.top().object->dynamicProperties.append(property); // process QML-like initializers (e.g. property Object o: Object {}) accept(node->binding); @@ -660,37 +1107,37 @@ bool ProcessAST::visit(AST::UiObjectBinding *node) return false; } -QDeclarativeParser::Variant ProcessAST::getVariant(AST::Statement *stmt) +QDeclarativeScript::Variant ProcessAST::getVariant(AST::Statement *stmt) { if (stmt) { if (AST::ExpressionStatement *exprStmt = AST::cast<AST::ExpressionStatement *>(stmt)) return getVariant(exprStmt->expression); - return QDeclarativeParser::Variant(asString(stmt), stmt); + return QDeclarativeScript::Variant(asStringRef(stmt), stmt); } - return QDeclarativeParser::Variant(); + return QDeclarativeScript::Variant(); } -QDeclarativeParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr) +QDeclarativeScript::Variant ProcessAST::getVariant(AST::ExpressionNode *expr) { if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) { - return QDeclarativeParser::Variant(lit->value->asString()); + return QDeclarativeScript::Variant(lit); } else if (expr->kind == AST::Node::Kind_TrueLiteral) { - return QDeclarativeParser::Variant(true); + return QDeclarativeScript::Variant(true); } else if (expr->kind == AST::Node::Kind_FalseLiteral) { - return QDeclarativeParser::Variant(false); + return QDeclarativeScript::Variant(false); } else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) { - return QDeclarativeParser::Variant(lit->value, asString(expr)); + return QDeclarativeScript::Variant(lit->value, asStringRef(expr)); } else { if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) { if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) { - return QDeclarativeParser::Variant(-lit->value, asString(expr)); + return QDeclarativeScript::Variant(-lit->value, asStringRef(expr)); } } - return QDeclarativeParser::Variant(asString(expr), expr); + return QDeclarativeScript::Variant(asStringRef(expr), expr); } } @@ -702,13 +1149,13 @@ bool ProcessAST::visit(AST::UiScriptBinding *node) AST::UiQualifiedId *propertyName = node->qualifiedId; for (AST::UiQualifiedId *name = propertyName; name; name = name->next){ ++propertyCount; - _stateStack.pushProperty(name->name->asString(), + _stateStack.pushProperty(name->name, location(name)); } Property *prop = currentProperty(); - if (prop->values.count()) { + if (!prop->values.isEmpty()) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Property value set multiple times")); error.setLine(this->location(propertyName).start.line); @@ -717,18 +1164,17 @@ bool ProcessAST::visit(AST::UiScriptBinding *node) return 0; } - QDeclarativeParser::Variant primitive; + QDeclarativeScript::Variant primitive; if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) { primitive = getVariant(stmt->expression); } else { // do binding - primitive = QDeclarativeParser::Variant(asString(node->statement), - node->statement); + primitive = QDeclarativeScript::Variant(asStringRef(node->statement), node->statement); } prop->location.range.length = prop->location.range.offset + prop->location.range.length - node->qualifiedId->identifierToken.offset; prop->location.range.offset = node->qualifiedId->identifierToken.offset; - QDeclarativeParser::Value *v = new QDeclarativeParser::Value; + QDeclarativeScript::Value *v = _parser->_pool.New<QDeclarativeScript::Value>(); v->value = primitive; v->location = location(node->statement->firstSourceLocation(), node->statement->lastSourceLocation()); @@ -748,13 +1194,13 @@ bool ProcessAST::visit(AST::UiArrayBinding *node) AST::UiQualifiedId *propertyName = node->qualifiedId; for (AST::UiQualifiedId *name = propertyName; name; name = name->next){ ++propertyCount; - _stateStack.pushProperty(name->name->asString(), + _stateStack.pushProperty(name->name, location(name)); } Property* prop = currentProperty(); - if (prop->values.count()) { + if (!prop->values.isEmpty()) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Property value set multiple times")); error.setLine(this->location(propertyName).start.line); @@ -777,26 +1223,26 @@ bool ProcessAST::visit(AST::UiArrayBinding *node) bool ProcessAST::visit(AST::UiSourceElement *node) { - QDeclarativeParser::Object *obj = currentObject(); + QDeclarativeScript::Object *obj = currentObject(); if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) { - Object::DynamicSlot slot; - slot.location = location(funDecl->firstSourceLocation(), funDecl->lastSourceLocation()); + Object::DynamicSlot *slot = _parser->_pool.New<Object::DynamicSlot>(); + slot->location = location(funDecl->firstSourceLocation(), funDecl->lastSourceLocation()); AST::FormalParameterList *f = funDecl->formals; while (f) { - slot.parameterNames << f->name->asString().toUtf8(); - f = f->finish(); + slot->parameterNames << f->name.toUtf8(); + f = f->next; } AST::SourceLocation loc = funDecl->rparenToken; loc.offset = loc.end(); loc.startColumn += 1; QString body = textAt(loc, funDecl->rbraceToken); - slot.name = funDecl->name->asString().toUtf8(); - slot.body = body; - obj->dynamicSlots << slot; + slot->name = funDecl->name; + slot->body = body; + obj->dynamicSlots.append(slot); } else { QDeclarativeError error; @@ -811,28 +1257,30 @@ bool ProcessAST::visit(AST::UiSourceElement *node) } // end of anonymous namespace -QDeclarativeScriptParser::QDeclarativeScriptParser() +QDeclarativeScript::Parser::Parser() : root(0), data(0) { } -QDeclarativeScriptParser::~QDeclarativeScriptParser() +QDeclarativeScript::Parser::~Parser() { clear(); } -class QDeclarativeScriptParserJsASTData +namespace QDeclarativeScript { +class ParserJsASTData { public: - QDeclarativeScriptParserJsASTData(const QString &filename) - : nodePool(filename, &engine) {} + ParserJsASTData(const QString &filename) + : filename(filename) {} + QString filename; Engine engine; - NodePool nodePool; }; +} -bool QDeclarativeScriptParser::parse(const QByteArray &qmldata, const QUrl &url) +bool QDeclarativeScript::Parser::parse(const QByteArray &qmldata, const QUrl &url) { clear(); @@ -843,14 +1291,14 @@ bool QDeclarativeScriptParser::parse(const QByteArray &qmldata, const QUrl &url) #ifndef QT_NO_TEXTCODEC stream.setCodec("UTF-8"); #endif - const QString code = stream.readAll(); + QString *code = _pool.NewString(stream.readAll()); - data = new QDeclarativeScriptParserJsASTData(fileName); + data = new QDeclarativeScript::ParserJsASTData(fileName); Lexer lexer(&data->engine); - lexer.setCode(code, /*line = */ 1); + lexer.setCode(*code, /*line = */ 1); - Parser parser(&data->engine); + QDeclarativeJS::Parser parser(&data->engine); if (! parser.parse() || !_errors.isEmpty()) { @@ -872,7 +1320,7 @@ bool QDeclarativeScriptParser::parse(const QByteArray &qmldata, const QUrl &url) if (_errors.isEmpty()) { ProcessAST process(this); - process(code, parser.ast()); + process(*code, parser.ast()); // Set the url for process errors for(int ii = 0; ii < _errors.count(); ++ii) @@ -882,22 +1330,22 @@ bool QDeclarativeScriptParser::parse(const QByteArray &qmldata, const QUrl &url) return _errors.isEmpty(); } -QList<QDeclarativeScriptParser::TypeReference*> QDeclarativeScriptParser::referencedTypes() const +QList<QDeclarativeScript::TypeReference*> QDeclarativeScript::Parser::referencedTypes() const { return _refTypes; } -QDeclarativeParser::Object *QDeclarativeScriptParser::tree() const +QDeclarativeScript::Object *QDeclarativeScript::Parser::tree() const { return root; } -QList<QDeclarativeScriptParser::Import> QDeclarativeScriptParser::imports() const +QList<QDeclarativeScript::Import> QDeclarativeScript::Parser::imports() const { return _imports; } -QList<QDeclarativeError> QDeclarativeScriptParser::errors() const +QList<QDeclarativeError> QDeclarativeScript::Parser::errors() const { return _errors; } @@ -910,13 +1358,13 @@ static void replaceWithSpace(QString &str, int idx, int n) *data++ = space; } -static QDeclarativeParser::LocationSpan +static QDeclarativeScript::LocationSpan locationFromLexer(const QDeclarativeJS::Lexer &lex, int startLine, int startColumn, int startOffset) { - QDeclarativeParser::LocationSpan l; + QDeclarativeScript::LocationSpan l; l.start.line = startLine; l.start.column = startColumn; - l.end.line = lex.endLineNo(); l.end.column = lex.endColumnNo(); + l.end.line = lex.tokenEndLine(); l.end.column = lex.tokenEndColumn(); l.range.offset = startOffset; l.range.length = lex.tokenOffset() + lex.tokenLength() - startOffset; @@ -928,9 +1376,9 @@ Searches for ".pragma <value>" declarations within \a script. Currently support are: library */ -QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptParser::extractPragmas(QString &script) +QDeclarativeScript::Object::ScriptBlock::Pragmas QDeclarativeScript::Parser::extractPragmas(QString &script) { - QDeclarativeParser::Object::ScriptBlock::Pragmas rv = QDeclarativeParser::Object::ScriptBlock::None; + QDeclarativeScript::Object::ScriptBlock::Pragmas rv = QDeclarativeScript::Object::ScriptBlock::None; const QString pragma(QLatin1String("pragma")); const QString library(QLatin1String("library")); @@ -945,30 +1393,30 @@ QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptParser::extra return rv; int startOffset = l.tokenOffset(); - int startLine = l.currentLineNo(); + int startLine = l.tokenStartLine(); token = l.lex(); if (token != QDeclarativeJSGrammar::T_IDENTIFIER || - l.currentLineNo() != startLine || + l.tokenStartLine() != startLine || script.mid(l.tokenOffset(), l.tokenLength()) != pragma) return rv; token = l.lex(); if (token != QDeclarativeJSGrammar::T_IDENTIFIER || - l.currentLineNo() != startLine) + l.tokenStartLine() != startLine) return rv; QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); int endOffset = l.tokenLength() + l.tokenOffset(); token = l.lex(); - if (l.currentLineNo() == startLine) + if (l.tokenStartLine() == startLine) return rv; if (pragmaValue == library) { - rv |= QDeclarativeParser::Object::ScriptBlock::Shared; + rv |= QDeclarativeScript::Object::ScriptBlock::Shared; replaceWithSpace(script, startOffset, endOffset - startOffset); } else { return rv; @@ -977,7 +1425,7 @@ QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptParser::extra return rv; } -#define CHECK_LINE if(l.currentLineNo() != startLine) return rv; +#define CHECK_LINE if (l.tokenStartLine() != startLine) return rv; #define CHECK_TOKEN(t) if (token != QDeclarativeJSGrammar:: t) return rv; static const int uriTokens[] = { @@ -1031,11 +1479,11 @@ static inline bool isUriToken(int token) return false; } -QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMetaData(QString &script) +QDeclarativeScript::Parser::JavaScriptMetaData QDeclarativeScript::Parser::extractMetaData(QString &script) { JavaScriptMetaData rv; - QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = rv.pragmas; + QDeclarativeScript::Object::ScriptBlock::Pragmas &pragmas = rv.pragmas; const QString pragma(QLatin1String("pragma")); const QString js(QLatin1String(".js")); @@ -1051,8 +1499,8 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe return rv; int startOffset = l.tokenOffset(); - int startLine = l.startLineNo(); - int startColumn = l.startColumnNo(); + int startLine = l.tokenStartLine(); + int startColumn = l.tokenStartColumn(); token = l.lex(); @@ -1069,7 +1517,8 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe if (token == QDeclarativeJSGrammar::T_STRING_LITERAL) { - QString file(l.characterBuffer(), l.characterCount()); + QString file = l.tokenText(); + if (!file.endsWith(js)) return rv; @@ -1090,11 +1539,11 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe if (!importId.at(0).isUpper()) return rv; - QDeclarativeParser::LocationSpan location = + QDeclarativeScript::LocationSpan location = locationFromLexer(l, startLine, startColumn, startOffset); token = l.lex(); - if (l.startLineNo() == startLine) + if (l.tokenStartLine() == startLine) return rv; replaceWithSpace(script, startOffset, endOffset - startOffset); @@ -1115,7 +1564,7 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe if (!isUriToken(token)) return rv; - uri.append(QString(l.characterBuffer(), l.characterCount())); + uri.append(l.tokenText()); token = l.lex(); CHECK_LINE; @@ -1148,11 +1597,11 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe if (!importId.at(0).isUpper()) return rv; - QDeclarativeParser::LocationSpan location = + QDeclarativeScript::LocationSpan location = locationFromLexer(l, startLine, startColumn, startOffset); token = l.lex(); - if (l.startLineNo() == startLine) + if (l.tokenStartLine() == startLine) return rv; replaceWithSpace(script, startOffset, endOffset - startOffset); @@ -1179,14 +1628,14 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe int endOffset = l.tokenLength() + l.tokenOffset(); if (pragmaValue == library) { - pragmas |= QDeclarativeParser::Object::ScriptBlock::Shared; + pragmas |= QDeclarativeScript::Object::ScriptBlock::Shared; replaceWithSpace(script, startOffset, endOffset - startOffset); } else { return rv; } token = l.lex(); - if (l.currentLineNo() == startLine) + if (l.tokenStartLine() == startLine) return rv; } else { @@ -1196,12 +1645,8 @@ QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMe return rv; } -void QDeclarativeScriptParser::clear() +void QDeclarativeScript::Parser::clear() { - if (root) { - root->release(); - root = 0; - } _imports.clear(); qDeleteAll(_refTypes); _refTypes.clear(); @@ -1211,9 +1656,11 @@ void QDeclarativeScriptParser::clear() delete data; data = 0; } + + _pool.clear(); } -QDeclarativeScriptParser::TypeReference *QDeclarativeScriptParser::findOrCreateType(const QString &name) +QDeclarativeScript::TypeReference *QDeclarativeScript::Parser::findOrCreateType(const QString &name) { TypeReference *type = 0; int i = 0; @@ -1231,7 +1678,7 @@ QDeclarativeScriptParser::TypeReference *QDeclarativeScriptParser::findOrCreateT return type; } -void QDeclarativeScriptParser::setTree(QDeclarativeParser::Object *tree) +void QDeclarativeScript::Parser::setTree(QDeclarativeScript::Object *tree) { Q_ASSERT(! root); diff --git a/src/declarative/qml/qdeclarativescript_p.h b/src/declarative/qml/qdeclarativescript_p.h new file mode 100644 index 0000000000..3aff31789a --- /dev/null +++ b/src/declarative/qml/qdeclarativescript_p.h @@ -0,0 +1,526 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QDECLARATIVESCRIPT_P_H +#define QDECLARATIVESCRIPT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtDeclarative/qdeclarativeerror.h> + +#include <private/qfieldlist_p.h> +#include <private/qhashfield_p.h> +#include <private/qfastmetabuilder_p.h> +#include <private/qdeclarativepool_p.h> +#include <private/qdeclarativepropertycache_p.h> + +#include <QtCore/QList> +#include <QtCore/QUrl> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QByteArray; +class QDeclarativePropertyCache; +namespace QDeclarativeJS { namespace AST { class Node; class StringLiteral; } } +namespace QDeclarativeCompilerTypes { class BindingReference; class ComponentCompileState; } + +namespace QDeclarativeScript { + +struct Location +{ + Location() : line(-1), column(-1) {} + int line; + int column; + + inline bool operator<(const Location &other) { + return line < other.line || + (line == other.line && column < other.column); + } +}; + +struct LocationRange +{ + LocationRange() : offset(0), length(0) {} + quint32 offset; + quint32 length; +}; + +struct LocationSpan +{ + Location start; + Location end; + LocationRange range; + + bool operator<(LocationSpan &o) const { + return (start.line < o.start.line) || + (start.line == o.start.line && start.column < o.start.column); + } +}; + +class Import +{ +public: + Import() : type(Library) {} + + enum Type { Library, File, Script }; + Type type; + + QString uri; + QString qualifier; + QString version; + + void extractVersion(int *maj, int *min) const; + + QDeclarativeScript::LocationSpan location; +}; + +class Object; +class TypeReference +{ +public: + TypeReference(int typeId, const QString &typeName) : id(typeId), name(typeName) {} + + int id; + // type as it has been referenced in Qml + QString name; + // objects in parse tree referencing the type + QList<QDeclarativeScript::Object*> refObjects; +}; + +class Object; +class Property; + +class Q_DECLARATIVE_EXPORT Variant +{ +public: + enum Type { + Invalid, + Boolean, + Number, + String, + Script + }; + + Variant(); + Variant(const Variant &); + explicit Variant(bool); + explicit Variant(double, const QStringRef &asWritten = QStringRef()); + explicit Variant(QDeclarativeJS::AST::StringLiteral *); + explicit Variant(const QStringRef &asWritten, QDeclarativeJS::AST::Node *); + Variant &operator=(const Variant &); + + Type type() const; + + bool isBoolean() const { return type() == Boolean; } + bool isNumber() const { return type() == Number; } + bool isString() const { return type() == String; } + bool isScript() const { return type() == Script; } + bool isStringList() const; + + bool asBoolean() const; + QString asString() const; + double asNumber() const; + QString asScript() const; + QDeclarativeJS::AST::Node *asAST() const; + QStringList asStringList() const; + +private: + Type t; + union { + bool b; + double d; + QDeclarativeJS::AST::StringLiteral *l; + QDeclarativeJS::AST::Node *n; + }; + QStringRef asWritten; +}; + +class Value : public QDeclarativePool::POD +{ +public: + Value(); + + enum Type { + // The type of this value assignment is not yet known + Unknown, + // This is used as a literal property assignment + Literal, + // This is used as a property binding assignment + PropertyBinding, + // This is used as a QDeclarativePropertyValueSource assignment + ValueSource, + // This is used as a QDeclarativePropertyValueInterceptor assignment + ValueInterceptor, + // This is used as a property QObject assignment + CreatedObject, + // This is used as a signal object assignment + SignalObject, + // This is used as a signal expression assignment + SignalExpression, + // This is used as an id assignment only + Id + }; + Type type; + + // ### Temporary (for id only) + QString primitive() const { return value.isString() ? value.asString() : value.asScript(); } + + // Primitive value + Variant value; + // Object value + Object *object; + + LocationSpan location; + + // Used by compiler + QDeclarativeCompilerTypes::BindingReference *bindingReference; + int signalExpressionContextStack; + + // Used in Property::ValueList lists + Value *nextValue; +}; + +class Property : public QDeclarativePool::POD +{ +public: + Property(); + + // The Object to which this property is attached + Object *parent; + + Object *getValue(const LocationSpan &); + void addValue(Value *v); + void addOnValue(Value *v); + + // The QVariant::Type of the property, or 0 (QVariant::Invalid) if + // unknown. + int type; + // The metaobject index of this property, or -1 if unknown. + int index; + // The core data in the case of a regular property. + // XXX This has to be a value now as the synthCache may change during + // compilation which invalidates pointers. We should fix this. + QDeclarativePropertyCache::Data core; + + // Returns true if this is an empty property - both value and values + // are unset. + bool isEmpty() const; + + typedef QFieldList<Value, &Value::nextValue> ValueList; + // The list of values assigned to this property. Content in values + // and value are mutually exclusive + ValueList values; + // The list of values assigned to this property using the "on" syntax + ValueList onValues; + // The accessed property. This is used to represent dot properties. + // Content in value and values are mutually exclusive. + Object *value; + // The property name + const QHashedStringRef &name() const { return _name; } + void setName(const QString &n) { _name = QHashedStringRef(pool()->NewString(n)); } + void setName(const QHashedStringRef &n) { _name = n; } + // True if this property was accessed as the default property. + bool isDefault; + // True if the setting of this property will be deferred. Set by the + // QDeclarativeCompiler + bool isDeferred; + // True if this property is a value-type pseudo-property + bool isValueTypeSubProperty; + // True if this property is a property alias. Set by the + // QDeclarativeCompiler + bool isAlias; + + // Used for scriptStringProperties + int scriptStringScope; + + LocationSpan location; + LocationRange listValueRange; + + // Used in Object::MainPropertyList + Property *nextMainProperty; + + // Used in Object::PropertyList lists + Property *nextProperty; + +private: + friend class Object; + QHashedStringRef _name; +}; + +class Object : public QDeclarativePool::Class +{ +public: + Object(); + virtual ~Object(); + + // Type of the object. The integer is an index into the + // QDeclarativeCompiledData::types array, or -1 if the object is a property + // group. + int type; + + // The fully-qualified name of this type + QByteArray typeName; + // The id assigned to the object (if any). Set by the QDeclarativeCompiler + QString id; + // The id index assigned to the object (if any). Set by the QDeclarativeCompiler + int idIndex; + // Custom parsed data + QByteArray custom; + // Bit mask of the properties assigned bindings + QByteArray bindingBitmask; + void setBindingBit(int); + // Returns the metaobject for this type, or 0 if not available. + // Internally selectd between the metatype and extObject variables + const QMetaObject *metaObject() const; + + // The compile time metaobject for this type + const QMetaObject *metatype; + // The synthesized metaobject, if QML added signals or properties to + // this type. Otherwise null + QAbstractDynamicMetaObject extObject; + QByteArray metadata; // Generated by compiler + QByteArray synthdata; // Generated by compiler + QDeclarativePropertyCache *synthCache; // Generated by compiler + + Property *getDefaultProperty(); + // name ptr must be guarenteed to remain valid + Property *getProperty(const QHashedStringRef &name, bool create=true); + Property *getProperty(const QStringRef &name, bool create=true); + Property *getProperty(const QString &name, bool create=true); + + Property *defaultProperty; + + typedef QFieldList<Property, &Property::nextMainProperty> MainPropertyList; + MainPropertyList properties; + QHashField propertiesHashField; + + // Output of the compilation phase (these properties continue to exist + // in either the defaultProperty or properties members too) + void addValueProperty(Property *); + void addSignalProperty(Property *); + void addAttachedProperty(Property *); + void addGroupedProperty(Property *); + void addValueTypeProperty(Property *); + void addScriptStringProperty(Property *); + + typedef QFieldList<Property, &Property::nextProperty> PropertyList; + PropertyList valueProperties; + PropertyList signalProperties; + PropertyList attachedProperties; + PropertyList groupedProperties; + PropertyList valueTypeProperties; + PropertyList scriptStringProperties; + + // Script blocks that were nested under this object + struct ScriptBlock { + enum Pragma { + None = 0x00000000, + Shared = 0x00000001 + }; + Q_DECLARE_FLAGS(Pragmas, Pragma) + + QString code; + QString file; + Pragmas pragmas; + }; + + // The bytes to cast instances by to get to the QDeclarativeParserStatus + // interface. -1 indicates the type doesn't support this interface. + // Set by the QDeclarativeCompiler. + int parserStatusCast; + + LocationSpan location; + + struct DynamicProperty : public QDeclarativePool::POD + { + DynamicProperty(); + + enum Type { Variant, Int, Bool, Real, String, Url, Color, Time, + Date, DateTime, Alias, Custom, CustomList }; + + bool isDefaultProperty; + Type type; + + QHashedStringRef customType; + QHashedStringRef name; + QDeclarativeScript::Property *defaultValue; + LocationSpan location; + + // Used by Object::DynamicPropertyList + DynamicProperty *nextProperty; + + // Used by the compiler + QByteArray *resolvedCustomTypeName; + QFastMetaBuilder::StringRef typeRef; + QFastMetaBuilder::StringRef nameRef; + QFastMetaBuilder::StringRef changedSignatureRef; + }; + + struct DynamicSignal : public QDeclarativePool::POD + { + DynamicSignal(); + + QHashedStringRef name; + QDeclarativePool::List<QHashedCStringRef> parameterTypes; + QDeclarativePool::List<QHashedStringRef> parameterNames; + + int parameterTypesLength() const; + int parameterNamesLength() const; + + // Used by Object::DynamicSignalList + DynamicSignal *nextSignal; + + // Used by the compiler + QFastMetaBuilder::StringRef signatureRef; + QFastMetaBuilder::StringRef parameterNamesRef; + LocationSpan location; + }; + + struct DynamicSlot : public QDeclarativePool::Class + { + DynamicSlot(); + + QHashedStringRef name; + QString body; + QList<QByteArray> parameterNames; + LocationSpan location; + + int parameterNamesLength() const; + + // Used by Object::DynamicSlotList + DynamicSlot *nextSlot; + + // Used by the compiler + QFastMetaBuilder::StringRef signatureRef; + QFastMetaBuilder::StringRef parameterNamesRef; + }; + + // The list of dynamic properties + typedef QFieldList<DynamicProperty, &DynamicProperty::nextProperty> DynamicPropertyList; + DynamicPropertyList dynamicProperties; + // The list of dynamic signals + typedef QFieldList<DynamicSignal, &DynamicSignal::nextSignal> DynamicSignalList; + DynamicSignalList dynamicSignals; + // The list of dynamic slots + typedef QFieldList<DynamicSlot, &DynamicSlot::nextSlot> DynamicSlotList; + DynamicSlotList dynamicSlots; + + // Used by compiler + QDeclarativeCompilerTypes::ComponentCompileState *componentCompileState; + + // Used by ComponentCompileState::AliasingObjectsList + Object *nextAliasingObject; + // Used by ComponentComppileState::IdList + Object *nextIdObject; +}; + +class ParserJsASTData; +class Q_AUTOTEST_EXPORT Parser +{ +public: + Parser(); + ~Parser(); + + bool parse(const QByteArray &data, const QUrl &url = QUrl()); + + QList<TypeReference*> referencedTypes() const; + + QDeclarativeScript::Object *tree() const; + QList<Import> imports() const; + + void clear(); + + QList<QDeclarativeError> errors() const; + + class JavaScriptMetaData { + public: + JavaScriptMetaData() + : pragmas(QDeclarativeScript::Object::ScriptBlock::None) {} + + QDeclarativeScript::Object::ScriptBlock::Pragmas pragmas; + QList<Import> imports; + }; + + static QDeclarativeScript::Object::ScriptBlock::Pragmas extractPragmas(QString &); + static JavaScriptMetaData extractMetaData(QString &); + + +// ### private: + TypeReference *findOrCreateType(const QString &name); + void setTree(QDeclarativeScript::Object *tree); + + void setScriptFile(const QString &filename) {_scriptFile = filename; } + QString scriptFile() const { return _scriptFile; } + +// ### private: + QList<QDeclarativeError> _errors; + + QDeclarativePool _pool; + QDeclarativeScript::Object *root; + QList<Import> _imports; + QList<TypeReference*> _refTypes; + QString _scriptFile; + ParserJsASTData *data; +}; + +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeScript::Object::ScriptBlock::Pragmas); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QDeclarativeScript::Variant) + +QT_END_HEADER + +#endif // QDECLARATIVESCRIPT_P_H diff --git a/src/declarative/qml/qdeclarativescriptparser_p.h b/src/declarative/qml/qdeclarativescriptparser_p.h deleted file mode 100644 index 73e797635a..0000000000 --- a/src/declarative/qml/qdeclarativescriptparser_p.h +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QDECLARATIVESCRIPTPARSER_P_H -#define QDECLARATIVESCRIPTPARSER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qdeclarativeerror.h" -#include "private/qdeclarativeparser_p.h" - -#include <QtCore/QList> -#include <QtCore/QUrl> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QByteArray; - -class QDeclarativeScriptParserJsASTData; -class Q_AUTOTEST_EXPORT QDeclarativeScriptParser -{ -public: - class Import - { - public: - Import() : type(Library) {} - - enum Type { Library, File, Script }; - Type type; - - QString uri; - QString qualifier; - QString version; - - void extractVersion(int *maj, int *min) const; - - QDeclarativeParser::LocationSpan location; - }; - - class TypeReference - { - public: - TypeReference(int typeId, const QString &typeName) : id(typeId), name(typeName) {} - - int id; - // type as it has been referenced in Qml - QString name; - // objects in parse tree referencing the type - QList<QDeclarativeParser::Object*> refObjects; - }; - - QDeclarativeScriptParser(); - ~QDeclarativeScriptParser(); - - bool parse(const QByteArray &data, const QUrl &url = QUrl()); - - QList<TypeReference*> referencedTypes() const; - - QDeclarativeParser::Object *tree() const; - QList<Import> imports() const; - - void clear(); - - QList<QDeclarativeError> errors() const; - - class JavaScriptMetaData { - public: - JavaScriptMetaData() - : pragmas(QDeclarativeParser::Object::ScriptBlock::None) {} - - QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas; - QList<Import> imports; - }; - - static QDeclarativeParser::Object::ScriptBlock::Pragmas extractPragmas(QString &); - static JavaScriptMetaData extractMetaData(QString &); - - -// ### private: - TypeReference *findOrCreateType(const QString &name); - void setTree(QDeclarativeParser::Object *tree); - - void setScriptFile(const QString &filename) {_scriptFile = filename; } - QString scriptFile() const { return _scriptFile; } - -// ### private: - QList<QDeclarativeError> _errors; - - QDeclarativeParser::Object *root; - QList<Import> _imports; - QList<TypeReference*> _refTypes; - QString _scriptFile; - QDeclarativeScriptParserJsASTData *data; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QDECLARATIVESCRIPTPARSER_P_H diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index 97c5b38c20..8bb40ce7a5 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -51,9 +51,94 @@ #include <QtCore/qdebug.h> #include <QtCore/qdir.h> #include <QtCore/qfile.h> +#include <QtCore/qdiriterator.h> + +#if defined (Q_OS_UNIX) +#include <sys/types.h> +#include <dirent.h> +#endif QT_BEGIN_NAMESPACE + +/* +Returns the set of QML files in path (qmldir, *.qml, *.js). The caller +is responsible for deleting the returned data. +Returns 0 if the directory does not exist. +*/ +#if defined (Q_OS_UNIX) && !defined(Q_OS_DARWIN) +static QStringHash<bool> *qmlFilesInDirectory(const QString &path) +{ + QByteArray name(QFile::encodeName(path)); + DIR *dd = opendir(name); + if (!dd) + return 0; + + struct dirent *result; + union { + struct dirent d; + char b[offsetof (struct dirent, d_name) + NAME_MAX + 1]; + } u; + + QStringHash<bool> *files = new QStringHash<bool>; + while (readdir_r(dd, &u.d, &result) == 0 && result != 0) { + if (!strcmp(u.d.d_name, "qmldir")) { + files->insert(QLatin1String("qmldir"), true); + continue; + } + int len = strlen(u.d.d_name); + if (len < 4) + continue; + if (!strcmp(u.d.d_name+len-4, ".qml") || !strcmp(u.d.d_name+len-3, ".js")) + files->insert(QFile::decodeName(u.d.d_name), true); +#if defined(Q_OS_DARWIN) + else if ((len > 6 && !strcmp(u.d.d_name+len-6, ".dylib")) || !strcmp(u.d.d_name+len-3, ".so") + || (len > 7 && !strcmp(u.d.d_name+len-7, ".bundle"))) + files->insert(QFile::decodeName(u.d.d_name), true); +#else // Unix + else if (!strcmp(u.d.d_name+len-3, ".so") || !strcmp(u.d.d_name+len-3, ".sl")) + files->insert(QFile::decodeName(u.d.d_name), true); +#endif + } + + closedir(dd); + return files; +} +#else +static QStringHash<bool> *qmlFilesInDirectory(const QString &path) +{ + QDirIterator dir(path, QDir::Files); + if (!dir.hasNext()) + return 0; + QStringHash<bool> *files = new QStringHash<bool>; + while (dir.hasNext()) { + dir.next(); + QString fileName = dir.fileName(); + if (fileName == QLatin1String("qmldir") + || fileName.endsWith(QLatin1String(".qml")) + || fileName.endsWith(QLatin1String(".js")) +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) + || fileName.endsWith(QLatin1String(".dll")) +#elif defined(Q_OS_DARWIN) + || fileName.endsWith(QLatin1String(".dylib")) + || fileName.endsWith(QLatin1String(".so")) + || fileName.endsWith(QLatin1String(".bundle")) +#else // Unix + || fileName.endsWith(QLatin1String(".so")) + || fileName.endsWith(QLatin1String(".sl")) +#endif + ) { +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + fileName = fileName.toLower(); +#endif + files->insert(fileName, true); + } + } + return files; +} +#endif + + /*! \class QDeclarativeDataBlob \brief The QDeclarativeDataBlob encapsulates a data request that can be issued to a QDeclarativeDataLoader. @@ -723,6 +808,113 @@ QDeclarativeQmldirData *QDeclarativeTypeLoader::getQmldir(const QUrl &url) } /*! +Returns the absolute filename of path via a directory cache for files named +"qmldir", "*.qml", "*.js", and plugins. +Returns a empty string if the path does not exist. +*/ +QString QDeclarativeTypeLoader::absoluteFilePath(const QString &path) +{ + if (path.isEmpty()) + return QString(); + if (path.at(0) == QLatin1Char(':')) { + // qrc resource + QFileInfo fileInfo(path); + return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString(); + } +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QString lowPath = path.toLower(); + int lastSlash = lowPath.lastIndexOf(QLatin1Char('/')); + QString dirPath = lowPath.left(lastSlash); +#else + int lastSlash = path.lastIndexOf(QLatin1Char('/')); + QStringRef dirPath(&path, 0, lastSlash); +#endif + + StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length())); + if (!fileSet) { +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QHashedString dirPathString(dirPath); +#else + QHashedString dirPathString(dirPath.toString()); +#endif + StringSet *files = qmlFilesInDirectory(dirPathString); + m_importDirCache.insert(dirPathString, files); + fileSet = m_importDirCache.value(dirPathString); + } + if (!(*fileSet)) + return QString(); + +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QString absoluteFilePath = (*fileSet)->contains(QHashedStringRef(lowPath.constData()+lastSlash+1, lowPath.length()-lastSlash-1)) ? path : QString(); +#else + QString absoluteFilePath = (*fileSet)->contains(QHashedStringRef(path.constData()+lastSlash+1, path.length()-lastSlash-1)) ? path : QString(); +#endif + if (absoluteFilePath.length() > 2 && absoluteFilePath.at(0) != QLatin1Char('/') && absoluteFilePath.at(1) != QLatin1Char(':')) + absoluteFilePath = QFileInfo(absoluteFilePath).absoluteFilePath(); + + return absoluteFilePath; +} + +/*! +Returns true if the path is a directory via a directory cache. Cache is +shared with absoluteFilePath(). +*/ +bool QDeclarativeTypeLoader::directoryExists(const QString &path) +{ + if (path.isEmpty()) + return false; + if (path.at(0) == QLatin1Char(':')) { + // qrc resource + QFileInfo fileInfo(path); + return fileInfo.exists() && fileInfo.isDir(); + } + + int length = path.length(); + if (path.endsWith(QLatin1Char('/'))) + --length; +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QString dirPath = path.left(length).toLower(); +#else + QStringRef dirPath(&path, 0, length); +#endif + + StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length())); + if (!fileSet) { +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN) + QHashedString dirPathString(dirPath); +#else + QHashedString dirPathString(dirPath.toString()); +#endif + StringSet *files = qmlFilesInDirectory(dirPathString); + m_importDirCache.insert(dirPathString, files); + fileSet = m_importDirCache.value(dirPathString); + } + + return (*fileSet); +} + + +/*! +Return a QDeclarativeDirParser for absoluteFilePath. The QDeclarativeDirParser may be cached. +*/ +const QDeclarativeDirParser *QDeclarativeTypeLoader::qmlDirParser(const QString &absoluteFilePath) +{ + QDeclarativeDirParser *qmldirParser; + QDeclarativeDirParser **val = m_importQmlDirCache.value(absoluteFilePath); + if (!val) { + qmldirParser = new QDeclarativeDirParser; + qmldirParser->setFileSource(absoluteFilePath); + qmldirParser->setUrl(QUrl::fromLocalFile(absoluteFilePath)); + qmldirParser->parse(); + m_importQmlDirCache.insert(absoluteFilePath, qmldirParser); + } else { + qmldirParser = *val; + } + + return qmldirParser; +} + +/*! Clears cached information about loaded files, including any type data, scripts and qmldir information. */ @@ -734,17 +926,21 @@ void QDeclarativeTypeLoader::clearCache() (*iter)->release(); for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter) (*iter)->release(); + qDeleteAll(m_importDirCache); + qDeleteAll(m_importQmlDirCache); m_typeCache.clear(); m_scriptCache.clear(); m_qmldirCache.clear(); + m_importDirCache.clear(); + m_importQmlDirCache.clear(); } QDeclarativeTypeData::QDeclarativeTypeData(const QUrl &url, QDeclarativeTypeLoader::Options options, QDeclarativeTypeLoader *manager) -: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_typesResolved(false), - m_compiledData(0), m_typeLoader(manager) +: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_imports(manager), m_typesResolved(false), + m_compiledData(0), m_typeLoader(manager) { } @@ -770,7 +966,7 @@ const QDeclarativeImports &QDeclarativeTypeData::imports() const return m_imports; } -const QDeclarativeScriptParser &QDeclarativeTypeData::parser() const +const QDeclarativeScript::Parser &QDeclarativeTypeData::parser() const { return scriptParser; } @@ -869,15 +1065,15 @@ void QDeclarativeTypeData::dataReceived(const QByteArray &data) m_imports.setBaseUrl(finalUrl()); - foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) { - if (import.type == QDeclarativeScriptParser::Import::File && import.qualifier.isEmpty()) { + foreach (const QDeclarativeScript::Import &import, scriptParser.imports()) { + if (import.type == QDeclarativeScript::Import::File && import.qualifier.isEmpty()) { QUrl importUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { QDeclarativeQmldirData *data = typeLoader()->getQmldir(importUrl); addDependency(data); m_qmldirs << data; } - } else if (import.type == QDeclarativeScriptParser::Import::Script) { + } else if (import.type == QDeclarativeScript::Import::Script) { QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); QDeclarativeScriptBlob *blob = typeLoader()->getScript(scriptUrl); addDependency(blob); @@ -928,7 +1124,7 @@ void QDeclarativeTypeData::compile() m_compiledData->name = m_compiledData->url.toString(); QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Compiling, m_compiledData->name); - QDeclarativeCompiler compiler; + QDeclarativeCompiler compiler(&scriptParser._pool); if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) { setError(compiler.errors()); m_compiledData->release(); @@ -948,11 +1144,11 @@ void QDeclarativeTypeData::resolveTypes() QList<QDeclarativeError> errors; if (QDeclarativeQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) { m_imports.addImport(importDatabase, QLatin1String("."), - QString(), -1, -1, QDeclarativeScriptParser::Import::File, + QString(), -1, -1, QDeclarativeScript::Import::File, qmldir->dirComponents(), &errors); } else { m_imports.addImport(importDatabase, QLatin1String("."), - QString(), -1, -1, QDeclarativeScriptParser::Import::File, + QString(), -1, -1, QDeclarativeScript::Import::File, QDeclarativeDirComponents(), &errors); } @@ -972,12 +1168,12 @@ void QDeclarativeTypeData::resolveTypes() return; } - foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) { + foreach (const QDeclarativeScript::Import &import, scriptParser.imports()) { QDeclarativeDirComponents qmldircomponentsnetwork; - if (import.type == QDeclarativeScriptParser::Import::Script) + if (import.type == QDeclarativeScript::Import::Script) continue; - if (import.type == QDeclarativeScriptParser::Import::File && import.qualifier.isEmpty()) { + if (import.type == QDeclarativeScript::Import::File && import.qualifier.isEmpty()) { QUrl qmldirUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); if (QDeclarativeQmldirData *qmldir = qmldirForUrl(qmldirUrl)) qmldircomponentsnetwork = qmldir->dirComponents(); @@ -1008,18 +1204,16 @@ void QDeclarativeTypeData::resolveTypes() } } - foreach (QDeclarativeScriptParser::TypeReference *parserRef, scriptParser.referencedTypes()) { - QByteArray typeName = parserRef->name.toUtf8(); - + foreach (QDeclarativeScript::TypeReference *parserRef, scriptParser.referencedTypes()) { TypeReference ref; - QUrl url; + QString url; int majorVersion; int minorVersion; QDeclarativeImportedNamespace *typeNamespace = 0; QList<QDeclarativeError> errors; - if (!m_imports.resolveType(typeName, &ref.type, &url, &majorVersion, &minorVersion, + if (!m_imports.resolveType(parserRef->name, &ref.type, &url, &majorVersion, &minorVersion, &typeNamespace, &errors) || typeNamespace) { // Known to not be a type: // - known to be a namespace (Namespace {}) @@ -1042,7 +1236,7 @@ void QDeclarativeTypeData::resolveTypes() } if (!parserRef->refObjects.isEmpty()) { - QDeclarativeParser::Object *obj = parserRef->refObjects.first(); + QDeclarativeScript::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); error.setColumn(obj->location.start.column); } @@ -1056,7 +1250,7 @@ void QDeclarativeTypeData::resolveTypes() ref.majorVersion = majorVersion; ref.minorVersion = minorVersion; } else { - ref.typeData = typeLoader()->get(url); + ref.typeData = typeLoader()->get(QUrl(url)); addDependency(ref.typeData); } @@ -1077,7 +1271,7 @@ QDeclarativeQmldirData *QDeclarativeTypeData::qmldirForUrl(const QUrl &url) } QDeclarativeScriptData::QDeclarativeScriptData(QDeclarativeEngine *engine) -: QDeclarativeCleanup(engine), importCache(0), pragmas(QDeclarativeParser::Object::ScriptBlock::None), +: QDeclarativeCleanup(engine), importCache(0), pragmas(QDeclarativeScript::Object::ScriptBlock::None), m_loaded(false) { } @@ -1103,8 +1297,8 @@ void QDeclarativeScriptData::clear() } QDeclarativeScriptBlob::QDeclarativeScriptBlob(const QUrl &url, QDeclarativeTypeLoader *loader) -: QDeclarativeDataBlob(url, JavaScriptFile), m_pragmas(QDeclarativeParser::Object::ScriptBlock::None), - m_scriptData(0), m_typeLoader(loader) +: QDeclarativeDataBlob(url, JavaScriptFile), m_pragmas(QDeclarativeScript::Object::ScriptBlock::None), + m_imports(loader), m_scriptData(0), m_typeLoader(loader) { } @@ -1116,7 +1310,7 @@ QDeclarativeScriptBlob::~QDeclarativeScriptBlob() } } -QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptBlob::pragmas() const +QDeclarativeScript::Object::ScriptBlock::Pragmas QDeclarativeScriptBlob::pragmas() const { return m_pragmas; } @@ -1148,17 +1342,17 @@ void QDeclarativeScriptBlob::dataReceived(const QByteArray &data) m_source = QString::fromUtf8(data); - QDeclarativeScriptParser::JavaScriptMetaData metadata = - QDeclarativeScriptParser::extractMetaData(m_source); + QDeclarativeScript::Parser::JavaScriptMetaData metadata = + QDeclarativeScript::Parser::extractMetaData(m_source); m_imports.setBaseUrl(finalUrl()); m_pragmas = metadata.pragmas; - foreach (const QDeclarativeScriptParser::Import &import, metadata.imports) { - Q_ASSERT(import.type != QDeclarativeScriptParser::Import::File); + foreach (const QDeclarativeScript::Import &import, metadata.imports) { + Q_ASSERT(import.type != QDeclarativeScript::Import::File); - if (import.type == QDeclarativeScriptParser::Import::Script) { + if (import.type == QDeclarativeScript::Import::Script) { QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); QDeclarativeScriptBlob *blob = typeLoader()->getScript(scriptUrl); addDependency(blob); @@ -1170,7 +1364,7 @@ void QDeclarativeScriptBlob::dataReceived(const QByteArray &data) blob->addref(); m_scripts << ref; } else { - Q_ASSERT(import.type == QDeclarativeScriptParser::Import::Library); + Q_ASSERT(import.type == QDeclarativeScript::Import::Library); int vmaj = -1; int vmin = -1; import.extractVersion(&vmaj, &vmin); diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h index 1ca6f8c9c2..349a9f8428 100644 --- a/src/declarative/qml/qdeclarativetypeloader_p.h +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -59,9 +59,10 @@ #include <QtDeclarative/qdeclarativeerror.h> #include <QtDeclarative/qdeclarativeengine.h> #include <private/qdeclarativecleanup_p.h> -#include <private/qdeclarativescriptparser_p.h> +#include <private/qdeclarativescript_p.h> #include <private/qdeclarativedirparser_p.h> #include <private/qdeclarativeimport_p.h> +#include "private/qhashedstring_p.h" #include <private/qv8_p.h> @@ -202,14 +203,24 @@ public: QDeclarativeScriptBlob *getScript(const QUrl &); QDeclarativeQmldirData *getQmldir(const QUrl &); + + QString absoluteFilePath(const QString &path); + bool directoryExists(const QString &path); + const QDeclarativeDirParser *qmlDirParser(const QString &absoluteFilePath); + private: typedef QHash<QUrl, QDeclarativeTypeData *> TypeCache; typedef QHash<QUrl, QDeclarativeScriptBlob *> ScriptCache; typedef QHash<QUrl, QDeclarativeQmldirData *> QmldirCache; + typedef QStringHash<bool> StringSet; + typedef QStringHash<StringSet*> ImportDirCache; + typedef QStringHash<QDeclarativeDirParser*> ImportQmlDirCache; TypeCache m_typeCache; ScriptCache m_scriptCache; QmldirCache m_qmldirCache; + ImportDirCache m_importDirCache; + ImportQmlDirCache m_importQmlDirCache; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeTypeLoader::Options) @@ -221,7 +232,7 @@ public: { TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0) {} - QDeclarativeParser::Location location; + QDeclarativeScript::Location location; QDeclarativeType *type; int majorVersion; int minorVersion; @@ -232,7 +243,7 @@ public: { ScriptReference() : script(0) {} - QDeclarativeParser::Location location; + QDeclarativeScript::Location location; QString qualifier; QDeclarativeScriptBlob *script; }; @@ -243,7 +254,7 @@ public: QDeclarativeTypeLoader *typeLoader() const; const QDeclarativeImports &imports() const; - const QDeclarativeScriptParser &parser() const; + const QDeclarativeScript::Parser &parser() const; const QList<TypeReference> &resolvedTypes() const; const QList<ScriptReference> &resolvedScripts() const; @@ -273,7 +284,7 @@ private: QDeclarativeQmldirData *qmldirForUrl(const QUrl &); - QDeclarativeScriptParser scriptParser; + QDeclarativeScript::Parser scriptParser; QDeclarativeImports m_imports; QList<ScriptReference> m_scripts; @@ -298,7 +309,7 @@ public: QUrl url; QDeclarativeTypeNameCache *importCache; QList<QDeclarativeScriptBlob *> scripts; - QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas; + QDeclarativeScript::Object::ScriptBlock::Pragmas pragmas; protected: virtual void clear(); // From QDeclarativeCleanup @@ -324,12 +335,12 @@ public: { ScriptReference() : script(0) {} - QDeclarativeParser::Location location; + QDeclarativeScript::Location location; QString qualifier; QDeclarativeScriptBlob *script; }; - QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas() const; + QDeclarativeScript::Object::ScriptBlock::Pragmas pragmas() const; QString scriptSource() const; QDeclarativeTypeLoader *typeLoader() const; @@ -342,7 +353,7 @@ protected: virtual void done(); private: - QDeclarativeParser::Object::ScriptBlock::Pragmas m_pragmas; + QDeclarativeScript::Object::ScriptBlock::Pragmas m_pragmas; QString m_source; QDeclarativeImports m_imports; diff --git a/src/declarative/qml/qdeclarativetypenamecache.cpp b/src/declarative/qml/qdeclarativetypenamecache.cpp index 23183aa9fb..b7e4259b4c 100644 --- a/src/declarative/qml/qdeclarativetypenamecache.cpp +++ b/src/declarative/qml/qdeclarativetypenamecache.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE QDeclarativeTypeNameCache::QDeclarativeTypeNameCache(QDeclarativeEngine *e) -: QDeclarativeCleanup(e), engine(e), m_moduleApi(0) +: QDeclarativeCleanup(e), engine(e) { } @@ -57,52 +57,93 @@ QDeclarativeTypeNameCache::~QDeclarativeTypeNameCache() void QDeclarativeTypeNameCache::clear() { - stringCache.clear(); - m_moduleApi = 0; + m_namedImports.clear(); + m_anonymousImports.clear(); engine = 0; } -void QDeclarativeTypeNameCache::add(const QString &name, int importedScriptIndex) +void QDeclarativeTypeNameCache::add(const QHashedString &name, int importedScriptIndex) { - if (stringCache.contains(name)) + if (m_namedImports.contains(name)) return; - Data data; - data.importedScriptIndex = importedScriptIndex; - stringCache.insert(name, data); + Import import; + import.scriptIndex = importedScriptIndex; + m_namedImports.insert(name, import); } -void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type) +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name) { - if (stringCache.contains(name)) - return; - - Data data; - data.type = type; - stringCache.insert(name, data); + Import *i = m_namedImports.value(name); + if (i) { + if (i->scriptIndex != -1) + return Result(i->scriptIndex); + else + return Result((const void *)i); + } + + for (int ii = 0; ii < m_anonymousImports.count(); ++ii) { + if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name)) + return Result(type); + } + + return Result(); } -void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeTypeNameCache *typeNamespace) +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name, + const void *importNamespace) { - if (stringCache.contains(name)) - return; - - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + Q_ASSERT(importNamespace); + Import *i = (Import *)importNamespace; + Q_ASSERT(i->scriptIndex == -1); + + for (int ii = 0; ii < i->modules.count(); ++ii) { + if (QDeclarativeType *type = i->modules.at(ii).type(name)) + return Result(type); + } + + return Result(); +} - Data data; - typeNamespace->addref(); - data.typeNamespace = typeNamespace; - stringCache.insert(name, data); +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedV8String &name) +{ + Import *i = m_namedImports.value(name); + if (i) { + if (i->scriptIndex != -1) + return Result(i->scriptIndex); + else + return Result((const void *)i); + } + + for (int ii = 0; ii < m_anonymousImports.count(); ++ii) { + if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name)) + return Result(type); + } + + return Result(); } -QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QString &id) const +QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedV8String &name, const void *importNamespace) { - return stringCache.value(id); + Q_ASSERT(importNamespace); + Import *i = (Import *)importNamespace; + Q_ASSERT(i->scriptIndex == -1); + + for (int ii = 0; ii < i->modules.count(); ++ii) { + if (QDeclarativeType *type = i->modules.at(ii).type(name)) + return Result(type); + } + + return Result(); } -void QDeclarativeTypeNameCache::setModuleApi(QDeclarativeMetaType::ModuleApiInstance *api) +QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi(const void *importNamespace) { - m_moduleApi = api; + Q_ASSERT(importNamespace); + Import *i = (Import *)importNamespace; + Q_ASSERT(i->scriptIndex == -1); + + return i->moduleApi; } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h index e89747b15a..a80bb6492c 100644 --- a/src/declarative/qml/qdeclarativetypenamecache_p.h +++ b/src/declarative/qml/qdeclarativetypenamecache_p.h @@ -59,6 +59,8 @@ #include <private/qhashedstring_p.h> +#include <QtCore/qvector.h> + QT_BEGIN_NAMESPACE class QDeclarativeType; @@ -69,78 +71,89 @@ public: QDeclarativeTypeNameCache(QDeclarativeEngine *); virtual ~QDeclarativeTypeNameCache(); - struct Data { - inline Data(); - inline Data(const Data &); - inline ~Data(); - inline Data &operator=(const Data &); - QDeclarativeType *type; - QDeclarativeTypeNameCache *typeNamespace; - int importedScriptIndex; - }; + inline bool isEmpty() const; - void add(const QString &, int); - void add(const QString &, QDeclarativeType *); - void add(const QString &, QDeclarativeTypeNameCache *); + void add(const QHashedString &, int); - Data *data(const QString &) const; - inline Data *data(const QHashedV8String &) const; - inline bool isEmpty() const; + struct Result { + inline Result(); + inline Result(const void *importNamespace); + inline Result(QDeclarativeType *type); + inline Result(int scriptIndex); + inline Result(const Result &); + + inline bool isValid() const; - inline QDeclarativeMetaType::ModuleApiInstance *moduleApi() const; - void setModuleApi(QDeclarativeMetaType::ModuleApiInstance *); + QDeclarativeType *type; + const void *importNamespace; + int scriptIndex; + }; + Result query(const QHashedStringRef &); + Result query(const QHashedStringRef &, const void *importNamespace); + Result query(const QHashedV8String &); + Result query(const QHashedV8String &, const void *importNamespace); + QDeclarativeMetaType::ModuleApiInstance *moduleApi(const void *importNamespace); protected: virtual void clear(); private: - typedef QStringHash<Data> StringCache; + friend class QDeclarativeImports; - StringCache stringCache; + struct Import { + inline Import(); + // Imported module + QDeclarativeMetaType::ModuleApiInstance *moduleApi; + QVector<QDeclarativeTypeModuleVersion> modules; + + // Or, imported script + int scriptIndex; + }; + + QStringHash<Import> m_namedImports; + QVector<QDeclarativeTypeModuleVersion> m_anonymousImports; QDeclarativeEngine *engine; - QDeclarativeMetaType::ModuleApiInstance *m_moduleApi; }; -QDeclarativeTypeNameCache::Data::Data() -: type(0), typeNamespace(0), importedScriptIndex(-1) +QDeclarativeTypeNameCache::Result::Result() +: type(0), importNamespace(0), scriptIndex(-1) { } -QDeclarativeTypeNameCache::Data::~Data() +QDeclarativeTypeNameCache::Result::Result(const void *importNamespace) +: type(0), importNamespace(importNamespace), scriptIndex(-1) { - if (typeNamespace) typeNamespace->release(); } -bool QDeclarativeTypeNameCache::isEmpty() const +QDeclarativeTypeNameCache::Result::Result(QDeclarativeType *type) +: type(type), importNamespace(0), scriptIndex(-1) { - return stringCache.isEmpty(); } -QDeclarativeTypeNameCache::Data::Data(const QDeclarativeTypeNameCache::Data &o) -: type(o.type), typeNamespace(o.typeNamespace), importedScriptIndex(o.importedScriptIndex) +QDeclarativeTypeNameCache::Result::Result(int scriptIndex) +: type(0), importNamespace(0), scriptIndex(scriptIndex) { - if (typeNamespace) typeNamespace->addref(); } -QDeclarativeTypeNameCache::Data &QDeclarativeTypeNameCache::Data::operator=(const QDeclarativeTypeNameCache::Data &o) +QDeclarativeTypeNameCache::Result::Result(const Result &o) +: type(o.type), importNamespace(o.importNamespace), scriptIndex(o.scriptIndex) { - if (o.typeNamespace) o.typeNamespace->addref(); - if (typeNamespace) typeNamespace->release(); - type = o.type; - typeNamespace = o.typeNamespace; - importedScriptIndex = o.importedScriptIndex; - return *this; } -QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi() const +bool QDeclarativeTypeNameCache::Result::isValid() const { - return m_moduleApi; + return type || importNamespace || scriptIndex != -1; } -QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QHashedV8String &name) const +QDeclarativeTypeNameCache::Import::Import() +: scriptIndex(-1) +{ +} + +bool QDeclarativeTypeNameCache::isEmpty() const { - return stringCache.value(name); + return m_namedImports.isEmpty() && m_anonymousImports.isEmpty(); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 6708b60834..bf290869b4 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -45,6 +45,7 @@ #include "private/qdeclarativeboundsignal_p.h" #include "private/qdeclarativestringconverters_p.h" #include "private/qmetaobjectbuilder_p.h" +#include "private/qfastmetabuilder_p.h" #include "private/qdeclarativedata_p.h" #include "qdeclarative.h" #include "private/qdeclarativecustomparser_p.h" @@ -240,7 +241,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, types.at(instr.type).createInstance(ctxt, bindings, &vmeErrors); if (!o) { - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.type).className)), instr.line); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(types.at(instr.type).className), instr.line); } QDeclarativeData *ddata = QDeclarativeData::get(o); @@ -356,7 +357,9 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, QMetaObject mo; const QByteArray &metadata = datas.at(instr.data); - QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata); + QFastMetaBuilder::fromData(&mo, 0, metadata); +// QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata); + const QDeclarativeVMEMetaData *data = (const QDeclarativeVMEMetaData *)datas.at(instr.aliasData).constData(); @@ -631,9 +634,9 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, QObject *assign = stack.pop(); QObject *target = stack.top(); int sigIdx = instr.signal; - const QByteArray &pr = datas.at(sigIdx); + const QString &pr = primitives.at(sigIdx); - QDeclarativeProperty prop(target, QString::fromUtf8(pr)); + QDeclarativeProperty prop(target, pr); if (prop.type() & QDeclarativeProperty::SignalProperty) { QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign); @@ -646,7 +649,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex()); } else { - VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)), instr.line); + VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(pr), instr.line); } @@ -1037,7 +1040,7 @@ v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentC QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine); QV8Engine *v8engine = ep->v8engine(); - bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared; + bool shared = script->pragmas & QDeclarativeScript::Object::ScriptBlock::Shared; QDeclarativeContextData *effectiveCtxt = parentCtxt; if (shared) diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index fc9bb887e8..e6af0ba964 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -365,7 +365,7 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); QString sourceCode = QString::fromUtf8(data); - QDeclarativeScriptParser::extractPragmas(sourceCode); + QDeclarativeScript::Parser::extractPragmas(sourceCode); v8::HandleScope handle_scope; v8::Context::Scope scope(workerEngine->context()); diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 18d59f7769..7ef28c0231 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -1,6 +1,5 @@ INCLUDEPATH += $$PWD SOURCES += \ - $$PWD/qdeclarativeparser.cpp \ $$PWD/qdeclarativeinstruction.cpp \ $$PWD/qdeclarativevmemetaobject.cpp \ $$PWD/qdeclarativeengine.cpp \ @@ -17,21 +16,19 @@ SOURCES += \ $$PWD/qdeclarativecompiler.cpp \ $$PWD/qdeclarativecompileddata.cpp \ $$PWD/qdeclarativeboundsignal.cpp \ - $$PWD/qdeclarativerefcount.cpp \ $$PWD/qdeclarativemetatype.cpp \ $$PWD/qdeclarativestringconverters.cpp \ $$PWD/qdeclarativeparserstatus.cpp \ $$PWD/qdeclarativetypeloader.cpp \ $$PWD/qdeclarativeinfo.cpp \ $$PWD/qdeclarativeerror.cpp \ - $$PWD/qdeclarativescriptparser.cpp \ + $$PWD/qdeclarativescript.cpp \ $$PWD/qdeclarativeenginedebug.cpp \ $$PWD/qdeclarativerewrite.cpp \ $$PWD/qdeclarativevaluetype.cpp \ $$PWD/qdeclarativefastproperties.cpp \ $$PWD/qdeclarativexmlhttprequest.cpp \ $$PWD/qdeclarativesqldatabase.cpp \ - $$PWD/qmetaobjectbuilder.cpp \ $$PWD/qdeclarativewatcher.cpp \ $$PWD/qdeclarativecleanup.cpp \ $$PWD/qdeclarativepropertycache.cpp \ @@ -47,10 +44,8 @@ SOURCES += \ $$PWD/qdeclarativeextensionplugin.cpp \ $$PWD/qdeclarativeimport.cpp \ $$PWD/qdeclarativelist.cpp \ - $$PWD/qintrusivelist.cpp \ HEADERS += \ - $$PWD/qdeclarativeparser_p.h \ $$PWD/qdeclarativeglobal_p.h \ $$PWD/qdeclarativeinstruction_p.h \ $$PWD/qdeclarativevmemetaobject_p.h \ @@ -72,7 +67,6 @@ HEADERS += \ $$PWD/qdeclarativeengine_p.h \ $$PWD/qdeclarativeexpression_p.h \ $$PWD/qdeclarativeprivate.h \ - $$PWD/qdeclarativerefcount_p.h \ $$PWD/qdeclarativemetatype_p.h \ $$PWD/qdeclarativeengine.h \ $$PWD/qdeclarativecontext.h \ @@ -86,16 +80,13 @@ HEADERS += \ $$PWD/qdeclarativelist_p.h \ $$PWD/qdeclarativedata_p.h \ $$PWD/qdeclarativeerror.h \ - $$PWD/qdeclarativescriptparser_p.h \ + $$PWD/qdeclarativescript_p.h \ $$PWD/qdeclarativeenginedebug_p.h \ $$PWD/qdeclarativerewrite_p.h \ - $$PWD/qpodvector_p.h \ - $$PWD/qbitfield_p.h \ $$PWD/qdeclarativevaluetype_p.h \ $$PWD/qdeclarativefastproperties_p.h \ $$PWD/qdeclarativexmlhttprequest_p.h \ $$PWD/qdeclarativesqldatabase_p.h \ - $$PWD/qmetaobjectbuilder_p.h \ $$PWD/qdeclarativewatcher_p.h \ $$PWD/qdeclarativecleanup_p.h \ $$PWD/qdeclarativepropertycache_p.h \ @@ -113,11 +104,11 @@ HEADERS += \ $$PWD/qdeclarativeimport_p.h \ $$PWD/qdeclarativeextensionplugin.h \ $$PWD/qdeclarativenullablevalue_p_p.h \ - $$PWD/qintrusivelist_p.h \ $$PWD/qdeclarativescriptstring_p.h QT += sql include(parser/parser.pri) include(rewriter/rewriter.pri) +include(ftw/ftw.pri) include(v4/v4.pri) include(v8/v8.pri) diff --git a/src/declarative/qml/v4/qdeclarativev4compiler.cpp b/src/declarative/qml/v4/qdeclarativev4compiler.cpp index 371edda6c9..fa4cd25952 100644 --- a/src/declarative/qml/v4/qdeclarativev4compiler.cpp +++ b/src/declarative/qml/v4/qdeclarativev4compiler.cpp @@ -85,17 +85,18 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column) currentBlockMask = 0x00000001; - for (int i = 0; i < blocks.size(); ++i) { + for (int i = 0; !_discarded && i < blocks.size(); ++i) { IR::BasicBlock *block = blocks.at(i); IR::BasicBlock *next = i + 1 < blocks.size() ? blocks.at(i + 1) : 0; if (IR::Stmt *terminator = block->terminator()) { if (IR::CJump *cj = terminator->asCJump()) { if (cj->iffalse != next) { - block->i(new IR::Jump(cj->iffalse)); + IR::Jump *jump = _function->pool->New<IR::Jump>(); + jump->init(cj->iffalse); + block->statements.append(jump); } } else if (IR::Jump *j = terminator->asJump()) { if (j->target == next) { - delete block->statements.back(); block->statements.resize(block->statements.size() - 1); } } @@ -136,8 +137,10 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column) blockop.block(currentBlockMask); gen(blockop); - foreach (IR::Stmt *s, block->statements) - s->accept(this); + foreach (IR::Stmt *s, block->statements) { + if (! _discarded) + s->accept(this); + } qSwap(usedSubscriptionIdsChanged, usic); @@ -147,7 +150,7 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column) return; } currentBlockMask <<= 1; - } else { + } else if (! _discarded) { const int adjust = bytecode.remove(blockopIndex); // Correct patches for (int ii = patchesCount; ii < patches.count(); ++ii) @@ -163,20 +166,21 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column) #endif - // back patching - foreach (const Patch &patch, patches) { - Instr &instr = bytecode[patch.offset]; - instr.branchop.offset = patch.block->offset - patch.offset - instr.size(); - } + if (! _discarded) { + // back patching + foreach (const Patch &patch, patches) { + Instr &instr = bytecode[patch.offset]; + instr.branchop.offset = patch.block->offset - patch.offset - instr.size(); + } - patches.clear(); + patches.clear(); + } } void QDeclarativeV4CompilerPrivate::trace(QVector<IR::BasicBlock *> *blocks) { - QList<IR::BasicBlock *> todo = QList<IR::BasicBlock *>::fromVector(_function->basicBlocks); - while (! todo.isEmpty()) { - IR::BasicBlock *block = todo.takeFirst(); + for (int i = 0; i < _function->basicBlocks.size(); ++i) { + IR::BasicBlock *block = _function->basicBlocks.at(i); while (! blocks->contains(block)) { blocks->append(block); @@ -270,7 +274,7 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e) instr.load_id(currentReg, e->index); gen(instr); - _subscribeName << QLatin1String("$$$ID_") + e->id; + _subscribeName << QLatin1String("$$$ID_") + *e->id; if (blockNeedsSubscription(_subscribeName)) { Instr sub; @@ -293,7 +297,7 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e) } break; case IR::Name::AttachType: { - _subscribeName << e->id; + _subscribeName << *e->id; Instr attached; attached.common.type = Instr::LoadAttached; @@ -306,7 +310,7 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e) } break; case IR::Name::Property: { - _subscribeName << e->id; + _subscribeName << *e->id; QMetaProperty prop = e->meta->property(e->index); int fastFetchIndex = QDeclarativeFastProperties::instance()->accessorIndexForProperty(e->meta, e->index); @@ -763,8 +767,9 @@ void QDeclarativeV4CompilerPrivate::visitBinop(IR::Binop *e) void QDeclarativeV4CompilerPrivate::visitCall(IR::Call *call) { if (IR::Name *name = call->base->asName()) { - if (call->args.size() == 1 && call->args.at(0)->type == IR::RealType) { - traceExpression(call->args.at(0), currentReg); + IR::Expr *arg = call->onlyArgument(); + if (arg != 0 && arg->type == IR::RealType) { + traceExpression(arg, currentReg); Instr instr; instr.common.type = Instr::Noop; @@ -981,7 +986,6 @@ This does not clear the global "committed binding" states. */ void QDeclarativeV4CompilerPrivate::resetInstanceState() { - registerCleanups.clear(); data = committed.data; exceptions = committed.exceptions; usedSubscriptionIds.clear(); @@ -989,6 +993,7 @@ void QDeclarativeV4CompilerPrivate::resetInstanceState() registeredStrings = committed.registeredStrings; bytecode.clear(); patches.clear(); + pool.clear(); currentReg = 0; } @@ -1003,7 +1008,7 @@ int QDeclarativeV4CompilerPrivate::commitCompile() int rv = committed.count(); committed.offsets << committed.bytecode.count(); committed.dependencies << usedSubscriptionIds; - committed.bytecode += bytecode.code(); + committed.bytecode.append(bytecode.constData(), bytecode.size()); committed.data = data; committed.exceptions = exceptions; committed.subscriptionIds = subscriptionIds; @@ -1032,11 +1037,10 @@ bool QDeclarativeV4CompilerPrivate::compile(QDeclarativeJS::AST::Node *node) return false; } - IR::Module module; - IR::Function *function = 0; + IR::Function thisFunction(&pool), *function = &thisFunction; QDeclarativeV4IRBuilder irBuilder(expression, engine); - if (!(function = irBuilder(&module, node))) + if (!irBuilder(function, node)) return false; bool discarded = false; @@ -1067,7 +1071,7 @@ bool QDeclarativeV4CompilerPrivate::compile(QDeclarativeJS::AST::Node *node) } // Returns a reg -int QDeclarativeV4CompilerPrivate::registerLiteralString(quint8 reg, const QString &str) +int QDeclarativeV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str) { // ### string cleanup @@ -1090,9 +1094,9 @@ int QDeclarativeV4CompilerPrivate::registerString(const QString &string) { Q_ASSERT(!string.isEmpty()); - QHash<QString, QPair<int, int> >::ConstIterator iter = registeredStrings.find(string); + QPair<int, int> *iter = registeredStrings.value(string); - if (iter == registeredStrings.end()) { + if (!iter) { quint32 len = string.length(); QByteArray lendata((const char *)&len, sizeof(quint32)); QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar)); @@ -1100,7 +1104,8 @@ int QDeclarativeV4CompilerPrivate::registerString(const QString &string) int rv = data.count(); data += strdata; - iter = registeredStrings.insert(string, qMakePair(registeredStrings.count(), rv)); + iter = ®isteredStrings[string]; + *iter = qMakePair(registeredStrings.count(), rv); } Instr reg; @@ -1118,12 +1123,12 @@ bool QDeclarativeV4CompilerPrivate::blockNeedsSubscription(const QStringList &su { QString str = sub.join(QLatin1String(".")); - QHash<QString, int>::ConstIterator iter = subscriptionIds.find(str); - if (iter == subscriptionIds.end()) + int *iter = subscriptionIds.value(str); + if (!iter) return true; - QHash<int, quint32>::ConstIterator uiter = usedSubscriptionIds.find(*iter); - if (uiter == usedSubscriptionIds.end()) + quint32 *uiter = usedSubscriptionIds.value(*iter); + if (!uiter) return true; else return !(*uiter & currentBlockMask); @@ -1132,11 +1137,15 @@ bool QDeclarativeV4CompilerPrivate::blockNeedsSubscription(const QStringList &su int QDeclarativeV4CompilerPrivate::subscriptionIndex(const QStringList &sub) { QString str = sub.join(QLatin1String(".")); - QHash<QString, int>::ConstIterator iter = subscriptionIds.find(str); - if (iter == subscriptionIds.end()) - iter = subscriptionIds.insert(str, subscriptionIds.count()); - if (!(usedSubscriptionIds[*iter] & currentBlockMask)) { - usedSubscriptionIds[*iter] |= currentBlockMask; + int *iter = subscriptionIds.value(str); + if (!iter) { + int count = subscriptionIds.count(); + iter = &subscriptionIds[str]; + *iter = count; + } + quint32 &u = usedSubscriptionIds[*iter]; + if (!(u & currentBlockMask)) { + u |= currentBlockMask; usedSubscriptionIdsChanged = true; } return *iter; @@ -1146,11 +1155,11 @@ quint32 QDeclarativeV4CompilerPrivate::subscriptionBlockMask(const QStringList & { QString str = sub.join(QLatin1String(".")); - QHash<QString, int>::ConstIterator iter = subscriptionIds.find(str); - Q_ASSERT(iter != subscriptionIds.end()); + int *iter = subscriptionIds.value(str); + Q_ASSERT(iter != 0); - QHash<int, quint32>::ConstIterator uiter = usedSubscriptionIds.find(*iter); - Q_ASSERT(uiter != usedSubscriptionIds.end()); + quint32 *uiter = usedSubscriptionIds.value(*iter); + Q_ASSERT(uiter != 0); return *uiter; } @@ -1225,9 +1234,9 @@ QByteArray QDeclarativeV4CompilerPrivate::buildSignalTable() const QHash<int, QList<QPair<int, quint32> > > table; for (int ii = 0; ii < committed.count(); ++ii) { - const QHash<int, quint32> &deps = committed.dependencies.at(ii); - for (QHash<int, quint32>::ConstIterator iter = deps.begin(); iter != deps.end(); ++iter) - table[iter.key()].append(qMakePair(ii, iter.value())); + const QDeclarativeAssociationList<int, quint32> &deps = committed.dependencies.at(ii); + for (QDeclarativeAssociationList<int, quint32>::const_iterator iter = deps.begin(); iter != deps.end(); ++iter) + table[iter->first].append(qMakePair(ii, iter->second)); } QVector<quint32> header; @@ -1278,8 +1287,10 @@ QByteArray QDeclarativeV4Compiler::program() const } - QByteArray bytecode = bc.code(); - bytecode += d->committed.bytecode; + QByteArray bytecode; + bytecode.reserve(bc.size() + d->committed.bytecode.size()); + bytecode.append(bc.constData(), bc.size()); + bytecode.append(d->committed.bytecode.constData(), d->committed.bytecode.size()); QByteArray data = d->committed.data; while (data.count() % 4) data.append('\0'); @@ -1308,13 +1319,12 @@ QByteArray QDeclarativeV4Compiler::program() const if (bindingsDump()) { qWarning().nospace() << "Subscription slots:"; - for (QHash<QString, int>::ConstIterator iter = d->committed.subscriptionIds.begin(); + for (QDeclarativeAssociationList<QString, int>::ConstIterator iter = d->committed.subscriptionIds.begin(); iter != d->committed.subscriptionIds.end(); ++iter) { - qWarning().nospace() << " " << iter.value() << "\t-> " << iter.key(); + qWarning().nospace() << " " << iter->first << "\t-> " << iter->second; } - QDeclarativeV4Compiler::dump(programData); } diff --git a/src/declarative/qml/v4/qdeclarativev4compiler_p.h b/src/declarative/qml/v4/qdeclarativev4compiler_p.h index cc93f4dbf2..0ed78bfdfc 100644 --- a/src/declarative/qml/v4/qdeclarativev4compiler_p.h +++ b/src/declarative/qml/v4/qdeclarativev4compiler_p.h @@ -53,8 +53,9 @@ // We mean it. // -#include "private/qdeclarativeexpression_p.h" -#include "private/qdeclarativebinding_p.h" +#include <private/qdeclarativeexpression_p.h> +#include <private/qdeclarativebinding_p.h> +#include <private/qdeclarativecompiler_p.h> QT_BEGIN_HEADER @@ -73,11 +74,12 @@ public: struct Expression { - QDeclarativeParser::Object *component; - QDeclarativeParser::Object *context; - QDeclarativeParser::Property *property; - QDeclarativeParser::Variant expression; - QHash<QString, QDeclarativeParser::Object *> ids; + Expression(const QDeclarativeImports &imp) : imports(imp) {} + QDeclarativeScript::Object *component; + QDeclarativeScript::Object *context; + QDeclarativeScript::Property *property; + QDeclarativeScript::Variant expression; + QDeclarativeCompilerTypes::IdList *ids; QDeclarativeTypeNameCache *importCache; QDeclarativeImports imports; }; diff --git a/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h b/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h index 1d9414dce6..eab609a45d 100644 --- a/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h +++ b/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h @@ -55,7 +55,7 @@ #include "qdeclarativev4instruction_p.h" #include "qdeclarativev4ir_p.h" -#include <private/qdeclarativeparser_p.h> +#include <private/qdeclarativescript_p.h> #include <private/qdeclarativeimport_p.h> #include <private/qdeclarativeengine_p.h> @@ -93,6 +93,54 @@ inline bool operator==(const QDeclarative1AnchorLine& a, const QDeclarative1Anch } +template <typename _Key, typename _Value> +class QDeclarativeAssociationList +{ +public: + typedef QVarLengthArray<QPair<_Key, _Value>, 8> Container; + typedef typename Container::const_iterator const_iterator; + typedef typename Container::const_iterator ConstIterator; + + const_iterator begin() const { return _container.begin(); } + const_iterator end() const { return _container.end(); } + int count() const { return _container.count(); } + void clear() { _container.clear(); } + + _Value *value(const _Key &key) { + for (int i = 0; i < _container.size(); ++i) { + QPair<_Key, _Value> &p = _container[i]; + if (p.first == key) + return &p.second; + } + return 0; + } + + _Value &operator[](const _Key &key) { + for (int i = 0; i < _container.size(); ++i) { + QPair<_Key, _Value> &p = _container[i]; + if (p.first == key) + return p.second; + } + int index = _container.size(); + _container.append(qMakePair(key, _Value())); + return _container[index].second; + } + + void insert(const _Key &key, _Value &value) { + for (int i = 0; i < _container.size(); ++i) { + QPair<_Key, _Value> &p = _container[i]; + if (p.first == key) { + p.second = value; + return; + } + } + _container.append(qMakePair(key, value)); + } + +private: + Container _container; +}; + class QDeclarativeV4CompilerPrivate: protected QDeclarativeJS::IR::ExprVisitor, protected QDeclarativeJS::IR::StmtVisitor { @@ -109,11 +157,9 @@ public: bool compile(QDeclarativeJS::AST::Node *); - QHash<int, QPair<int, int> > registerCleanups; - - int registerLiteralString(quint8 reg, const QString &); + int registerLiteralString(quint8 reg, const QStringRef &); int registerString(const QString &); - QHash<QString, QPair<int, int> > registeredStrings; + QDeclarativeAssociationList<QString, QPair<int, int> > registeredStrings; QByteArray data; bool blockNeedsSubscription(const QStringList &); @@ -124,9 +170,9 @@ public: quint8 exceptionId(QDeclarativeJS::AST::ExpressionNode *); QVector<quint64> exceptions; - QHash<int, quint32> usedSubscriptionIds; + QDeclarativeAssociationList<int, quint32> usedSubscriptionIds; - QHash<QString, int> subscriptionIds; + QDeclarativeAssociationList<QString, int> subscriptionIds; QDeclarativeJS::Bytecode bytecode; // back patching @@ -137,19 +183,20 @@ public: : block(block), offset(index) {} }; QVector<Patch> patches; + QDeclarativePool pool; // Committed binding data struct { QList<int> offsets; - QList<QHash<int, quint32> > dependencies; + QList<QDeclarativeAssociationList<int, quint32> > dependencies; //QDeclarativeJS::Bytecode bytecode; QByteArray bytecode; QByteArray data; - QHash<QString, int> subscriptionIds; + QDeclarativeAssociationList<QString, int> subscriptionIds; QVector<quint64> exceptions; - QHash<QString, QPair<int, int> > registeredStrings; + QDeclarativeAssociationList<QString, QPair<int, int> > registeredStrings; int count() const { return offsets.count(); } } committed; diff --git a/src/declarative/qml/v4/qdeclarativev4instruction.cpp b/src/declarative/qml/v4/qdeclarativev4instruction.cpp index a520a3584a..dd6892369b 100644 --- a/src/declarative/qml/v4/qdeclarativev4instruction.cpp +++ b/src/declarative/qml/v4/qdeclarativev4instruction.cpp @@ -530,12 +530,6 @@ void Bytecode::append(const Instr &instr) d.append(it, instr.size()); } -void Bytecode::append(const QVector<Instr> &instrs) -{ - foreach (const Instr &i, instrs) - append(i); -} - int Bytecode::remove(int offset) { const Instr *instr = (const Instr *) (d.begin() + offset); diff --git a/src/declarative/qml/v4/qdeclarativev4instruction_p.h b/src/declarative/qml/v4/qdeclarativev4instruction_p.h index e3ac9027f7..6efe9332d1 100644 --- a/src/declarative/qml/v4/qdeclarativev4instruction_p.h +++ b/src/declarative/qml/v4/qdeclarativev4instruction_p.h @@ -56,6 +56,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qbytearray.h> #include <QtCore/qvector.h> +#include <QtCore/qvarlengtharray.h> QT_BEGIN_HEADER @@ -414,21 +415,27 @@ class Bytecode public: Bytecode(); - QByteArray code() const { return d; } const char *constData() const { return d.constData(); } int size() const { return d.size(); } int count() const { return d.count(); } void clear() { d.clear(); } bool isEmpty() const { return d.isEmpty(); } void append(const Instr &instr); - void append(const QVector<Instr> &instrs); + + template <typename _It> + void append(_It it, _It last) + { + for (; it != last; ++it) + append(*it); + } + int remove(int index); const Instr &operator[](int offset) const; Instr &operator[](int offset); private: - QByteArray d; + QVarLengthArray<char, 4 * 1024> d; #ifdef QML_THREADED_INTERPRETER void **decodeInstr; #endif diff --git a/src/declarative/qml/v4/qdeclarativev4ir.cpp b/src/declarative/qml/v4/qdeclarativev4ir.cpp index 86eeeec12c..7490efe2aa 100644 --- a/src/declarative/qml/v4/qdeclarativev4ir.cpp +++ b/src/declarative/qml/v4/qdeclarativev4ir.cpp @@ -165,10 +165,11 @@ void String::dump(QTextStream &out) out << '"' << escape(value) << '"'; } -QString String::escape(const QString &s) +QString String::escape(const QStringRef &s) { QString r; - foreach (const QChar &ch, s) { + for (int i = 0; i < s.length(); ++i) { + const QChar ch = s.at(i); if (ch == QLatin1Char('\n')) r += QLatin1String("\\n"); else if (ch == QLatin1Char('\r')) @@ -185,29 +186,30 @@ QString String::escape(const QString &s) return r; } -Name::Name(Name *base, Type type, const QString &id, Symbol symbol, quint32 line, quint32 column) -: Expr(type) - , base(base) - , id(id) - , symbol(symbol) - , ptr(0) - , index(-1) - , storage(MemberStorage) - , builtin(NoBuiltinSymbol) - , line(line) - , column(column) +void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column) { - if (id.length() == 8 && id == QLatin1String("Math.sin")) { + this->type = type; + this->base = base; + this->id = id; + this->symbol = symbol; + this->ptr = 0; + this->index = -1; + this->storage = MemberStorage; + this->builtin = NoBuiltinSymbol; + this->line = line; + this->column = column; + + if (id->length() == 8 && *id == QLatin1String("Math.sin")) { builtin = MathSinBultinFunction; - } else if (id.length() == 8 && id == QLatin1String("Math.cos")) { + } else if (id->length() == 8 && *id == QLatin1String("Math.cos")) { builtin = MathCosBultinFunction; - } else if (id.length() == 10 && id == QLatin1String("Math.round")) { + } else if (id->length() == 10 && *id == QLatin1String("Math.round")) { builtin = MathRoundBultinFunction; - } else if (id.length() == 10 && id == QLatin1String("Math.floor)")) { + } else if (id->length() == 10 && *id == QLatin1String("Math.floor)")) { builtin = MathFloorBultinFunction; - } else if (id.length() == 7 && id == QLatin1String("Math.PI")) { + } else if (id->length() == 7 && *id == QLatin1String("Math.PI")) { builtin = MathPIBuiltinConstant; - type = RealType; + this->type = RealType; } } @@ -218,7 +220,7 @@ void Name::dump(QTextStream &out) out << '.'; } - out << id; + out << *id; } void Temp::dump(QTextStream &out) @@ -318,10 +320,10 @@ void Call::dump(QTextStream &out) { base->dump(out); out << '('; - for (int i = 0; i < args.size(); ++i) { - if (i) + for (ExprList *it = args; it; it = it->next) { + if (it != args) out << ", "; - args.at(i)->dump(out); + it->expr->dump(out); } out << ')'; } @@ -396,7 +398,11 @@ void Ret::dump(QTextStream &out, Mode) Function::~Function() { qDeleteAll(basicBlocks); - qDeleteAll(temps); +} + +QString *Function::newString(const QString &text) +{ + return pool->NewString(text); } BasicBlock *Function::newBasicBlock() @@ -407,12 +413,7 @@ BasicBlock *Function::newBasicBlock() void Function::dump(QTextStream &out) { - QString fname; - if (name) - fname = name->asString(); - else - fname = QLatin1String("$anonymous"); - out << "function " << fname << "() {" << endl; + out << "function () {" << endl; foreach (BasicBlock *bb, basicBlocks) { bb->dump(out); } @@ -421,7 +422,9 @@ void Function::dump(QTextStream &out) Temp *BasicBlock::TEMP(Type type, int index) { - return function->e(new Temp(type, index)); + Temp *e = function->pool->New<Temp>(); + e->init(type, index); + return e; } Temp *BasicBlock::TEMP(Type type) @@ -436,12 +439,16 @@ Expr *BasicBlock::CONST(double value) Expr *BasicBlock::CONST(Type type, double value) { - return function->e(new Const(type, value)); + Const *e = function->pool->New<Const>(); + e->init(type, value); + return e; } -Expr *BasicBlock::STRING(const QString &value) -{ - return function->e(new String(value)); +Expr *BasicBlock::STRING(const QStringRef &value) +{ + String *e = function->pool->New<String>(); + e->init(value); + return e; } Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) @@ -451,7 +458,11 @@ Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column) Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 column) { - return function->e(new Name(base, InvalidType, id, Name::Unbound, line, column)); + Name *e = function->pool->New<Name>(); + e->init(base, InvalidType, + function->newString(id), + Name::Unbound, line, column); + return e; } Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, @@ -465,44 +476,56 @@ Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, quint32 line, quint32 column) { - Name *name = new Name(base, type, id, Name::Property, line, column); + Name *name = function->pool->New<Name>(); + name->init(base, type, function->newString(id), + Name::Property, line, column); name->meta = meta; name->index = index; name->storage = storage; - return function->e(name); + return name; } Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, quint32 line, quint32 column) { - Name *name = new Name(base, type, id, Name::Property, line, column); + Name *name = function->pool->New<Name>(); + name->init(base, type, function->newString(id), + Name::Property, line, column); name->meta = meta; name->index = index; - return function->e(name); + return name; } -Name *BasicBlock::ID_OBJECT(const QString &id, const QDeclarativeParser::Object *object, quint32 line, quint32 column) +Name *BasicBlock::ID_OBJECT(const QString &id, const QDeclarativeScript::Object *object, quint32 line, quint32 column) { - Name *name = new Name(/*base = */ 0, IR::ObjectType, id, Name::IdObject, line, column); + Name *name = function->pool->New<Name>(); + name->init(/*base = */ 0, IR::ObjectType, + function->newString(id), + Name::IdObject, line, column); name->idObject = object; name->index = object->idIndex; name->storage = Name::IdStorage; - return function->e(name); + return name; } Name *BasicBlock::ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage, quint32 line, quint32 column) { - Name *name = new Name(/*base = */ 0, IR::AttachType, id, Name::AttachType, line, column); + Name *name = function->pool->New<Name>(); + name->init(/*base = */ 0, IR::AttachType, + function->newString(id), + Name::AttachType, line, column); name->declarativeType = attachType; name->storage = storage; - return function->e(name); + return name; } Expr *BasicBlock::UNOP(AluOp op, Expr *expr) { - return function->e(new Unop(op, expr)); + Unop *e = function->pool->New<Unop>(); + e->init(op, expr); + return e; } Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) @@ -545,45 +568,65 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) } } - return function->e(new Binop(op, left, right)); + Binop *e = function->pool->New<Binop>(); + e->init(op, left, right); + return e; } -Expr *BasicBlock::CALL(Expr *base, const QVector<Expr *> &args) +Expr *BasicBlock::CALL(Expr *base, ExprList *args) { - return function->e(new Call(base, args)); + Call *e = function->pool->New<Call>(); + e->init(base, args); + return e; } Stmt *BasicBlock::EXP(Expr *expr) { - return i(new Exp(expr)); + Exp *s = function->pool->New<Exp>(); + s->init(expr); + statements.append(s); + return s; } Stmt *BasicBlock::MOVE(Expr *target, Expr *source, bool isMoveForReturn) { - return i(new Move(target, source, isMoveForReturn)); + Move *s = function->pool->New<Move>(); + s->init(target, source, isMoveForReturn); + statements.append(s); + return s; } Stmt *BasicBlock::JUMP(BasicBlock *target) { if (isTerminated()) return 0; - else - return i(new Jump(target)); + + Jump *s = function->pool->New<Jump>(); + s->init(target); + statements.append(s); + return s; } Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) { if (isTerminated()) return 0; - return i(new CJump(cond, iftrue, iffalse)); + + CJump *s = function->pool->New<CJump>(); + s->init(cond, iftrue, iffalse); + statements.append(s); + return s; } Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column) { if (isTerminated()) return 0; - else - return i(new Ret(expr, type, line, column)); + + Ret *s = function->pool->New<Ret>(); + s->init(expr, type, line, column); + statements.append(s); + return s; } void BasicBlock::dump(QTextStream &out) @@ -596,14 +639,6 @@ void BasicBlock::dump(QTextStream &out) } } -void Module::dump(QTextStream &out) -{ - foreach (Function *fun, functions) { - fun->dump(out); - out << endl; - } -} - #ifdef DEBUG_IR_STRUCTURE static const char *symbolname(Name::Symbol s) diff --git a/src/declarative/qml/v4/qdeclarativev4ir_p.h b/src/declarative/qml/v4/qdeclarativev4ir_p.h index 87891bfc4e..2c8f658378 100644 --- a/src/declarative/qml/v4/qdeclarativev4ir_p.h +++ b/src/declarative/qml/v4/qdeclarativev4ir_p.h @@ -55,12 +55,13 @@ #include <private/qdeclarativejsast_p.h> #include <private/qdeclarativejsengine_p.h> -#include <private/qdeclarativeparser_p.h> +#include <private/qdeclarativescript_p.h> #include <private/qdeclarativeimport_p.h> #include <private/qdeclarativeengine_p.h> #include <private/qdeclarativev4compiler_p.h> -#include <QtCore/qvector.h> +#include <qdeclarativepool_p.h> +#include <QtCore/qvarlengtharray.h> // #define DEBUG_IR_STRUCTURE @@ -77,7 +78,6 @@ namespace IR { struct BasicBlock; struct Function; -struct Module; struct Stmt; struct Expr; @@ -175,10 +175,10 @@ struct StmtVisitor { virtual void visitRet(Ret *) {} }; -struct Expr { +struct Expr: QDeclarativePool::POD { Type type; - Expr(Type type): type(type) {} + Expr(): type(InvalidType) {} virtual ~Expr() {} virtual void accept(ExprVisitor *) = 0; virtual Const *asConst() { return 0; } @@ -191,9 +191,25 @@ struct Expr { virtual void dump(QTextStream &out) = 0; }; +struct ExprList: QDeclarativePool::POD { + Expr *expr; + ExprList *next; + + void init(Expr *expr, ExprList *next = 0) + { + this->expr = expr; + this->next = next; + } +}; + struct Const: Expr { double value; - Const(Type type, double value): Expr(type), value(value) {} + + void init(Type type, double value) + { + this->type = type; + this->value = value; + } virtual void accept(ExprVisitor *v) { v->visitConst(this); } virtual Const *asConst() { return this; } @@ -202,14 +218,19 @@ struct Const: Expr { }; struct String: Expr { - QString value; - String(const QString &value): Expr(StringType), value(value) {} + QStringRef value; + + void init(const QStringRef &value) + { + this->type = StringType; + this->value = value; + } virtual void accept(ExprVisitor *v) { v->visitString(this); } virtual String *asString() { return this; } virtual void dump(QTextStream &out); - static QString escape(const QString &s); + static QString escape(const QStringRef &s); }; enum BuiltinSymbol { @@ -240,13 +261,13 @@ struct Name: Expr { }; Name *base; - QString id; + const QString *id; Symbol symbol; union { void *ptr; const QMetaObject *meta; const QDeclarativeType *declarativeType; - const QDeclarativeParser::Object *idObject; + const QDeclarativeScript::Object *idObject; }; int index; Storage storage; @@ -254,7 +275,7 @@ struct Name: Expr { quint32 line; quint32 column; - Name(Name *base, Type type, const QString &id, Symbol symbol, quint32 line, quint32 column); + void init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column); inline bool is(Symbol s) const { return s == symbol; } inline bool isNot(Symbol s) const { return s != symbol; } @@ -267,7 +288,12 @@ struct Name: Expr { struct Temp: Expr { int index; - Temp(Type type, int index): Expr(type), index(index) {} + + void init(Type type, int index) + { + this->type = type; + this->index = index; + } virtual void accept(ExprVisitor *v) { v->visitTemp(this); } virtual Temp *asTemp() { return this; } @@ -279,8 +305,12 @@ struct Unop: Expr { AluOp op; Expr *expr; - Unop(AluOp op, Expr *expr) - : Expr(typeForOp(op, expr)), op(op), expr(expr) {} + void init(AluOp op, Expr *expr) + { + this->typeForOp(op, expr); + this->op = op; + this->expr = expr; + } virtual void accept(ExprVisitor *v) { v->visitUnop(this); } virtual Unop *asUnop() { return this; } @@ -295,8 +325,14 @@ struct Binop: Expr { AluOp op; Expr *left; Expr *right; - Binop(AluOp op, Expr *left, Expr *right) - : Expr(typeForOp(op, left, right)), op(op), left(left), right(right) {} + + void init(AluOp op, Expr *left, Expr *right) + { + this->type = typeForOp(op, left, right); + this->op = op; + this->left = left; + this->right = right; + } virtual void accept(ExprVisitor *v) { v->visitBinop(this); } virtual Binop *asBinop() { return this; } @@ -309,10 +345,20 @@ private: struct Call: Expr { Expr *base; - QVector<Expr *> args; + ExprList *args; - Call(Expr *base, const QVector<Expr *> &args) - : Expr(typeForFunction(base)), base(base), args(args) {} + void init(Expr *base, ExprList *args) + { + this->type = typeForFunction(base); + this->base = base; + this->args = args; + } + + Expr *onlyArgument() const { + if (args && ! args->next) + return args->expr; + return 0; + } virtual void accept(ExprVisitor *v) { v->visitCall(this); } virtual Call *asCall() { return this; } @@ -323,7 +369,7 @@ private: static Type typeForFunction(Expr *base); }; -struct Stmt { +struct Stmt: QDeclarativePool::POD { enum Mode { HIR, MIR @@ -343,7 +389,11 @@ struct Stmt { struct Exp: Stmt { Expr *expr; - Exp(Expr *expr): expr(expr) {} + + void init(Expr *expr) + { + this->expr = expr; + } virtual void accept(StmtVisitor *v) { v->visitExp(this); } virtual Exp *asExp() { return this; } @@ -355,7 +405,13 @@ struct Move: Stmt { Expr *target; Expr *source; bool isMoveForReturn; - Move(Expr *target, Expr *source, bool isMoveForReturn): target(target), source(source), isMoveForReturn(isMoveForReturn) {} + + void init(Expr *target, Expr *source, bool isMoveForReturn) + { + this->target = target; + this->source = source; + this->isMoveForReturn = isMoveForReturn; + } virtual void accept(StmtVisitor *v) { v->visitMove(this); } virtual Move *asMove() { return this; } @@ -365,7 +421,11 @@ struct Move: Stmt { struct Jump: Stmt { BasicBlock *target; - Jump(BasicBlock *target): target(target) {} + + void init(BasicBlock *target) + { + this->target = target; + } virtual Stmt *asTerminator() { return this; } @@ -379,8 +439,13 @@ struct CJump: Stmt { Expr *cond; BasicBlock *iftrue; BasicBlock *iffalse; - CJump(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) - : cond(cond), iftrue(iftrue), iffalse(iffalse) {} + + void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) + { + this->cond = cond; + this->iftrue = iftrue; + this->iffalse = iffalse; + } virtual Stmt *asTerminator() { return this; } @@ -395,7 +460,14 @@ struct Ret: Stmt { Type type; quint32 line; quint32 column; - Ret(Expr *expr, Type type, quint32 line, quint32 column): expr(expr), type(type), line(line), column(column) {} + + void init(Expr *expr, Type type, quint32 line, quint32 column) + { + this->expr = expr; + this->type = type; + this->line = line; + this->column = column; + } virtual Stmt *asTerminator() { return this; } @@ -406,19 +478,19 @@ struct Ret: Stmt { }; struct Function { - Module *module; - const NameId *name; + QDeclarativePool *pool; + QVarLengthArray<BasicBlock *, 8> basicBlocks; int tempCount; - QVector<BasicBlock *> basicBlocks; - QVector<Expr *> temps; - template <typename BB> inline BB i(BB i) { basicBlocks.append(i); return i; } - template <typename E> inline E e(E e) { temps.append(e); return e; } + Function(QDeclarativePool *pool) + : pool(pool), tempCount(0) {} - Function(Module *module, const NameId *name = 0): module(module), name(name), tempCount(0) {} ~Function(); BasicBlock *newBasicBlock(); + QString *newString(const QString &text); + + inline BasicBlock *i(BasicBlock *block) { basicBlocks.append(block); return block; } virtual void dump(QTextStream &out); }; @@ -426,11 +498,11 @@ struct Function { struct BasicBlock { Function *function; int index; - QVector<Stmt *> statements; int offset; + QVarLengthArray<Stmt *, 32> statements; BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {} - ~BasicBlock() { qDeleteAll(statements); } + ~BasicBlock() {} template <typename Instr> inline Instr i(Instr i) { statements.append(i); return i; } @@ -439,8 +511,8 @@ struct BasicBlock { } inline Stmt *terminator() const { - if (! statements.isEmpty() && statements.last()->asTerminator() != 0) - return statements.last(); + if (! statements.isEmpty() && statements.at(statements.size() - 1)->asTerminator() != 0) + return statements.at(statements.size() - 1); return 0; } @@ -455,19 +527,19 @@ struct BasicBlock { Expr *CONST(double value); Expr *CONST(Type type, double value); - Expr *STRING(const QString &value); + Expr *STRING(const QStringRef &value); Name *NAME(const QString &id, quint32 line, quint32 column); Name *NAME(Name *base, const QString &id, quint32 line, quint32 column); Name *SYMBOL(Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, quint32 line, quint32 column); Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, quint32 line, quint32 column); Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage, quint32 line, quint32 column); - Name *ID_OBJECT(const QString &id, const QDeclarativeParser::Object *object, quint32 line, quint32 column); + Name *ID_OBJECT(const QString &id, const QDeclarativeScript::Object *object, quint32 line, quint32 column); Name *ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage, quint32 line, quint32 column); Expr *UNOP(AluOp op, Expr *expr); Expr *BINOP(AluOp op, Expr *left, Expr *right); - Expr *CALL(Expr *base, const QVector<Expr *> &args); + Expr *CALL(Expr *base, ExprList *args); Stmt *EXP(Expr *expr); Stmt *MOVE(Expr *target, Expr *source, bool = false); @@ -479,19 +551,6 @@ struct BasicBlock { virtual void dump(QTextStream &out); }; -struct Module { - QVector<Function *> functions; - - Module() {} - ~Module() { qDeleteAll(functions); } - - template <typename BB> inline BB i(BB i) { functions.append(i); return i; } - - Function *newFunction(const NameId *name = 0) { return i(new Function(this, name)); } - - virtual void dump(QTextStream &out); -}; - #ifdef DEBUG_IR_STRUCTURE struct IRDump : public ExprVisitor, public StmtVisitor diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp index bddfca18b4..9237a3e1e9 100644 --- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp @@ -44,6 +44,7 @@ #include <private/qsganchors_p_p.h> // For AnchorLine #include <private/qdeclarativetypenamecache_p.h> +#include <private/qdeclarativeutils_p.h> DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER) @@ -85,19 +86,15 @@ static IR::Type irTypeFromVariantType(int t, QDeclarativeEnginePrivate *engine, QDeclarativeV4IRBuilder::QDeclarativeV4IRBuilder(const QDeclarativeV4Compiler::Expression *expr, QDeclarativeEnginePrivate *engine) -: m_expression(expr), m_engine(engine), _module(0), _function(0), _block(0), _discard(false) +: m_expression(expr), m_engine(engine), _function(0), _block(0), _discard(false) { } -QDeclarativeJS::IR::Function * -QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Module *module, +bool QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Function *function, QDeclarativeJS::AST::Node *ast) { bool discarded = false; - qSwap(_module, module); - - IR::Function *function = _module->newFunction(); IR::BasicBlock *block = function->newBasicBlock(); qSwap(_discard, discarded); @@ -130,17 +127,15 @@ QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Module *module, qSwap(_function, function); qSwap(_discard, discarded); - qSwap(_module, module); - - return discarded?0:function; + return !discarded; } -bool QDeclarativeV4IRBuilder::buildName(QStringList &name, +bool QDeclarativeV4IRBuilder::buildName(QList<QStringRef> &name, AST::Node *node, QList<AST::ExpressionNode *> *nodes) { if (node->kind == AST::Node::Kind_IdentifierExpression) { - name << static_cast<AST::IdentifierExpression*>(node)->name->asString(); + name << static_cast<AST::IdentifierExpression*>(node)->name; if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node); } else if (node->kind == AST::Node::Kind_FieldMemberExpression) { AST::FieldMemberExpression *expr = @@ -149,7 +144,7 @@ bool QDeclarativeV4IRBuilder::buildName(QStringList &name, if (!buildName(name, expr->base, nodes)) return false; - name << expr->name->asString(); + name << expr->name; if (nodes) *nodes << expr; } else { return false; @@ -341,27 +336,28 @@ bool QDeclarativeV4IRBuilder::visit(AST::UiFormal *) // JS -bool QDeclarativeV4IRBuilder::visit(AST::Program *ast) +bool QDeclarativeV4IRBuilder::visit(AST::Program *) { - _function = _module->newFunction(); - _block = _function->newBasicBlock(); - accept(ast->elements); + Q_ASSERT(!"unreachable"); return false; } bool QDeclarativeV4IRBuilder::visit(AST::SourceElements *) { + Q_ASSERT(!"unreachable"); return false; } bool QDeclarativeV4IRBuilder::visit(AST::FunctionSourceElement *) { - return true; // look inside + Q_ASSERT(!"unreachable"); + return false; } bool QDeclarativeV4IRBuilder::visit(AST::StatementSourceElement *) { - return true; // look inside + Q_ASSERT(!"unreachable"); + return false; } // object literals @@ -432,76 +428,75 @@ bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast) const quint32 line = ast->identifierToken.startLine; const quint32 column = ast->identifierToken.startColumn; - const QString name = ast->name->asString(); + const QString name = ast->name.toString(); if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) { _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value } else if (m_engine->v8engine()->illegalNames().contains(name) ) { if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name; return false; - } else if (const QDeclarativeParser::Object *obj = m_expression->ids.value(name)) { + } else if (const QDeclarativeScript::Object *obj = m_expression->ids->value(name)) { IR::Name *code = _block->ID_OBJECT(name, obj, line, column); if (obj == m_expression->component) code->storage = IR::Name::RootStorage; _expr.code = code; - } else if (QDeclarativeTypeNameCache::Data *typeNameData = m_expression->importCache->data(name)) { - if (typeNameData->importedScriptIndex != -1) { - // We don't support invoking imported scripts - } else if (typeNameData->type) { - _expr.code = _block->ATTACH_TYPE(name, typeNameData->type, IR::Name::ScopeStorage, line, column); - } else if (typeNameData->typeNamespace) { - // We don't support namespaces - } else { - Q_ASSERT(!"Unreachable"); - } } else { - bool found = false; - if (m_expression->context != m_expression->component) { - // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same - QDeclarativePropertyCache *cache = m_expression->context->synthCache; - const QMetaObject *metaObject = m_expression->context->metaObject(); - if (!cache) cache = m_engine->cache(metaObject); + QDeclarativeTypeNameCache::Result r = m_expression->importCache->query(name); + if (r.isValid()) { + if (r.type) { + _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); + } + // We don't support anything else + } else { + bool found = false; - QDeclarativePropertyCache::Data *data = cache->property(name); + if (m_expression->context != m_expression->component) { + // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same + QDeclarativePropertyCache *cache = m_expression->context->synthCache; + const QMetaObject *metaObject = m_expression->context->metaObject(); + if (!cache) cache = m_engine->cache(metaObject); + + QDeclarativePropertyCache::Data *data = cache->property(name); - if (data && data->revision != 0) { - if (qmlVerboseCompiler()) - qWarning() << "*** versioned symbol:" << name; - discard(); - return false; + if (data && data->revision != 0) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } + + if (data && !data->isFunction()) { + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); + _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column); + found = true; + } } - if (data && !data->isFunction()) { - IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); - _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column); - found = true; - } - } + if (!found) { + QDeclarativePropertyCache *cache = m_expression->component->synthCache; + const QMetaObject *metaObject = m_expression->component->metaObject(); + if (!cache) cache = m_engine->cache(metaObject); - if (!found) { - QDeclarativePropertyCache *cache = m_expression->component->synthCache; - const QMetaObject *metaObject = m_expression->component->metaObject(); - if (!cache) cache = m_engine->cache(metaObject); + QDeclarativePropertyCache::Data *data = cache->property(name); - QDeclarativePropertyCache::Data *data = cache->property(name); + if (data && data->revision != 0) { + if (qmlVerboseCompiler()) + qWarning() << "*** versioned symbol:" << name; + discard(); + return false; + } - if (data && data->revision != 0) { - if (qmlVerboseCompiler()) - qWarning() << "*** versioned symbol:" << name; - discard(); - return false; + if (data && !data->isFunction()) { + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); + _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column); + found = true; + } } - if (data && !data->isFunction()) { - IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject); - _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column); - found = true; - } + if (!found && qmlVerboseCompiler()) + qWarning() << "*** unknown symbol:" << name; } - - if (!found && qmlVerboseCompiler()) - qWarning() << "*** unknown symbol:" << name; } if (_expr.code && _expr.hint == ExprResult::cx) { @@ -544,7 +539,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FalseLiteral *) bool QDeclarativeV4IRBuilder::visit(AST::StringLiteral *ast) { // ### TODO: cx format - _expr.code = _block->STRING(ast->value->asString()); + _expr.code = _block->STRING(ast->value); return false; } @@ -581,14 +576,14 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) const quint32 line = ast->identifierToken.startLine; const quint32 column = ast->identifierToken.startColumn; - QString name = ast->name->asString(); + QString name = ast->name.toString(); switch(baseName->symbol) { case IR::Name::Unbound: break; case IR::Name::AttachType: - if (name.at(0).isUpper()) { + if (QDeclarativeUtils::isUpper(name.at(0))) { QByteArray utf8Name = name.toUtf8(); const char *enumName = utf8Name.constData(); @@ -606,7 +601,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) if (!found && qmlVerboseCompiler()) qWarning() << "*** unresolved enum:" - << (baseName->id + QLatin1String(".") + ast->name->asString()); + << (*baseName->id + QLatin1String(".") + ast->name.toString()); } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) { QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta); QDeclarativePropertyCache::Data *data = cache->property(name); @@ -617,7 +612,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) if(!data->isFinal()) { if (qmlVerboseCompiler()) qWarning() << "*** non-final attached property:" - << (baseName->id + QLatin1String(".") + ast->name->asString()); + << (*baseName->id + QLatin1String(".") + ast->name.toString()); return false; // We don't know enough about this property } @@ -627,7 +622,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) break; case IR::Name::IdObject: { - const QDeclarativeParser::Object *idObject = baseName->idObject; + const QDeclarativeScript::Object *idObject = baseName->idObject; QDeclarativePropertyCache *cache = idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject()); @@ -663,7 +658,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) if(!data->isFinal()) { if (qmlVerboseCompiler()) qWarning() << "*** non-final property access:" - << (baseName->id + QLatin1String(".") + ast->name->asString()); + << (*baseName->id + QLatin1String(".") + ast->name.toString()); return false; // We don't know enough about this property } @@ -683,6 +678,11 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast) return false; } +bool QDeclarativeV4IRBuilder::preVisit(AST::Node *) +{ + return ! _discard; +} + bool QDeclarativeV4IRBuilder::visit(AST::NewMemberExpression *) { return false; @@ -695,18 +695,30 @@ bool QDeclarativeV4IRBuilder::visit(AST::NewExpression *) bool QDeclarativeV4IRBuilder::visit(AST::CallExpression *ast) { - QStringList names; + QList<QStringRef> names; QList<AST::ExpressionNode *> nameNodes; + + names.reserve(4); + nameNodes.reserve(4); + if (buildName(names, ast->base, &nameNodes)) { //ExprResult base = expression(ast->base); - const QString id = names.join(QLatin1String(".")); - const quint32 line = nameNodes.last()->firstSourceLocation().startLine; - const quint32 column = nameNodes.last()->firstSourceLocation().startColumn; - IR::Expr *base = _block->NAME(id, line, column); - - QVector<IR::Expr *> args; - for (AST::ArgumentList *it = ast->arguments; it; it = it->next) - args.append(expression(it->expression)); + QString id; + for (int i = 0; i < names.size(); ++i) { + if (! i) + id += QLatin1Char('.'); + id += names.at(i); + } + const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation(); + IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn); + + IR::ExprList *args = 0, **argsInserter = &args; + for (AST::ArgumentList *it = ast->arguments; it; it = it->next) { + IR::Expr *arg = expression(it->expression); + *argsInserter = _function->pool->New<IR::ExprList>(); + (*argsInserter)->init(arg); + argsInserter = &(*argsInserter)->next; + } IR::Temp *r = _block->TEMP(IR::InvalidType); IR::Expr *call = _block->CALL(base, args); diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h b/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h index 69f9cbabed..004e3a1a11 100644 --- a/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h @@ -55,7 +55,7 @@ class QDeclarativeV4IRBuilder : public QDeclarativeJS::AST::Visitor public: QDeclarativeV4IRBuilder(const QDeclarativeV4Compiler::Expression *, QDeclarativeEnginePrivate *); - QDeclarativeJS::IR::Function *operator()(QDeclarativeJS::IR::Module *, QDeclarativeJS::AST::Node *); + bool operator()(QDeclarativeJS::IR::Function *, QDeclarativeJS::AST::Node *); protected: struct ExprResult { @@ -115,6 +115,8 @@ protected: void implicitCvt(ExprResult &expr, QDeclarativeJS::IR::Type type); + virtual bool preVisit(QDeclarativeJS::AST::Node *ast); + // QML virtual bool visit(QDeclarativeJS::AST::UiProgram *ast); virtual bool visit(QDeclarativeJS::AST::UiImportList *ast); @@ -220,14 +222,13 @@ protected: virtual bool visit(QDeclarativeJS::AST::DebuggerStatement *ast); private: - bool buildName(QStringList &name, QDeclarativeJS::AST::Node *node, + bool buildName(QList<QStringRef> &name, QDeclarativeJS::AST::Node *node, QList<QDeclarativeJS::AST::ExpressionNode *> *nodes); void discard(); const QDeclarativeV4Compiler::Expression *m_expression; QDeclarativeEnginePrivate *m_engine; - QDeclarativeJS::IR::Module *_module; QDeclarativeJS::IR::Function *_function; QDeclarativeJS::IR::BasicBlock *_block; bool _discard; diff --git a/src/declarative/qml/v8/qhashedstring.cpp b/src/declarative/qml/v8/qhashedstring.cpp deleted file mode 100644 index 2e2af98ff4..0000000000 --- a/src/declarative/qml/v8/qhashedstring.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qhashedstring_p.h" - -inline unsigned stringHash(const QChar* data, unsigned length) -{ - return v8::String::ComputeHash((uint16_t *)data, length); -} - -void QHashedString::computeHash() const -{ - m_hash = stringHash(constData(), length()); -} - -void QHashedStringRef::computeHash() const -{ - m_hash = stringHash(m_data, m_length); -} - -/* - A QHash has initially around pow(2, MinNumBits) buckets. For - example, if MinNumBits is 4, it has 17 buckets. -*/ -const int MinNumBits = 4; - -/* - The prime_deltas array is a table of selected prime values, even - though it doesn't look like one. The primes we are using are 1, - 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate - surrounding of a power of two. - - The primeForNumBits() function returns the prime associated to a - power of two. For example, primeForNumBits(8) returns 257. -*/ - -static const uchar prime_deltas[] = { - 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, - 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 -}; - -static inline int primeForNumBits(int numBits) -{ - return (1 << numBits) + prime_deltas[numBits]; -} - -void QStringHashData::rehash() -{ - numBits = qMax(MinNumBits, numBits + 1); - numBuckets = primeForNumBits(numBits); - - delete [] buckets; - buckets = new QStringHashNode *[numBuckets]; - ::memset(buckets, 0, sizeof(QStringHashNode *) * numBuckets); - - QStringHashNode *nodeList = nodes; - while (nodeList) { - int bucket = nodeList->key.hash() % numBuckets; - nodeList->next = buckets[bucket]; - buckets[bucket] = nodeList; - - nodeList = nodeList->nlist; - } -} - diff --git a/src/declarative/qml/v8/qhashedstring_p.h b/src/declarative/qml/v8/qhashedstring_p.h deleted file mode 100644 index e0ca1d466a..0000000000 --- a/src/declarative/qml/v8/qhashedstring_p.h +++ /dev/null @@ -1,664 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QHASHEDSTRING_P_H -#define QHASHEDSTRING_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtCore/qstring.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QHashedStringRef; -class QHashedString : public QString -{ -public: - inline QHashedString(); - inline QHashedString(const QString &string); - inline QHashedString(const QString &string, quint32); - inline QHashedString(const QHashedString &string); - - inline QHashedString &operator=(const QHashedString &string); - inline bool operator==(const QHashedString &string) const; - inline bool operator==(const QHashedStringRef &string) const; - - inline quint32 hash() const; - inline quint32 existingHash() const; - - static inline bool isUpper(const QChar &); -private: - friend class QHashedStringRef; - - void computeHash() const; - mutable quint32 m_hash; -}; - -class QHashedV8String -{ -public: - inline QHashedV8String(); - explicit inline QHashedV8String(v8::Handle<v8::String>); - inline QHashedV8String(const QHashedV8String &string); - inline QHashedV8String &operator=(const QHashedV8String &other); - - inline bool operator==(const QHashedV8String &string); - - inline quint32 hash() const; - inline int length() const; - inline quint32 symbolId() const; - - inline v8::Handle<v8::String> string() const; - -private: - v8::String::CompleteHashData m_hash; - v8::Handle<v8::String> m_string; -}; - -class QHashedStringRef -{ -public: - inline QHashedStringRef(); - inline QHashedStringRef(const QString &); - inline QHashedStringRef(const QChar *, int); - inline QHashedStringRef(const QChar *, int, quint32); - inline QHashedStringRef(const QHashedString &); - inline QHashedStringRef(const QHashedStringRef &); - - inline bool operator==(const QHashedString &string) const; - inline bool operator==(const QHashedStringRef &string) const; - - inline quint32 hash() const; - - inline const QChar *constData() const; - inline quint32 length() const; - inline bool startsWithUpper() const; - -private: - friend class QHashedString; - - void computeHash() const; - - const QChar *m_data; - quint32 m_length; - mutable quint32 m_hash; -}; - -class QStringHashData; -class QStringHashNode -{ -public: - QStringHashNode(const QHashedString &key) - : nlist(0), next(0), key(key), symbolId(0) { - } - - QStringHashNode *nlist; - QStringHashNode *next; - QHashedString key; - quint32 symbolId; - - inline bool equals(v8::Handle<v8::String> string) { - return string->Equals((uint16_t*)key.constData(), key.length()); - } -}; - -struct QStringHashData -{ -public: - QStringHashData() - : nodes(0), buckets(0), numBuckets(0), size(0), numBits(0) {} - - QStringHashNode *nodes; - QStringHashNode **buckets; - int numBuckets; - int size; - short numBits; - - void rehash(); -}; - -template<class T> -class QStringHash -{ -private: - struct Node : public QStringHashNode { - Node(const QHashedString &key, const T &value) : QStringHashNode(key), value(value) {} - T value; - }; - - QStringHashData data; - - inline Node *findNode(const QHashedStringRef &) const; - inline Node *findNode(const QHashedV8String &) const; - inline Node *findSymbolNode(const QHashedV8String &) const; - Node *createNode(const QHashedString &, const T &); - -public: - inline QStringHash(); - inline QStringHash(const QStringHash &); - inline ~QStringHash(); - - QStringHash &operator=(const QStringHash<T> &); - - inline bool isEmpty() const; - inline void clear(); - inline int count() const; - - inline void insert(const QString &, const T &); - inline void insert(const QHashedString &, const T &); - inline void insert(const QHashedStringRef &, const T &); - - inline T *value(const QString &) const; - inline T *value(const QHashedString &) const; - inline T *value(const QHashedStringRef &) const; - inline T *value(const QHashedV8String &) const; - - inline bool contains(const QString &) const; - inline bool contains(const QHashedString &) const; - inline bool contains(const QHashedStringRef &) const; - - T &operator[](const QString &); - T &operator[](const QHashedString &); - T &operator[](const QHashedStringRef &); - - class ConstIterator { - public: - ConstIterator() : n(0) {} - ConstIterator(Node *n) : n(n) {} - - ConstIterator &operator++() { n = (Node *)n->nlist; return *this; } - bool operator==(const ConstIterator &o) const { return n == o.n; } - bool operator!=(const ConstIterator &o) const { return n != o.n; } - - const QHashedString &key() const { return n->key; } - const T &value() const { return n->value; } - const T &operator*() const { return n->value; } - private: - Node *n; - }; - - ConstIterator begin() const { return ConstIterator((Node *)data.nodes); } - ConstIterator end() const { return ConstIterator(); } -}; - -template<class T> -QStringHash<T>::QStringHash() -{ -} - -template<class T> -QStringHash<T>::QStringHash(const QStringHash<T> &other) -: data(other.data) -{ - data.nodes = 0; - data.buckets = 0; - - QStringHashNode *n = other.data.nodes; - while (n) { - Node *o = (Node *)n; - Node *mynode = new Node(o->key, o->value); - mynode->nlist = data.nodes; - data.nodes = mynode; - n = o->nlist; - } - - data.rehash(); -} - -template<class T> -QStringHash<T> &QStringHash<T>::operator=(const QStringHash<T> &other) -{ - if (&other == this) - return *this; - - clear(); - data = other.data; - data.nodes = 0; - data.buckets = 0; - - QStringHashNode *n = other.data.nodes; - while (n) { - Node *o = (Node *)n; - Node *mynode = new Node(o->key, o->value); - mynode->nlist = data.nodes; - data.nodes = mynode; - n = o->nlist; - } - - data.rehash(); - - return *this; -} - -template<class T> -QStringHash<T>::~QStringHash() -{ - clear(); -} - -template<class T> -void QStringHash<T>::clear() -{ - QStringHashNode *n = data.nodes; - while (n) { - Node *o = (Node *)n; - n = n->nlist; - delete o; - } - - delete [] data.buckets; - - data = QStringHashData(); -} - -template<class T> -bool QStringHash<T>::isEmpty() const -{ - return data.nodes == 0; -} - -template<class T> -int QStringHash<T>::count() const -{ - return data.size; -} - -template<class T> -typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedString &key, const T &value) -{ - if (data.size == data.numBuckets) - data.rehash(); - - Node *n = new Node(key, value); - n->nlist = data.nodes; - data.nodes = n; - - int bucket = key.hash() % data.numBuckets; - n->next = data.buckets[bucket]; - data.buckets[bucket] = n; - - data.size++; - - return n; -} - -template<class T> -void QStringHash<T>::insert(const QString &key, const T &value) -{ - QHashedStringRef ch(key); - Node *n = findNode(key); - if (n) n->value = value; - else createNode(QHashedString(key, ch.hash()), value); -} - -template<class T> -void QStringHash<T>::insert(const QHashedString &key, const T &value) -{ - Node *n = findNode(key); - if (n) n->value = value; - else createNode(key, value); -} - -template<class T> -void QStringHash<T>::insert(const QHashedStringRef &key, const T &value) -{ - Node *n = findNode(key); - if (n) n->value = value; - else createNode(key, value); -} - -template<class T> -typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedStringRef &string) const -{ - QStringHashNode *node = 0; - if (data.numBuckets) { - node = data.buckets[string.hash() % data.numBuckets]; - while (node && !(node->key == string)) - node = node->next; - } - - return (Node *)node; -} - -template<class T> -typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedV8String &string) const -{ - QStringHashNode *node = 0; - if (data.numBuckets) { - quint32 hash = string.hash(); - node = data.buckets[hash % data.numBuckets]; - int length = string.length(); - while (node && (length != node->key.length() || hash != node->key.hash() || !node->equals(string.string()))) - node = node->next; - } - - return (Node *)node; -} - -template<class T> -typename QStringHash<T>::Node *QStringHash<T>::findSymbolNode(const QHashedV8String &string) const -{ - Q_ASSERT(string.symbolId() != 0); - - QStringHashNode *node = 0; - if (data.numBuckets) { - quint32 hash = string.hash(); - quint32 symbolId = string.symbolId(); - node = data.buckets[hash % data.numBuckets]; - int length = string.length(); - while (node && (length != node->key.length() || hash != node->key.hash() || - !(node->symbolId == symbolId || node->equals(string.string())))) - node = node->next; - if (node) - node->symbolId = symbolId; - } - - return (Node *)node; -} - -template<class T> -T *QStringHash<T>::value(const QString &key) const -{ - Node *n = findNode(key); - return n?&n->value:0; -} - -template<class T> -T *QStringHash<T>::value(const QHashedString &key) const -{ - Node *n = findNode(key); - return n?&n->value:0; -} - -template<class T> -T *QStringHash<T>::value(const QHashedStringRef &key) const -{ - Node *n = findNode(key); - return n?&n->value:0; -} - -template<class T> -T *QStringHash<T>::value(const QHashedV8String &string) const -{ - Node *n = string.symbolId()?findSymbolNode(string):findNode(string); - return n?&n->value:0; -} - -template<class T> -bool QStringHash<T>::contains(const QString &s) const -{ - return 0 != value(s); -} - -template<class T> -bool QStringHash<T>::contains(const QHashedString &s) const -{ - return 0 != value(s); -} -template<class T> -bool QStringHash<T>::contains(const QHashedStringRef &s) const -{ - return 0 != value(s); -} - -template<class T> -T &QStringHash<T>::operator[](const QString &key) -{ - QHashedStringRef cs(key); - Node *n = findNode(cs); - if (n) return n->value; - else return createNode(QHashedString(key, cs.hash()), T())->value; -} - -template<class T> -T &QStringHash<T>::operator[](const QHashedString &key) -{ - Node *n = findNode(key); - if (n) return n->value; - else return createNode(key, T())->value; -} - -template<class T> -T &QStringHash<T>::operator[](const QHashedStringRef &key) -{ - Node *n = findNode(key); - if (n) return n->value; - else return createNode(key, T())->value; -} - -inline uint qHash(const QHashedString &string) -{ - return uint(string.hash()); -} - -inline uint qHash(const QHashedStringRef &string) -{ - return uint(string.hash()); -} - -QHashedString::QHashedString() -: QString(), m_hash(0) -{ -} - -QHashedString::QHashedString(const QString &string) -: QString(string), m_hash(0) -{ -} - -QHashedString::QHashedString(const QString &string, quint32 hash) -: QString(string), m_hash(hash) -{ -} - -QHashedString::QHashedString(const QHashedString &string) -: QString(string), m_hash(string.m_hash) -{ -} - -QHashedString &QHashedString::operator=(const QHashedString &string) -{ - static_cast<QString &>(*this) = string; - m_hash = string.m_hash; - return *this; -} - -bool QHashedString::operator==(const QHashedString &string) const -{ - return (string.m_hash == m_hash || !string.m_hash || !m_hash) && - static_cast<const QString &>(*this) == static_cast<const QString &>(string); -} - -bool QHashedString::operator==(const QHashedStringRef &string) const -{ - return (uint)length() == string.m_length && - (string.m_hash == m_hash || !string.m_hash || !m_hash) && - 0 == ::memcmp(constData(), string.m_data, string.m_length * sizeof(QChar)); -} - -quint32 QHashedString::hash() const -{ - if (!m_hash) computeHash(); - return m_hash; -} - -quint32 QHashedString::existingHash() const -{ - return m_hash; -} - -bool QHashedString::isUpper(const QChar &qc) -{ - ushort c = qc.unicode(); - // Optimize for _, a-z and A-Z. - return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) && - ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase)); -} - -QHashedV8String::QHashedV8String() -{ -} - -QHashedV8String::QHashedV8String(v8::Handle<v8::String> string) -: m_hash(string->CompleteHash()), m_string(string) -{ - Q_ASSERT(!m_string.IsEmpty()); -} - -QHashedV8String::QHashedV8String(const QHashedV8String &string) -: m_hash(string.m_hash), m_string(string.m_string) -{ -} - -QHashedV8String &QHashedV8String::operator=(const QHashedV8String &other) -{ - m_hash = other.m_hash; - m_string = other.m_string; - return *this; -} - -bool QHashedV8String::operator==(const QHashedV8String &string) -{ - return m_hash.hash == string.m_hash.hash && m_hash.length == string.m_hash.length && - m_string.IsEmpty() == m_string.IsEmpty() && - (m_string.IsEmpty() || m_string->StrictEquals(string.m_string)); -} - -quint32 QHashedV8String::hash() const -{ - return m_hash.hash; -} - -int QHashedV8String::length() const -{ - return m_hash.length; -} - -quint32 QHashedV8String::symbolId() const -{ - return m_hash.symbol_id; -} - -v8::Handle<v8::String> QHashedV8String::string() const -{ - return m_string; -} - -QHashedStringRef::QHashedStringRef() -: m_data(0), m_length(0), m_hash(0) -{ -} - -QHashedStringRef::QHashedStringRef(const QString &str) -: m_data(str.constData()), m_length(str.length()), m_hash(0) -{ -} - -QHashedStringRef::QHashedStringRef(const QChar *data, int length) -: m_data(data), m_length(length), m_hash(0) -{ -} - -QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash) -: m_data(data), m_length(length), m_hash(hash) -{ -} - -QHashedStringRef::QHashedStringRef(const QHashedString &string) -: m_data(string.constData()), m_length(string.length()), m_hash(string.m_hash) -{ -} - -QHashedStringRef::QHashedStringRef(const QHashedStringRef &string) -: m_data(string.m_data), m_length(string.m_length), m_hash(string.m_hash) -{ -} - -bool QHashedStringRef::operator==(const QHashedString &string) const -{ - return m_length == (uint)string.length() && - (m_hash == string.m_hash || !m_hash || !string.m_hash) && - 0 == ::memcmp(string.constData(), m_data, m_length * sizeof(QChar)); -} - -bool QHashedStringRef::operator==(const QHashedStringRef &string) const -{ - return m_length == string.m_length && - (m_hash == string.m_hash || !m_hash || !string.m_hash) && - 0 == ::memcmp(string.m_data, m_data, m_length * sizeof(QChar)); -} - -const QChar *QHashedStringRef::constData() const -{ - return m_data; -} - -quint32 QHashedStringRef::length() const -{ - return m_length; -} - -bool QHashedStringRef::startsWithUpper() const -{ - if (m_length < 1) return false; - return QHashedString::isUpper(m_data[0]); -} - -quint32 QHashedStringRef::hash() const -{ - if (!m_hash) computeHash(); - return m_hash; -} - -QT_END_NAMESPACE - -#endif // QHASHEDSTRING_P_H diff --git a/src/declarative/qml/v8/qv8_p.h b/src/declarative/qml/v8/qv8_p.h index 8df007e804..d41fb559f7 100644 --- a/src/declarative/qml/v8/qv8_p.h +++ b/src/declarative/qml/v8/qv8_p.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include "../../../3rdparty/v8/include/v8.h" +#include <private/v8.h> diff --git a/src/declarative/qml/v8/qv8contextwrapper.cpp b/src/declarative/qml/v8/qv8contextwrapper.cpp index f41c994a0d..29857b2585 100644 --- a/src/declarative/qml/v8/qv8contextwrapper.cpp +++ b/src/declarative/qml/v8/qv8contextwrapper.cpp @@ -282,19 +282,19 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property, if (context->imports && QV8Engine::startsWithUpper(property)) { // Search for attached properties, enums and imported scripts - QDeclarativeTypeNameCache::Data *data = context->imports->data(propertystring); - - if (data) { - if (data->importedScriptIndex != -1) { - int index = data->importedScriptIndex; + QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring); + + if (r.isValid()) { + if (r.scriptIndex != -1) { + int index = r.scriptIndex; if (index < context->importedScripts.count()) return context->importedScripts.at(index); else return v8::Undefined(); - } else if (data->type) { - return engine->typeWrapper()->newObject(scopeObject, data->type); - } else if (data->typeNamespace) { - return engine->typeWrapper()->newObject(scopeObject, data->typeNamespace); + } else if (r.type) { + return engine->typeWrapper()->newObject(scopeObject, r.type); + } else if (r.importNamespace) { + return engine->typeWrapper()->newObject(scopeObject, context->imports, r.importNamespace); } Q_ASSERT(!"Unreachable"); } diff --git a/src/declarative/qml/v8/qv8debug_p.h b/src/declarative/qml/v8/qv8debug_p.h index 51208aac8e..e6bfdb7845 100644 --- a/src/declarative/qml/v8/qv8debug_p.h +++ b/src/declarative/qml/v8/qv8debug_p.h @@ -1 +1 @@ -#include "../../../3rdparty/v8/include/v8-debug.h" +#include <private/v8-debug.h> diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index 4f5caa13f4..8eaf9024ea 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -391,7 +391,7 @@ QNetworkAccessManager *QV8Engine::networkAccessManager() return QDeclarativeEnginePrivate::get(m_engine)->getNetworkAccessManager(); } -const QSet<QString> &QV8Engine::illegalNames() const +const QStringHash<bool> &QV8Engine::illegalNames() const { return m_illegalNames; } @@ -561,7 +561,7 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global) v8::Local<v8::Value> names = m_getOwnPropertyNames->Call(global, 1, args); v8::Local<v8::Array> namesArray = v8::Local<v8::Array>::Cast(names); for (quint32 ii = 0; ii < namesArray->Length(); ++ii) - m_illegalNames.insert(toString(namesArray->Get(ii))); + m_illegalNames.insert(toString(namesArray->Get(ii)), true); } { diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h index 43ef9821ac..bd5f360748 100644 --- a/src/declarative/qml/v8/qv8engine_p.h +++ b/src/declarative/qml/v8/qv8engine_p.h @@ -330,7 +330,7 @@ public: virtual QNetworkAccessManager *networkAccessManager(); // Return the list of illegal id names (the names of the properties on the global object) - const QSet<QString> &illegalNames() const; + const QStringHash<bool> &illegalNames() const; inline void collectGarbage() { gc(); } static void gc(); @@ -419,7 +419,7 @@ protected: QVector<Deletable *> m_extensionData; Deletable *m_listModelData; - QSet<QString> m_illegalNames; + QStringHash<bool> m_illegalNames; Exception m_exception; diff --git a/src/declarative/qml/v8/qv8include.cpp b/src/declarative/qml/v8/qv8include.cpp index 1d68e8e4be..2e23914f2d 100644 --- a/src/declarative/qml/v8/qv8include.cpp +++ b/src/declarative/qml/v8/qv8include.cpp @@ -130,7 +130,7 @@ void QV8Include::finished() QByteArray data = m_reply->readAll(); QString code = QString::fromUtf8(data); - QDeclarativeScriptParser::extractPragmas(code); + QDeclarativeScript::Parser::extractPragmas(code); QDeclarativeContextData *importContext = new QDeclarativeContextData; importContext->isInternal = true; @@ -203,7 +203,7 @@ v8::Handle<v8::Value> QV8Include::include(const v8::Arguments &args) if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); QString code = QString::fromUtf8(data); - QDeclarativeScriptParser::extractPragmas(code); + QDeclarativeScript::Parser::extractPragmas(code); QDeclarativeContextData *importContext = new QDeclarativeContextData; importContext->isInternal = true; diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp index c7ed0116e1..52e106494c 100644 --- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp +++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp @@ -280,8 +280,8 @@ void QV8QObjectWrapper::init(QV8Engine *engine) { v8::Local<v8::Object> prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject(); - prototype->Set(v8::String::New("connect"), V8FUNCTION(Connect, engine)); - prototype->Set(v8::String::New("disconnect"), V8FUNCTION(Disconnect, engine)); + prototype->Set(v8::String::New("connect"), V8FUNCTION(Connect, engine), v8::DontEnum); + prototype->Set(v8::String::New("disconnect"), V8FUNCTION(Disconnect, engine), v8::DontEnum); } } @@ -618,14 +618,20 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property, if (QV8Engine::startsWithUpper(property)) { // Check for attached properties QDeclarativeContextData *context = v8engine->callingContext(); - QDeclarativeTypeNameCache::Data *data = - context && (context->imports)?context->imports->data(propertystring):0; - - if (data) { - if (data->type) { - return v8engine->typeWrapper()->newObject(object, data->type, QV8TypeWrapper::ExcludeEnums); - } else if (data->typeNamespace) { - return v8engine->typeWrapper()->newObject(object, data->typeNamespace, QV8TypeWrapper::ExcludeEnums); + + if (context && context->imports) { + QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring); + + if (r.isValid()) { + if (r.scriptIndex != -1) { + return v8::Undefined(); + } else if (r.type) { + return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums); + } else if (r.importNamespace) { + return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace, + QV8TypeWrapper::ExcludeEnums); + } + Q_ASSERT(!"Unreachable"); } } } diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp index c51a2eeb7f..f46aaab320 100644 --- a/src/declarative/qml/v8/qv8typewrapper.cpp +++ b/src/declarative/qml/v8/qv8typewrapper.cpp @@ -45,6 +45,9 @@ #include <private/qdeclarativeengine_p.h> #include <private/qdeclarativecontext_p.h> +#include <private/qjsvalue_p.h> +#include <private/qscript_impl_p.h> + QT_BEGIN_NAMESPACE class QV8TypeResource : public QV8ObjectResource @@ -58,12 +61,14 @@ public: QV8TypeWrapper::TypeNameMode mode; QDeclarativeGuard<QObject> object; + QDeclarativeType *type; QDeclarativeTypeNameCache *typeNamespace; + const void *importNamespace; }; QV8TypeResource::QV8TypeResource(QV8Engine *engine) -: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0) +: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0), importNamespace(0) { } @@ -95,6 +100,7 @@ void QV8TypeWrapper::init(QV8Engine *engine) m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); } +// Returns a type wrapper for type t on o. This allows access of enums, and attached properties. v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode) { Q_ASSERT(t); @@ -106,14 +112,18 @@ v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, return rv; } -v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, TypeNameMode mode) +// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a +// namespace. +v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, + const void *importNamespace, TypeNameMode mode) { Q_ASSERT(t); + Q_ASSERT(importNamespace); // XXX NewInstance() should be optimized v8::Local<v8::Object> rv = m_constructor->NewInstance(); QV8TypeResource *r = new QV8TypeResource(m_engine); t->addref(); - r->mode = mode; r->object = o; r->typeNamespace = t; + r->mode = mode; r->object = o; r->typeNamespace = t; r->importNamespace = importNamespace; rv->SetExternalResource(r); return rv; } @@ -136,19 +146,9 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, QDeclarativeType *type = resource->type; if (QV8Engine::startsWithUpper(property)) { - if (resource->mode == IncludeEnums) { - QString name = v8engine->toString(property); - - // ### Optimize - QByteArray enumName = name.toUtf8(); - const QMetaObject *metaObject = type->baseMetaObject(); - for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { - QMetaEnum e = metaObject->enumerator(ii); - int value = e.keyToValue(enumName.constData()); - if (value != -1) - return v8::Integer::New(value); - } - } + int value = type->enumValue(propertystring); + if (-1 != value) + return v8::Integer::New(value); // Fall through to return empty handle @@ -164,14 +164,15 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, // Fall through to return empty handle } else if (resource->typeNamespace) { + Q_ASSERT(resource->importNamespace); + QDeclarativeTypeNameCache::Result r = resource->typeNamespace->query(propertystring, + resource->importNamespace); - QDeclarativeTypeNameCache *typeNamespace = resource->typeNamespace; - QDeclarativeTypeNameCache::Data *d = typeNamespace->data(propertystring); - Q_ASSERT(!d || !d->typeNamespace); // Nested namespaces not supported + if (r.isValid()) { + Q_ASSERT(r.type); - if (d && d->type) { - return v8engine->typeWrapper()->newObject(object, d->type, resource->mode); - } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) { + return v8engine->typeWrapper()->newObject(object, r.type, resource->mode); + } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { if (moduleApi->scriptCallback) { moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); @@ -184,8 +185,31 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, } if (moduleApi->qobjectApi) { + // check for enum value + if (QV8Engine::startsWithUpper(property)) { + if (resource->mode == IncludeEnums) { + QString name = v8engine->toString(property); + + // ### Optimize + QByteArray enumName = name.toUtf8(); + const QMetaObject *metaObject = moduleApi->qobjectApi->metaObject(); + for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + int value = e.keyToValue(enumName.constData()); + if (value != -1) + return v8::Integer::New(value); + } + } + } + + // check for property. v8::Handle<v8::Value> rv = v8engine->qobjectWrapper()->getProperty(moduleApi->qobjectApi, propertystring, QV8QObjectWrapper::IgnoreRevision); return rv; + } else if (moduleApi->scriptApi.isValid()) { + // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable. + QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi); + QScopedPointer<QJSValuePrivate> propertyValue(apiprivate->property(property).give()); + return propertyValue->asV8Value(v8engine); } else { return v8::Handle<v8::Value>(); } @@ -212,8 +236,6 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, QV8Engine *v8engine = resource->engine; - // XXX TODO: Implement writes to module API objects - QHashedV8String propertystring(property); if (resource->type && resource->object) { @@ -224,7 +246,7 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, v8engine->qobjectWrapper()->setProperty(ao, propertystring, value, QV8QObjectWrapper::IgnoreRevision); } else if (resource->typeNamespace) { - if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi()) { + if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { if (moduleApi->scriptCallback) { moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); moduleApi->scriptCallback = 0; @@ -235,9 +257,20 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, moduleApi->qobjectCallback = 0; } - if (moduleApi->qobjectApi) + if (moduleApi->qobjectApi) { v8engine->qobjectWrapper()->setProperty(moduleApi->qobjectApi, propertystring, value, QV8QObjectWrapper::IgnoreRevision); + } else if (moduleApi->scriptApi.isValid()) { + QScopedPointer<QJSValuePrivate> setvalp(new QJSValuePrivate(v8engine, value)); + QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi); + if (apiprivate->propertyFlags(property) & QJSValue::ReadOnly) { + QString error = QLatin1String("Cannot assign to read-only property \"") + + v8engine->toString(property) + QLatin1Char('\"'); + v8::ThrowException(v8::Exception::Error(v8engine->toString(error))); + } else { + apiprivate->setProperty(property, setvalp.data()); + } + } } } diff --git a/src/declarative/qml/v8/qv8typewrapper_p.h b/src/declarative/qml/v8/qv8typewrapper_p.h index e7403dfa40..2e79946a6e 100644 --- a/src/declarative/qml/v8/qv8typewrapper_p.h +++ b/src/declarative/qml/v8/qv8typewrapper_p.h @@ -73,7 +73,8 @@ public: enum TypeNameMode { IncludeEnums, ExcludeEnums }; v8::Local<v8::Object> newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums); - v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums); + v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, const void *, + TypeNameMode = IncludeEnums); private: static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri index 9349742c78..175efd6b6c 100644 --- a/src/declarative/qml/v8/v8.pri +++ b/src/declarative/qml/v8/v8.pri @@ -8,7 +8,6 @@ HEADERS += \ $$PWD/qv8debug_p.h \ $$PWD/qv8stringwrapper_p.h \ $$PWD/qv8engine_p.h \ - $$PWD/qhashedstring_p.h \ $$PWD/qv8contextwrapper_p.h \ $$PWD/qv8qobjectwrapper_p.h \ $$PWD/qv8typewrapper_p.h \ @@ -25,7 +24,6 @@ HEADERS += \ SOURCES += \ $$PWD/qv8stringwrapper.cpp \ $$PWD/qv8engine.cpp \ - $$PWD/qhashedstring.cpp \ $$PWD/qv8contextwrapper.cpp \ $$PWD/qv8qobjectwrapper.cpp \ $$PWD/qv8typewrapper.cpp \ diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 11e1c7cc0a..6cdba7c5d9 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -827,12 +827,8 @@ void QDeclarativeScriptActionPrivate::execute() QDeclarativeScriptString scriptStr = hasRunScriptScript ? runScriptScript : script; - const QString &str = scriptStr.script(); - if (!str.isEmpty()) { - QDeclarativeExpression expr(scriptStr.context(), scriptStr.scopeObject(), str); - QDeclarativeData *ddata = QDeclarativeData::get(q); - if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) - expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); + if (!scriptStr.script().isEmpty()) { + QDeclarativeExpression expr(scriptStr); expr.evaluate(); if (expr.hasError()) qmlInfo(q) << expr.error(); diff --git a/src/declarative/util/qdeclarativeconnections.cpp b/src/declarative/util/qdeclarativeconnections.cpp index 6559d4bb20..57bb79c302 100644 --- a/src/declarative/util/qdeclarativeconnections.cpp +++ b/src/declarative/util/qdeclarativeconnections.cpp @@ -220,7 +220,7 @@ QDeclarativeConnectionsParser::compile(const QList<QDeclarativeCustomParserPrope error(props.at(ii), QDeclarativeConnections::tr("Connections: syntax error")); return QByteArray(); } else { - QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(value); + QDeclarativeScript::Variant v = qvariant_cast<QDeclarativeScript::Variant>(value); if (v.isScript()) { ds << propName; ds << v.asScript(); diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp index 7a1dec88f0..f7a7738172 100644 --- a/src/declarative/util/qdeclarativefontloader.cpp +++ b/src/declarative/util/qdeclarativefontloader.cpp @@ -193,10 +193,9 @@ void QDeclarativeFontLoader::setSource(const QUrl &url) Q_D(QDeclarativeFontLoader); if (url == d->url) return; - d->url = qmlContext(this)->resolvedUrl(url); + d->url = url; emit sourceChanged(); -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url); if (!localFile.isEmpty()) { if (!d->fonts.contains(d->url)) { @@ -211,9 +210,7 @@ void QDeclarativeFontLoader::setSource(const QUrl &url) } else { updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready); } - } else -#endif - { + } else { if (!d->fonts.contains(d->url)) { QDeclarativeFontObject *fo = new QDeclarativeFontObject; d->fonts[d->url] = fo; diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 15d87c828d..3add850570 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -46,7 +46,7 @@ #include "parser/qdeclarativejsengine_p.h" #include <qdeclarativecustomparser_p.h> -#include <qdeclarativeparser_p.h> +#include <qdeclarativescript_p.h> #include <qdeclarativeengine_p.h> #include <qdeclarativecontext.h> #include <qdeclarativeinfo.h> @@ -822,8 +822,8 @@ bool QDeclarativeListModelParser::compileProperty(const QDeclarativeCustomParser } else { - QDeclarativeParser::Variant variant = - qvariant_cast<QDeclarativeParser::Variant>(value); + QDeclarativeScript::Variant variant = + qvariant_cast<QDeclarativeScript::Variant>(value); int ref = data.count(); @@ -837,7 +837,7 @@ bool QDeclarativeListModelParser::compileProperty(const QDeclarativeCustomParser d += char(variant.asBoolean()); } else if (variant.isScript()) { if (definesEmptyList(variant.asScript())) { - d[0] = char(QDeclarativeParser::Variant::Invalid); // marks empty list + d[0] = char(QDeclarativeScript::Variant::Invalid); // marks empty list } else { QByteArray script = variant.asScript().toUtf8(); int v = evaluateEnum(script); @@ -847,14 +847,14 @@ bool QDeclarativeListModelParser::compileProperty(const QDeclarativeCustomParser AST::StringLiteral *literal = 0; if (AST::CallExpression *callExpr = AST::cast<AST::CallExpression *>(node)) { if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(callExpr->base)) { - if (idExpr->name->asString() == QLatin1String("QT_TR_NOOP")) { + if (idExpr->name == QLatin1String("QT_TR_NOOP") || idExpr->name == QLatin1String("QT_TRID_NOOP")) { if (callExpr->arguments && !callExpr->arguments->next) literal = AST::cast<AST::StringLiteral *>(callExpr->arguments->expression); if (!literal) { - error(prop, QDeclarativeListModel::tr("ListElement: improperly specified QT_TR_NOOP")); + error(prop, QDeclarativeListModel::tr("ListElement: improperly specified %1").arg(idExpr->name.toString())); return false; } - } else if (idExpr->name->asString() == QLatin1String("QT_TRANSLATE_NOOP")) { + } else if (idExpr->name == QLatin1String("QT_TRANSLATE_NOOP")) { if (callExpr->arguments && callExpr->arguments->next && !callExpr->arguments->next->next) literal = AST::cast<AST::StringLiteral *>(callExpr->arguments->next->expression); if (!literal) { @@ -866,14 +866,14 @@ bool QDeclarativeListModelParser::compileProperty(const QDeclarativeCustomParser } if (literal) { - d[0] = char(QDeclarativeParser::Variant::String); - d += literal->value->asString().toUtf8(); + d[0] = char(QDeclarativeScript::Variant::String); + d += literal->value.toUtf8(); } else { error(prop, QDeclarativeListModel::tr("ListElement: cannot use script for property value")); return false; } } else { - d[0] = char(QDeclarativeParser::Variant::Number); + d[0] = char(QDeclarativeScript::Variant::Number); d += QByteArray::number(v); } } @@ -932,6 +932,7 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & QDeclarativeListModel *rv = static_cast<QDeclarativeListModel *>(obj); ModelNode *root = new ModelNode(rv->m_nested); + rv->m_nested->m_ownsRoot = true; rv->m_nested->_root = root; QStack<ModelNode *> nodes; nodes << root; @@ -963,17 +964,17 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & case ListInstruction::Value: { ModelNode *n = nodes.top(); - switch (QDeclarativeParser::Variant::Type(data[instr.dataIdx])) { - case QDeclarativeParser::Variant::Invalid: + switch (QDeclarativeScript::Variant::Type(data[instr.dataIdx])) { + case QDeclarativeScript::Variant::Invalid: n->isArray = true; break; - case QDeclarativeParser::Variant::Boolean: + case QDeclarativeScript::Variant::Boolean: n->values.append(bool(data[1 + instr.dataIdx])); break; - case QDeclarativeParser::Variant::Number: + case QDeclarativeScript::Variant::Number: n->values.append(QByteArray(data + 1 + instr.dataIdx).toDouble()); break; - case QDeclarativeParser::Variant::String: + case QDeclarativeScript::Variant::String: n->values.append(QString::fromUtf8(data + 1 + instr.dataIdx)); break; default: diff --git a/src/declarative/util/qdeclarativepackage_p.h b/src/declarative/util/qdeclarativepackage_p.h index df6bfe9b91..8ae88488d0 100644 --- a/src/declarative/util/qdeclarativepackage_p.h +++ b/src/declarative/util/qdeclarativepackage_p.h @@ -58,7 +58,7 @@ class Q_AUTOTEST_EXPORT QDeclarativePackage : public QObject Q_DECLARE_PRIVATE(QDeclarativePackage) Q_CLASSINFO("DefaultProperty", "data") - Q_PROPERTY(QDeclarativeListProperty<QObject> data READ data SCRIPTABLE false) + Q_PROPERTY(QDeclarativeListProperty<QObject> data READ data) public: QDeclarativePackage(QObject *parent=0); diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index d03cd3bb1a..039803002c 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -48,7 +48,7 @@ #include <qdeclarativeinfo.h> #include <qdeclarativecustomparser_p.h> -#include <qdeclarativeparser_p.h> +#include <qdeclarativescript_p.h> #include <qdeclarativeexpression.h> #include <qdeclarativebinding_p.h> #include <qdeclarativecontext.h> @@ -279,22 +279,22 @@ QDeclarativePropertyChangesParser::compile(const QList<QDeclarativeCustomParserP ds << data.count(); for(int ii = 0; ii < data.count(); ++ii) { - QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(data.at(ii).second); + QDeclarativeScript::Variant v = qvariant_cast<QDeclarativeScript::Variant>(data.at(ii).second); QVariant var; bool isScript = v.isScript(); QDeclarativeBinding::Identifier id = 0; switch(v.type()) { - case QDeclarativeParser::Variant::Boolean: + case QDeclarativeScript::Variant::Boolean: var = QVariant(v.asBoolean()); break; - case QDeclarativeParser::Variant::Number: + case QDeclarativeScript::Variant::Number: var = QVariant(v.asNumber()); break; - case QDeclarativeParser::Variant::String: + case QDeclarativeScript::Variant::String: var = QVariant(v.asString()); break; - case QDeclarativeParser::Variant::Invalid: - case QDeclarativeParser::Variant::Script: + case QDeclarativeScript::Variant::Invalid: + case QDeclarativeScript::Variant::Script: var = QVariant(v.asScript()); { // Pre-rewrite the expression diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index 32f36105fc..4f198a537e 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -131,12 +131,8 @@ void QDeclarativeStateChangeScript::setName(const QString &n) void QDeclarativeStateChangeScript::execute(Reason) { Q_D(QDeclarativeStateChangeScript); - const QString &script = d->script.script(); - if (!script.isEmpty()) { - QDeclarativeExpression expr(d->script.context(), d->script.scopeObject(), script); - QDeclarativeData *ddata = QDeclarativeData::get(this); - if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) - expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); + if (!d->script.script().isEmpty()) { + QDeclarativeExpression expr(d->script); expr.evaluate(); if (expr.hasError()) qmlInfo(this, expr.error()); diff --git a/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch b/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch deleted file mode 100644 index 1fb3b90733..0000000000 --- a/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch +++ /dev/null @@ -1,343 +0,0 @@ -From e13ce09287a56c920d5ffdc5d4662d49f1838f16 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Mon, 23 May 2011 15:47:20 +1000 -Subject: [PATCH 01/13] Add hashing and comparison methods to v8::String - -This allows us to more rapidly search for a v8::String inside -a hash of QStrings. ---- - include/v8.h | 44 ++++++++++++++++++++++++++++++ - src/api.cc | 43 +++++++++++++++++++++++++++++ - src/heap-inl.h | 2 + - src/heap.cc | 3 ++ - src/objects-inl.h | 1 + - src/objects.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++- - src/objects.h | 15 +++++++++- - 7 files changed, 182 insertions(+), 3 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index d15d024..bbd29e9 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -994,6 +994,48 @@ class String : public Primitive { - V8EXPORT int Utf8Length() const; - - /** -+ * Returns the hash of this string. -+ */ -+ V8EXPORT uint32_t Hash() const; -+ -+ struct CompleteHashData { -+ CompleteHashData() : length(0), hash(0), symbol_id(0) {} -+ int length; -+ uint32_t hash; -+ uint32_t symbol_id; -+ }; -+ -+ /** -+ * Returns the "complete" hash of the string. This is -+ * all the information about the string needed to implement -+ * a very efficient hash keyed on the string. -+ * -+ * The members of CompleteHashData are: -+ * length: The length of the string. Equivalent to Length() -+ * hash: The hash of the string. Equivalent to Hash() -+ * symbol_id: If the string is a sequential symbol, the symbol -+ * id, otherwise 0. If the symbol ids of two strings are -+ * the same (and non-zero) the two strings are identical. -+ * If the symbol ids are different the strings may still be -+ * identical, but an Equals() check must be performed. -+ */ -+ V8EXPORT CompleteHashData CompleteHash() const; -+ -+ /** -+ * Compute a hash value for the passed UTF16 string -+ * data. -+ */ -+ V8EXPORT static uint32_t ComputeHash(uint16_t *string, int length); -+ V8EXPORT static uint32_t ComputeHash(char *string, int length); -+ -+ /** -+ * Returns true if this string is equal to the external -+ * string data provided. -+ */ -+ V8EXPORT bool Equals(uint16_t *string, int length); -+ V8EXPORT bool Equals(char *string, int length); -+ -+ /** - * Write the contents of the string to an external buffer. - * If no arguments are given, expects the buffer to be large - * enough to hold the entire string and NULL terminator. Copies -@@ -1023,6 +1065,8 @@ class String : public Primitive { - HINT_MANY_WRITES_EXPECTED = 1 - }; - -+ V8EXPORT uint16_t GetCharacter(int index); -+ - V8EXPORT int Write(uint16_t* buffer, - int start = 0, - int length = -1, -diff --git a/src/api.cc b/src/api.cc -index a2373cd..381935b 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3284,6 +3284,49 @@ int String::Utf8Length() const { - return str->Utf8Length(); - } - -+uint32_t String::Hash() const { -+ i::Handle<i::String> str = Utils::OpenHandle(this); -+ if (IsDeadCheck(str->GetIsolate(), "v8::String::Hash()")) return 0; -+ return str->Hash(); -+} -+ -+String::CompleteHashData String::CompleteHash() const { -+ i::Handle<i::String> str = Utils::OpenHandle(this); -+ if (IsDeadCheck(str->GetIsolate(), "v8::String::CompleteHash()")) return CompleteHashData(); -+ CompleteHashData result; -+ result.length = str->length(); -+ result.hash = str->Hash(); -+ if (str->IsSeqString()) -+ result.symbol_id = i::SeqString::cast(*str)->symbol_id(); -+ return result; -+} -+ -+uint32_t String::ComputeHash(uint16_t *string, int length) { -+ return i::HashSequentialString<i::uc16>(string, length) >> i::String::kHashShift; -+} -+ -+uint32_t String::ComputeHash(char *string, int length) { -+ return i::HashSequentialString<char>(string, length) >> i::String::kHashShift; -+} -+ -+uint16_t String::GetCharacter(int index) -+{ -+ i::Handle<i::String> str = Utils::OpenHandle(this); -+ return str->Get(index); -+} -+ -+bool String::Equals(uint16_t *string, int length) { -+ i::Handle<i::String> str = Utils::OpenHandle(this); -+ if (IsDeadCheck(str->GetIsolate(), "v8::String::Equals()")) return 0; -+ return str->SlowEqualsExternal(string, length); -+} -+ -+bool String::Equals(char *string, int length) -+{ -+ i::Handle<i::String> str = Utils::OpenHandle(this); -+ if (IsDeadCheck(str->GetIsolate(), "v8::String::Equals()")) return 0; -+ return str->SlowEqualsExternal(string, length); -+} - - int String::WriteUtf8(char* buffer, - int capacity, -diff --git a/src/heap-inl.h b/src/heap-inl.h -index 99737ed..f4fce7b 100644 ---- a/src/heap-inl.h -+++ b/src/heap-inl.h -@@ -93,6 +93,7 @@ MaybeObject* Heap::AllocateAsciiSymbol(Vector<const char> str, - String* answer = String::cast(result); - answer->set_length(str.length()); - answer->set_hash_field(hash_field); -+ SeqString::cast(answer)->set_symbol_id(0); - - ASSERT_EQ(size, answer->Size()); - -@@ -126,6 +127,7 @@ MaybeObject* Heap::AllocateTwoByteSymbol(Vector<const uc16> str, - String* answer = String::cast(result); - answer->set_length(str.length()); - answer->set_hash_field(hash_field); -+ SeqString::cast(answer)->set_symbol_id(0); - - ASSERT_EQ(size, answer->Size()); - -diff --git a/src/heap.cc b/src/heap.cc -index 2b6c11f..930c97b 100644 ---- a/src/heap.cc -+++ b/src/heap.cc -@@ -3519,6 +3519,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, - String* answer = String::cast(result); - answer->set_length(chars); - answer->set_hash_field(hash_field); -+ SeqString::cast(result)->set_symbol_id(0); - - ASSERT_EQ(size, answer->Size()); - -@@ -3561,6 +3562,7 @@ MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { - HeapObject::cast(result)->set_map(ascii_string_map()); - String::cast(result)->set_length(length); - String::cast(result)->set_hash_field(String::kEmptyHashField); -+ SeqString::cast(result)->set_symbol_id(0); - ASSERT_EQ(size, HeapObject::cast(result)->Size()); - return result; - } -@@ -3596,6 +3598,7 @@ MaybeObject* Heap::AllocateRawTwoByteString(int length, - HeapObject::cast(result)->set_map(string_map()); - String::cast(result)->set_length(length); - String::cast(result)->set_hash_field(String::kEmptyHashField); -+ SeqString::cast(result)->set_symbol_id(0); - ASSERT_EQ(size, HeapObject::cast(result)->Size()); - return result; - } -diff --git a/src/objects-inl.h b/src/objects-inl.h -index 65aec5d..c82080d 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -1924,6 +1924,7 @@ INT_ACCESSORS(ExternalArray, length, kLengthOffset) - - - SMI_ACCESSORS(String, length, kLengthOffset) -+SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset) - - - uint32_t String::hash_field() { -diff --git a/src/objects.cc b/src/objects.cc -index df61956..dc4b260 100644 ---- a/src/objects.cc -+++ b/src/objects.cc -@@ -5346,6 +5346,66 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, - } - } - -+bool String::SlowEqualsExternal(uc16 *string, int length) { -+ int len = this->length(); -+ if (len != length) return false; -+ if (len == 0) return true; -+ -+ // We know the strings are both non-empty. Compare the first chars -+ // before we try to flatten the strings. -+ if (this->Get(0) != string[0]) return false; -+ -+ String* lhs = this->TryFlattenGetString(); -+ -+ if (lhs->IsFlat()) { -+ if (lhs->IsAsciiRepresentation()) { -+ Vector<const char> vec1 = lhs->ToAsciiVector(); -+ VectorIterator<char> buf1(vec1); -+ VectorIterator<uc16> ib(string, length); -+ return CompareStringContents(&buf1, &ib); -+ } else { -+ Vector<const uc16> vec1 = lhs->ToUC16Vector(); -+ Vector<const uc16> vec2(string, length); -+ return CompareRawStringContents(vec1, vec2); -+ } -+ } else { -+ Isolate* isolate = GetIsolate(); -+ isolate->objects_string_compare_buffer_a()->Reset(0, lhs); -+ VectorIterator<uc16> ib(string, length); -+ return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib); -+ } -+} -+ -+bool String::SlowEqualsExternal(char *string, int length) -+{ -+ int len = this->length(); -+ if (len != length) return false; -+ if (len == 0) return true; -+ -+ // We know the strings are both non-empty. Compare the first chars -+ // before we try to flatten the strings. -+ if (this->Get(0) != string[0]) return false; -+ -+ String* lhs = this->TryFlattenGetString(); -+ -+ if (StringShape(lhs).IsSequentialAscii()) { -+ const char* str1 = SeqAsciiString::cast(lhs)->GetChars(); -+ return CompareRawStringContents(Vector<const char>(str1, len), -+ Vector<const char>(string, len)); -+ } -+ -+ if (lhs->IsFlat()) { -+ Vector<const uc16> vec1 = lhs->ToUC16Vector(); -+ VectorIterator<const uc16> buf1(vec1); -+ VectorIterator<char> buf2(string, length); -+ return CompareStringContents(&buf1, &buf2); -+ } else { -+ Isolate* isolate = GetIsolate(); -+ isolate->objects_string_compare_buffer_a()->Reset(0, lhs); -+ VectorIterator<char> ib(string, length); -+ return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib); -+ } -+} - - bool String::SlowEquals(String* other) { - // Fast check: negative check with lengths. -@@ -8655,9 +8715,24 @@ class AsciiSymbolKey : public SequentialSymbolKey<char> { - - MaybeObject* AsObject() { - if (hash_field_ == 0) Hash(); -- return HEAP->AllocateAsciiSymbol(string_, hash_field_); -+ MaybeObject *result = HEAP->AllocateAsciiSymbol(string_, hash_field_); -+ if (!result->IsFailure() && result->ToObjectUnchecked()->IsSeqString()) { -+ while (true) { -+ Atomic32 my_symbol_id = next_symbol_id; -+ if (my_symbol_id > Smi::kMaxValue) -+ break; -+ if (my_symbol_id == NoBarrier_CompareAndSwap(&next_symbol_id, my_symbol_id, my_symbol_id + 1)) { -+ SeqString::cast(result->ToObjectUnchecked())->set_symbol_id(my_symbol_id); -+ break; -+ } -+ } -+ } -+ return result; - } -+ -+ static Atomic32 next_symbol_id; - }; -+Atomic32 AsciiSymbolKey::next_symbol_id = 1; - - - class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { -diff --git a/src/objects.h b/src/objects.h -index e966b3d..6e26f57 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -5359,6 +5359,9 @@ class String: public HeapObject { - bool IsAsciiEqualTo(Vector<const char> str); - bool IsTwoByteEqualTo(Vector<const uc16> str); - -+ bool SlowEqualsExternal(uc16 *string, int length); -+ bool SlowEqualsExternal(char *string, int length); -+ - // Return a UTF8 representation of the string. The string is null - // terminated but may optionally contain nulls. Length is returned - // in length_output if length_output is not a null pointer The string -@@ -5610,9 +5613,17 @@ class String: public HeapObject { - class SeqString: public String { - public: - -+ // Get and set the symbol id of the string -+ inline int symbol_id(); -+ inline void set_symbol_id(int value); -+ - // Casting. - static inline SeqString* cast(Object* obj); - -+ // Layout description. -+ static const int kSymbolIdOffset = String::kSize; -+ static const int kSize = kSymbolIdOffset + kPointerSize; -+ - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString); - }; -@@ -5647,7 +5658,7 @@ class SeqAsciiString: public SeqString { - } - - // Layout description. -- static const int kHeaderSize = String::kSize; -+ static const int kHeaderSize = SeqString::kSize; - static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); - - // Maximal memory usage for a single sequential ASCII string. -@@ -5701,7 +5712,7 @@ class SeqTwoByteString: public SeqString { - } - - // Layout description. -- static const int kHeaderSize = String::kSize; -+ static const int kHeaderSize = SeqString::kSize; - static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); - - // Maximal memory usage for a single sequential two-byte string. --- -1.7.2.3 - diff --git a/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch b/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch deleted file mode 100644 index daf8b35570..0000000000 --- a/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 7c9cfff80b7864d5687432d424074e51712c4a07 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Mon, 23 May 2011 15:55:26 +1000 -Subject: [PATCH 02/13] Add a bit field 3 to Map - -Bit field 3 will be used to add QML specific map flags. ---- - src/heap.cc | 2 ++ - src/objects-inl.h | 10 ++++++++++ - src/objects.cc | 2 ++ - src/objects.h | 9 ++++++++- - 4 files changed, 22 insertions(+), 1 deletions(-) - -diff --git a/src/heap.cc b/src/heap.cc -index 930c97b..900f462 100644 ---- a/src/heap.cc -+++ b/src/heap.cc -@@ -1573,6 +1573,7 @@ MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, - reinterpret_cast<Map*>(result)->set_unused_property_fields(0); - reinterpret_cast<Map*>(result)->set_bit_field(0); - reinterpret_cast<Map*>(result)->set_bit_field2(0); -+ reinterpret_cast<Map*>(result)->set_bit_field3(0); - return result; - } - -@@ -1599,6 +1600,7 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type, int instance_size) { - map->set_unused_property_fields(0); - map->set_bit_field(0); - map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements)); -+ map->set_bit_field3(0); - - // If the map object is aligned fill the padding area with Smi 0 objects. - if (Map::kPadStart < Map::kSize) { -diff --git a/src/objects-inl.h b/src/objects-inl.h -index c82080d..cce3edd 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -2430,6 +2430,16 @@ void Map::set_bit_field2(byte value) { - } - - -+byte Map::bit_field3() { -+ return READ_BYTE_FIELD(this, kBitField3Offset); -+} -+ -+ -+void Map::set_bit_field3(byte value) { -+ WRITE_BYTE_FIELD(this, kBitField3Offset, value); -+} -+ -+ - void Map::set_non_instance_prototype(bool value) { - if (value) { - set_bit_field(bit_field() | (1 << kHasNonInstancePrototype)); -diff --git a/src/objects.cc b/src/objects.cc -index dc4b260..79d7240 100644 ---- a/src/objects.cc -+++ b/src/objects.cc -@@ -3614,6 +3614,7 @@ MaybeObject* Map::CopyDropDescriptors() { - } - Map::cast(result)->set_bit_field(bit_field()); - Map::cast(result)->set_bit_field2(bit_field2()); -+ Map::cast(result)->set_bit_field3(bit_field3()); - Map::cast(result)->set_is_shared(false); - Map::cast(result)->ClearCodeCache(heap); - return result; -@@ -3642,6 +3643,7 @@ MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, - - Map::cast(result)->set_bit_field(bit_field()); - Map::cast(result)->set_bit_field2(bit_field2()); -+ Map::cast(result)->set_bit_field3(bit_field3()); - - Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP); - -diff --git a/src/objects.h b/src/objects.h -index 6e26f57..07e1089 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -3597,6 +3597,10 @@ class Map: public HeapObject { - inline byte bit_field2(); - inline void set_bit_field2(byte value); - -+ // Bit field 3. -+ inline byte bit_field3(); -+ inline void set_bit_field3(byte value); -+ - // Tells whether the object in the prototype property will be used - // for instances created from this function. If the prototype - // property is set to a value that is not a JSObject, the prototype -@@ -3844,7 +3848,7 @@ class Map: public HeapObject { - // Layout description. - static const int kInstanceSizesOffset = HeapObject::kHeaderSize; - static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize; -- static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize; -+ static const int kPrototypeOffset = POINTER_SIZE_ALIGN(kInstanceAttributesOffset + 2 * kIntSize); - static const int kConstructorOffset = kPrototypeOffset + kPointerSize; - static const int kInstanceDescriptorsOffset = - kConstructorOffset + kPointerSize; -@@ -3876,6 +3880,7 @@ class Map: public HeapObject { - static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1; - static const int kBitFieldOffset = kInstanceAttributesOffset + 2; - static const int kBitField2Offset = kInstanceAttributesOffset + 3; -+ static const int kBitField3Offset = kInstanceAttributesOffset + 4; - - STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset); - -@@ -3898,6 +3903,8 @@ class Map: public HeapObject { - static const int kIsShared = 5; - static const int kHasExternalArrayElements = 6; - -+ // Bit positions for bit field 3 -+ - // Layout of the default cache. It holds alternating name and code objects. - static const int kCodeCacheEntrySize = 2; - static const int kCodeCacheEntryNameOffset = 0; --- -1.7.2.3 - diff --git a/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch deleted file mode 100644 index 1c81b2af9d..0000000000 --- a/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch +++ /dev/null @@ -1,364 +0,0 @@ -From ae8688b53d67044f2c9b0cce25fc282b078610c1 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Mon, 23 May 2011 16:21:02 +1000 -Subject: [PATCH 03/13] Add a "fallback" mode for named property interceptors - -By default interceptors are called before the normal property -resolution on objects. When an interceptor is installed as a -"fallback" interceptor, it is only called if the object doesn't -already have the property. - -In the case of a global object having an fallback interceptor, -the interceptor is not invoked at all for var or function -declarations. ---- - include/v8.h | 8 ++++++++ - src/api.cc | 29 +++++++++++++++++++++++++++++ - src/factory.cc | 4 ++++ - src/handles.cc | 6 ++++-- - src/handles.h | 3 ++- - src/objects-inl.h | 16 ++++++++++++++++ - src/objects.cc | 22 ++++++++++++++++------ - src/objects.h | 18 ++++++++++++++---- - src/runtime.cc | 11 ++++++----- - 9 files changed, 99 insertions(+), 18 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index bbd29e9..85452aa 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -2169,6 +2169,7 @@ class V8EXPORT FunctionTemplate : public Template { - NamedPropertyQuery query, - NamedPropertyDeleter remover, - NamedPropertyEnumerator enumerator, -+ bool is_fallback, - Handle<Value> data); - void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter, - IndexedPropertySetter setter, -@@ -2253,6 +2254,13 @@ class V8EXPORT ObjectTemplate : public Template { - NamedPropertyEnumerator enumerator = 0, - Handle<Value> data = Handle<Value>()); - -+ void SetFallbackPropertyHandler(NamedPropertyGetter getter, -+ NamedPropertySetter setter = 0, -+ NamedPropertyQuery query = 0, -+ NamedPropertyDeleter deleter = 0, -+ NamedPropertyEnumerator enumerator = 0, -+ Handle<Value> data = Handle<Value>()); -+ - /** - * Sets an indexed property handler on the object template. - * -diff --git a/src/api.cc b/src/api.cc -index 381935b..8b0b32a 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -981,6 +981,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( - NamedPropertyQuery query, - NamedPropertyDeleter remover, - NamedPropertyEnumerator enumerator, -+ bool is_fallback, - Handle<Value> data) { - i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - if (IsDeadCheck(isolate, -@@ -999,6 +1000,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( - if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); - if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); - if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); -+ obj->set_is_fallback(i::Smi::FromInt(is_fallback)); - - if (data.IsEmpty()) data = v8::Undefined(); - obj->set_data(*Utils::OpenHandle(*data)); -@@ -1143,6 +1145,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, - query, - remover, - enumerator, -+ false, -+ data); -+} -+ -+ -+void ObjectTemplate::SetFallbackPropertyHandler(NamedPropertyGetter getter, -+ NamedPropertySetter setter, -+ NamedPropertyQuery query, -+ NamedPropertyDeleter remover, -+ NamedPropertyEnumerator enumerator, -+ Handle<Value> data) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetFallbackPropertyHandler()")) { -+ return; -+ } -+ ENTER_V8(isolate); -+ i::HandleScope scope(isolate); -+ EnsureConstructor(this); -+ i::FunctionTemplateInfo* constructor = -+ i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); -+ i::Handle<i::FunctionTemplateInfo> cons(constructor); -+ Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter, -+ setter, -+ query, -+ remover, -+ enumerator, -+ true, - data); - } - -diff --git a/src/factory.cc b/src/factory.cc -index 7dee66f..dcdc645 100644 ---- a/src/factory.cc -+++ b/src/factory.cc -@@ -1058,6 +1058,10 @@ Handle<JSFunction> Factory::CreateApiFunction( - // Set interceptor information in the map. - if (!obj->named_property_handler()->IsUndefined()) { - map->set_has_named_interceptor(); -+ -+ InterceptorInfo *nph = InterceptorInfo::cast(obj->named_property_handler()); -+ bool is_fallback = nph->is_fallback()->IsUndefined()?false:nph->is_fallback()->value(); -+ map->set_named_interceptor_is_fallback(is_fallback); - } - if (!obj->indexed_property_handler()->IsUndefined()) { - map->set_has_indexed_interceptor(); -diff --git a/src/handles.cc b/src/handles.cc -index 326de86..dd3a86c 100644 ---- a/src/handles.cc -+++ b/src/handles.cc -@@ -262,9 +262,11 @@ Handle<Object> SetProperty(Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor) { - CALL_HEAP_FUNCTION(object->GetIsolate(), -- object->SetProperty(*key, *value, attributes, strict_mode), -+ object->SetProperty(*key, *value, attributes, strict_mode, -+ skip_fallback_interceptor), - Object); - } - -diff --git a/src/handles.h b/src/handles.h -index 3839f37..4b42506 100644 ---- a/src/handles.h -+++ b/src/handles.h -@@ -188,7 +188,8 @@ Handle<Object> SetProperty(Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode); -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor = false); - - Handle<Object> SetProperty(Handle<Object> object, - Handle<Object> key, -diff --git a/src/objects-inl.h b/src/objects-inl.h -index cce3edd..6aaca2f 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -2521,6 +2521,21 @@ bool Map::is_shared() { - } - - -+void Map::set_named_interceptor_is_fallback(bool value) -+{ -+ if (value) { -+ set_bit_field3(bit_field3() | (1 << kNamedInterceptorIsFallback)); -+ } else { -+ set_bit_field3(bit_field3() & ~(1 << kNamedInterceptorIsFallback)); -+ } -+} -+ -+bool Map::named_interceptor_is_fallback() -+{ -+ return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0; -+} -+ -+ - JSFunction* Map::unchecked_constructor() { - return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset)); - } -@@ -2970,6 +2985,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) - ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) - ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) - ACCESSORS(InterceptorInfo, data, Object, kDataOffset) -+ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset) - - ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) - ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) -diff --git a/src/objects.cc b/src/objects.cc -index 79d7240..15e2cdb 100644 ---- a/src/objects.cc -+++ b/src/objects.cc -@@ -1712,9 +1712,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( - MaybeObject* JSObject::SetProperty(String* name, - Object* value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor) { - LookupResult result; -- LocalLookup(name, &result); -+ LocalLookup(name, &result, skip_fallback_interceptor); - return SetProperty(&result, name, value, attributes, strict_mode); - } - -@@ -3148,7 +3149,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { - } - - --void JSObject::LocalLookup(String* name, LookupResult* result) { -+void JSObject::LocalLookup(String* name, LookupResult* result, -+ bool skip_fallback_interceptor) { - ASSERT(name->IsString()); - - Heap* heap = GetHeap(); -@@ -3174,22 +3176,30 @@ void JSObject::LocalLookup(String* name, LookupResult* result) { - } - - // Check for lookup interceptor except when bootstrapping. -- if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { -+ bool wouldIntercept = HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive(); -+ if (wouldIntercept && !map()->named_interceptor_is_fallback()) { - result->InterceptorResult(this); - return; - } - - LocalLookupRealNamedProperty(name, result); -+ -+ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && -+ map()->named_interceptor_is_fallback()) { -+ result->InterceptorResult(this); -+ return; -+ } - } - - --void JSObject::Lookup(String* name, LookupResult* result) { -+void JSObject::Lookup(String* name, LookupResult* result, -+ bool skip_fallback_interceptor) { - // Ecma-262 3rd 8.6.2.4 - Heap* heap = GetHeap(); - for (Object* current = this; - current != heap->null_value(); - current = JSObject::cast(current)->GetPrototype()) { -- JSObject::cast(current)->LocalLookup(name, result); -+ JSObject::cast(current)->LocalLookup(name, result, skip_fallback_interceptor); - if (result->IsProperty()) return; - } - result->NotFound(); -diff --git a/src/objects.h b/src/objects.h -index 07e1089..a209cd0 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -1405,7 +1405,8 @@ class JSObject: public HeapObject { - MUST_USE_RESULT MaybeObject* SetProperty(String* key, - Object* value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode); -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor = false); - MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result, - String* key, - Object* value, -@@ -1637,8 +1638,8 @@ class JSObject: public HeapObject { - - // Lookup a property. If found, the result is valid and has - // detailed information. -- void LocalLookup(String* name, LookupResult* result); -- void Lookup(String* name, LookupResult* result); -+ void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); -+ void Lookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); - - // The following lookup functions skip interceptors. - void LocalLookupRealNamedProperty(String* name, LookupResult* result); -@@ -3714,6 +3715,12 @@ class Map: public HeapObject { - inline void set_is_access_check_needed(bool access_check_needed); - inline bool is_access_check_needed(); - -+ -+ // Whether the named interceptor is a fallback interceptor or not -+ inline void set_named_interceptor_is_fallback(bool value); -+ inline bool named_interceptor_is_fallback(); -+ -+ - // [prototype]: implicit prototype object. - DECL_ACCESSORS(prototype, Object) - -@@ -3904,6 +3911,7 @@ class Map: public HeapObject { - static const int kHasExternalArrayElements = 6; - - // Bit positions for bit field 3 -+ static const int kNamedInterceptorIsFallback = 0; - - // Layout of the default cache. It holds alternating name and code objects. - static const int kCodeCacheEntrySize = 2; -@@ -6276,6 +6284,7 @@ class InterceptorInfo: public Struct { - DECL_ACCESSORS(deleter, Object) - DECL_ACCESSORS(enumerator, Object) - DECL_ACCESSORS(data, Object) -+ DECL_ACCESSORS(is_fallback, Smi) - - static inline InterceptorInfo* cast(Object* obj); - -@@ -6295,7 +6304,8 @@ class InterceptorInfo: public Struct { - static const int kDeleterOffset = kQueryOffset + kPointerSize; - static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; - static const int kDataOffset = kEnumeratorOffset + kPointerSize; -- static const int kSize = kDataOffset + kPointerSize; -+ static const int kFallbackOffset = kDataOffset + kPointerSize; -+ static const int kSize = kFallbackOffset + kPointerSize; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); -diff --git a/src/runtime.cc b/src/runtime.cc -index 7335da8..660352c 100644 ---- a/src/runtime.cc -+++ b/src/runtime.cc -@@ -1097,7 +1097,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - // Lookup the property in the global object, and don't set the - // value of the variable if the property is already there. - LookupResult lookup; -- global->Lookup(*name, &lookup); -+ global->Lookup(*name, &lookup, true); - if (lookup.IsProperty()) { - // Determine if the property is local by comparing the holder - // against the global object. The information will be used to -@@ -1152,7 +1152,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - } - - LookupResult lookup; -- global->LocalLookup(*name, &lookup); -+ global->LocalLookup(*name, &lookup, true); - - PropertyAttributes attributes = is_const_property - ? static_cast<PropertyAttributes>(base | READ_ONLY) -@@ -1196,7 +1196,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - name, - value, - attributes, -- strict_mode)); -+ strict_mode, -+ true)); - } - } - -@@ -1343,7 +1344,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - JSObject* real_holder = global; - LookupResult lookup; - while (true) { -- real_holder->LocalLookup(*name, &lookup); -+ real_holder->LocalLookup(*name, &lookup, true); - if (lookup.IsProperty()) { - // Determine if this is a redeclaration of something read-only. - if (lookup.IsReadOnly()) { -@@ -1400,7 +1401,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - - global = isolate->context()->global(); - if (assign) { -- return global->SetProperty(*name, args[2], attributes, strict_mode); -+ return global->SetProperty(*name, args[2], attributes, strict_mode, true); - } - return isolate->heap()->undefined_value(); - } --- -1.7.2.3 - diff --git a/src/declarative/v8/0004-Generalize-external-object-resources.patch b/src/declarative/v8/0004-Generalize-external-object-resources.patch deleted file mode 100644 index 6b85666cf0..0000000000 --- a/src/declarative/v8/0004-Generalize-external-object-resources.patch +++ /dev/null @@ -1,894 +0,0 @@ -From 4827116b12c50f6662794017c5a662b5dbb2da0b Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Mon, 23 May 2011 16:55:35 +1000 -Subject: [PATCH 04/13] Generalize external object resources - -V8 was already able to manage and finalize an external string -resource. This change generalizes that mechanism to handle a -single generic external resource - a v8::Object::ExternalResource -derived instance - on normal JSObject's. - -This is useful for mapping C++ objects to JS objects where the -C++ object's memory is effectively owned by the JS Object, and -thus needs to destroyed when the JS Object is garbage collected. -The V8 mailing list suggests using a weak persistent handle for -this purpose, but that seems to incur a fairly massive performance -penalty for short lived objects as weak persistent handle callbacks -are not called until the object has been promoted into the old -object space. ---- - include/v8.h | 25 ++++++ - src/api.cc | 64 ++++++++++++++- - src/extensions/externalize-string-extension.cc | 4 +- - src/factory.cc | 11 +++ - src/heap-inl.h | 101 +++++++++++++++--------- - src/heap.cc | 68 ++++++++-------- - src/heap.h | 42 +++++----- - src/liveobjectlist.cc | 4 +- - src/mark-compact.cc | 21 +++--- - src/objects-inl.h | 41 +++++++++- - src/objects.h | 14 +++- - 11 files changed, 280 insertions(+), 115 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 85452aa..7f06ae7 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1630,6 +1630,25 @@ class Object : public Value { - /** Sets a native pointer in an internal field. */ - V8EXPORT void SetPointerInInternalField(int index, void* value); - -+ class V8EXPORT ExternalResource { // NOLINT -+ public: -+ ExternalResource() {} -+ virtual ~ExternalResource() {} -+ -+ protected: -+ virtual void Dispose() { delete this; } -+ -+ private: -+ // Disallow copying and assigning. -+ ExternalResource(const ExternalResource&); -+ void operator=(const ExternalResource&); -+ -+ friend class v8::internal::Heap; -+ }; -+ -+ V8EXPORT void SetExternalResource(ExternalResource *); -+ V8EXPORT ExternalResource *GetExternalResource(); -+ - // Testers for local properties. - V8EXPORT bool HasRealNamedProperty(Handle<String> key); - V8EXPORT bool HasRealIndexedProperty(uint32_t index); -@@ -2331,6 +2350,12 @@ class V8EXPORT ObjectTemplate : public Template { - */ - void SetInternalFieldCount(int value); - -+ /** -+ * Sets whether the object can store an "external resource" object. -+ */ -+ bool HasExternalResource(); -+ void SetHasExternalResource(bool value); -+ - private: - ObjectTemplate(); - static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor); -diff --git a/src/api.cc b/src/api.cc -index 8b0b32a..1a6fbbb 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -1294,6 +1294,34 @@ void ObjectTemplate::SetInternalFieldCount(int value) { - } - - -+bool ObjectTemplate::HasExternalResource() -+{ -+ if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(), -+ "v8::ObjectTemplate::HasExternalResource()")) { -+ return 0; -+ } -+ return !Utils::OpenHandle(this)->has_external_resource()->IsUndefined(); -+} -+ -+ -+void ObjectTemplate::SetHasExternalResource(bool value) -+{ -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetHasExternalResource()")) { -+ return; -+ } -+ ENTER_V8(isolate); -+ if (value) { -+ EnsureConstructor(this); -+ } -+ if (value) { -+ Utils::OpenHandle(this)->set_has_external_resource(i::Smi::FromInt(1)); -+ } else { -+ Utils::OpenHandle(this)->set_has_external_resource(Utils::OpenHandle(this)->GetHeap()->undefined_value()); -+ } -+} -+ -+ - // --- S c r i p t D a t a --- - - -@@ -3652,6 +3680,34 @@ void v8::Object::SetPointerInInternalField(int index, void* value) { - } - - -+void v8::Object::SetExternalResource(v8::Object::ExternalResource *resource) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ENTER_V8(isolate); -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ if (CanBeEncodedAsSmi(resource)) { -+ obj->SetExternalResourceObject(EncodeAsSmi(resource)); -+ } else { -+ obj->SetExternalResourceObject(*isolate->factory()->NewProxy(static_cast<i::Address>((void *)resource))); -+ } -+ if (!obj->IsSymbol()) { -+ isolate->heap()->external_resource_table()->AddObject(*obj); -+ } -+} -+ -+ -+v8::Object::ExternalResource *v8::Object::GetExternalResource() { -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ i::Object* value = obj->GetExternalResourceObject(); -+ if (value->IsSmi()) { -+ return reinterpret_cast<v8::Object::ExternalResource*>(i::Internals::GetExternalPointerFromSmi(value)); -+ } else if (value->IsProxy()) { -+ return reinterpret_cast<v8::Object::ExternalResource*>(i::Proxy::cast(value)->proxy()); -+ } else { -+ return NULL; -+ } -+} -+ -+ - // --- E n v i r o n m e n t --- - - -@@ -4144,7 +4200,7 @@ Local<String> v8::String::NewExternal( - LOG_API(isolate, "String::NewExternal"); - ENTER_V8(isolate); - i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); -- isolate->heap()->external_string_table()->AddString(*result); -+ isolate->heap()->external_resource_table()->AddString(*result); - return Utils::ToLocal(result); - } - -@@ -4162,7 +4218,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { - } - bool result = obj->MakeExternal(resource); - if (result && !obj->IsSymbol()) { -- isolate->heap()->external_string_table()->AddString(*obj); -+ isolate->heap()->external_resource_table()->AddString(*obj); - } - return result; - } -@@ -4175,7 +4231,7 @@ Local<String> v8::String::NewExternal( - LOG_API(isolate, "String::NewExternal"); - ENTER_V8(isolate); - i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); -- isolate->heap()->external_string_table()->AddString(*result); -+ isolate->heap()->external_resource_table()->AddString(*result); - return Utils::ToLocal(result); - } - -@@ -4194,7 +4250,7 @@ bool v8::String::MakeExternal( - } - bool result = obj->MakeExternal(resource); - if (result && !obj->IsSymbol()) { -- isolate->heap()->external_string_table()->AddString(*obj); -+ isolate->heap()->external_resource_table()->AddString(*obj); - } - return result; - } -diff --git a/src/extensions/externalize-string-extension.cc b/src/extensions/externalize-string-extension.cc -index b3f83fe..8e50904 100644 ---- a/src/extensions/externalize-string-extension.cc -+++ b/src/extensions/externalize-string-extension.cc -@@ -100,7 +100,7 @@ v8::Handle<v8::Value> ExternalizeStringExtension::Externalize( - data, string->length()); - result = string->MakeExternal(resource); - if (result && !string->IsSymbol()) { -- HEAP->external_string_table()->AddString(*string); -+ HEAP->external_resource_table()->AddString(*string); - } - if (!result) delete resource; - } else { -@@ -110,7 +110,7 @@ v8::Handle<v8::Value> ExternalizeStringExtension::Externalize( - data, string->length()); - result = string->MakeExternal(resource); - if (result && !string->IsSymbol()) { -- HEAP->external_string_table()->AddString(*string); -+ HEAP->external_resource_table()->AddString(*string); - } - if (!result) delete resource; - } -diff --git a/src/factory.cc b/src/factory.cc -index dcdc645..d530a75 100644 ---- a/src/factory.cc -+++ b/src/factory.cc -@@ -997,15 +997,21 @@ Handle<JSFunction> Factory::CreateApiFunction( - Handle<Code> construct_stub = isolate()->builtins()->JSConstructStubApi(); - - int internal_field_count = 0; -+ bool has_external_resource = false; -+ - if (!obj->instance_template()->IsUndefined()) { - Handle<ObjectTemplateInfo> instance_template = - Handle<ObjectTemplateInfo>( - ObjectTemplateInfo::cast(obj->instance_template())); - internal_field_count = - Smi::cast(instance_template->internal_field_count())->value(); -+ has_external_resource = -+ !instance_template->has_external_resource()->IsUndefined(); - } - - int instance_size = kPointerSize * internal_field_count; -+ if (has_external_resource) instance_size += kPointerSize; -+ - InstanceType type = INVALID_TYPE; - switch (instance_type) { - case JavaScriptObject: -@@ -1040,6 +1046,11 @@ Handle<JSFunction> Factory::CreateApiFunction( - - Handle<Map> map = Handle<Map>(result->initial_map()); - -+ // Mark as having external data object if needed -+ if (has_external_resource) { -+ map->set_has_external_resource(true); -+ } -+ - // Mark as undetectable if needed. - if (obj->undetectable()) { - map->set_is_undetectable(); -diff --git a/src/heap-inl.h b/src/heap-inl.h -index f4fce7b..58e7adf 100644 ---- a/src/heap-inl.h -+++ b/src/heap-inl.h -@@ -205,21 +205,36 @@ MaybeObject* Heap::NumberFromUint32(uint32_t value) { - } - - --void Heap::FinalizeExternalString(String* string) { -- ASSERT(string->IsExternalString()); -- v8::String::ExternalStringResourceBase** resource_addr = -- reinterpret_cast<v8::String::ExternalStringResourceBase**>( -- reinterpret_cast<byte*>(string) + -- ExternalString::kResourceOffset - -- kHeapObjectTag); -- -- // Dispose of the C++ object if it has not already been disposed. -- if (*resource_addr != NULL) { -- (*resource_addr)->Dispose(); -- } -+void Heap::FinalizeExternalString(HeapObject* string) { -+ ASSERT(string->IsExternalString() || string->map()->has_external_resource()); -+ -+ if (string->IsExternalString()) { -+ v8::String::ExternalStringResourceBase** resource_addr = -+ reinterpret_cast<v8::String::ExternalStringResourceBase**>( -+ reinterpret_cast<byte*>(string) + -+ ExternalString::kResourceOffset - -+ kHeapObjectTag); -+ -+ // Dispose of the C++ object if it has not already been disposed. -+ if (*resource_addr != NULL) { -+ (*resource_addr)->Dispose(); -+ } - -- // Clear the resource pointer in the string. -- *resource_addr = NULL; -+ // Clear the resource pointer in the string. -+ *resource_addr = NULL; -+ } else { -+ JSObject *object = JSObject::cast(string); -+ Object *value = object->GetExternalResourceObject(); -+ v8::Object::ExternalResource *resource = 0; -+ if (value->IsSmi()) { -+ resource = reinterpret_cast<v8::Object::ExternalResource*>(Internals::GetExternalPointerFromSmi(value)); -+ } else if (value->IsProxy()) { -+ resource = reinterpret_cast<v8::Object::ExternalResource*>(Proxy::cast(value)->proxy()); -+ } -+ if (resource) { -+ resource->Dispose(); -+ } -+ } - } - - -@@ -556,53 +571,63 @@ inline bool Heap::allow_allocation(bool new_state) { - #endif - - --void ExternalStringTable::AddString(String* string) { -- ASSERT(string->IsExternalString()); -+void ExternalResourceTable::AddString(String* string) { -+ ASSERT(string->IsExternalString() ); - if (heap_->InNewSpace(string)) { -- new_space_strings_.Add(string); -+ new_space_objects_.Add(string); -+ } else { -+ old_space_objects_.Add(string); -+ } -+} -+ -+ -+void ExternalResourceTable::AddObject(HeapObject* object) { -+ ASSERT(object->map()->has_external_resource()); -+ if (heap_->InNewSpace(object)) { -+ new_space_objects_.Add(object); - } else { -- old_space_strings_.Add(string); -+ old_space_objects_.Add(object); - } - } - - --void ExternalStringTable::Iterate(ObjectVisitor* v) { -- if (!new_space_strings_.is_empty()) { -- Object** start = &new_space_strings_[0]; -- v->VisitPointers(start, start + new_space_strings_.length()); -+void ExternalResourceTable::Iterate(ObjectVisitor* v) { -+ if (!new_space_objects_.is_empty()) { -+ Object** start = &new_space_objects_[0]; -+ v->VisitPointers(start, start + new_space_objects_.length()); - } -- if (!old_space_strings_.is_empty()) { -- Object** start = &old_space_strings_[0]; -- v->VisitPointers(start, start + old_space_strings_.length()); -+ if (!old_space_objects_.is_empty()) { -+ Object** start = &old_space_objects_[0]; -+ v->VisitPointers(start, start + old_space_objects_.length()); - } - } - - - // Verify() is inline to avoid ifdef-s around its calls in release - // mode. --void ExternalStringTable::Verify() { -+void ExternalResourceTable::Verify() { - #ifdef DEBUG -- for (int i = 0; i < new_space_strings_.length(); ++i) { -- ASSERT(heap_->InNewSpace(new_space_strings_[i])); -- ASSERT(new_space_strings_[i] != HEAP->raw_unchecked_null_value()); -+ for (int i = 0; i < new_space_objects_.length(); ++i) { -+ ASSERT(heap_->InNewSpace(new_space_objects_[i])); -+ ASSERT(new_space_objects_[i] != HEAP->raw_unchecked_null_value()); - } -- for (int i = 0; i < old_space_strings_.length(); ++i) { -- ASSERT(!heap_->InNewSpace(old_space_strings_[i])); -- ASSERT(old_space_strings_[i] != HEAP->raw_unchecked_null_value()); -+ for (int i = 0; i < old_space_objects_.length(); ++i) { -+ ASSERT(!heap_->InNewSpace(old_space_objects_[i])); -+ ASSERT(old_space_objects_[i] != HEAP->raw_unchecked_null_value()); - } - #endif - } - - --void ExternalStringTable::AddOldString(String* string) { -- ASSERT(string->IsExternalString()); -- ASSERT(!heap_->InNewSpace(string)); -- old_space_strings_.Add(string); -+void ExternalResourceTable::AddOldObject(HeapObject* object) { -+ ASSERT(object->IsExternalString() || object->map()->has_external_resource()); -+ ASSERT(!heap_->InNewSpace(object)); -+ old_space_objects_.Add(object); - } - - --void ExternalStringTable::ShrinkNewStrings(int position) { -- new_space_strings_.Rewind(position); -+void ExternalResourceTable::ShrinkNewObjects(int position) { -+ new_space_objects_.Rewind(position); - Verify(); - } - -diff --git a/src/heap.cc b/src/heap.cc -index 900f462..bf2940e 100644 ---- a/src/heap.cc -+++ b/src/heap.cc -@@ -155,7 +155,7 @@ Heap::Heap() - memset(roots_, 0, sizeof(roots_[0]) * kRootListLength); - global_contexts_list_ = NULL; - mark_compact_collector_.heap_ = this; -- external_string_table_.heap_ = this; -+ external_resource_table_.heap_ = this; - } - - -@@ -1030,8 +1030,8 @@ void Heap::Scavenge() { - - new_space_front = DoScavenge(&scavenge_visitor, new_space_front); - -- UpdateNewSpaceReferencesInExternalStringTable( -- &UpdateNewSpaceReferenceInExternalStringTableEntry); -+ UpdateNewSpaceReferencesInExternalResourceTable( -+ &UpdateNewSpaceReferenceInExternalResourceTableEntry); - - LiveObjectList::UpdateReferencesForScavengeGC(); - isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); -@@ -1053,38 +1053,38 @@ void Heap::Scavenge() { - } - - --String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, -- Object** p) { -+HeapObject* Heap::UpdateNewSpaceReferenceInExternalResourceTableEntry(Heap* heap, -+ Object** p) { - MapWord first_word = HeapObject::cast(*p)->map_word(); - - if (!first_word.IsForwardingAddress()) { - // Unreachable external string can be finalized. -- heap->FinalizeExternalString(String::cast(*p)); -+ heap->FinalizeExternalString(HeapObject::cast(*p)); - return NULL; - } - - // String is still reachable. -- return String::cast(first_word.ToForwardingAddress()); -+ return HeapObject::cast(first_word.ToForwardingAddress()); - } - - --void Heap::UpdateNewSpaceReferencesInExternalStringTable( -- ExternalStringTableUpdaterCallback updater_func) { -- external_string_table_.Verify(); -+void Heap::UpdateNewSpaceReferencesInExternalResourceTable( -+ ExternalResourceTableUpdaterCallback updater_func) { -+ external_resource_table_.Verify(); - -- if (external_string_table_.new_space_strings_.is_empty()) return; -+ if (external_resource_table_.new_space_objects_.is_empty()) return; - -- Object** start = &external_string_table_.new_space_strings_[0]; -- Object** end = start + external_string_table_.new_space_strings_.length(); -+ Object** start = &external_resource_table_.new_space_objects_[0]; -+ Object** end = start + external_resource_table_.new_space_objects_.length(); - Object** last = start; - - for (Object** p = start; p < end; ++p) { - ASSERT(InFromSpace(*p)); -- String* target = updater_func(this, p); -+ HeapObject* target = updater_func(this, p); - - if (target == NULL) continue; - -- ASSERT(target->IsExternalString()); -+ ASSERT(target->IsExternalString() || target->map()->has_external_resource()); - - if (InNewSpace(target)) { - // String is still in new space. Update the table entry. -@@ -1092,12 +1092,12 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( - ++last; - } else { - // String got promoted. Move it to the old string list. -- external_string_table_.AddOldString(target); -+ external_resource_table_.AddOldObject(target); - } - } - - ASSERT(last <= end); -- external_string_table_.ShrinkNewStrings(static_cast<int>(last - start)); -+ external_resource_table_.ShrinkNewObjects(static_cast<int>(last - start)); - } - - -@@ -4468,7 +4468,7 @@ void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { - v->Synchronize("symbol_table"); - if (mode != VISIT_ALL_IN_SCAVENGE) { - // Scavenge collections have special processing for this. -- external_string_table_.Iterate(v); -+ external_resource_table_.Iterate(v); - } - v->Synchronize("external_string_table"); - } -@@ -4970,7 +4970,7 @@ void Heap::TearDown() { - - isolate_->global_handles()->TearDown(); - -- external_string_table_.TearDown(); -+ external_resource_table_.TearDown(); - - new_space_.TearDown(); - -@@ -5835,31 +5835,31 @@ void TranscendentalCache::Clear() { - } - - --void ExternalStringTable::CleanUp() { -+void ExternalResourceTable::CleanUp() { - int last = 0; -- for (int i = 0; i < new_space_strings_.length(); ++i) { -- if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; -- if (heap_->InNewSpace(new_space_strings_[i])) { -- new_space_strings_[last++] = new_space_strings_[i]; -+ for (int i = 0; i < new_space_objects_.length(); ++i) { -+ if (new_space_objects_[i] == heap_->raw_unchecked_null_value()) continue; -+ if (heap_->InNewSpace(new_space_objects_[i])) { -+ new_space_objects_[last++] = new_space_objects_[i]; - } else { -- old_space_strings_.Add(new_space_strings_[i]); -+ old_space_objects_.Add(new_space_objects_[i]); - } - } -- new_space_strings_.Rewind(last); -+ new_space_objects_.Rewind(last); - last = 0; -- for (int i = 0; i < old_space_strings_.length(); ++i) { -- if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; -- ASSERT(!heap_->InNewSpace(old_space_strings_[i])); -- old_space_strings_[last++] = old_space_strings_[i]; -+ for (int i = 0; i < old_space_objects_.length(); ++i) { -+ if (old_space_objects_[i] == heap_->raw_unchecked_null_value()) continue; -+ ASSERT(!heap_->InNewSpace(old_space_objects_[i])); -+ old_space_objects_[last++] = old_space_objects_[i]; - } -- old_space_strings_.Rewind(last); -+ old_space_objects_.Rewind(last); - Verify(); - } - - --void ExternalStringTable::TearDown() { -- new_space_strings_.Free(); -- old_space_strings_.Free(); -+void ExternalResourceTable::TearDown() { -+ new_space_objects_.Free(); -+ old_space_objects_.Free(); - } - - -diff --git a/src/heap.h b/src/heap.h -index ae4e9e7..8cbf378 100644 ---- a/src/heap.h -+++ b/src/heap.h -@@ -237,8 +237,8 @@ class Isolate; - class WeakObjectRetainer; - - --typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, -- Object** pointer); -+typedef HeapObject* (*ExternalResourceTableUpdaterCallback)(Heap* heap, -+ Object** pointer); - - typedef bool (*DirtyRegionCallback)(Heap* heap, - Address start, -@@ -284,43 +284,45 @@ class PromotionQueue { - }; - - --// External strings table is a place where all external strings are --// registered. We need to keep track of such strings to properly --// finalize them. --class ExternalStringTable { -+// External resource table is a place where all external strings and -+// objects with an external resource are registered. We need to keep -+// track of such strings to properly finalize them. -+class ExternalResourceTable { - public: - // Registers an external string. - inline void AddString(String* string); -+ // Registers an external object. -+ inline void AddObject(HeapObject* object); - - inline void Iterate(ObjectVisitor* v); - - // Restores internal invariant and gets rid of collected strings. -- // Must be called after each Iterate() that modified the strings. -+ // Must be called after each Iterate() that modified the objects. - void CleanUp(); - - // Destroys all allocated memory. - void TearDown(); - - private: -- ExternalStringTable() { } -+ ExternalResourceTable() { } - - friend class Heap; - - inline void Verify(); - -- inline void AddOldString(String* string); -+ inline void AddOldObject(HeapObject* object); - - // Notifies the table that only a prefix of the new list is valid. -- inline void ShrinkNewStrings(int position); -+ inline void ShrinkNewObjects(int position); - - // To speed up scavenge collections new space string are kept - // separate from old space strings. -- List<Object*> new_space_strings_; -- List<Object*> old_space_strings_; -+ List<Object*> new_space_objects_; -+ List<Object*> old_space_objects_; - - Heap* heap_; - -- DISALLOW_COPY_AND_ASSIGN(ExternalStringTable); -+ DISALLOW_COPY_AND_ASSIGN(ExternalResourceTable); - }; - - -@@ -753,7 +755,7 @@ class Heap { - - // Finalizes an external string by deleting the associated external - // data and clearing the resource pointer. -- inline void FinalizeExternalString(String* string); -+ inline void FinalizeExternalString(HeapObject* string); - - // Allocates an uninitialized object. The memory is non-executable if the - // hardware and OS allow. -@@ -1191,8 +1193,8 @@ class Heap { - survived_since_last_expansion_ += survived; - } - -- void UpdateNewSpaceReferencesInExternalStringTable( -- ExternalStringTableUpdaterCallback updater_func); -+ void UpdateNewSpaceReferencesInExternalResourceTable( -+ ExternalResourceTableUpdaterCallback updater_func); - - void ProcessWeakReferences(WeakObjectRetainer* retainer); - -@@ -1228,8 +1230,8 @@ class Heap { - return &mark_compact_collector_; - } - -- ExternalStringTable* external_string_table() { -- return &external_string_table_; -+ ExternalResourceTable* external_resource_table() { -+ return &external_resource_table_; - } - - inline Isolate* isolate(); -@@ -1462,7 +1464,7 @@ class Heap { - // Performs a minor collection in new generation. - void Scavenge(); - -- static String* UpdateNewSpaceReferenceInExternalStringTableEntry( -+ static HeapObject* UpdateNewSpaceReferenceInExternalResourceTableEntry( - Heap* heap, - Object** pointer); - -@@ -1593,7 +1595,7 @@ class Heap { - // configured through the API until it is setup. - bool configured_; - -- ExternalStringTable external_string_table_; -+ ExternalResourceTable external_resource_table_; - - bool is_safe_to_read_maps_; - -diff --git a/src/liveobjectlist.cc b/src/liveobjectlist.cc -index 5795a6b..8866e58 100644 ---- a/src/liveobjectlist.cc -+++ b/src/liveobjectlist.cc -@@ -1989,7 +1989,7 @@ Object* LiveObjectList::PrintObj(int obj_id) { - ASSERT(resource->IsAscii()); - Handle<String> dump_string = - Factory::NewExternalStringFromAscii(resource); -- ExternalStringTable::AddString(*dump_string); -+ ExternalResourceTable::AddString(*dump_string); - return *dump_string; - } else { - delete resource; -@@ -2193,7 +2193,7 @@ Object* LiveObjectList::GetPathPrivate(HeapObject* obj1, HeapObject* obj2) { - ASSERT(resource->IsAscii()); - Handle<String> path_string = - Factory::NewExternalStringFromAscii(resource); -- ExternalStringTable::AddString(*path_string); -+ ExternalResourceTable::AddString(*path_string); - return *path_string; - } else { - delete resource; -diff --git a/src/mark-compact.cc b/src/mark-compact.cc -index 68a5062..1b1e361 100644 ---- a/src/mark-compact.cc -+++ b/src/mark-compact.cc -@@ -163,7 +163,7 @@ void MarkCompactCollector::Finish() { - // objects (empty string, illegal builtin). - heap()->isolate()->stub_cache()->Clear(); - -- heap()->external_string_table_.CleanUp(); -+ heap()->external_resource_table_.CleanUp(); - - // If we've just compacted old space there's no reason to check the - // fragmentation limit. Just return. -@@ -1019,8 +1019,9 @@ class SymbolTableCleaner : public ObjectVisitor { - - // Since no objects have yet been moved we can safely access the map of - // the object. -- if ((*p)->IsExternalString()) { -- heap_->FinalizeExternalString(String::cast(*p)); -+ if ((*p)->IsExternalString() || -+ (*p)->IsHeapObject() && HeapObject::cast(*p)->map()->has_external_resource()) { -+ heap_->FinalizeExternalString(HeapObject::cast(*p)); - } - // Set the entry to null_value (as deleted). - *p = heap_->raw_unchecked_null_value(); -@@ -1433,8 +1434,8 @@ void MarkCompactCollector::MarkLiveObjects() { - SymbolTableCleaner v(heap()); - symbol_table->IterateElements(&v); - symbol_table->ElementsRemoved(v.PointersRemoved()); -- heap()->external_string_table_.Iterate(&v); -- heap()->external_string_table_.CleanUp(); -+ heap()->external_resource_table_.Iterate(&v); -+ heap()->external_resource_table_.CleanUp(); - - // Process the weak references. - MarkCompactWeakObjectRetainer mark_compact_object_retainer; -@@ -1948,11 +1949,11 @@ static void UpdatePointerToNewGen(HeapObject** p) { - } - - --static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, -- Object** p) { -+static HeapObject* UpdateNewSpaceReferenceInExternalResourceTableEntry(Heap* heap, -+ Object** p) { - Address old_addr = HeapObject::cast(*p)->address(); - Address new_addr = Memory::Address_at(old_addr); -- return String::cast(HeapObject::FromAddress(new_addr)); -+ return HeapObject::FromAddress(new_addr); - } - - -@@ -2083,8 +2084,8 @@ static void SweepNewSpace(Heap* heap, NewSpace* space) { - updating_visitor.VisitPointer(heap->global_contexts_list_address()); - - // Update pointers from external string table. -- heap->UpdateNewSpaceReferencesInExternalStringTable( -- &UpdateNewSpaceReferenceInExternalStringTableEntry); -+ heap->UpdateNewSpaceReferencesInExternalResourceTable( -+ &UpdateNewSpaceReferenceInExternalResourceTableEntry); - - // All pointers were updated. Update auxiliary allocation info. - heap->IncrementYoungSurvivorsCounter(survivors_size); -diff --git a/src/objects-inl.h b/src/objects-inl.h -index 6aaca2f..231b835 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -1392,13 +1392,13 @@ int JSObject::GetInternalFieldCount() { - // Make sure to adjust for the number of in-object properties. These - // properties do contribute to the size, but are not internal fields. - return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) - -- map()->inobject_properties(); -+ map()->inobject_properties() - map()->has_external_resource()?1:0; - } - - - int JSObject::GetInternalFieldOffset(int index) { - ASSERT(index < GetInternalFieldCount() && index >= 0); -- return GetHeaderSize() + (kPointerSize * index); -+ return GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0)); - } - - -@@ -1407,7 +1407,7 @@ Object* JSObject::GetInternalField(int index) { - // Internal objects do follow immediately after the header, whereas in-object - // properties are at the end of the object. Therefore there is no need - // to adjust the index here. -- return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); -+ return READ_FIELD(this, GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0))); - } - - -@@ -1416,12 +1416,29 @@ void JSObject::SetInternalField(int index, Object* value) { - // Internal objects do follow immediately after the header, whereas in-object - // properties are at the end of the object. Therefore there is no need - // to adjust the index here. -- int offset = GetHeaderSize() + (kPointerSize * index); -+ int offset = GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0)); - WRITE_FIELD(this, offset, value); - WRITE_BARRIER(this, offset); - } - - -+void JSObject::SetExternalResourceObject(Object *value) { -+ ASSERT(map()->has_external_resource()); -+ int offset = GetHeaderSize(); -+ WRITE_FIELD(this, offset, value); -+ WRITE_BARRIER(this, offset); -+} -+ -+ -+Object *JSObject::GetExternalResourceObject() { -+ if (map()->has_external_resource()) { -+ return READ_FIELD(this, GetHeaderSize()); -+ } else { -+ return GetHeap()->undefined_value(); -+ } -+} -+ -+ - // Access fast-case object properties at index. The use of these routines - // is needed to correctly distinguish between properties stored in-object and - // properties stored in the properties array. -@@ -2521,6 +2538,20 @@ bool Map::is_shared() { - } - - -+void Map::set_has_external_resource(bool value) { -+ if (value) { -+ set_bit_field3(bit_field3() | (1 << kHasExternalResource)); -+ } else { -+ set_bit_field3(bit_field3() & ~(1 << kHasExternalResource)); -+ } -+} -+ -+bool Map::has_external_resource() -+{ -+ return ((1 << kHasExternalResource) & bit_field3()) != 0; -+} -+ -+ - void Map::set_named_interceptor_is_fallback(bool value) - { - if (value) { -@@ -3017,6 +3048,8 @@ ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset) - ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) - ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, - kInternalFieldCountOffset) -+ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, -+ kHasExternalResourceOffset) - - ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) - ACCESSORS(SignatureInfo, args, Object, kArgsOffset) -diff --git a/src/objects.h b/src/objects.h -index a209cd0..1bdb5c7 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -1636,6 +1636,9 @@ class JSObject: public HeapObject { - inline Object* GetInternalField(int index); - inline void SetInternalField(int index, Object* value); - -+ inline void SetExternalResourceObject(Object *); -+ inline Object *GetExternalResourceObject(); -+ - // Lookup a property. If found, the result is valid and has - // detailed information. - void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); -@@ -3715,6 +3718,12 @@ class Map: public HeapObject { - inline void set_is_access_check_needed(bool access_check_needed); - inline bool is_access_check_needed(); - -+ -+ // Tells whether the instance has the space for an external resource -+ // object -+ inline void set_has_external_resource(bool value); -+ inline bool has_external_resource(); -+ - - // Whether the named interceptor is a fallback interceptor or not - inline void set_named_interceptor_is_fallback(bool value); -@@ -3912,6 +3921,7 @@ class Map: public HeapObject { - - // Bit positions for bit field 3 - static const int kNamedInterceptorIsFallback = 0; -+ static const int kHasExternalResource = 1; - - // Layout of the default cache. It holds alternating name and code objects. - static const int kCodeCacheEntrySize = 2; -@@ -6426,6 +6436,7 @@ class ObjectTemplateInfo: public TemplateInfo { - public: - DECL_ACCESSORS(constructor, Object) - DECL_ACCESSORS(internal_field_count, Object) -+ DECL_ACCESSORS(has_external_resource, Object) - - static inline ObjectTemplateInfo* cast(Object* obj); - -@@ -6442,7 +6453,8 @@ class ObjectTemplateInfo: public TemplateInfo { - static const int kConstructorOffset = TemplateInfo::kHeaderSize; - static const int kInternalFieldCountOffset = - kConstructorOffset + kPointerSize; -- static const int kSize = kInternalFieldCountOffset + kPointerSize; -+ static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize; -+ static const int kSize = kHasExternalResourceOffset + kPointerSize; - }; - - --- -1.7.2.3 - diff --git a/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch deleted file mode 100644 index 2dfd3d9699..0000000000 --- a/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch +++ /dev/null @@ -1,1777 +0,0 @@ -From fd7d475e298e5b63cd6383c78cc900635c82aa38 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Mon, 23 May 2011 18:26:19 +1000 -Subject: [PATCH 05/13] Introduce a QML compilation mode - -In QML mode, there is a second global object - known as the QML -global object. During property resolution, if a property is not -present on the JS global object, it is resolve on the QML global -object. - -This global object behavior is only enabled if a script is being -compiled in QML mode. The object to use as the QML global object -is passed as a parameter to the Script::Run() method. Any function -closures etc. created during the run will retain a reference to this -object, so different objects can be passed in different script -runs. ---- - include/v8.h | 18 ++++++++-- - src/api.cc | 52 ++++++++++++++++++++++++----- - src/arm/code-stubs-arm.cc | 4 ++ - src/arm/full-codegen-arm.cc | 26 ++++++++------ - src/arm/lithium-arm.cc | 2 +- - src/arm/lithium-arm.h | 6 +++- - src/arm/lithium-codegen-arm.cc | 7 ++-- - src/arm/macro-assembler-arm.h | 5 +++ - src/ast-inl.h | 5 +++ - src/ast.h | 1 + - src/code-stubs.h | 2 +- - src/compiler.cc | 15 +++++++- - src/compiler.h | 22 ++++++++++-- - src/contexts.cc | 23 +++++++++++++ - src/contexts.h | 4 ++ - src/execution.cc | 28 +++++++++++++-- - src/execution.h | 6 +++ - src/full-codegen.cc | 3 +- - src/full-codegen.h | 1 + - src/heap.cc | 2 + - src/hydrogen-instructions.h | 10 ++++- - src/hydrogen.cc | 2 + - src/ia32/code-stubs-ia32.cc | 7 ++++ - src/ia32/full-codegen-ia32.cc | 26 ++++++++------ - src/ia32/lithium-codegen-ia32.cc | 7 ++-- - src/ia32/lithium-ia32.cc | 2 +- - src/ia32/lithium-ia32.h | 6 +++- - src/ia32/macro-assembler-ia32.h | 5 +++ - src/objects-inl.h | 12 +++++++ - src/objects.h | 5 +++ - src/parser.cc | 27 +++++++++++++-- - src/parser.h | 4 ++- - src/prettyprinter.cc | 3 ++ - src/runtime.cc | 68 ++++++++++++++++++++++++------------- - src/runtime.h | 8 ++-- - src/scopes.cc | 10 +++++ - src/scopes.h | 7 ++++ - src/variables.cc | 3 +- - src/variables.h | 5 +++ - src/x64/code-stubs-x64.cc | 4 ++ - src/x64/full-codegen-x64.cc | 26 ++++++++------ - src/x64/lithium-codegen-x64.cc | 7 ++-- - src/x64/lithium-x64.cc | 2 +- - src/x64/lithium-x64.h | 6 +++ - src/x64/macro-assembler-x64.h | 5 +++ - 45 files changed, 391 insertions(+), 108 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 7f06ae7..a858eae 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -577,6 +577,10 @@ class ScriptOrigin { - */ - class V8EXPORT Script { - public: -+ enum CompileFlags { -+ Default = 0x00, -+ QmlMode = 0x01 -+ }; - - /** - * Compiles the specified script (context-independent). -@@ -596,7 +600,8 @@ class V8EXPORT Script { - static Local<Script> New(Handle<String> source, - ScriptOrigin* origin = NULL, - ScriptData* pre_data = NULL, -- Handle<String> script_data = Handle<String>()); -+ Handle<String> script_data = Handle<String>(), -+ CompileFlags = Default); - - /** - * Compiles the specified script using the specified file name -@@ -609,7 +614,8 @@ class V8EXPORT Script { - * will use the currently entered context). - */ - static Local<Script> New(Handle<String> source, -- Handle<Value> file_name); -+ Handle<Value> file_name, -+ CompileFlags = Default); - - /** - * Compiles the specified script (bound to current context). -@@ -630,7 +636,8 @@ class V8EXPORT Script { - static Local<Script> Compile(Handle<String> source, - ScriptOrigin* origin = NULL, - ScriptData* pre_data = NULL, -- Handle<String> script_data = Handle<String>()); -+ Handle<String> script_data = Handle<String>(), -+ CompileFlags = Default); - - /** - * Compiles the specified script using the specified file name -@@ -647,7 +654,8 @@ class V8EXPORT Script { - */ - static Local<Script> Compile(Handle<String> source, - Handle<Value> file_name, -- Handle<String> script_data = Handle<String>()); -+ Handle<String> script_data = Handle<String>(), -+ CompileFlags = Default); - - /** - * Runs the script returning the resulting value. If the script is -@@ -657,6 +665,7 @@ class V8EXPORT Script { - * compiled. - */ - Local<Value> Run(); -+ Local<Value> Run(Handle<Object> qml); - - /** - * Returns the script id value. -@@ -3326,6 +3335,7 @@ class V8EXPORT Context { - * JavaScript frames an empty handle is returned. - */ - static Local<Context> GetCalling(); -+ static Local<Object> GetCallingQmlGlobal(); - - /** - * Sets the security token for the context. To access an object in -diff --git a/src/api.cc b/src/api.cc -index 1a6fbbb..39767f4 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -1372,7 +1372,8 @@ ScriptData* ScriptData::New(const char* data, int length) { - Local<Script> Script::New(v8::Handle<String> source, - v8::ScriptOrigin* origin, - v8::ScriptData* pre_data, -- v8::Handle<String> script_data) { -+ v8::Handle<String> script_data, -+ v8::Script::CompileFlags compile_flags) { - i::Isolate* isolate = i::Isolate::Current(); - ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>()); - LOG_API(isolate, "Script::New"); -@@ -1409,7 +1410,8 @@ Local<Script> Script::New(v8::Handle<String> source, - NULL, - pre_data_impl, - Utils::OpenHandle(*script_data), -- i::NOT_NATIVES_CODE); -+ i::NOT_NATIVES_CODE, -+ compile_flags); - has_pending_exception = result.is_null(); - EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>()); - return Local<Script>(ToApi<Script>(result)); -@@ -1417,21 +1419,23 @@ Local<Script> Script::New(v8::Handle<String> source, - - - Local<Script> Script::New(v8::Handle<String> source, -- v8::Handle<Value> file_name) { -+ v8::Handle<Value> file_name, -+ v8::Script::CompileFlags compile_flags) { - ScriptOrigin origin(file_name); -- return New(source, &origin); -+ return New(source, &origin, 0, Handle<String>(), compile_flags); - } - - - Local<Script> Script::Compile(v8::Handle<String> source, - v8::ScriptOrigin* origin, - v8::ScriptData* pre_data, -- v8::Handle<String> script_data) { -+ v8::Handle<String> script_data, -+ v8::Script::CompileFlags compile_flags) { - i::Isolate* isolate = i::Isolate::Current(); - ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>()); - LOG_API(isolate, "Script::Compile"); - ENTER_V8(isolate); -- Local<Script> generic = New(source, origin, pre_data, script_data); -+ Local<Script> generic = New(source, origin, pre_data, script_data, compile_flags); - if (generic.IsEmpty()) - return generic; - i::Handle<i::Object> obj = Utils::OpenHandle(*generic); -@@ -1447,13 +1451,18 @@ Local<Script> Script::Compile(v8::Handle<String> source, - - Local<Script> Script::Compile(v8::Handle<String> source, - v8::Handle<Value> file_name, -- v8::Handle<String> script_data) { -+ v8::Handle<String> script_data, -+ v8::Script::CompileFlags compile_flags) { - ScriptOrigin origin(file_name); -- return Compile(source, &origin, 0, script_data); -+ return Compile(source, &origin, 0, script_data, compile_flags); - } - - - Local<Value> Script::Run() { -+ return Run(Handle<Object>()); -+} -+ -+Local<Value> Script::Run(Handle<Object> qml) { - i::Isolate* isolate = i::Isolate::Current(); - ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>()); - LOG_API(isolate, "Script::Run"); -@@ -1472,10 +1481,11 @@ Local<Value> Script::Run() { - fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate); - } - EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> qmlglobal = Utils::OpenHandle(*qml); - i::Handle<i::Object> receiver( - isolate->context()->global_proxy(), isolate); - i::Handle<i::Object> result = -- i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception); -+ i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception, qmlglobal); - EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); - raw_result = *result; - } -@@ -3943,6 +3953,30 @@ v8::Local<v8::Context> Context::GetCalling() { - } - - -+v8::Local<v8::Object> Context::GetCallingQmlGlobal() { -+ i::Isolate* isolate = i::Isolate::Current(); -+ if (IsDeadCheck(isolate, "v8::Context::GetCallingQmlGlobal()")) { -+ return Local<Object>(); -+ } -+ -+ i::Context *context = isolate->context(); -+ if (!context->qml_global()->IsUndefined()) { -+ i::Handle<i::Object> qmlglobal(context->qml_global()); -+ return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal)); -+ } -+ -+ i::JavaScriptFrameIterator it; -+ if (it.done()) return Local<Object>(); -+ context = i::Context::cast(it.frame()->context()); -+ if (!context->qml_global()->IsUndefined()) { -+ i::Handle<i::Object> qmlglobal(context->qml_global()); -+ return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal)); -+ } else { -+ return Local<Object>(); -+ } -+} -+ -+ - v8::Local<v8::Object> Context::Global() { - if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) { - return Local<v8::Object>(); -diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc -index 8c147f9..a2626bf 100644 ---- a/src/arm/code-stubs-arm.cc -+++ b/src/arm/code-stubs-arm.cc -@@ -166,6 +166,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { - __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); - __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX))); - -+ // Copy the qml global object from the surrounding context. -+ __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); -+ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); -+ - // Initialize the rest of the slots to undefined. - __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); - for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { -diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc -index 871b453..a69f10d 100644 ---- a/src/arm/full-codegen-arm.cc -+++ b/src/arm/full-codegen-arm.cc -@@ -154,12 +154,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { - - // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; -- if (heap_slots > 0) { -+ if (heap_slots > 0 || -+ (scope()->is_qml_mode() && scope()->is_global_scope())) { - Comment cmnt(masm_, "[ Allocate local context"); - // Argument to NewContext is the function, which is in r1. - __ push(r1); - if (heap_slots <= FastNewContextStub::kMaximumSlots) { -- FastNewContextStub stub(heap_slots); -+ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); - __ CallStub(&stub); - } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -1247,9 +1248,9 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( - __ bind(&fast); - } - -- __ ldr(r0, GlobalObjectOperand()); -+ __ ldr(r0, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(r2, Operand(slot->var()->name())); -- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) -+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) - ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -@@ -1268,10 +1269,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) { - Comment cmnt(masm_, "Global variable"); - // Use inline caching. Variable name is passed in r2 and the global - // object (receiver) in r0. -- __ ldr(r0, GlobalObjectOperand()); -+ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(r2, Operand(var->name())); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - context()->Plug(r0); - - } else if (slot != NULL && slot->type() == Slot::LOOKUP) { -@@ -1893,11 +1894,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, - // assignment. Right-hand-side value is passed in r0, variable name in - // r2, and the global object in r1. - __ mov(r2, Operand(var->name())); -- __ ldr(r1, GlobalObjectOperand()); -+ __ ldr(r1, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - Handle<Code> ic = is_strict_mode() - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - - } else if (op == Token::INIT_CONST) { - // Like var declarations, const declarations are hoisted to function -@@ -2184,10 +2185,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, - // Push the strict mode flag. - __ mov(r1, Operand(Smi::FromInt(strict_mode_flag()))); - __ push(r1); -+ // Push the qml mode flag. -+ __ mov(r1, Operand(Smi::FromInt(is_qml_mode()))); -+ __ push(r1); - - __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP - ? Runtime::kResolvePossiblyDirectEvalNoLookup -- : Runtime::kResolvePossiblyDirectEval, 4); -+ : Runtime::kResolvePossiblyDirectEval, 5); - } - - -@@ -2263,9 +2267,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { - context()->DropAndPlug(1, r0); - } else if (var != NULL && !var->is_this() && var->is_global()) { - // Push global object as receiver for the call IC. -- __ ldr(r0, GlobalObjectOperand()); -+ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ push(r0); -- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->AsSlot() != NULL && - var->AsSlot()->type() == Slot::LOOKUP) { - // Call to a lookup slot (dynamically introduced variable). -diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc -index 3f1d15b..8406a96 100644 ---- a/src/arm/lithium-arm.cc -+++ b/src/arm/lithium-arm.cc -@@ -1195,7 +1195,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { - - LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { - LOperand* context = UseRegisterAtStart(instr->value()); -- return DefineAsRegister(new LGlobalObject(context)); -+ return DefineAsRegister(new LGlobalObject(context, instr->qml_global())); - } - - -diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h -index 6da7c86..10b901f 100644 ---- a/src/arm/lithium-arm.h -+++ b/src/arm/lithium-arm.h -@@ -1378,13 +1378,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { - - class LGlobalObject: public LTemplateInstruction<1, 1, 0> { - public: -- explicit LGlobalObject(LOperand* context) { -+ explicit LGlobalObject(LOperand* context, bool qml_global) { - inputs_[0] = context; -+ qml_global_ = qml_global; - } - - DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") - - LOperand* context() { return InputAt(0); } -+ bool qml_global() { return qml_global_; } -+ private: -+ bool qml_global_; - }; - - -diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc -index 4912449..db114ea 100644 ---- a/src/arm/lithium-codegen-arm.cc -+++ b/src/arm/lithium-codegen-arm.cc -@@ -166,12 +166,13 @@ bool LCodeGen::GeneratePrologue() { - - // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; -- if (heap_slots > 0) { -+ if (heap_slots > 0 || -+ (scope()->is_qml_mode() && scope()->is_global_scope())) { - Comment(";;; Allocate local context"); - // Argument to NewContext is the function, which is in r1. - __ push(r1); - if (heap_slots <= FastNewContextStub::kMaximumSlots) { -- FastNewContextStub stub(heap_slots); -+ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); - __ CallStub(&stub); - } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -2664,7 +2665,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { - void LCodeGen::DoGlobalObject(LGlobalObject* instr) { - Register context = ToRegister(instr->context()); - Register result = ToRegister(instr->result()); -- __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX)); -+ __ ldr(result, ContextOperand(cp, instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX)); - } - - -diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h -index ab5efb0..d40cdbc 100644 ---- a/src/arm/macro-assembler-arm.h -+++ b/src/arm/macro-assembler-arm.h -@@ -1056,6 +1056,11 @@ static inline MemOperand GlobalObjectOperand() { - } - - -+static inline MemOperand QmlGlobalObjectOperand() { -+ return ContextOperand(cp, Context::QML_GLOBAL_INDEX); -+} -+ -+ - #ifdef GENERATED_CODE_COVERAGE - #define CODE_COVERAGE_STRINGIFY(x) #x - #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) -diff --git a/src/ast-inl.h b/src/ast-inl.h -index d80684a..adc5a1f 100644 ---- a/src/ast-inl.h -+++ b/src/ast-inl.h -@@ -106,6 +106,11 @@ bool FunctionLiteral::strict_mode() const { - } - - -+bool FunctionLiteral::qml_mode() const { -+ return scope()->is_qml_mode(); -+} -+ -+ - } } // namespace v8::internal - - #endif // V8_AST_INL_H_ -diff --git a/src/ast.h b/src/ast.h -index 65a25a9..f790dc0 100644 ---- a/src/ast.h -+++ b/src/ast.h -@@ -1712,6 +1712,7 @@ class FunctionLiteral: public Expression { - int end_position() const { return end_position_; } - bool is_expression() const { return is_expression_; } - bool strict_mode() const; -+ bool qml_mode() const; - - int materialized_literal_count() { return materialized_literal_count_; } - int expected_property_count() { return expected_property_count_; } -diff --git a/src/code-stubs.h b/src/code-stubs.h -index 56ef072..37e5383 100644 ---- a/src/code-stubs.h -+++ b/src/code-stubs.h -@@ -303,7 +303,7 @@ class FastNewContextStub : public CodeStub { - static const int kMaximumSlots = 64; - - explicit FastNewContextStub(int slots) : slots_(slots) { -- ASSERT(slots_ > 0 && slots <= kMaximumSlots); -+ ASSERT(slots_ >= 0 && slots <= kMaximumSlots); - } - - void Generate(MacroAssembler* masm); -diff --git a/src/compiler.cc b/src/compiler.cc -index 86d5de3..d2191b9 100755 ---- a/src/compiler.cc -+++ b/src/compiler.cc -@@ -462,7 +462,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, - v8::Extension* extension, - ScriptDataImpl* input_pre_data, - Handle<Object> script_data, -- NativesFlag natives) { -+ NativesFlag natives, -+ v8::Script::CompileFlags compile_flags) { - Isolate* isolate = source->GetIsolate(); - int source_length = source->length(); - isolate->counters()->total_load_size()->Increment(source_length); -@@ -523,6 +524,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, - info.MarkAsGlobal(); - info.SetExtension(extension); - info.SetPreParseData(pre_data); -+ if (compile_flags & v8::Script::QmlMode) info.MarkAsQmlMode(); - if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax(); - result = MakeFunctionInfo(&info); - if (extension == NULL && !result.is_null()) { -@@ -543,7 +545,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, - Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, - Handle<Context> context, - bool is_global, -- StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, -+ bool qml_mode) { - Isolate* isolate = source->GetIsolate(); - int source_length = source->length(); - isolate->counters()->total_eval_size()->Increment(source_length); -@@ -567,6 +570,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, - CompilationInfo info(script); - info.MarkAsEval(); - if (is_global) info.MarkAsGlobal(); -+ if (qml_mode) info.MarkAsQmlMode(); - if (strict_mode == kStrictMode) info.MarkAsStrictMode(); - info.SetCallingContext(context); - result = MakeFunctionInfo(&info); -@@ -610,6 +614,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { - info->MarkAsStrictMode(); - } - -+ // After parsing we know function's qml mode. Remember it. -+ if (info->function()->qml_mode()) { -+ shared->set_qml_mode(true); -+ info->MarkAsQmlMode(); -+ } -+ - // Compile the code. - if (!MakeCode(info)) { - if (!isolate->has_pending_exception()) { -@@ -755,6 +765,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info, - *lit->this_property_assignments()); - function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); - function_info->set_strict_mode(lit->strict_mode()); -+ function_info->set_qml_mode(lit->qml_mode()); - } - - -diff --git a/src/compiler.h b/src/compiler.h -index e75e869..17cd369 100644 ---- a/src/compiler.h -+++ b/src/compiler.h -@@ -54,6 +54,7 @@ class CompilationInfo BASE_EMBEDDED { - bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; } - bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; } - bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; } -+ bool is_qml_mode() const { return (flags_ & IsQmlMode::mask()) != 0; } - FunctionLiteral* function() const { return function_; } - Scope* scope() const { return scope_; } - Handle<Code> code() const { return code_; } -@@ -83,6 +84,9 @@ class CompilationInfo BASE_EMBEDDED { - ASSERT(is_lazy()); - flags_ |= IsInLoop::encode(true); - } -+ void MarkAsQmlMode() { -+ flags_ |= IsQmlMode::encode(true); -+ } - void MarkAsAllowingNativesSyntax() { - flags_ |= IsNativesSyntaxAllowed::encode(true); - } -@@ -141,6 +145,7 @@ class CompilationInfo BASE_EMBEDDED { - - // Determine whether or not we can adaptively optimize. - bool AllowOptimize() { -+ // XXX - fix qml mode optimizations - return V8::UseCrankshaft() && !closure_.is_null(); - } - -@@ -163,8 +168,13 @@ class CompilationInfo BASE_EMBEDDED { - - void Initialize(Mode mode) { - mode_ = V8::UseCrankshaft() ? mode : NONOPT; -- if (!shared_info_.is_null() && shared_info_->strict_mode()) { -- MarkAsStrictMode(); -+ if (!shared_info_.is_null()) { -+ if (shared_info_->strict_mode()) { -+ MarkAsStrictMode(); -+ } -+ if (shared_info_->qml_mode()) { -+ MarkAsQmlMode(); -+ } - } - } - -@@ -187,6 +197,8 @@ class CompilationInfo BASE_EMBEDDED { - class IsStrictMode: public BitField<bool, 4, 1> {}; - // Native syntax (%-stuff) allowed? - class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {}; -+ // Qml mode -+ class IsQmlMode: public BitField<bool, 6, 1> {}; - - unsigned flags_; - -@@ -252,13 +264,15 @@ class Compiler : public AllStatic { - v8::Extension* extension, - ScriptDataImpl* pre_data, - Handle<Object> script_data, -- NativesFlag is_natives_code); -+ NativesFlag is_natives_code, -+ v8::Script::CompileFlags compile_flags = v8::Script::Default); - - // Compile a String source within a context for Eval. - static Handle<SharedFunctionInfo> CompileEval(Handle<String> source, - Handle<Context> context, - bool is_global, -- StrictModeFlag strict_mode); -+ StrictModeFlag strict_mode, -+ bool qml_mode); - - // Compile from function info (used for lazy compilation). Returns true on - // success and false if the compilation resulted in a stack overflow. -diff --git a/src/contexts.cc b/src/contexts.cc -index 520f3dd..da5cacb 100644 ---- a/src/contexts.cc -+++ b/src/contexts.cc -@@ -89,6 +89,8 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, - PrintF(")\n"); - } - -+ Handle<JSObject> qml_global; -+ - do { - if (FLAG_trace_contexts) { - PrintF(" - looking in context %p", reinterpret_cast<void*>(*context)); -@@ -119,6 +121,10 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, - } - } - -+ if (qml_global.is_null() && !context->qml_global()->IsUndefined()) { -+ qml_global = Handle<JSObject>(context->qml_global(), isolate); -+ } -+ - if (context->is_function_context()) { - // we have context-local slots - -@@ -198,6 +204,23 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, - } - } while (follow_context_chain); - -+ if (!qml_global.is_null()) { -+ if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0) { -+ *attributes = qml_global->GetLocalPropertyAttribute(*name); -+ } else { -+ *attributes = qml_global->GetPropertyAttribute(*name); -+ } -+ -+ if (*attributes != ABSENT) { -+ // property found -+ if (FLAG_trace_contexts) { -+ PrintF("=> found property in qml global object %p\n", -+ reinterpret_cast<void*>(*qml_global)); -+ } -+ return qml_global; -+ } -+ } -+ - // slot not found - if (FLAG_trace_contexts) { - PrintF("=> no property/slot found\n"); -diff --git a/src/contexts.h b/src/contexts.h -index e46619e..57d8e7b 100644 ---- a/src/contexts.h -+++ b/src/contexts.h -@@ -182,6 +182,7 @@ class Context: public FixedArray { - FCONTEXT_INDEX, - PREVIOUS_INDEX, - EXTENSION_INDEX, -+ QML_GLOBAL_INDEX, - GLOBAL_INDEX, - MIN_CONTEXT_SLOTS, - -@@ -273,6 +274,9 @@ class Context: public FixedArray { - } - void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); } - -+ JSObject *qml_global() { return reinterpret_cast<JSObject *>(get(QML_GLOBAL_INDEX)); } -+ void set_qml_global(JSObject *qml_global) { set(QML_GLOBAL_INDEX, qml_global); } -+ - // Returns a JSGlobalProxy object or null. - JSObject* global_proxy(); - void set_global_proxy(JSObject* global); -diff --git a/src/execution.cc b/src/execution.cc -index eb26438..1632076 100644 ---- a/src/execution.cc -+++ b/src/execution.cc -@@ -70,7 +70,8 @@ static Handle<Object> Invoke(bool construct, - Handle<Object> receiver, - int argc, - Object*** args, -- bool* has_pending_exception) { -+ bool* has_pending_exception, -+ Handle<Object> qml) { - Isolate* isolate = func->GetIsolate(); - - // Entering JavaScript. -@@ -107,6 +108,12 @@ static Handle<Object> Invoke(bool construct, - // make the current one is indeed a global object. - ASSERT(func->context()->global()->IsGlobalObject()); - -+ Handle<JSObject> oldqml; -+ if (!qml.is_null()) { -+ oldqml = Handle<JSObject>(func->context()->qml_global()); -+ func->context()->set_qml_global(JSObject::cast(*qml)); -+ } -+ - { - // Save and restore context around invocation and block the - // allocation of handles without explicit handle scopes. -@@ -122,6 +129,9 @@ static Handle<Object> Invoke(bool construct, - receiver_pointer, argc, args); - } - -+ if (!qml.is_null()) -+ func->context()->set_qml_global(*oldqml); -+ - #ifdef DEBUG - value->Verify(); - #endif -@@ -150,14 +160,24 @@ Handle<Object> Execution::Call(Handle<JSFunction> func, - int argc, - Object*** args, - bool* pending_exception) { -- return Invoke(false, func, receiver, argc, args, pending_exception); -+ return Invoke(false, func, receiver, argc, args, pending_exception, Handle<Object>()); -+} -+ -+ -+Handle<Object> Execution::Call(Handle<JSFunction> func, -+ Handle<Object> receiver, -+ int argc, -+ Object*** args, -+ bool* pending_exception, -+ Handle<Object> qml) { -+ return Invoke(false, func, receiver, argc, args, pending_exception, qml); - } - - - Handle<Object> Execution::New(Handle<JSFunction> func, int argc, - Object*** args, bool* pending_exception) { - return Invoke(true, func, Isolate::Current()->global(), argc, args, -- pending_exception); -+ pending_exception, Handle<Object>()); - } - - -@@ -175,7 +195,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func, - catcher.SetCaptureMessage(false); - - Handle<Object> result = Invoke(false, func, receiver, argc, args, -- caught_exception); -+ caught_exception, Handle<Object>()); - - if (*caught_exception) { - ASSERT(catcher.HasCaught()); -diff --git a/src/execution.h b/src/execution.h -index d4b80d2..a476eb4 100644 ---- a/src/execution.h -+++ b/src/execution.h -@@ -56,6 +56,12 @@ class Execution : public AllStatic { - int argc, - Object*** args, - bool* pending_exception); -+ static Handle<Object> Call(Handle<JSFunction> func, -+ Handle<Object> receiver, -+ int argc, -+ Object*** args, -+ bool* pending_exception, -+ Handle<Object> qml); - - // Construct object from function, the caller supplies an array of - // arguments. Arguments are Object* type. After function returns, -diff --git a/src/full-codegen.cc b/src/full-codegen.cc -index d6ba56e..2eaef0f 100644 ---- a/src/full-codegen.cc -+++ b/src/full-codegen.cc -@@ -542,7 +542,7 @@ void FullCodeGenerator::VisitDeclarations( - // Do nothing in case of no declared global functions or variables. - if (globals > 0) { - Handle<FixedArray> array = -- isolate()->factory()->NewFixedArray(2 * globals, TENURED); -+ isolate()->factory()->NewFixedArray(3 * globals, TENURED); - for (int j = 0, i = 0; i < length; i++) { - Declaration* decl = declarations->at(i); - Variable* var = decl->proxy()->var(); -@@ -567,6 +567,7 @@ void FullCodeGenerator::VisitDeclarations( - } - array->set(j++, *function); - } -+ array->set(j++, Smi::FromInt(var->is_qml_global())); - } - } - // Invoke the platform-dependent code generator to do the actual -diff --git a/src/full-codegen.h b/src/full-codegen.h -index d6ed1b9..e3241aa 100644 ---- a/src/full-codegen.h -+++ b/src/full-codegen.h -@@ -505,6 +505,7 @@ class FullCodeGenerator: public AstVisitor { - StrictModeFlag strict_mode_flag() { - return is_strict_mode() ? kStrictMode : kNonStrictMode; - } -+ bool is_qml_mode() { return function()->qml_mode(); } - FunctionLiteral* function() { return info_->function(); } - Scope* scope() { return info_->scope(); } - -diff --git a/src/heap.cc b/src/heap.cc -index bf2940e..da958c2 100644 ---- a/src/heap.cc -+++ b/src/heap.cc -@@ -3795,6 +3795,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { - context->set_previous(NULL); - context->set_extension(NULL); - context->set_global(function->context()->global()); -+ context->set_qml_global(function->context()->qml_global()); - ASSERT(!context->IsGlobalContext()); - ASSERT(context->is_function_context()); - ASSERT(result->IsContext()); -@@ -3817,6 +3818,7 @@ MaybeObject* Heap::AllocateWithContext(Context* previous, - context->set_previous(previous); - context->set_extension(extension); - context->set_global(previous->global()); -+ context->set_qml_global(previous->qml_global()); - ASSERT(!context->IsGlobalContext()); - ASSERT(!context->is_function_context()); - ASSERT(result->IsContext()); -diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h -index a623775..52455bc 100644 ---- a/src/hydrogen-instructions.h -+++ b/src/hydrogen-instructions.h -@@ -1148,7 +1148,7 @@ class HOuterContext: public HUnaryOperation { - - class HGlobalObject: public HUnaryOperation { - public: -- explicit HGlobalObject(HValue* context) : HUnaryOperation(context) { -+ explicit HGlobalObject(HValue* context) : HUnaryOperation(context), qml_global_(false) { - set_representation(Representation::Tagged()); - SetFlag(kUseGVN); - } -@@ -1159,8 +1159,14 @@ class HGlobalObject: public HUnaryOperation { - return Representation::Tagged(); - } - -+ bool qml_global() { return qml_global_; } -+ void set_qml_global(bool v) { qml_global_ = v; } -+ - protected: - virtual bool DataEquals(HValue* other) { return true; } -+ -+ private: -+ bool qml_global_; - }; - - -@@ -1177,7 +1183,7 @@ class HGlobalReceiver: public HUnaryOperation { - virtual Representation RequiredInputRepresentation(int index) const { - return Representation::Tagged(); - } -- -+ - protected: - virtual bool DataEquals(HValue* other) { return true; } - }; -diff --git a/src/hydrogen.cc b/src/hydrogen.cc -index 73ea97d..d17e304 100644 ---- a/src/hydrogen.cc -+++ b/src/hydrogen.cc -@@ -2918,6 +2918,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { - HContext* context = new(zone()) HContext; - AddInstruction(context); - HGlobalObject* global_object = new(zone()) HGlobalObject(context); -+ if (variable->is_qml_global()) global_object->set_qml_global(true); - AddInstruction(global_object); - HLoadGlobalGeneric* instr = - new(zone()) HLoadGlobalGeneric(context, -@@ -3307,6 +3308,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, - HContext* context = new(zone()) HContext; - AddInstruction(context); - HGlobalObject* global_object = new(zone()) HGlobalObject(context); -+ if (var->is_qml_global()) global_object->set_qml_global(true); - AddInstruction(global_object); - HStoreGlobalGeneric* instr = - new(zone()) HStoreGlobalGeneric(context, -diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc -index 5d32095..afa599e 100644 ---- a/src/ia32/code-stubs-ia32.cc -+++ b/src/ia32/code-stubs-ia32.cc -@@ -147,6 +147,13 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { - __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX))); - __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); - -+ // Copy the qml global object from the surrounding context. We go through the -+ // context in the function (ecx) to match the allocation behavior we have -+ // in the runtime system (see Heap::AllocateFunctionContext). -+ __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset)); -+ __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); -+ __ mov(Operand(eax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), ebx); -+ - // Initialize the rest of the slots to undefined. - __ mov(ebx, factory->undefined_value()); - for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { -diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc -index 5d153a8..0ddcde2 100644 ---- a/src/ia32/full-codegen-ia32.cc -+++ b/src/ia32/full-codegen-ia32.cc -@@ -142,12 +142,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { - - // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; -- if (heap_slots > 0) { -+ if (heap_slots > 0 || -+ (scope()->is_qml_mode() && scope()->is_global_scope())) { - Comment cmnt(masm_, "[ Allocate local context"); - // Argument to NewContext is the function, which is still in edi. - __ push(edi); - if (heap_slots <= FastNewContextStub::kMaximumSlots) { -- FastNewContextStub stub(heap_slots); -+ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); - __ CallStub(&stub); - } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -1107,10 +1108,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( - - // All extension objects were empty and it is safe to use a global - // load IC call. -- __ mov(eax, GlobalObjectOperand()); -+ __ mov(eax, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(ecx, slot->var()->name()); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) -+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) - ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - EmitCallIC(ic, mode); -@@ -1214,10 +1215,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) { - Comment cmnt(masm_, "Global variable"); - // Use inline caching. Variable name is passed in ecx and the global - // object on the stack. -- __ mov(eax, GlobalObjectOperand()); -+ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(ecx, var->name()); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - context()->Plug(eax); - - } else if (slot != NULL && slot->type() == Slot::LOOKUP) { -@@ -1837,11 +1838,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, - // assignment. Right-hand-side value is passed in eax, variable name in - // ecx, and the global object on the stack. - __ mov(ecx, var->name()); -- __ mov(edx, GlobalObjectOperand()); -+ __ mov(edx, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - Handle<Code> ic = is_strict_mode() - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - - } else if (op == Token::INIT_CONST) { - // Like var declarations, const declarations are hoisted to function -@@ -2113,9 +2114,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, - // Push the strict mode flag. - __ push(Immediate(Smi::FromInt(strict_mode_flag()))); - -+ // Push the qml mode flag -+ __ push(Immediate(Smi::FromInt(is_qml_mode()))); -+ - __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP - ? Runtime::kResolvePossiblyDirectEvalNoLookup -- : Runtime::kResolvePossiblyDirectEval, 4); -+ : Runtime::kResolvePossiblyDirectEval, 5); - } - - -@@ -2188,8 +2192,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { - context()->DropAndPlug(1, eax); - } else if (var != NULL && !var->is_this() && var->is_global()) { - // Push global object as receiver for the call IC. -- __ push(GlobalObjectOperand()); -- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); -+ __ push(var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); -+ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->AsSlot() != NULL && - var->AsSlot()->type() == Slot::LOOKUP) { - // Call to a lookup slot (dynamically introduced variable). -diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc -index 0f96f78..c1da075 100644 ---- a/src/ia32/lithium-codegen-ia32.cc -+++ b/src/ia32/lithium-codegen-ia32.cc -@@ -159,12 +159,13 @@ bool LCodeGen::GeneratePrologue() { - - // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; -- if (heap_slots > 0) { -+ if (heap_slots > 0 || -+ (scope()->is_qml_mode() && scope()->is_global_scope())) { - Comment(";;; Allocate local context"); - // Argument to NewContext is the function, which is still in edi. - __ push(edi); - if (heap_slots <= FastNewContextStub::kMaximumSlots) { -- FastNewContextStub stub(heap_slots); -+ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); - __ CallStub(&stub); - } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -2525,7 +2526,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { - void LCodeGen::DoGlobalObject(LGlobalObject* instr) { - Register context = ToRegister(instr->context()); - Register result = ToRegister(instr->result()); -- __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX))); -+ __ mov(result, Operand(context, Context::SlotOffset(instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX))); - } - - -diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc -index 9ccd189..8e98b73 100644 ---- a/src/ia32/lithium-ia32.cc -+++ b/src/ia32/lithium-ia32.cc -@@ -1205,7 +1205,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { - - LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { - LOperand* context = UseRegisterAtStart(instr->value()); -- return DefineAsRegister(new LGlobalObject(context)); -+ return DefineAsRegister(new LGlobalObject(context, instr->qml_global())); - } - - -diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h -index 9ace8f8..95ed001 100644 ---- a/src/ia32/lithium-ia32.h -+++ b/src/ia32/lithium-ia32.h -@@ -1416,13 +1416,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { - - class LGlobalObject: public LTemplateInstruction<1, 1, 0> { - public: -- explicit LGlobalObject(LOperand* context) { -+ explicit LGlobalObject(LOperand* context, bool qml_global) { - inputs_[0] = context; -+ qml_global_ = qml_global; - } - - DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") - - LOperand* context() { return InputAt(0); } -+ bool qml_global() { return qml_global_; } -+ private: -+ bool qml_global_; - }; - - -diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h -index b986264..f8479ae 100644 ---- a/src/ia32/macro-assembler-ia32.h -+++ b/src/ia32/macro-assembler-ia32.h -@@ -778,6 +778,11 @@ static inline Operand GlobalObjectOperand() { - } - - -+static inline Operand QmlGlobalObjectOperand() { -+ return ContextOperand(esi, Context::QML_GLOBAL_INDEX); -+} -+ -+ - // Generates an Operand for saving parameters after PrepareCallApiFunction. - Operand ApiParameterOperand(int index); - -diff --git a/src/objects-inl.h b/src/objects-inl.h -index 231b835..1c7f83e 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -3242,6 +3242,18 @@ void SharedFunctionInfo::set_strict_mode(bool value) { - } - - -+bool SharedFunctionInfo::qml_mode() { -+ return BooleanBit::get(compiler_hints(), kQmlModeFunction); -+} -+ -+ -+void SharedFunctionInfo::set_qml_mode(bool value) { -+ set_compiler_hints(BooleanBit::set(compiler_hints(), -+ kQmlModeFunction, -+ value)); -+} -+ -+ - ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset) - ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset) - -diff --git a/src/objects.h b/src/objects.h -index 1bdb5c7..edbc47a 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -4331,6 +4331,10 @@ class SharedFunctionInfo: public HeapObject { - inline bool strict_mode(); - inline void set_strict_mode(bool value); - -+ // Indicates whether the function is a qml mode function -+ inline bool qml_mode(); -+ inline void set_qml_mode(bool value); -+ - // Indicates whether or not the code in the shared function support - // deoptimization. - inline bool has_deoptimization_support(); -@@ -4511,6 +4515,7 @@ class SharedFunctionInfo: public HeapObject { - static const int kCodeAgeMask = 0x7; - static const int kOptimizationDisabled = 6; - static const int kStrictModeFunction = 7; -+ static const int kQmlModeFunction = 8; - - private: - #if V8_HOST_ARCH_32_BIT -diff --git a/src/parser.cc b/src/parser.cc -index a84ec6f..7f5c361 100644 ---- a/src/parser.cc -+++ b/src/parser.cc -@@ -593,7 +593,8 @@ Parser::Parser(Handle<Script> script, - - FunctionLiteral* Parser::ParseProgram(Handle<String> source, - bool in_global_context, -- StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, -+ bool qml_mode) { - CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); - - HistogramTimerScope timer(isolate()->counters()->parse()); -@@ -609,11 +610,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, - ExternalTwoByteStringUC16CharacterStream stream( - Handle<ExternalTwoByteString>::cast(source), 0, source->length()); - scanner_.Initialize(&stream); -- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); -+ return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope); - } else { - GenericStringUC16CharacterStream stream(source, 0, source->length()); - scanner_.Initialize(&stream); -- return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); -+ return DoParseProgram(source, in_global_context, strict_mode, qml_mode, &zone_scope); - } - } - -@@ -621,6 +622,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, - FunctionLiteral* Parser::DoParseProgram(Handle<String> source, - bool in_global_context, - StrictModeFlag strict_mode, -+ bool qml_mode, - ZoneScope* zone_scope) { - ASSERT(target_stack_ == NULL); - if (pre_data_ != NULL) pre_data_->Initialize(); -@@ -641,6 +643,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, - if (strict_mode == kStrictMode) { - top_scope_->EnableStrictMode(); - } -+ if (qml_mode) { -+ scope->EnableQmlMode(); -+ } - ZoneList<Statement*>* body = new ZoneList<Statement*>(16); - bool ok = true; - int beg_loc = scanner().location().beg_pos; -@@ -729,6 +734,9 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, - if (shared_info->strict_mode()) { - top_scope_->EnableStrictMode(); - } -+ if (shared_info->qml_mode()) { -+ top_scope_->EnableQmlMode(); -+ } - - FunctionLiteralType type = - shared_info->is_expression() ? EXPRESSION : DECLARATION; -@@ -1661,6 +1669,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, - arguments->Add(value); - value = NULL; // zap the value to avoid the unnecessary assignment - -+ int qml_mode = 0; -+ if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name)) -+ qml_mode = 1; -+ arguments->Add(NewNumberLiteral(qml_mode)); -+ - // Construct the call to Runtime_InitializeConstGlobal - // and add it to the initialization statement block. - // Note that the function does different things depending on -@@ -1676,6 +1689,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, - arguments->Add(NewNumberLiteral( - top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode)); - -+ int qml_mode = 0; -+ if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name)) -+ qml_mode = 1; -+ arguments->Add(NewNumberLiteral(qml_mode)); -+ - // Be careful not to assign a value to the global variable if - // we're in a with. The initialization value should not - // necessarily be stored in the global object in that case, -@@ -5157,7 +5175,8 @@ bool ParserApi::Parse(CompilationInfo* info) { - Handle<String> source = Handle<String>(String::cast(script->source())); - result = parser.ParseProgram(source, - info->is_global(), -- info->StrictMode()); -+ info->StrictMode(), -+ info->is_qml_mode()); - } - } - -diff --git a/src/parser.h b/src/parser.h -index 64f1303..4d45e45 100644 ---- a/src/parser.h -+++ b/src/parser.h -@@ -431,7 +431,8 @@ class Parser { - // Returns NULL if parsing failed. - FunctionLiteral* ParseProgram(Handle<String> source, - bool in_global_context, -- StrictModeFlag strict_mode); -+ StrictModeFlag strict_mode, -+ bool qml_mode); - - FunctionLiteral* ParseLazy(CompilationInfo* info); - -@@ -464,6 +465,7 @@ class Parser { - FunctionLiteral* DoParseProgram(Handle<String> source, - bool in_global_context, - StrictModeFlag strict_mode, -+ bool qml_mode, - ZoneScope* zone_scope); - - // Report syntax error -diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc -index c777ab4..1964e02 100644 ---- a/src/prettyprinter.cc -+++ b/src/prettyprinter.cc -@@ -656,6 +656,9 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info, - EmbeddedVector<char, 256> buf; - int pos = OS::SNPrintF(buf, "%s (mode = %s", info, - Variable::Mode2String(var->mode())); -+ if (var->is_qml_global()) { -+ pos += OS::SNPrintF(buf + pos, ":QML"); -+ } - OS::SNPrintF(buf + pos, ")"); - PrintLiteralIndented(buf.start(), value, true); - } -diff --git a/src/runtime.cc b/src/runtime.cc -index 660352c..827d954 100644 ---- a/src/runtime.cc -+++ b/src/runtime.cc -@@ -1065,8 +1065,6 @@ static Failure* ThrowRedeclarationError(Isolate* isolate, - RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - ASSERT(args.length() == 4); - HandleScope scope(isolate); -- Handle<GlobalObject> global = Handle<GlobalObject>( -- isolate->context()->global()); - - Handle<Context> context = args.at<Context>(0); - CONVERT_ARG_CHECKED(FixedArray, pairs, 1); -@@ -1075,6 +1073,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - static_cast<StrictModeFlag>(Smi::cast(args[3])->value()); - ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); - -+ Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global()); -+ Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global()); -+ - // Compute the property attributes. According to ECMA-262, section - // 13, page 71, the property must be read-only and - // non-deletable. However, neither SpiderMonkey nor KJS creates the -@@ -1083,10 +1084,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - - // Traverse the name/value pairs and set the properties. - int length = pairs->length(); -- for (int i = 0; i < length; i += 2) { -+ for (int i = 0; i < length; i += 3) { - HandleScope scope(isolate); - Handle<String> name(String::cast(pairs->get(i))); - Handle<Object> value(pairs->get(i + 1), isolate); -+ Handle<Smi> is_qml_global(Smi::cast(pairs->get(i + 2))); -+ -+ Handle<JSObject> global = is_qml_global->value()?qml_global:js_global; - - // We have to declare a global const property. To capture we only - // assign to it when evaluating the assignment for "const x = -@@ -1316,20 +1320,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - NoHandleAllocation nha; - // args[0] == name - // args[1] == strict_mode -- // args[2] == value (optional) -+ // args[2] == qml_mode -+ // args[3] == value (optional) - - // Determine if we need to assign to the variable if it already - // exists (based on the number of arguments). -- RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); -- bool assign = args.length() == 3; -+ RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); -+ bool assign = args.length() == 4; - - CONVERT_ARG_CHECKED(String, name, 0); -- GlobalObject* global = isolate->context()->global(); - RUNTIME_ASSERT(args[1]->IsSmi()); - StrictModeFlag strict_mode = - static_cast<StrictModeFlag>(Smi::cast(args[1])->value()); - ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); - -+ RUNTIME_ASSERT(args[2]->IsSmi()); -+ int qml_mode = Smi::cast(args[2])->value(); -+ -+ JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global(); -+ - // According to ECMA-262, section 12.2, page 62, the property must - // not be deletable. - PropertyAttributes attributes = DONT_DELETE; -@@ -1350,7 +1359,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - if (lookup.IsReadOnly()) { - // If we found readonly property on one of hidden prototypes, - // just shadow it. -- if (real_holder != isolate->context()->global()) break; -+ if (real_holder != global) break; - return ThrowRedeclarationError(isolate, "const", name); - } - -@@ -1372,7 +1381,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - // overwrite it with a variable declaration we must throw a - // re-declaration error. However if we found readonly property - // on one of hidden prototypes, just shadow it. -- if (real_holder != isolate->context()->global()) break; -+ if (real_holder != global) break; - return ThrowRedeclarationError(isolate, "const", name); - } - } -@@ -1384,7 +1393,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - } - - // Assign the value (or undefined) to the property. -- Object* value = (assign) ? args[2] : isolate->heap()->undefined_value(); -+ Object* value = (assign) ? args[3] : isolate->heap()->undefined_value(); - return real_holder->SetProperty( - &lookup, *name, value, attributes, strict_mode); - } -@@ -1399,9 +1408,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - real_holder = JSObject::cast(proto); - } - -- global = isolate->context()->global(); -+ global = qml_mode?isolate->context()->qml_global():isolate->context()->global(); - if (assign) { -- return global->SetProperty(*name, args[2], attributes, strict_mode, true); -+ return global->SetProperty(*name, args[3], attributes, strict_mode, true); - } - return isolate->heap()->undefined_value(); - } -@@ -1411,12 +1420,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { - // All constants are declared with an initial value. The name - // of the constant is the first argument and the initial value - // is the second. -- RUNTIME_ASSERT(args.length() == 2); -+ RUNTIME_ASSERT(args.length() == 3); - CONVERT_ARG_CHECKED(String, name, 0); - Handle<Object> value = args.at<Object>(1); - -+ RUNTIME_ASSERT(args[2]->IsSmi()); -+ int qml_mode = Smi::cast(args[2])->value(); -+ - // Get the current global object from top. -- GlobalObject* global = isolate->context()->global(); -+ JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global(); - - // According to ECMA-262, section 12.2, page 62, the property must - // not be deletable. Since it's a const, it must be READ_ONLY too. -@@ -1456,7 +1468,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { - // with setting the value because the property is either absent or - // read-only. We also have to do redo the lookup. - HandleScope handle_scope(isolate); -- Handle<GlobalObject> global(isolate->context()->global()); -+ Handle<JSObject> global(qml_mode?isolate->context()->qml_global():isolate->context()->global()); - - // BUG 1213575: Handle the case where we have to set a read-only - // property through an interceptor and only do it if it's -@@ -8160,7 +8172,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { - Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source, - context, - true, -- kNonStrictMode); -+ kNonStrictMode, -+ false); - if (shared.is_null()) return Failure::Exception(); - Handle<JSFunction> fun = - isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, -@@ -8173,14 +8186,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { - static ObjectPair CompileGlobalEval(Isolate* isolate, - Handle<String> source, - Handle<Object> receiver, -- StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, -+ bool qml_mode) { - // Deal with a normal eval call with a string argument. Compile it - // and return the compiled function bound in the local context. - Handle<SharedFunctionInfo> shared = Compiler::CompileEval( - source, - Handle<Context>(isolate->context()), - isolate->context()->IsGlobalContext(), -- strict_mode); -+ strict_mode, -+ qml_mode); - if (shared.is_null()) return MakePair(Failure::Exception(), NULL); - Handle<JSFunction> compiled = - isolate->factory()->NewFunctionFromSharedFunctionInfo( -@@ -8190,7 +8205,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, - - - RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { -- ASSERT(args.length() == 4); -+ ASSERT(args.length() == 5); - - HandleScope scope(isolate); - Handle<Object> callee = args.at<Object>(0); -@@ -8257,16 +8272,18 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { - } - - ASSERT(args[3]->IsSmi()); -+ ASSERT(args[4]->IsSmi()); - return CompileGlobalEval(isolate, - args.at<String>(1), - args.at<Object>(2), - static_cast<StrictModeFlag>( -- Smi::cast(args[3])->value())); -+ Smi::cast(args[3])->value()), -+ Smi::cast(args[4])->value()); - } - - - RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { -- ASSERT(args.length() == 4); -+ ASSERT(args.length() == 5); - - HandleScope scope(isolate); - Handle<Object> callee = args.at<Object>(0); -@@ -8280,11 +8297,13 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { - } - - ASSERT(args[3]->IsSmi()); -+ ASSERT(args[4]->IsSmi()); - return CompileGlobalEval(isolate, - args.at<String>(1), - args.at<Object>(2), - static_cast<StrictModeFlag>( -- Smi::cast(args[3])->value())); -+ Smi::cast(args[3])->value()), -+ Smi::cast(args[4])->value()); - } - - -@@ -10633,7 +10652,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { - Compiler::CompileEval(function_source, - context, - context->IsGlobalContext(), -- kNonStrictMode); -+ kNonStrictMode, -+ false); - if (shared.is_null()) return Failure::Exception(); - Handle<JSFunction> compiled_function = - isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context); -@@ -10722,7 +10742,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) { - // Currently, the eval code will be executed in non-strict mode, - // even in the strict code context. - Handle<SharedFunctionInfo> shared = -- Compiler::CompileEval(source, context, is_global, kNonStrictMode); -+ Compiler::CompileEval(source, context, is_global, kNonStrictMode, false); - if (shared.is_null()) return Failure::Exception(); - Handle<JSFunction> compiled_function = - Handle<JSFunction>( -diff --git a/src/runtime.h b/src/runtime.h -index bf1ba68..5e97173 100644 ---- a/src/runtime.h -+++ b/src/runtime.h -@@ -241,8 +241,8 @@ namespace internal { - \ - /* Eval */ \ - F(GlobalReceiver, 1, 1) \ -- F(ResolvePossiblyDirectEval, 4, 2) \ -- F(ResolvePossiblyDirectEvalNoLookup, 4, 2) \ -+ F(ResolvePossiblyDirectEval, 5, 2) \ -+ F(ResolvePossiblyDirectEvalNoLookup, 5, 2) \ - \ - F(SetProperty, -1 /* 4 or 5 */, 1) \ - F(DefineOrRedefineDataProperty, 4, 1) \ -@@ -296,8 +296,8 @@ namespace internal { - /* Declarations and initialization */ \ - F(DeclareGlobals, 4, 1) \ - F(DeclareContextSlot, 4, 1) \ -- F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \ -- F(InitializeConstGlobal, 2, 1) \ -+ F(InitializeVarGlobal, -1 /* 3 or 4 */, 1) \ -+ F(InitializeConstGlobal, 3, 1) \ - F(InitializeConstContextSlot, 3, 1) \ - F(OptimizeObjectForAddingMultipleProperties, 2, 1) \ - \ -diff --git a/src/scopes.cc b/src/scopes.cc -index 8df93c5..734a217 100644 ---- a/src/scopes.cc -+++ b/src/scopes.cc -@@ -198,6 +198,7 @@ void Scope::SetDefaults(Type type, - scope_calls_eval_ = false; - // Inherit the strict mode from the parent scope. - strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; -+ qml_mode_ = (outer_scope != NULL) && outer_scope->qml_mode_; - outer_scope_calls_eval_ = false; - inner_scope_calls_eval_ = false; - outer_scope_is_eval_scope_ = false; -@@ -796,6 +797,10 @@ void Scope::ResolveVariable(Scope* global_scope, - ASSERT(global_scope != NULL); - var = global_scope->DeclareGlobal(proxy->name()); - -+ if (qml_mode_ && !Isolate::Current()->global()->HasProperty(*(proxy->name()))) { -+ var->set_is_qml_global(true); -+ } -+ - } else if (scope_inside_with_) { - // If we are inside a with statement we give up and look up - // the variable at runtime. -@@ -816,6 +821,8 @@ void Scope::ResolveVariable(Scope* global_scope, - // variables. - if (context->GlobalIfNotShadowedByEval(proxy->name())) { - var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); -+ if (qml_mode_ && !Isolate::Current()->global()->HasProperty(*(proxy->name()))) -+ var->set_is_qml_global(true); - - } else { - var = NonLocal(proxy->name(), Variable::DYNAMIC); -@@ -827,6 +834,9 @@ void Scope::ResolveVariable(Scope* global_scope, - // variable is global unless it is shadowed by eval-introduced - // variables. - var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); -+ -+ if (qml_mode_ && !Isolate::Current()->global()->HasProperty(*(proxy->name()))) -+ var->set_is_qml_global(true); - } - } - } -diff --git a/src/scopes.h b/src/scopes.h -index a0e56a4..6dd3f65 100644 ---- a/src/scopes.h -+++ b/src/scopes.h -@@ -210,6 +210,11 @@ class Scope: public ZoneObject { - strict_mode_ = FLAG_strict_mode; - } - -+ // Enable qml mode for this scope -+ void EnableQmlMode() { -+ qml_mode_ = true; -+ } -+ - // --------------------------------------------------------------------------- - // Predicates. - -@@ -218,6 +223,7 @@ class Scope: public ZoneObject { - bool is_function_scope() const { return type_ == FUNCTION_SCOPE; } - bool is_global_scope() const { return type_ == GLOBAL_SCOPE; } - bool is_strict_mode() const { return strict_mode_; } -+ bool is_qml_mode() const { return qml_mode_; } - - // Information about which scopes calls eval. - bool calls_eval() const { return scope_calls_eval_; } -@@ -376,6 +382,7 @@ class Scope: public ZoneObject { - bool scope_contains_with_; // this scope contains a 'with' statement - bool scope_calls_eval_; // this scope contains an 'eval' call - bool strict_mode_; // this scope is a strict mode scope -+ bool qml_mode_; // this scope is a qml mode scope - - // Computed via PropagateScopeInfo. - bool outer_scope_calls_eval_; -diff --git a/src/variables.cc b/src/variables.cc -index 0502722..190baf6 100644 ---- a/src/variables.cc -+++ b/src/variables.cc -@@ -99,7 +99,8 @@ Variable::Variable(Scope* scope, - rewrite_(NULL), - is_valid_LHS_(is_valid_LHS), - is_accessed_from_inner_scope_(false), -- is_used_(false) { -+ is_used_(false), -+ is_qml_global_(false) { - // names must be canonicalized for fast equality checks - ASSERT(name->IsSymbol()); - } -diff --git a/src/variables.h b/src/variables.h -index b1ff0db..0b31d1a 100644 ---- a/src/variables.h -+++ b/src/variables.h -@@ -141,6 +141,8 @@ class Variable: public ZoneObject { - Expression* rewrite() const { return rewrite_; } - void set_rewrite(Expression* expr) { rewrite_ = expr; } - -+ bool is_qml_global() const { return is_qml_global_; } -+ void set_is_qml_global(bool is_qml_global) { is_qml_global_ = is_qml_global; } - private: - Scope* scope_; - Handle<String> name_; -@@ -159,6 +161,9 @@ class Variable: public ZoneObject { - // Usage info. - bool is_accessed_from_inner_scope_; // set by variable resolver - bool is_used_; -+ -+ // QML info -+ bool is_qml_global_; - }; - - -diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc -index c365385..d923494 100644 ---- a/src/x64/code-stubs-x64.cc -+++ b/src/x64/code-stubs-x64.cc -@@ -140,6 +140,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { - __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); - __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx); - -+ // Copy the qml global object from the surrounding context. -+ __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); -+ __ movq(Operand(rax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), rbx); -+ - // Initialize the rest of the slots to undefined. - __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); - for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { -diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc -index 97168cd..c45cdb6 100644 ---- a/src/x64/full-codegen-x64.cc -+++ b/src/x64/full-codegen-x64.cc -@@ -141,12 +141,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { - - // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; -- if (heap_slots > 0) { -+ if (heap_slots > 0 || -+ (scope()->is_qml_mode() && scope()->is_global_scope())) { - Comment cmnt(masm_, "[ Allocate local context"); - // Argument to NewContext is the function, which is still in rdi. - __ push(rdi); - if (heap_slots <= FastNewContextStub::kMaximumSlots) { -- FastNewContextStub stub(heap_slots); -+ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); - __ CallStub(&stub); - } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -1119,10 +1120,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( - - // All extension objects were empty and it is safe to use a global - // load IC call. -- __ movq(rax, GlobalObjectOperand()); -+ __ movq(rax, slot->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); - __ Move(rcx, slot->var()->name()); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) -+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) - ? RelocInfo::CODE_TARGET - : RelocInfo::CODE_TARGET_CONTEXT; - EmitCallIC(ic, mode); -@@ -1227,9 +1228,9 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) { - // Use inline caching. Variable name is passed in rcx and the global - // object on the stack. - __ Move(rcx, var->name()); -- __ movq(rax, GlobalObjectOperand()); -+ __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); - context()->Plug(rax); - - } else if (slot != NULL && slot->type() == Slot::LOOKUP) { -@@ -1806,11 +1807,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, - // assignment. Right-hand-side value is passed in rax, variable name in - // rcx, and the global object on the stack. - __ Move(rcx, var->name()); -- __ movq(rdx, GlobalObjectOperand()); -+ __ movq(rdx, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); - Handle<Code> ic = is_strict_mode() - ? isolate()->builtins()->StoreIC_Initialize_Strict() - : isolate()->builtins()->StoreIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); - - } else if (op == Token::INIT_CONST) { - // Like var declarations, const declarations are hoisted to function -@@ -2085,9 +2086,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, - // Push the strict mode flag. - __ Push(Smi::FromInt(strict_mode_flag())); - -+ // Push the qml mode flag -+ __ Push(Smi::FromInt(is_qml_mode())); -+ - __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP - ? Runtime::kResolvePossiblyDirectEvalNoLookup -- : Runtime::kResolvePossiblyDirectEval, 4); -+ : Runtime::kResolvePossiblyDirectEval, 5); - } - - -@@ -2160,8 +2164,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { - } else if (var != NULL && !var->is_this() && var->is_global()) { - // Call to a global variable. - // Push global object as receiver for the call IC lookup. -- __ push(GlobalObjectOperand()); -- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); -+ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); -+ EmitCallWithIC(expr, var->name(), var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->AsSlot() != NULL && - var->AsSlot()->type() == Slot::LOOKUP) { - // Call to a lookup slot (dynamically introduced variable). -diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc -index 202e7a2..45acbdf 100644 ---- a/src/x64/lithium-codegen-x64.cc -+++ b/src/x64/lithium-codegen-x64.cc -@@ -174,12 +174,13 @@ bool LCodeGen::GeneratePrologue() { - - // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; -- if (heap_slots > 0) { -+ if (heap_slots > 0 || -+ (scope()->is_qml_mode() && scope()->is_global_scope())) { - Comment(";;; Allocate local context"); - // Argument to NewContext is the function, which is still in rdi. - __ push(rdi); - if (heap_slots <= FastNewContextStub::kMaximumSlots) { -- FastNewContextStub stub(heap_slots); -+ FastNewContextStub stub((heap_slots < 0)?0:heap_slots); - __ CallStub(&stub); - } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -2540,7 +2541,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { - - void LCodeGen::DoGlobalObject(LGlobalObject* instr) { - Register result = ToRegister(instr->result()); -- __ movq(result, GlobalObjectOperand()); -+ __ movq(result, instr->qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - } - - -diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc -index 07ca3a5..00feeac 100644 ---- a/src/x64/lithium-x64.cc -+++ b/src/x64/lithium-x64.cc -@@ -1194,7 +1194,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { - - - LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { -- return DefineAsRegister(new LGlobalObject); -+ return DefineAsRegister(new LGlobalObject(instr->qml_global())); - } - - -diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h -index 15bb894..16f754c 100644 ---- a/src/x64/lithium-x64.h -+++ b/src/x64/lithium-x64.h -@@ -1365,7 +1365,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { - - class LGlobalObject: public LTemplateInstruction<1, 0, 0> { - public: -+ explicit LGlobalObject(bool qml_global) : qml_global_(qml_global) {} -+ - DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object") -+ -+ bool qml_global() { return qml_global_; } -+ private: -+ bool qml_global_; - }; - - -diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h -index 4c17720..aa284ed 100644 ---- a/src/x64/macro-assembler-x64.h -+++ b/src/x64/macro-assembler-x64.h -@@ -1233,6 +1233,11 @@ static inline Operand GlobalObjectOperand() { - } - - -+static inline Operand QmlGlobalObjectOperand() { -+ return ContextOperand(rsi, Context::QML_GLOBAL_INDEX); -+} -+ -+ - // Provides access to exit frame stack space (not GCed). - static inline Operand StackSpaceOperand(int index) { - #ifdef _WIN64 --- -1.7.2.3 - diff --git a/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch b/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch deleted file mode 100644 index b9c44654cd..0000000000 --- a/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch +++ /dev/null @@ -1,48 +0,0 @@ -From f890f0d1a1e5bd62711815489c87755a4f382436 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Wed, 25 May 2011 10:36:13 +1000 -Subject: [PATCH 06/13] Allow access to the calling script data - ---- - include/v8.h | 1 + - src/api.cc | 12 ++++++++++++ - 2 files changed, 13 insertions(+), 0 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index a858eae..9aba4a8 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -3336,6 +3336,7 @@ class V8EXPORT Context { - */ - static Local<Context> GetCalling(); - static Local<Object> GetCallingQmlGlobal(); -+ static Local<Value> GetCallingScriptData(); - - /** - * Sets the security token for the context. To access an object in -diff --git a/src/api.cc b/src/api.cc -index 39767f4..ff74efb 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3976,6 +3976,18 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() { - } - } - -+v8::Local<v8::Value> Context::GetCallingScriptData() -+{ -+ i::Isolate* isolate = i::Isolate::Current(); -+ if (IsDeadCheck(isolate, "v8::Context::GetCallingScriptData()")) { -+ return Local<Object>(); -+ } -+ -+ i::JavaScriptFrameIterator it; -+ if (it.done()) return Local<Object>(); -+ i::Handle<i::Script> script(i::Script::cast(i::JSFunction::cast(it.frame()->function())->shared()->script())); -+ return Utils::ToLocal(i::Handle<i::Object>(script->data())); -+} - - v8::Local<v8::Object> Context::Global() { - if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) { --- -1.7.2.3 - diff --git a/src/declarative/v8/0007-Fix-warnings.patch b/src/declarative/v8/0007-Fix-warnings.patch deleted file mode 100644 index 60fb24c138..0000000000 --- a/src/declarative/v8/0007-Fix-warnings.patch +++ /dev/null @@ -1,46 +0,0 @@ -From dac5d9db84cf20564621c679937ca7b9c6a8e880 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Fri, 27 May 2011 13:04:15 +1000 -Subject: [PATCH 07/13] Fix warnings - ---- - include/v8.h | 16 ++++++++-------- - 1 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 9aba4a8..8891dab 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -2415,7 +2415,7 @@ class V8EXPORT Extension { // NOLINT - const char** deps = 0); - virtual ~Extension() { } - virtual v8::Handle<v8::FunctionTemplate> -- GetNativeFunction(v8::Handle<v8::String> name) { -+ GetNativeFunction(v8::Handle<v8::String>) { - return v8::Handle<v8::FunctionTemplate>(); - } - -@@ -3721,13 +3721,13 @@ class Internals { - return *reinterpret_cast<T*>(addr); - } - -- static inline bool CanCastToHeapObject(void* o) { return false; } -- static inline bool CanCastToHeapObject(Context* o) { return true; } -- static inline bool CanCastToHeapObject(String* o) { return true; } -- static inline bool CanCastToHeapObject(Object* o) { return true; } -- static inline bool CanCastToHeapObject(Message* o) { return true; } -- static inline bool CanCastToHeapObject(StackTrace* o) { return true; } -- static inline bool CanCastToHeapObject(StackFrame* o) { return true; } -+ static inline bool CanCastToHeapObject(void*) { return false; } -+ static inline bool CanCastToHeapObject(Context*) { return true; } -+ static inline bool CanCastToHeapObject(String*) { return true; } -+ static inline bool CanCastToHeapObject(Object*) { return true; } -+ static inline bool CanCastToHeapObject(Message*) { return true; } -+ static inline bool CanCastToHeapObject(StackTrace*) { return true; } -+ static inline bool CanCastToHeapObject(StackFrame*) { return true; } - }; - - } // namespace internal --- -1.7.2.3 - diff --git a/src/declarative/v8/0008-Add-custom-object-compare-callback.patch b/src/declarative/v8/0008-Add-custom-object-compare-callback.patch deleted file mode 100644 index fdb0895f06..0000000000 --- a/src/declarative/v8/0008-Add-custom-object-compare-callback.patch +++ /dev/null @@ -1,489 +0,0 @@ -From bec11b8b7f89d135e7d9a823ac4fe98c70d017cf Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Mon, 27 Jun 2011 14:57:28 +1000 -Subject: [PATCH 08/13] Add custom object compare callback - -A global custom object comparison callback can be set with: - V8::SetUserObjectComparisonCallbackFunction() -When two JSObjects are compared (== or !=), if either one has -the MarkAsUseUserObjectComparison() bit set, the custom comparison -callback is invoked to do the actual comparison. - -This is useful when you have "value" objects that you want to -compare as equal, even though they are actually different JS object -instances. ---- - include/v8.h | 13 +++++++++++++ - src/api.cc | 19 +++++++++++++++++++ - src/arm/code-stubs-arm.cc | 42 ++++++++++++++++++++++++++++++++++++++++-- - src/factory.cc | 8 ++++++++ - src/ia32/code-stubs-ia32.cc | 40 ++++++++++++++++++++++++++++++++++++++++ - src/isolate.h | 8 ++++++++ - src/objects-inl.h | 15 +++++++++++++++ - src/objects.h | 10 +++++++++- - src/runtime.cc | 23 +++++++++++++++++++++++ - src/runtime.h | 1 + - src/top.cc | 5 +++++ - src/x64/code-stubs-x64.cc | 37 +++++++++++++++++++++++++++++++++++++ - 12 files changed, 218 insertions(+), 3 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 8891dab..d5d6972 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -2365,6 +2365,12 @@ class V8EXPORT ObjectTemplate : public Template { - bool HasExternalResource(); - void SetHasExternalResource(bool value); - -+ /** -+ * Mark object instances of the template as using the user object -+ * comparison callback. -+ */ -+ void MarkAsUseUserObjectComparison(); -+ - private: - ObjectTemplate(); - static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor); -@@ -2565,6 +2571,10 @@ typedef void (*FailedAccessCheckCallback)(Local<Object> target, - AccessType type, - Local<Value> data); - -+// --- U s e r O b j e c t C o m p a r i s o n C a l l b a c k --- -+typedef bool (*UserObjectComparisonCallback)(Local<Object> lhs, -+ Local<Object> rhs); -+ - // --- G a r b a g e C o l l e c t i o n C a l l b a c k s - - /** -@@ -2815,6 +2825,9 @@ class V8EXPORT V8 { - /** Callback function for reporting failed access checks.*/ - static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback); - -+ /** Callback for user object comparisons */ -+ static void SetUserObjectComparisonCallbackFunction(UserObjectComparisonCallback); -+ - /** - * Enables the host application to receive a notification before a - * garbage collection. Allocations are not allowed in the -diff --git a/src/api.cc b/src/api.cc -index ff74efb..2436031 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -1321,6 +1321,16 @@ void ObjectTemplate::SetHasExternalResource(bool value) - } - } - -+void ObjectTemplate::MarkAsUseUserObjectComparison() -+{ -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::MarkAsUseUserObjectComparison()")) { -+ return; -+ } -+ ENTER_V8(isolate); -+ EnsureConstructor(this); -+ Utils::OpenHandle(this)->set_use_user_object_comparison(i::Smi::FromInt(1)); -+} - - // --- S c r i p t D a t a --- - -@@ -4632,6 +4642,15 @@ void V8::SetFailedAccessCheckCallbackFunction( - isolate->SetFailedAccessCheckCallback(callback); - } - -+void V8::SetUserObjectComparisonCallbackFunction( -+ UserObjectComparisonCallback callback) { -+ i::Isolate* isolate = i::Isolate::Current(); -+ if (IsDeadCheck(isolate, "v8::V8::SetUserObjectComparisonCallbackFunction()")) { -+ return; -+ } -+ isolate->SetUserObjectComparisonCallback(callback); -+} -+ - void V8::AddObjectGroup(Persistent<Value>* objects, - size_t length, - RetainedObjectInfo* info) { -diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc -index a2626bf..749c9be 100644 ---- a/src/arm/code-stubs-arm.cc -+++ b/src/arm/code-stubs-arm.cc -@@ -1563,6 +1563,36 @@ void CompareStub::Generate(MacroAssembler* masm) { - // NOTICE! This code is only reached after a smi-fast-case check, so - // it is certain that at least one operand isn't a smi. - -+ { -+ Label not_user_equal, user_equal; -+ __ and_(r2, r1, Operand(r0)); -+ __ tst(r2, Operand(kSmiTagMask)); -+ __ b(eq, ¬_user_equal); -+ -+ __ CompareObjectType(r0, r2, r4, JS_OBJECT_TYPE); -+ __ b(ne, ¬_user_equal); -+ -+ __ CompareObjectType(r1, r3, r4, JS_OBJECT_TYPE); -+ __ b(ne, ¬_user_equal); -+ -+ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset)); -+ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ b(eq, &user_equal); -+ -+ __ ldrb(r3, FieldMemOperand(r3, Map::kBitField3Offset)); -+ __ and_(r3, r3, Operand(1 << Map::kUseUserObjectComparison)); -+ __ cmp(r3, Operand(1 << Map::kUseUserObjectComparison)); -+ __ b(ne, ¬_user_equal); -+ -+ __ bind(&user_equal); -+ -+ __ Push(r0, r1); -+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1); -+ -+ __ bind(¬_user_equal); -+ } -+ - // Handle the case where the objects are identical. Either returns the answer - // or goes to slow. Only falls through if the objects were not identical. - EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); -@@ -5802,10 +5832,18 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - __ tst(r2, Operand(kSmiTagMask)); - __ b(eq, &miss); - -- __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); -+ __ CompareObjectType(r0, r2, r3, JS_OBJECT_TYPE); - __ b(ne, &miss); -- __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); -+ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset)); -+ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ b(eq, &miss); -+ __ CompareObjectType(r1, r2, r3, JS_OBJECT_TYPE); - __ b(ne, &miss); -+ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset)); -+ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ b(eq, &miss); - - ASSERT(GetCondition() == eq); - __ sub(r0, r0, Operand(r1)); -diff --git a/src/factory.cc b/src/factory.cc -index d530a75..6f8c7de 100644 ---- a/src/factory.cc -+++ b/src/factory.cc -@@ -998,6 +998,7 @@ Handle<JSFunction> Factory::CreateApiFunction( - - int internal_field_count = 0; - bool has_external_resource = false; -+ bool use_user_object_comparison = false; - - if (!obj->instance_template()->IsUndefined()) { - Handle<ObjectTemplateInfo> instance_template = -@@ -1007,6 +1008,8 @@ Handle<JSFunction> Factory::CreateApiFunction( - Smi::cast(instance_template->internal_field_count())->value(); - has_external_resource = - !instance_template->has_external_resource()->IsUndefined(); -+ use_user_object_comparison = -+ !instance_template->use_user_object_comparison()->IsUndefined(); - } - - int instance_size = kPointerSize * internal_field_count; -@@ -1051,6 +1054,11 @@ Handle<JSFunction> Factory::CreateApiFunction( - map->set_has_external_resource(true); - } - -+ // Mark as using user object comparison if needed -+ if (use_user_object_comparison) { -+ map->set_use_user_object_comparison(true); -+ } -+ - // Mark as undetectable if needed. - if (obj->undetectable()) { - map->set_is_undetectable(); -diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc -index afa599e..0964ab9 100644 ---- a/src/ia32/code-stubs-ia32.cc -+++ b/src/ia32/code-stubs-ia32.cc -@@ -3447,6 +3447,40 @@ void CompareStub::Generate(MacroAssembler* masm) { - __ Assert(not_zero, "Unexpected smi operands."); - } - -+ { -+ NearLabel not_user_equal, user_equal; -+ __ test(eax, Immediate(kSmiTagMask)); -+ __ j(zero, ¬_user_equal); -+ __ test(edx, Immediate(kSmiTagMask)); -+ __ j(zero, ¬_user_equal); -+ -+ __ CmpObjectType(eax, JS_OBJECT_TYPE, ebx); -+ __ j(not_equal, ¬_user_equal); -+ -+ __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); -+ __ j(not_equal, ¬_user_equal); -+ -+ __ test_b(FieldOperand(ebx, Map::kBitField3Offset), -+ 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &user_equal); -+ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), -+ 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &user_equal); -+ -+ __ jmp(¬_user_equal); -+ -+ __ bind(&user_equal); -+ -+ __ pop(ebx); // Return address. -+ __ push(eax); -+ __ push(edx); -+ __ push(ebx); -+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1); -+ -+ __ bind(¬_user_equal); -+ } -+ -+ - // NOTICE! This code is only reached after a smi-fast-case check, so - // it is certain that at least one operand isn't a smi. - -@@ -5592,8 +5626,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - - __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); - __ j(not_equal, &miss, not_taken); -+ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), -+ 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &miss); - __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); - __ j(not_equal, &miss, not_taken); -+ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), -+ 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &miss); - - ASSERT(GetCondition() == equal); - __ sub(eax, Operand(edx)); -diff --git a/src/isolate.h b/src/isolate.h -index 35ffcb4..8130397 100644 ---- a/src/isolate.h -+++ b/src/isolate.h -@@ -267,6 +267,9 @@ class ThreadLocalTop BASE_EMBEDDED { - // Call back function to report unsafe JS accesses. - v8::FailedAccessCheckCallback failed_access_check_callback_; - -+ // Call back function for user object comparisons -+ v8::UserObjectComparisonCallback user_object_comparison_callback_; -+ - private: - void InitializeInternal(); - -@@ -699,6 +702,11 @@ class Isolate { - void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback); - void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type); - -+ void SetUserObjectComparisonCallback(v8::UserObjectComparisonCallback callback); -+ inline v8::UserObjectComparisonCallback UserObjectComparisonCallback() { -+ return thread_local_top()->user_object_comparison_callback_; -+ } -+ - // Exception throwing support. The caller should use the result - // of Throw() as its return value. - Failure* Throw(Object* exception, MessageLocation* location = NULL); -diff --git a/src/objects-inl.h b/src/objects-inl.h -index 1c7f83e..1765441 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -2552,6 +2552,19 @@ bool Map::has_external_resource() - } - - -+void Map::set_use_user_object_comparison(bool value) { -+ if (value) { -+ set_bit_field3(bit_field3() | (1 << kUseUserObjectComparison)); -+ } else { -+ set_bit_field3(bit_field3() & ~(1 << kUseUserObjectComparison)); -+ } -+} -+ -+bool Map::use_user_object_comparison() { -+ return ((1 << kUseUserObjectComparison) & bit_field3()) != 0; -+} -+ -+ - void Map::set_named_interceptor_is_fallback(bool value) - { - if (value) { -@@ -3050,6 +3063,8 @@ ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, - kInternalFieldCountOffset) - ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, - kHasExternalResourceOffset) -+ACCESSORS(ObjectTemplateInfo, use_user_object_comparison, Object, -+ kUseUserObjectComparisonOffset) - - ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) - ACCESSORS(SignatureInfo, args, Object, kArgsOffset) -diff --git a/src/objects.h b/src/objects.h -index edbc47a..e75e9f1 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -3724,6 +3724,11 @@ class Map: public HeapObject { - inline void set_has_external_resource(bool value); - inline bool has_external_resource(); - -+ -+ // Tells whether the user object comparison callback should be used for -+ // comparisons involving this object -+ inline void set_use_user_object_comparison(bool value); -+ inline bool use_user_object_comparison(); - - // Whether the named interceptor is a fallback interceptor or not - inline void set_named_interceptor_is_fallback(bool value); -@@ -3922,6 +3927,7 @@ class Map: public HeapObject { - // Bit positions for bit field 3 - static const int kNamedInterceptorIsFallback = 0; - static const int kHasExternalResource = 1; -+ static const int kUseUserObjectComparison = 2; - - // Layout of the default cache. It holds alternating name and code objects. - static const int kCodeCacheEntrySize = 2; -@@ -6442,6 +6448,7 @@ class ObjectTemplateInfo: public TemplateInfo { - DECL_ACCESSORS(constructor, Object) - DECL_ACCESSORS(internal_field_count, Object) - DECL_ACCESSORS(has_external_resource, Object) -+ DECL_ACCESSORS(use_user_object_comparison, Object) - - static inline ObjectTemplateInfo* cast(Object* obj); - -@@ -6459,7 +6466,8 @@ class ObjectTemplateInfo: public TemplateInfo { - static const int kInternalFieldCountOffset = - kConstructorOffset + kPointerSize; - static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize; -- static const int kSize = kHasExternalResourceOffset + kPointerSize; -+ static const int kUseUserObjectComparisonOffset = kHasExternalResourceOffset + kPointerSize; -+ static const int kSize = kUseUserObjectComparisonOffset + kPointerSize; - }; - - -diff --git a/src/runtime.cc b/src/runtime.cc -index 827d954..d552ddb 100644 ---- a/src/runtime.cc -+++ b/src/runtime.cc -@@ -6279,6 +6279,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { - } - - -+RUNTIME_FUNCTION(MaybeObject*, Runtime_UserObjectEquals) { -+ NoHandleAllocation ha; -+ ASSERT(args.length() == 2); -+ -+ CONVERT_CHECKED(JSObject, lhs, args[1]); -+ CONVERT_CHECKED(JSObject, rhs, args[0]); -+ -+ bool result; -+ -+ v8::UserObjectComparisonCallback callback = isolate->UserObjectComparisonCallback(); -+ if (callback) { -+ HandleScope scope(isolate); -+ Handle<JSObject> lhs_handle(lhs); -+ Handle<JSObject> rhs_handle(rhs); -+ result = callback(v8::Utils::ToLocal(lhs_handle), v8::Utils::ToLocal(rhs_handle)); -+ } else { -+ result = (lhs == rhs); -+ } -+ -+ return Smi::FromInt(result?0:1); -+} -+ -+ - RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) { - NoHandleAllocation ha; - ASSERT(args.length() == 3); -diff --git a/src/runtime.h b/src/runtime.h -index 5e97173..0d754f9 100644 ---- a/src/runtime.h -+++ b/src/runtime.h -@@ -146,6 +146,7 @@ namespace internal { - /* Comparisons */ \ - F(NumberEquals, 2, 1) \ - F(StringEquals, 2, 1) \ -+ F(UserObjectEquals, 2, 1) \ - \ - F(NumberCompare, 3, 1) \ - F(SmiLexicographicCompare, 2, 1) \ -diff --git a/src/top.cc b/src/top.cc -index e078ee9..c345383 100644 ---- a/src/top.cc -+++ b/src/top.cc -@@ -68,6 +68,7 @@ void ThreadLocalTop::InitializeInternal() { - thread_id_ = ThreadId::Invalid(); - external_caught_exception_ = false; - failed_access_check_callback_ = NULL; -+ user_object_comparison_callback_ = NULL; - save_context_ = NULL; - catcher_ = NULL; - } -@@ -387,6 +388,10 @@ void Isolate::SetFailedAccessCheckCallback( - thread_local_top()->failed_access_check_callback_ = callback; - } - -+void Isolate::SetUserObjectComparisonCallback( -+ v8::UserObjectComparisonCallback callback) { -+ thread_local_top()->user_object_comparison_callback_ = callback; -+} - - void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { - if (!thread_local_top()->failed_access_check_callback_) return; -diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc -index d923494..10b9b56 100644 ---- a/src/x64/code-stubs-x64.cc -+++ b/src/x64/code-stubs-x64.cc -@@ -2443,6 +2443,37 @@ void CompareStub::Generate(MacroAssembler* masm) { - __ bind(&ok); - } - -+ { -+ NearLabel not_user_equal, user_equal; -+ __ JumpIfSmi(rax, ¬_user_equal); -+ __ JumpIfSmi(rdx, ¬_user_equal); -+ -+ __ CmpObjectType(rax, JS_OBJECT_TYPE, rbx); -+ __ j(not_equal, ¬_user_equal); -+ -+ __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); -+ __ j(not_equal, ¬_user_equal); -+ -+ __ testb(FieldOperand(rbx, Map::kBitField3Offset), -+ Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &user_equal); -+ __ testb(FieldOperand(rcx, Map::kBitField3Offset), -+ Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &user_equal); -+ -+ __ jmp(¬_user_equal); -+ -+ __ bind(&user_equal); -+ -+ __ pop(rbx); // Return address. -+ __ push(rax); -+ __ push(rdx); -+ __ push(rbx); -+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1); -+ -+ __ bind(¬_user_equal); -+ } -+ - // The compare stub returns a positive, negative, or zero 64-bit integer - // value in rax, corresponding to result of comparing the two inputs. - // NOTICE! This code is only reached after a smi-fast-case check, so -@@ -4471,8 +4502,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - - __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); - __ j(not_equal, &miss, not_taken); -+ __ testb(FieldOperand(rcx, Map::kBitField3Offset), -+ Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &miss); - __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); - __ j(not_equal, &miss, not_taken); -+ __ testb(FieldOperand(rcx, Map::kBitField3Offset), -+ Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &miss); - - ASSERT(GetCondition() == equal); - __ subq(rax, rdx); --- -1.7.2.3 - diff --git a/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch b/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch deleted file mode 100644 index 89ec7b96bc..0000000000 --- a/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch +++ /dev/null @@ -1,286 +0,0 @@ -From 4183b973ed3bd603784c798dfa63ba48f6b68003 Mon Sep 17 00:00:00 2001 -From: ager@chromium.org <ager@chromium.org> -Date: Wed, 4 May 2011 13:03:08 +0000 -Subject: [PATCH 09/13] Add CallAsFunction method to the Object class in the API - -Patch by Peter Varga. - -BUG=v8:1336 -TEST=cctest/test-api/CallAsFunction - -Review URL: http://codereview.chromium.org/6883045 - -git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 ---- - include/v8.h | 8 +++ - src/api.cc | 31 +++++++++++ - src/execution.cc | 24 ++++++++ - src/execution.h | 2 + - test/cctest/test-api.cc | 135 ++++++++++++++++++++++++++++++++++------------- - 5 files changed, 163 insertions(+), 37 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index d5d6972..8a8e1cd 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1757,6 +1757,14 @@ class Object : public Value { - V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType(); - V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); - -+ /** -+ * Call an Object as a function if a callback is set by the -+ * ObjectTemplate::SetCallAsFunctionHandler method. -+ */ -+ V8EXPORT Local<Value> CallAsFunction(Handle<Object> recv, -+ int argc, -+ Handle<Value> argv[]); -+ - V8EXPORT static Local<Object> New(); - static inline Object* Cast(Value* obj); - private: -diff --git a/src/api.cc b/src/api.cc -index 2436031..e412e51 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3259,6 +3259,37 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { - } - - -+Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, -+ v8::Handle<v8::Value> argv[]) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ON_BAILOUT(isolate, "v8::Object::CallAsFunction()", -+ return Local<v8::Value>()); -+ LOG_API(isolate, "Object::CallAsFunction"); -+ ENTER_V8(isolate); -+ HandleScope scope; -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); -+ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -+ i::Object*** args = reinterpret_cast<i::Object***>(argv); -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>(); -+ if (obj->IsJSFunction()) { -+ fun = i::Handle<i::JSFunction>::cast(obj); -+ } else { -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> delegate = -+ i::Execution::TryGetFunctionDelegate(obj, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); -+ fun = i::Handle<i::JSFunction>::cast(delegate); -+ recv_obj = obj; -+ } -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); -+ return scope.Close(Utils::ToLocal(returned)); -+} -+ -+ - Local<v8::Object> Function::NewInstance() const { - return NewInstance(0, NULL); - } -diff --git a/src/execution.cc b/src/execution.cc -index 1632076..894d741 100644 ---- a/src/execution.cc -+++ b/src/execution.cc -@@ -254,6 +254,30 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { - } - - -+Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object, -+ bool* has_pending_exception) { -+ ASSERT(!object->IsJSFunction()); -+ Isolate* isolate = Isolate::Current(); -+ -+ // Objects created through the API can have an instance-call handler -+ // that should be used when calling the object as a function. -+ if (object->IsHeapObject() && -+ HeapObject::cast(*object)->map()->has_instance_call_handler()) { -+ return Handle<JSFunction>( -+ isolate->global_context()->call_as_function_delegate()); -+ } -+ -+ // If the Object doesn't have an instance-call handler we should -+ // throw a non-callable exception. -+ i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( -+ "called_non_callable", i::HandleVector<i::Object>(&object, 1)); -+ isolate->Throw(*error_obj); -+ *has_pending_exception = true; -+ -+ return isolate->factory()->undefined_value(); -+} -+ -+ - Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { - ASSERT(!object->IsJSFunction()); - Isolate* isolate = Isolate::Current(); -diff --git a/src/execution.h b/src/execution.h -index a476eb4..0a0be51 100644 ---- a/src/execution.h -+++ b/src/execution.h -@@ -144,6 +144,8 @@ class Execution : public AllStatic { - // Get a function delegate (or undefined) for the given non-function - // object. Used for support calling objects as functions. - static Handle<Object> GetFunctionDelegate(Handle<Object> object); -+ static Handle<Object> TryGetFunctionDelegate(Handle<Object> object, -+ bool* has_pending_exception); - - // Get a function delegate (or undefined) for the given non-function - // object. Used for support calling objects as constructors. -diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc -index d7621d1..693d51e 100644 ---- a/test/cctest/test-api.cc -+++ b/test/cctest/test-api.cc -@@ -6962,50 +6962,111 @@ THREADED_TEST(CallAsFunction) { - v8::HandleScope scope; - LocalContext context; - -- Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -- Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -- instance_template->SetCallAsFunctionHandler(call_as_function); -- Local<v8::Object> instance = t->GetFunction()->NewInstance(); -- context->Global()->Set(v8_str("obj"), instance); -- v8::TryCatch try_catch; -- Local<Value> value; -- CHECK(!try_catch.HasCaught()); -+ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -+ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -+ instance_template->SetCallAsFunctionHandler(call_as_function); -+ Local<v8::Object> instance = t->GetFunction()->NewInstance(); -+ context->Global()->Set(v8_str("obj"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); - -- value = CompileRun("obj(42)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(42, value->Int32Value()); -+ value = CompileRun("obj(42)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(42, value->Int32Value()); - -- value = CompileRun("(function(o){return o(49)})(obj)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(49, value->Int32Value()); -+ value = CompileRun("(function(o){return o(49)})(obj)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(49, value->Int32Value()); - -- // test special case of call as function -- value = CompileRun("[obj]['0'](45)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(45, value->Int32Value()); -+ // test special case of call as function -+ value = CompileRun("[obj]['0'](45)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(45, value->Int32Value()); - -- value = CompileRun("obj.call = Function.prototype.call;" -- "obj.call(null, 87)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(87, value->Int32Value()); -+ value = CompileRun("obj.call = Function.prototype.call;" -+ "obj.call(null, 87)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(87, value->Int32Value()); - -- // Regression tests for bug #1116356: Calling call through call/apply -- // must work for non-function receivers. -- const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; -- value = CompileRun(apply_99); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(99, value->Int32Value()); -+ // Regression tests for bug #1116356: Calling call through call/apply -+ // must work for non-function receivers. -+ const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; -+ value = CompileRun(apply_99); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(99, value->Int32Value()); - -- const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; -- value = CompileRun(call_17); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(17, value->Int32Value()); -+ const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; -+ value = CompileRun(call_17); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(17, value->Int32Value()); - -- // Check that the call-as-function handler can be called through -- // new. -- value = CompileRun("new obj(43)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(-43, value->Int32Value()); -+ // Check that the call-as-function handler can be called through -+ // new. -+ value = CompileRun("new obj(43)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(-43, value->Int32Value()); -+ -+ // Check that the call-as-function handler can be called through -+ // the API. -+ v8::Handle<Value> args[] = { v8_num(28) }; -+ value = instance->CallAsFunction(instance, 1, args); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(28, value->Int32Value()); -+ } -+ -+ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -+ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -+ Local<v8::Object> instance = t->GetFunction()->NewInstance(); -+ context->Global()->Set(v8_str("obj2"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ // Call an object without call-as-function handler through the JS -+ value = CompileRun("obj2(28)"); -+ CHECK(value.IsEmpty()); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ(*exception_value1, -+ "TypeError: Property 'obj2' of object " -+ "#<Object> is not a function"); -+ try_catch.Reset(); -+ -+ // Call an object without call-as-function handler through the API -+ value = CompileRun("obj2(28)"); -+ v8::Handle<Value> args[] = { v8_num(28) }; -+ value = instance->CallAsFunction(instance, 1, args); -+ CHECK(value.IsEmpty()); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ(*exception_value2, "TypeError: [object Object] is not a function"); -+ try_catch.Reset(); -+ } -+ -+ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -+ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -+ instance_template->SetCallAsFunctionHandler(ThrowValue); -+ Local<v8::Object> instance = t->GetFunction()->NewInstance(); -+ context->Global()->Set(v8_str("obj3"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ // Catch the exception which is thrown by call-as-function handler -+ value = CompileRun("obj3(22)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ(*exception_value1, "22"); -+ try_catch.Reset(); -+ -+ v8::Handle<Value> args[] = { v8_num(23) }; -+ value = instance->CallAsFunction(instance, 1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ(*exception_value2, "23"); -+ try_catch.Reset(); -+ } - } - - --- -1.7.2.3 - diff --git a/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch b/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch deleted file mode 100644 index 09c2d4af1a..0000000000 --- a/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch +++ /dev/null @@ -1,397 +0,0 @@ -From 3d6d4249878f7960eac4c9c94e0f2529f9a58c4a Mon Sep 17 00:00:00 2001 -From: ager@chromium.org <ager@chromium.org> -Date: Fri, 6 May 2011 11:07:52 +0000 -Subject: [PATCH 10/13] Implement CallAsConstructor method for Object in the API - -Patch by Peter Varga. - -BUG=v8:1348 -TEST=cctest/test-api/ConstructorForObject - -Review URL: http://codereview.chromium.org/6902108 - -git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7803 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 ---- - include/v8.h | 8 ++ - src/api.cc | 41 +++++++++- - src/execution.cc | 28 +++++++ - src/execution.h | 2 + - test/cctest/test-api.cc | 205 +++++++++++++++++++++++++++++++++++++++++++++-- - 5 files changed, 276 insertions(+), 8 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 8a8e1cd..84462b5 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1765,6 +1765,14 @@ class Object : public Value { - int argc, - Handle<Value> argv[]); - -+ /** -+ * Call an Object as a consturctor if a callback is set by the -+ * ObjectTemplate::SetCallAsFunctionHandler method. -+ * Note: This method behaves like the Function::NewInstance method. -+ */ -+ V8EXPORT Local<Value> CallAsConstructor(int argc, -+ Handle<Value> argv[]); -+ - V8EXPORT static Local<Object> New(); - static inline Object* Cast(Value* obj); - private: -diff --git a/src/api.cc b/src/api.cc -index e412e51..1a585d6 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3266,7 +3266,7 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - return Local<v8::Value>()); - LOG_API(isolate, "Object::CallAsFunction"); - ENTER_V8(isolate); -- HandleScope scope; -+ i::HandleScope scope(isolate); - i::Handle<i::JSObject> obj = Utils::OpenHandle(this); - i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); - STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -@@ -3286,7 +3286,44 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - i::Handle<i::Object> returned = - i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); - EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); -- return scope.Close(Utils::ToLocal(returned)); -+ return Utils::ToLocal(scope.CloseAndEscape(returned)); -+} -+ -+ -+Local<v8::Value> Object::CallAsConstructor(int argc, -+ v8::Handle<v8::Value> argv[]) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()", -+ return Local<v8::Object>()); -+ LOG_API(isolate, "Object::CallAsConstructor"); -+ ENTER_V8(isolate); -+ i::HandleScope scope(isolate); -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -+ i::Object*** args = reinterpret_cast<i::Object***>(argv); -+ if (obj->IsJSFunction()) { -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj); -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::New(fun, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ return Utils::ToLocal(scope.CloseAndEscape( -+ i::Handle<i::JSObject>::cast(returned))); -+ } -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> delegate = -+ i::Execution::TryGetConstructorDelegate(obj, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ if (!delegate->IsUndefined()) { -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate); -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::Call(fun, obj, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ ASSERT(!delegate->IsUndefined()); -+ return Utils::ToLocal(scope.CloseAndEscape(returned)); -+ } -+ return Local<v8::Object>(); - } - - -diff --git a/src/execution.cc b/src/execution.cc -index 894d741..afb352c 100644 ---- a/src/execution.cc -+++ b/src/execution.cc -@@ -297,6 +297,34 @@ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { - } - - -+Handle<Object> Execution::TryGetConstructorDelegate( -+ Handle<Object> object, -+ bool* has_pending_exception) { -+ ASSERT(!object->IsJSFunction()); -+ Isolate* isolate = Isolate::Current(); -+ -+ // If you return a function from here, it will be called when an -+ // attempt is made to call the given object as a constructor. -+ -+ // Objects created through the API can have an instance-call handler -+ // that should be used when calling the object as a function. -+ if (object->IsHeapObject() && -+ HeapObject::cast(*object)->map()->has_instance_call_handler()) { -+ return Handle<JSFunction>( -+ isolate->global_context()->call_as_constructor_delegate()); -+ } -+ -+ // If the Object doesn't have an instance-call handler we should -+ // throw a non-callable exception. -+ i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( -+ "called_non_callable", i::HandleVector<i::Object>(&object, 1)); -+ isolate->Throw(*error_obj); -+ *has_pending_exception = true; -+ -+ return isolate->factory()->undefined_value(); -+} -+ -+ - bool StackGuard::IsStackOverflow() { - ExecutionAccess access(isolate_); - return (thread_local_.jslimit_ != kInterruptLimit && -diff --git a/src/execution.h b/src/execution.h -index 0a0be51..ec2a195 100644 ---- a/src/execution.h -+++ b/src/execution.h -@@ -150,6 +150,8 @@ class Execution : public AllStatic { - // Get a function delegate (or undefined) for the given non-function - // object. Used for support calling objects as constructors. - static Handle<Object> GetConstructorDelegate(Handle<Object> object); -+ static Handle<Object> TryGetConstructorDelegate(Handle<Object> object, -+ bool* has_pending_exception); - }; - - -diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc -index 693d51e..1334f63 100644 ---- a/test/cctest/test-api.cc -+++ b/test/cctest/test-api.cc -@@ -6746,6 +6746,200 @@ THREADED_TEST(Constructor) { - CHECK(value->BooleanValue()); - } - -+ -+static Handle<Value> ConstructorCallback(const Arguments& args) { -+ ApiTestFuzzer::Fuzz(); -+ Local<Object> This; -+ -+ if (args.IsConstructCall()) { -+ Local<Object> Holder = args.Holder(); -+ This = Object::New(); -+ Local<Value> proto = Holder->GetPrototype(); -+ if (proto->IsObject()) { -+ This->SetPrototype(proto); -+ } -+ } else { -+ This = args.This(); -+ } -+ -+ This->Set(v8_str("a"), args[0]); -+ return This; -+} -+ -+ -+static Handle<Value> FakeConstructorCallback(const Arguments& args) { -+ ApiTestFuzzer::Fuzz(); -+ return args[0]; -+} -+ -+ -+THREADED_TEST(ConstructorForObject) { -+ v8::HandleScope handle_scope; -+ LocalContext context; -+ -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(ConstructorCallback); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ // Call the Object's constructor with a 32-bit signed integer. -+ value = CompileRun("(function() { var o = new obj(28); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsInt32()); -+ CHECK_EQ(28, value->Int32Value()); -+ -+ Local<Value> args1[] = { v8_num(28) }; -+ Local<Value> value_obj1 = instance->CallAsConstructor(1, args1); -+ CHECK(value_obj1->IsObject()); -+ Local<Object> object1 = Local<Object>::Cast(value_obj1); -+ value = object1->Get(v8_str("a")); -+ CHECK(value->IsInt32()); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(28, value->Int32Value()); -+ -+ // Call the Object's constructor with a String. -+ value = CompileRun( -+ "(function() { var o = new obj('tipli'); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsString()); -+ String::AsciiValue string_value1(value->ToString()); -+ CHECK_EQ("tipli", *string_value1); -+ -+ Local<Value> args2[] = { v8_str("tipli") }; -+ Local<Value> value_obj2 = instance->CallAsConstructor(1, args2); -+ CHECK(value_obj2->IsObject()); -+ Local<Object> object2 = Local<Object>::Cast(value_obj2); -+ value = object2->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsString()); -+ String::AsciiValue string_value2(value->ToString()); -+ CHECK_EQ("tipli", *string_value2); -+ -+ // Call the Object's constructor with a Boolean. -+ value = CompileRun("(function() { var o = new obj(true); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsBoolean()); -+ CHECK_EQ(true, value->BooleanValue()); -+ -+ Handle<Value> args3[] = { v8::Boolean::New(true) }; -+ Local<Value> value_obj3 = instance->CallAsConstructor(1, args3); -+ CHECK(value_obj3->IsObject()); -+ Local<Object> object3 = Local<Object>::Cast(value_obj3); -+ value = object3->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsBoolean()); -+ CHECK_EQ(true, value->BooleanValue()); -+ -+ // Call the Object's constructor with undefined. -+ Handle<Value> args4[] = { v8::Undefined() }; -+ Local<Value> value_obj4 = instance->CallAsConstructor(1, args4); -+ CHECK(value_obj4->IsObject()); -+ Local<Object> object4 = Local<Object>::Cast(value_obj4); -+ value = object4->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsUndefined()); -+ -+ // Call the Object's constructor with null. -+ Handle<Value> args5[] = { v8::Null() }; -+ Local<Value> value_obj5 = instance->CallAsConstructor(1, args5); -+ CHECK(value_obj5->IsObject()); -+ Local<Object> object5 = Local<Object>::Cast(value_obj5); -+ value = object5->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsNull()); -+ } -+ -+ // Check exception handling when there is no constructor set for the Object. -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj2"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ value = CompileRun("new obj2(28)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ("TypeError: object is not a function", *exception_value1); -+ try_catch.Reset(); -+ -+ Local<Value> args[] = { v8_num(29) }; -+ value = instance->CallAsConstructor(1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2); -+ try_catch.Reset(); -+ } -+ -+ // Check the case when constructor throws exception. -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(ThrowValue); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj3"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ value = CompileRun("new obj3(22)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ("22", *exception_value1); -+ try_catch.Reset(); -+ -+ Local<Value> args[] = { v8_num(23) }; -+ value = instance->CallAsConstructor(1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ("23", *exception_value2); -+ try_catch.Reset(); -+ } -+ -+ // Check whether constructor returns with an object or non-object. -+ { Local<FunctionTemplate> function_template = -+ FunctionTemplate::New(FakeConstructorCallback); -+ Local<Function> function = function_template->GetFunction(); -+ Local<Object> instance1 = function; -+ context->Global()->Set(v8_str("obj4"), instance1); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ CHECK(instance1->IsObject()); -+ CHECK(instance1->IsFunction()); -+ -+ value = CompileRun("new obj4(28)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsObject()); -+ -+ Local<Value> args1[] = { v8_num(28) }; -+ value = instance1->CallAsConstructor(1, args1); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsObject()); -+ -+ Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(FakeConstructorCallback); -+ Local<Object> instance2 = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj5"), instance2); -+ CHECK(!try_catch.HasCaught()); -+ -+ CHECK(instance2->IsObject()); -+ CHECK(!instance2->IsFunction()); -+ -+ value = CompileRun("new obj5(28)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(!value->IsObject()); -+ -+ Local<Value> args2[] = { v8_num(28) }; -+ value = instance2->CallAsConstructor(1, args2); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(!value->IsObject()); -+ } -+} -+ -+ - THREADED_TEST(FunctionDescriptorException) { - v8::HandleScope handle_scope; - LocalContext context; -@@ -7028,9 +7222,8 @@ THREADED_TEST(CallAsFunction) { - CHECK(value.IsEmpty()); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value1(try_catch.Exception()); -- CHECK_EQ(*exception_value1, -- "TypeError: Property 'obj2' of object " -- "#<Object> is not a function"); -+ CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function", -+ *exception_value1); - try_catch.Reset(); - - // Call an object without call-as-function handler through the API -@@ -7040,7 +7233,7 @@ THREADED_TEST(CallAsFunction) { - CHECK(value.IsEmpty()); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value2(try_catch.Exception()); -- CHECK_EQ(*exception_value2, "TypeError: [object Object] is not a function"); -+ CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2); - try_catch.Reset(); - } - -@@ -7057,14 +7250,14 @@ THREADED_TEST(CallAsFunction) { - value = CompileRun("obj3(22)"); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value1(try_catch.Exception()); -- CHECK_EQ(*exception_value1, "22"); -+ CHECK_EQ("22", *exception_value1); - try_catch.Reset(); - - v8::Handle<Value> args[] = { v8_num(23) }; - value = instance->CallAsFunction(instance, 1, args); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value2(try_catch.Exception()); -- CHECK_EQ(*exception_value2, "23"); -+ CHECK_EQ("23", *exception_value2); - try_catch.Reset(); - } - } --- -1.7.2.3 - diff --git a/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch b/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch deleted file mode 100644 index f4a15bf97a..0000000000 --- a/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch +++ /dev/null @@ -1,63 +0,0 @@ -From f22d0312faeb93ced8747d9aae8c6d77e11b4aba Mon Sep 17 00:00:00 2001 -From: Jedrzej Nowacki <jedrzej.nowacki@nokia.com> -Date: Tue, 7 Dec 2010 11:56:42 +0100 -Subject: [PATCH 11/13] QtScript/V8: Add new v8 api to check if a value is an error. - -New function v8::Value::IsError was created. - -This API is experimental and added only for the purposes of our -research. ---- - include/v8.h | 5 +++++ - src/api.cc | 6 ++++++ - src/heap.h | 1 + - 3 files changed, 12 insertions(+), 0 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 84462b5..08b0ec2 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -937,6 +937,11 @@ class Value : public Data { - */ - V8EXPORT bool IsRegExp() const; - -+ /** -+ * Returns true if this value is an Error. -+ */ -+ V8EXPORT bool IsError() const; -+ - V8EXPORT Local<Boolean> ToBoolean() const; - V8EXPORT Local<Number> ToNumber() const; - V8EXPORT Local<String> ToString() const; -diff --git a/src/api.cc b/src/api.cc -index 1a585d6..bd435eb 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -2108,6 +2108,12 @@ bool Value::IsRegExp() const { - return obj->IsJSRegExp(); - } - -+bool Value::IsError() const { -+ if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsError()")) return false; -+ i::Handle<i::Object> obj = Utils::OpenHandle(this); -+ return obj->HasSpecificClassOf(HEAP->Error_symbol()); -+} -+ - - Local<String> Value::ToString() const { - i::Handle<i::Object> obj = Utils::OpenHandle(this); -diff --git a/src/heap.h b/src/heap.h -index 8cbf378..db90bb9 100644 ---- a/src/heap.h -+++ b/src/heap.h -@@ -169,6 +169,7 @@ inline Heap* _inline_get_heap_(); - V(string_symbol, "string") \ - V(String_symbol, "String") \ - V(Date_symbol, "Date") \ -+ V(Error_symbol, "Error") \ - V(this_symbol, "this") \ - V(to_string_symbol, "toString") \ - V(char_at_symbol, "CharAt") \ --- -1.7.2.3 - diff --git a/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch b/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch deleted file mode 100644 index e4c46b0cbf..0000000000 --- a/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 472c04c9e7a64e8734c76d2cf97a7cc5b773b788 Mon Sep 17 00:00:00 2001 -From: ager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00> -Date: Mon, 9 May 2011 15:24:48 +0000 -Subject: [PATCH 12/13] Add IsCallable method for Object in the API - -Patch by Peter Varga. - -BUG=none -TEST=cctest/test-api/CallableObject - -Review URL: http://codereview.chromium.org/6964005 - -git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7828 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 ---- - include/v8.h | 7 +++++++ - src/api.cc | 11 +++++++++++ - test/cctest/test-api.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 61 insertions(+), 0 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 08b0ec2..4194d4a 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1763,6 +1763,13 @@ class Object : public Value { - V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); - - /** -+ * Checks whether a callback is set by the -+ * ObjectTemplate::SetCallAsFunctionHandler method. -+ * When an Object is callable this method returns true. -+ */ -+ V8EXPORT bool IsCallable(); -+ -+ /** - * Call an Object as a function if a callback is set by the - * ObjectTemplate::SetCallAsFunctionHandler method. - */ -diff --git a/src/api.cc b/src/api.cc -index bd435eb..a5a637f 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3265,6 +3265,17 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { - } - - -+bool v8::Object::IsCallable() { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false); -+ ENTER_V8(isolate); -+ i::HandleScope scope(isolate); -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ if (obj->IsJSFunction()) return true; -+ return i::Execution::GetFunctionDelegate(obj)->IsJSFunction(); -+} -+ -+ - Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - v8::Handle<v8::Value> argv[]) { - i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc -index 1334f63..45db5a1 100644 ---- a/test/cctest/test-api.cc -+++ b/test/cctest/test-api.cc -@@ -7263,6 +7263,49 @@ THREADED_TEST(CallAsFunction) { - } - - -+// Check whether a non-function object is callable. -+THREADED_TEST(CallableObject) { -+ v8::HandleScope scope; -+ LocalContext context; -+ -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(call_as_function); -+ Local<Object> instance = instance_template->NewInstance(); -+ v8::TryCatch try_catch; -+ -+ CHECK(instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+ -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ Local<Object> instance = instance_template->NewInstance(); -+ v8::TryCatch try_catch; -+ -+ CHECK(!instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+ -+ { Local<FunctionTemplate> function_template = -+ FunctionTemplate::New(call_as_function); -+ Local<Function> function = function_template->GetFunction(); -+ Local<Object> instance = function; -+ v8::TryCatch try_catch; -+ -+ CHECK(instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+ -+ { Local<FunctionTemplate> function_template = FunctionTemplate::New(); -+ Local<Function> function = function_template->GetFunction(); -+ Local<Object> instance = function; -+ v8::TryCatch try_catch; -+ -+ CHECK(instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+} -+ -+ - static int CountHandles() { - return v8::HandleScope::NumberOfHandles(); - } --- -1.7.2.3 - diff --git a/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch b/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch deleted file mode 100644 index 0a769921cd..0000000000 --- a/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch +++ /dev/null @@ -1,15 +0,0 @@ -From dc2cad4f8fc88c52fcea09b8d0262d35cd32dc44 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Thu, 25 Aug 2011 11:09:58 +1000 -Subject: [PATCH 13/13] Remove execute flag from v8-debug.h - ---- - 0 files changed, 0 insertions(+), 0 deletions(-) - mode change 100755 => 100644 include/v8-debug.h - -diff --git a/include/v8-debug.h b/include/v8-debug.h -old mode 100755 -new mode 100644 --- -1.7.2.3 - diff --git a/src/declarative/v8/README b/src/declarative/v8/README deleted file mode 100644 index 2dc39705aa..0000000000 --- a/src/declarative/v8/README +++ /dev/null @@ -1 +0,0 @@ -These patches apply cleanly against v8 at 2eaa4b29586fdbd5d41f7b7d9e72ecca6d53dbd2 diff --git a/src/declarative/v8/v8.pri b/src/declarative/v8/v8.pri deleted file mode 100644 index c526fccbe6..0000000000 --- a/src/declarative/v8/v8.pri +++ /dev/null @@ -1,253 +0,0 @@ -equals(QT_ARCH, x86_64)|contains(CONFIG, x86_64):CONFIG += arch_x86_64 -else:equals(QT_ARCH, "i386"):CONFIG += arch_i386 -else:equals(QT_ARCH, "arm"):CONFIG += arch_arm - -include($$PWD/v8base.pri) - -V8_GENERATED_SOURCES_DIR = generated - -DEFINES += V8_SHARED BUILDING_V8_SHARED - -# this maybe removed in future -DEFINES += ENABLE_DEBUGGER_SUPPORT - -# this is needed by crankshaft ( http://code.google.com/p/v8/issues/detail?id=1271 ) -DEFINES += ENABLE_VMSTATE_TRACKING ENABLE_LOGGING_AND_PROFILING - -CONFIG(debug, debug|release) { - DEFINES += DEBUG V8_ENABLE_CHECKS OBJECT_PRINT ENABLE_DISASSEMBLER -} else { - DEFINES += NDEBUG -} - -INCLUDEPATH += \ - $$V8DIR/src - -# $$V8DIR/include - -V8SOURCES = \ - $$V8DIR/src/accessors.cc \ - $$V8DIR/src/allocation.cc \ - $$V8DIR/src/api.cc \ - $$V8DIR/src/assembler.cc \ - $$V8DIR/src/ast.cc \ - $$V8DIR/src/atomicops_internals_x86_gcc.cc \ - $$V8DIR/src/bignum.cc \ - $$V8DIR/src/bignum-dtoa.cc \ - $$V8DIR/src/bootstrapper.cc \ - $$V8DIR/src/builtins.cc \ - $$V8DIR/src/cached-powers.cc \ - $$V8DIR/src/checks.cc \ - $$V8DIR/src/circular-queue.cc \ - $$V8DIR/src/code-stubs.cc \ - $$V8DIR/src/codegen.cc \ - $$V8DIR/src/compilation-cache.cc \ - $$V8DIR/src/compiler.cc \ - $$V8DIR/src/contexts.cc \ - $$V8DIR/src/conversions.cc \ - $$V8DIR/src/counters.cc \ - $$V8DIR/src/cpu-profiler.cc \ - $$V8DIR/src/data-flow.cc \ - $$V8DIR/src/dateparser.cc \ - $$V8DIR/src/debug-agent.cc \ - $$V8DIR/src/debug.cc \ - $$V8DIR/src/deoptimizer.cc \ - $$V8DIR/src/disassembler.cc \ - $$V8DIR/src/diy-fp.cc \ - $$V8DIR/src/dtoa.cc \ - $$V8DIR/src/execution.cc \ - $$V8DIR/src/factory.cc \ - $$V8DIR/src/flags.cc \ - $$V8DIR/src/frame-element.cc \ - $$V8DIR/src/frames.cc \ - $$V8DIR/src/full-codegen.cc \ - $$V8DIR/src/func-name-inferrer.cc \ - $$V8DIR/src/gdb-jit.cc \ - $$V8DIR/src/global-handles.cc \ - $$V8DIR/src/fast-dtoa.cc \ - $$V8DIR/src/fixed-dtoa.cc \ - $$V8DIR/src/handles.cc \ - $$V8DIR/src/hashmap.cc \ - $$V8DIR/src/heap-profiler.cc \ - $$V8DIR/src/heap.cc \ - $$V8DIR/src/hydrogen.cc \ - $$V8DIR/src/hydrogen-instructions.cc \ - $$V8DIR/src/ic.cc \ - $$V8DIR/src/inspector.cc \ - $$V8DIR/src/interpreter-irregexp.cc \ - $$V8DIR/src/isolate.cc \ - $$V8DIR/src/jsregexp.cc \ - $$V8DIR/src/lithium-allocator.cc \ - $$V8DIR/src/lithium.cc \ - $$V8DIR/src/liveedit.cc \ - $$V8DIR/src/liveobjectlist.cc \ - $$V8DIR/src/log-utils.cc \ - $$V8DIR/src/log.cc \ - $$V8DIR/src/mark-compact.cc \ - $$V8DIR/src/messages.cc \ - $$V8DIR/src/objects.cc \ - $$V8DIR/src/objects-printer.cc \ - $$V8DIR/src/objects-visiting.cc \ - $$V8DIR/src/parser.cc \ - $$V8DIR/src/preparser.cc \ - $$V8DIR/src/preparse-data.cc \ - $$V8DIR/src/profile-generator.cc \ - $$V8DIR/src/property.cc \ - $$V8DIR/src/regexp-macro-assembler-irregexp.cc \ - $$V8DIR/src/regexp-macro-assembler.cc \ - $$V8DIR/src/regexp-stack.cc \ - $$V8DIR/src/rewriter.cc \ - $$V8DIR/src/runtime.cc \ - $$V8DIR/src/runtime-profiler.cc \ - $$V8DIR/src/safepoint-table.cc \ - $$V8DIR/src/scanner-base.cc \ - $$V8DIR/src/scanner.cc \ - $$V8DIR/src/scopeinfo.cc \ - $$V8DIR/src/scopes.cc \ - $$V8DIR/src/serialize.cc \ - $$V8DIR/src/snapshot-common.cc \ - $$V8DIR/src/spaces.cc \ - $$V8DIR/src/string-search.cc \ - $$V8DIR/src/string-stream.cc \ - $$V8DIR/src/strtod.cc \ - $$V8DIR/src/stub-cache.cc \ - $$V8DIR/src/token.cc \ - $$V8DIR/src/top.cc \ - $$V8DIR/src/type-info.cc \ - $$V8DIR/src/unicode.cc \ - $$V8DIR/src/utils.cc \ - $$V8DIR/src/v8-counters.cc \ - $$V8DIR/src/v8.cc \ - $$V8DIR/src/v8threads.cc \ - $$V8DIR/src/variables.cc \ - $$V8DIR/src/version.cc \ - $$V8DIR/src/zone.cc \ - $$V8DIR/src/extensions/gc-extension.cc \ - $$V8DIR/src/extensions/externalize-string-extension.cc - -V8SOURCES += \ - $$V8DIR/src/snapshot-empty.cc \ - -arch_arm { -DEFINES += V8_TARGET_ARCH_ARM -V8SOURCES += \ - $$V8DIR/src/arm/builtins-arm.cc \ - $$V8DIR/src/arm/code-stubs-arm.cc \ - $$V8DIR/src/arm/codegen-arm.cc \ - $$V8DIR/src/arm/constants-arm.cc \ - $$V8DIR/src/arm/cpu-arm.cc \ - $$V8DIR/src/arm/debug-arm.cc \ - $$V8DIR/src/arm/deoptimizer-arm.cc \ - $$V8DIR/src/arm/disasm-arm.cc \ - $$V8DIR/src/arm/frames-arm.cc \ - $$V8DIR/src/arm/full-codegen-arm.cc \ - $$V8DIR/src/arm/ic-arm.cc \ - $$V8DIR/src/arm/lithium-arm.cc \ - $$V8DIR/src/arm/lithium-codegen-arm.cc \ - $$V8DIR/src/arm/lithium-gap-resolver-arm.cc \ - $$V8DIR/src/arm/macro-assembler-arm.cc \ - $$V8DIR/src/arm/regexp-macro-assembler-arm.cc \ - $$V8DIR/src/arm/stub-cache-arm.cc \ - $$V8DIR/src/arm/assembler-arm.cc -} - -arch_i386 { -DEFINES += V8_TARGET_ARCH_IA32 -V8SOURCES += \ - $$V8DIR/src/ia32/assembler-ia32.cc \ - $$V8DIR/src/ia32/builtins-ia32.cc \ - $$V8DIR/src/ia32/code-stubs-ia32.cc \ - $$V8DIR/src/ia32/codegen-ia32.cc \ - $$V8DIR/src/ia32/cpu-ia32.cc \ - $$V8DIR/src/ia32/debug-ia32.cc \ - $$V8DIR/src/ia32/deoptimizer-ia32.cc \ - $$V8DIR/src/ia32/disasm-ia32.cc \ - $$V8DIR/src/ia32/frames-ia32.cc \ - $$V8DIR/src/ia32/full-codegen-ia32.cc \ - $$V8DIR/src/ia32/ic-ia32.cc \ - $$V8DIR/src/ia32/lithium-codegen-ia32.cc \ - $$V8DIR/src/ia32/lithium-gap-resolver-ia32.cc \ - $$V8DIR/src/ia32/lithium-ia32.cc \ - $$V8DIR/src/ia32/macro-assembler-ia32.cc \ - $$V8DIR/src/ia32/regexp-macro-assembler-ia32.cc \ - $$V8DIR/src/ia32/stub-cache-ia32.cc -} - -# FIXME Should we use QT_CONFIG instead? What about 32 bit Macs? -arch_x86_64 { -DEFINES += V8_TARGET_ARCH_X64 -V8SOURCES += \ - $$V8DIR/src/x64/assembler-x64.cc \ - $$V8DIR/src/x64/builtins-x64.cc \ - $$V8DIR/src/x64/code-stubs-x64.cc \ - $$V8DIR/src/x64/codegen-x64.cc \ - $$V8DIR/src/x64/cpu-x64.cc \ - $$V8DIR/src/x64/debug-x64.cc \ - $$V8DIR/src/x64/deoptimizer-x64.cc \ - $$V8DIR/src/x64/disasm-x64.cc \ - $$V8DIR/src/x64/frames-x64.cc \ - $$V8DIR/src/x64/full-codegen-x64.cc \ - $$V8DIR/src/x64/ic-x64.cc \ - $$V8DIR/src/x64/lithium-codegen-x64.cc \ - $$V8DIR/src/x64/lithium-gap-resolver-x64.cc \ - $$V8DIR/src/x64/lithium-x64.cc \ - $$V8DIR/src/x64/macro-assembler-x64.cc \ - $$V8DIR/src/x64/regexp-macro-assembler-x64.cc \ - $$V8DIR/src/x64/stub-cache-x64.cc -} - -unix:!symbian:!macx { -V8SOURCES += \ - $$V8DIR/src/platform-linux.cc \ - $$V8DIR/src/platform-posix.cc -} - -#os:macos -macx { -V8SOURCES += \ - $$V8DIR/src/platform-macos.cc \ - $$V8DIR/src/platform-posix.cc -} - -win32 { -V8SOURCES += \ - $$V8DIR/src/platform-win32.cc -} - -#mode:debug -CONFIG(debug) { - V8SOURCES += \ - $$V8DIR/src/objects-debug.cc \ - $$V8DIR/src/prettyprinter.cc \ - $$V8DIR/src/regexp-macro-assembler-tracer.cc -} - -V8_LIBRARY_FILES = \ - $$V8DIR/src/runtime.js \ - $$V8DIR/src/v8natives.js \ - $$V8DIR/src/array.js \ - $$V8DIR/src/string.js \ - $$V8DIR/src/uri.js \ - $$V8DIR/src/math.js \ - $$V8DIR/src/messages.js \ - $$V8DIR/src/apinatives.js \ - $$V8DIR/src/date.js \ - $$V8DIR/src/regexp.js \ - $$V8DIR/src/json.js \ - $$V8DIR/src/liveedit-debugger.js \ - $$V8DIR/src/mirror-debugger.js \ - $$V8DIR/src/debug-debugger.js - -SOURCES += $$V8SOURCES - -v8_js2c.commands = python $$V8DIR/tools/js2c.py $$V8_GENERATED_SOURCES_DIR/libraries.cpp $$V8_GENERATED_SOURCES_DIR/libraries-empty.cpp CORE -v8_js2c.commands += $$V8DIR/src/macros.py ${QMAKE_FILE_IN} -v8_js2c.output = $$V8_GENERATED_SOURCES_DIR/libraries.cpp -v8_js2c.input = V8_LIBRARY_FILES -v8_js2c.variable_out = SOURCES -v8_js2c.dependency_type = TYPE_C -v8_js2c.depends = $$V8DIR/tools/js2c.py $$V8DIR/src/macros.py -v8_js2c.CONFIG += combine -v8_js2c.name = generating[v8] ${QMAKE_FILE_IN} -silent:v8_js2c.commands = @echo generating[v8] ${QMAKE_FILE_IN} && $$v8_js2c.commands -QMAKE_EXTRA_COMPILERS += v8_js2c diff --git a/src/declarative/v8/v8base.pri b/src/declarative/v8/v8base.pri deleted file mode 100644 index 9cea5cf575..0000000000 --- a/src/declarative/v8/v8base.pri +++ /dev/null @@ -1,19 +0,0 @@ -V8DIR = $$(V8DIR) -isEmpty(V8DIR) { - V8DIR = $$PWD/../../3rdparty/v8 -} else { - message(using external V8 from $$V8DIR) -} - -*-g++*: { - QMAKE_CFLAGS_WARN_ON += -Wno-unused-parameter - QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter - - # mksnapshot hangs if gcc 4.5 is used - # for reference look at http://code.google.com/p/v8/issues/detail?id=884 - equals(QT_GCC_MAJOR_VERSION, 4): equals(QT_GCC_MINOR_VERSION, 5) { - message(because of a bug in gcc / v8 we need to add -fno-strict-aliasing) - QMAKE_CFLAGS += -fno-strict-aliasing - QMAKE_CXXFLAGS += -fno-strict-aliasing - } -} diff --git a/src/declarative/v8/wrapcc.pl b/src/declarative/v8/wrapcc.pl deleted file mode 100755 index 27f5f867b0..0000000000 --- a/src/declarative/v8/wrapcc.pl +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/perl -############################################################################# -## -## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -## All rights reserved. -## Contact: Nokia Corporation (qt-info@nokia.com) -## -## This file is part of the translations module of the Qt Toolkit. -## -## $QT_BEGIN_LICENSE:LGPL$ -## GNU Lesser General Public License Usage -## This file may be used under the terms of the GNU Lesser General Public -## License version 2.1 as published by the Free Software Foundation and -## appearing in the file LICENSE.LGPL included in the packaging of this -## file. Please review the following information to ensure the GNU Lesser -## General Public License version 2.1 requirements will be met: -## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -## -## In addition, as a special exception, Nokia gives you certain additional -## rights. These rights are described in the Nokia Qt LGPL Exception -## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU General -## Public License version 3.0 as published by the Free Software Foundation -## and appearing in the file LICENSE.GPL included in the packaging of this -## file. Please review the following information to ensure the GNU General -## Public License version 3.0 requirements will be met: -## http://www.gnu.org/copyleft/gpl.html. -## -## Other Usage -## Alternatively, this file may be used in accordance with the terms and -## conditions contained in a signed written agreement between you and Nokia. -## -## -## -## -## -## $QT_END_LICENSE$ -## -############################################################################# - -scalar(@ARGV) == 2 or die "Usage: $0 INFILE OUTFILE"; -my $inFile = $ARGV[0]; -my $outFile = $ARGV[1]; -open FILE, ">", $outFile or die "Error: could not open $outFile for writing"; -print FILE "#include \"$inFile\"\n"; -close FILE; diff --git a/src/imports/gestures/gestures.pro b/src/imports/gestures/gestures.pro index 3b735efac5..e7095956b2 100644 --- a/src/imports/gestures/gestures.pro +++ b/src/imports/gestures/gestures.pro @@ -2,7 +2,7 @@ TARGET = qmlgesturesplugin TARGETPATH = Qt/labs/gestures include(../qimportbase.pri) -QT += core-private gui-private declarative-private qtquick1 qtquick1-private widgets-private +QT += core-private gui-private declarative-private qtquick1 qtquick1-private widgets-private v8-private SOURCES += qdeclarativegesturearea.cpp plugin.cpp HEADERS += qdeclarativegesturearea_p.h diff --git a/src/imports/gestures/qdeclarativegesturearea.cpp b/src/imports/gestures/qdeclarativegesturearea.cpp index c0d88a3318..1631831c7f 100644 --- a/src/imports/gestures/qdeclarativegesturearea.cpp +++ b/src/imports/gestures/qdeclarativegesturearea.cpp @@ -46,6 +46,7 @@ #include <qdeclarativeinfo.h> #include <private/qdeclarativeproperty_p.h> +#include <private/qdeclarativescript_p.h> #include <QtQuick1/private/qdeclarativeitem_p.h> #include <QtCore/qdebug.h> @@ -196,7 +197,7 @@ QDeclarativeGestureAreaParser::compile(const QList<QDeclarativeCustomParserPrope error(props.at(ii), QDeclarativeGestureArea::tr("GestureArea: syntax error")); return QByteArray(); } else { - QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(value); + QDeclarativeScript::Variant v = qvariant_cast<QDeclarativeScript::Variant>(value); if (v.isScript()) { ds << propName; ds << int(type); diff --git a/src/imports/particles/particles.pro b/src/imports/particles/particles.pro index 79906563f8..74dab8dcf3 100644 --- a/src/imports/particles/particles.pro +++ b/src/imports/particles/particles.pro @@ -9,7 +9,7 @@ SOURCES += \ particles.cpp \ V1/qdeclarativeparticles.cpp -QT += declarative opengl core gui declarative-private core-private gui-private qtquick1 qtquick1-private widgets-private +QT += declarative opengl core gui declarative-private core-private gui-private qtquick1 qtquick1-private widgets-private v8-private OTHER_FILES += \ qmldir diff --git a/src/imports/testlib/testlib.pro b/src/imports/testlib/testlib.pro index 5adde2ae85..da072d34b1 100644 --- a/src/imports/testlib/testlib.pro +++ b/src/imports/testlib/testlib.pro @@ -21,7 +21,7 @@ symbian { } -QT += declarative qmltest qmltest-private declarative-private core-private testlib +QT += declarative qmltest qmltest-private v8-private declarative-private core-private testlib SOURCES += main.cpp HEADERS += diff --git a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp index 3cb35e5738..8dcc076630 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/abstractviewinspector.cpp @@ -47,7 +47,7 @@ #include <QtDeclarative/QDeclarativeEngine> #include <QtDeclarative/QDeclarativeComponent> -#include <QtDeclarative/private/qdeclarativedebughelper_p.h> +#include <QtCore/private/qabstractanimation_p.h> #include "QtDeclarative/private/qdeclarativeinspectorservice_p.h" #include <QtWidgets/QVBoxLayout> @@ -180,7 +180,8 @@ void AbstractViewInspector::animationSpeedChangeRequested(qreal factor) } const float effectiveFactor = m_animationPaused ? 0 : factor; - QDeclarativeDebugHelper::setAnimationSlowDownFactor(effectiveFactor); + QUnifiedTimer::instance()->setSlowModeEnabled(effectiveFactor != 1.0); + QUnifiedTimer::instance()->setSlowdownFactor(effectiveFactor); } void AbstractViewInspector::animationPausedChangeRequested(bool paused) @@ -191,7 +192,8 @@ void AbstractViewInspector::animationPausedChangeRequested(bool paused) } const float effectiveFactor = paused ? 0 : m_slowDownFactor; - QDeclarativeDebugHelper::setAnimationSlowDownFactor(effectiveFactor); + QUnifiedTimer::instance()->setSlowModeEnabled(effectiveFactor != 1.0); + QUnifiedTimer::instance()->setSlowdownFactor(effectiveFactor); } void AbstractViewInspector::setShowAppOnTop(bool appOnTop) diff --git a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro index d547422cb0..c165832013 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro +++ b/src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro @@ -1,7 +1,7 @@ load(qt_module) TARGET = qmldbg_inspector -QT += declarative-private core-private gui-private opengl-private qtquick1 widgets widgets-private +QT += declarative-private core-private gui-private opengl-private qtquick1 widgets widgets-private v8-private load(qt_plugin) diff --git a/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp index bb9ad52fee..497e51db4d 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/sgviewinspector.cpp @@ -46,7 +46,6 @@ #include "sgselectiontool.h" #include <QtDeclarative/private/qdeclarativeinspectorservice_p.h> -#include <QtDeclarative/private/qdeclarativedebughelper_p.h> #include <QtDeclarative/private/qsgitem_p.h> #include <QtDeclarative/QSGView> diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro index 418136aa0a..b19ad55092 100644 --- a/src/qmltest/qmltest.pro +++ b/src/qmltest/qmltest.pro @@ -4,7 +4,7 @@ TARGET = QtQuickTest QPRO_PWD = $$PWD CONFIG += module -CONFIG += dll warn_on +CONFIG += dll warn_on declarative_debug MODULE_PRI += ../../modules/qt_qmltest.pri QT += testlib-private declarative testlib qtquick1 diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 7f16eddc7e..c7d9747a3e 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -67,15 +67,6 @@ QT_BEGIN_NAMESPACE -// Copied from qdeclarativedebughelper_p.h in Qt, to avoid a dependency -// on a private header from Qt. -class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper -{ -public: - static QJSEngine *getScriptEngine(QDeclarativeEngine *engine); - static void setAnimationSlowDownFactor(qreal factor); - static void enableDebugging(); -}; class QTestRootObject : public QObject { diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp index 534c57e1c2..80c3f8b3d5 100644 --- a/src/qmltest/quicktestresult.cpp +++ b/src/qmltest/quicktestresult.cpp @@ -442,14 +442,14 @@ bool QuickTestResult::compare void QuickTestResult::skipSingle (const QString &message, const QString &file, int line) { - QTestResult::addSkip(message.toLatin1().constData(), QTest::SkipSingle, + QTestResult::addSkip(message.toLatin1().constData(), qtest_fixFile(file).toLatin1().constData(), line); } void QuickTestResult::skipAll (const QString &message, const QString &file, int line) { - QTestResult::addSkip(message.toLatin1().constData(), QTest::SkipAll, + QTestResult::addSkip(message.toLatin1().constData(), qtest_fixFile(file).toLatin1().constData(), line); QTestResult::setSkipCurrentTest(true); } diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp index b32898fe38..c719067e2e 100644 --- a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp +++ b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp @@ -3665,8 +3665,8 @@ void QDeclarativeItem::setSize(const QSizeF &size) bool QDeclarativeItem::hasActiveFocus() const { Q_D(const QDeclarativeItem); - return focusItem() == this || - (d->flags & QGraphicsItem::ItemIsFocusScope && focusItem() != 0); + return (focusItem() && focusItem()->isVisible()) && (focusItem() == this || + (d->flags & QGraphicsItem::ItemIsFocusScope && focusItem() != 0)); } /*! diff --git a/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp index 5d8a3d4b37..f76a4d9f08 100644 --- a/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -1379,7 +1379,7 @@ void QDeclarative1VisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, Q_D(QDeclarative1VisualDataModel); const int count = sourceEnd - sourceStart + 1; if (destinationParent == d->m_root && sourceParent == d->m_root) { - _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-1, count); + _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-count, count); } else if (sourceParent == d->m_root) { _q_itemsRemoved(sourceStart, count); } else if (destinationParent == d->m_root) { diff --git a/src/qtquick1/qtquick1.pro b/src/qtquick1/qtquick1.pro index 2e3113e214..66f2c848f2 100644 --- a/src/qtquick1/qtquick1.pro +++ b/src/qtquick1/qtquick1.pro @@ -7,7 +7,8 @@ CONFIG += module CONFIG += dll warn_on MODULE_PRI += ../../modules/qt_qtquick1.pri -QT += testlib-private declarative testlib declarative-private core-private gui-private network widgets-private +QT += testlib-private declarative testlib declarative-private core-private gui-private network widgets-private v8-private +DEFINES += QT_NO_URL_CAST_FROM_STRING load(qt_module_config) diff --git a/src/qtquick1/util/qdeclarativeconnections.cpp b/src/qtquick1/util/qdeclarativeconnections.cpp index 5fc019c4c1..54f51acd12 100644 --- a/src/qtquick1/util/qdeclarativeconnections.cpp +++ b/src/qtquick1/util/qdeclarativeconnections.cpp @@ -223,7 +223,7 @@ QDeclarative1ConnectionsParser::compile(const QList<QDeclarativeCustomParserProp error(props.at(ii), QDeclarative1Connections::tr("Connections: syntax error")); return QByteArray(); } else { - QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(value); + QDeclarativeScript::Variant v = qvariant_cast<QDeclarativeScript::Variant>(value); if (v.isScript()) { ds << propName; ds << v.asScript(); diff --git a/src/qtquick1/util/qdeclarativelistmodel.cpp b/src/qtquick1/util/qdeclarativelistmodel.cpp index d5aa75bec5..5c31a8bd79 100644 --- a/src/qtquick1/util/qdeclarativelistmodel.cpp +++ b/src/qtquick1/util/qdeclarativelistmodel.cpp @@ -44,7 +44,7 @@ #include "QtQuick1/private/qdeclarativeopenmetaobject_p.h" #include <QtDeclarative/private/qdeclarativecustomparser_p.h> -#include <QtDeclarative/private/qdeclarativeparser_p.h> +#include <QtDeclarative/private/qdeclarativescript_p.h> #include <QtDeclarative/private/qdeclarativeengine_p.h> #include <QtDeclarative/qdeclarativecontext.h> #include <QtDeclarative/qdeclarativeinfo.h> @@ -787,6 +787,7 @@ void QDeclarative1ListModelParser::setCustomData(QObject *obj, const QByteArray QDeclarative1ListModel *rv = static_cast<QDeclarative1ListModel *>(obj); ModelNode *root = new ModelNode(rv->m_nested); + rv->m_nested->m_ownsRoot = true; rv->m_nested->_root = root; QStack<ModelNode *> nodes; nodes << root; diff --git a/src/qtquick1/util/qdeclarativepropertychanges.cpp b/src/qtquick1/util/qdeclarativepropertychanges.cpp index 776701e58f..fc063cafb0 100644 --- a/src/qtquick1/util/qdeclarativepropertychanges.cpp +++ b/src/qtquick1/util/qdeclarativepropertychanges.cpp @@ -48,7 +48,7 @@ #include <QtDeclarative/qdeclarativeinfo.h> #include <QtDeclarative/private/qdeclarativecustomparser_p.h> -#include <QtDeclarative/private/qdeclarativeparser_p.h> +#include <QtDeclarative/private/qdeclarativescript_p.h> #include <QtDeclarative/qdeclarativeexpression.h> #include <QtDeclarative/private/qdeclarativebinding_p.h> #include <QtDeclarative/qdeclarativecontext.h> @@ -282,22 +282,22 @@ QDeclarative1PropertyChangesParser::compile(const QList<QDeclarativeCustomParser ds << data.count(); for(int ii = 0; ii < data.count(); ++ii) { - QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(data.at(ii).second); + QDeclarativeScript::Variant v = qvariant_cast<QDeclarativeScript::Variant>(data.at(ii).second); QVariant var; bool isScript = v.isScript(); QDeclarativeBinding::Identifier id = 0; switch(v.type()) { - case QDeclarativeParser::Variant::Boolean: + case QDeclarativeScript::Variant::Boolean: var = QVariant(v.asBoolean()); break; - case QDeclarativeParser::Variant::Number: + case QDeclarativeScript::Variant::Number: var = QVariant(v.asNumber()); break; - case QDeclarativeParser::Variant::String: + case QDeclarativeScript::Variant::String: var = QVariant(v.asString()); break; - case QDeclarativeParser::Variant::Invalid: - case QDeclarativeParser::Variant::Script: + case QDeclarativeScript::Variant::Invalid: + case QDeclarativeScript::Variant::Script: var = QVariant(v.asScript()); { // Pre-rewrite the expression diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index a99656a3ee..5c5e76d78a 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -33,7 +33,6 @@ PRIVATETESTS += \ qdeclarativeconnection \ qdeclarativedebug \ qdeclarativedebugclient \ - qdeclarativedebughelper \ qdeclarativedebugservice \ qdeclarativeecmascript \ qdeclarativeimageprovider \ @@ -54,8 +53,7 @@ PRIVATETESTS += \ qdeclarativeworkerscript \ qdeclarativexmllistmodel \ qpacketprotocol \ - qdeclarativev4 \ - v8 + qdeclarativev4 SGTESTS = \ qsganimatedimage \ diff --git a/tests/auto/declarative/examples/examples.pro b/tests/auto/declarative/examples/examples.pro index 297559ef97..75adbb53ba 100644 --- a/tests/auto/declarative/examples/examples.pro +++ b/tests/auto/declarative/examples/examples.pro @@ -18,6 +18,6 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private widgets-private +QT += core-private gui-private declarative-private qtquick1-private widgets-private v8-private qpa:CONFIG+=insignificant_test # QTBUG-20990, aborts diff --git a/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro b/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro index 2669e5a8e3..049e1b3acb 100644 --- a/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro +++ b/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro @@ -13,4 +13,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private opengl-private +QT += core-private gui-private v8-private declarative-private opengl-private diff --git a/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro b/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro index e0720aa6fd..03ba50ad15 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro +++ b/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro @@ -13,4 +13,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private opengl-private +QT += core-private gui-private v8-private declarative-private opengl-private diff --git a/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro b/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro index 49150c8481..7cd78ab1fc 100644 --- a/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro +++ b/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private opengl-private +QT += core-private gui-private v8-private declarative-private opengl-private diff --git a/tests/auto/declarative/qdeclarativedebug/qdeclarativedebug.pro b/tests/auto/declarative/qdeclarativedebug/qdeclarativedebug.pro index cd5577219d..6187020a38 100644 --- a/tests/auto/declarative/qdeclarativedebug/qdeclarativedebug.pro +++ b/tests/auto/declarative/qdeclarativedebug/qdeclarativedebug.pro @@ -6,6 +6,6 @@ HEADERS += ../shared/debugutil_p.h SOURCES += tst_qdeclarativedebug.cpp \ ../shared/debugutil.cpp -CONFIG += parallel_test +CONFIG += parallel_test declarative_debug -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index ade51c43f6..b47579ea6a 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -55,11 +55,9 @@ #include <private/qdeclarativebinding_p.h> #include <private/qdeclarativedebug_p.h> #include <private/qdeclarativeenginedebug_p.h> -#include <private/qdeclarativedebugclient_p.h> #include <private/qdeclarativedebugservice_p.h> #include <private/qdeclarativemetatype_p.h> #include <private/qdeclarativeproperty_p.h> -#include <private/qdeclarativedebughelper_p.h> #include "../../../shared/util.h" #include "../shared/debugutil_p.h" @@ -296,9 +294,6 @@ void tst_QDeclarativeDebug::initTestCase() qRegisterMetaType<QDeclarativeDebugWatch::State>(); qmlRegisterType<NonScriptProperty>("Test", 1, 0, "NonScriptPropertyElement"); - QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); - QDeclarativeDebugHelper::enableDebugging(); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3768..."); m_engine = new QDeclarativeEngine(this); @@ -1089,7 +1084,7 @@ void tst_QDeclarativeDebug::setBindingInStates() // change the binding - QDeclarativeDebugObjectReference state = obj.children()[0]; + QDeclarativeDebugObjectReference state = obj.children()[1]; QCOMPARE(state.className(), QString("State")); QVERIFY(state.children().count() > 0); @@ -1173,7 +1168,7 @@ void tst_QDeclarativeDebug::queryObjectTree() // check state - QDeclarativeDebugObjectReference state = obj.children()[0]; + QDeclarativeDebugObjectReference state = obj.children()[1]; QCOMPARE(state.className(), QString("State")); QVERIFY(state.children().count() > 0); @@ -1189,7 +1184,7 @@ void tst_QDeclarativeDebug::queryObjectTree() // check transition - QDeclarativeDebugObjectReference transition = obj.children()[1]; + QDeclarativeDebugObjectReference transition = obj.children()[0]; QCOMPARE(transition.className(), QString("Transition")); QCOMPARE(findProperty(transition.properties(),"from").value().toString(), QString("*")); QCOMPARE(findProperty(transition.properties(),"to").value(), findProperty(state.properties(),"name").value()); diff --git a/tests/auto/declarative/qdeclarativedebugclient/qdeclarativedebugclient.pro b/tests/auto/declarative/qdeclarativedebugclient/qdeclarativedebugclient.pro index 189133a526..28e25e9450 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/qdeclarativedebugclient.pro +++ b/tests/auto/declarative/qdeclarativedebugclient/qdeclarativedebugclient.pro @@ -5,4 +5,8 @@ macx:CONFIG -= app_bundle HEADERS += ../shared/debugutil_p.h SOURCES += tst_qdeclarativedebugclient.cpp \ ../shared/debugutil.cpp + +CONFIG += declarative_debug + QT += core-private gui-private declarative-private + diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp index d41cfa3d4d..d7f53c9620 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp +++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp @@ -49,9 +49,7 @@ #include <private/qdeclarativedebug_p.h> #include <private/qdeclarativeenginedebug_p.h> -#include <private/qdeclarativedebugclient_p.h> #include <private/qdeclarativedebugservice_p.h> -#include <private/qdeclarativedebughelper_p.h> #include "../../../shared/util.h" #include "../shared/debugutil_p.h" @@ -73,9 +71,6 @@ private slots: void tst_QDeclarativeDebugClient::initTestCase() { - QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); - QDeclarativeDebugHelper::enableDebugging(); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13770..."); new QDeclarativeEngine(this); diff --git a/tests/auto/declarative/qdeclarativedebughelper/qdeclarativedebughelper.pro b/tests/auto/declarative/qdeclarativedebughelper/qdeclarativedebughelper.pro deleted file mode 100644 index 1e62c12363..0000000000 --- a/tests/auto/declarative/qdeclarativedebughelper/qdeclarativedebughelper.pro +++ /dev/null @@ -1,6 +0,0 @@ -load(qttest_p4) -contains(QT_CONFIG,declarative): QT += network declarative -macx:CONFIG -= app_bundle - -SOURCES += tst_qdeclarativedebughelper.cpp -QT += core-private gui-private declarative-private diff --git a/tests/auto/declarative/qdeclarativedebughelper/tst_qdeclarativedebughelper.cpp b/tests/auto/declarative/qdeclarativedebughelper/tst_qdeclarativedebughelper.cpp deleted file mode 100644 index f67d5c5a89..0000000000 --- a/tests/auto/declarative/qdeclarativedebughelper/tst_qdeclarativedebughelper.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <qtest.h> - -#include <QDeclarativeEngine> -#include <private/qdeclarativeengine_p.h> -#include <QAbstractAnimation> -#include <private/qabstractanimation_p.h> - -// We have copied the header which is used in the qmljsdebugger (part of QtCreator) -// to catch BC changes. Don't update it unless you know what you are doing! -#include "private_headers/qdeclarativedebughelper_p.h" - -class tst_qdeclarativedebughelper : public QObject { - Q_OBJECT -private slots: - void setAnimationSlowDownFactor(); - void enableDebugging(); -}; - -class TestAnimation : public QAbstractAnimation { -public: - int updateCalled; - - TestAnimation() : updateCalled(0) {} - - virtual void updateCurrentTime(int /*currentTime*/) { - updateCalled++; - } - virtual int duration() const { - return 100; - } -}; - -void tst_qdeclarativedebughelper::setAnimationSlowDownFactor() -{ - TestAnimation animation; - - // first check whether setup works - QCOMPARE(animation.updateCalled, 0); - animation.start(); - QTest::qWait(animation.totalDuration() + 150); -#ifdef Q_OS_WIN - if (animation.state() != QAbstractAnimation::Stopped) - QEXPECT_FAIL("", "On windows, consistent timing is not working properly due to bad timer resolution", Abort); -#endif - QCOMPARE(animation.state(), QAbstractAnimation::Stopped); - QVERIFY(animation.updateCalled > 1); - - // check if we can pause all animations - animation.updateCalled = 0; - QDeclarativeDebugHelper::setAnimationSlowDownFactor(0.0); - animation.start(); - QTest::qWait(animation.totalDuration() + 150); - QVERIFY(animation.updateCalled <= 1); // updateCurrentTime seems to be called at least once - - // now run them again - animation.updateCalled = 0; - QDeclarativeDebugHelper::setAnimationSlowDownFactor(2.0); - animation.start(); - QTest::qWait(animation.totalDuration() + 150); - QVERIFY(animation.updateCalled > 1); -} - -void tst_qdeclarativedebughelper::enableDebugging() -{ - QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); - QDeclarativeDebugHelper::enableDebugging(); -} - -QTEST_MAIN(tst_qdeclarativedebughelper) - -#include "tst_qdeclarativedebughelper.moc" - diff --git a/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro b/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro index 785e8a7bf1..999e19279b 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro +++ b/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro @@ -6,6 +6,6 @@ HEADERS += ../shared/debugutil_p.h SOURCES += tst_qdeclarativedebugservice.cpp \ ../shared/debugutil.cpp -CONFIG += parallel_test +CONFIG += parallel_test declarative_debug QT += core-private gui-private declarative-private diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index 3fa8bba682..74f549c076 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -46,7 +46,6 @@ #include <QThread> #include <QtDeclarative/qdeclarativeengine.h> -#include <private/qdeclarativedebughelper_p.h> #include <private/qdeclarativedebug_p.h> #include <private/qdeclarativeenginedebug_p.h> @@ -76,9 +75,6 @@ private slots: void tst_QDeclarativeDebugService::initTestCase() { - QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); - QDeclarativeDebugHelper::enableDebugging(); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13769..."); new QDeclarativeEngine(this); diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiMajorVersionFail.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/moduleApiMajorVersionFail.qml index fb050f65bc..fb050f65bc 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiMajorVersionFail.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/moduleApiMajorVersionFail.qml diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiMinorVersionFail.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/moduleApiMinorVersionFail.qml index e06be667f7..e06be667f7 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiMinorVersionFail.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/moduleApiMinorVersionFail.qml diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApi.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApi.qml index 67e8c1b08a..718a64652d 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApi.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApi.qml @@ -1,7 +1,6 @@ import QtQuick 2.0 import Qt.test 1.0 as QtTest // module API installed into existing uri -import Qt.test.scriptApi 1.0 as QtTestScriptApi // script module API installed into new uri import Qt.test.qobjectApi 1.0 as QtTestQObjectApi // qobject module API installed into new uri import Qt.test.qobjectApi 1.3 as QtTestMinorVersionQObjectApi // qobject module API installed into existing uri with new minor version import Qt.test.qobjectApi 2.0 as QtTestMajorVersionQObjectApi // qobject module API installed into existing uri with new major version @@ -9,7 +8,6 @@ import Qt.test.qobjectApiParented 1.0 as QtTestParentedQObjectApi // qobject (wi QtObject { property int existingUriTest: QtTest.qobjectTestProperty - property int scriptTest: QtTestScriptApi.scriptTestProperty property int qobjectTest: QtTestQObjectApi.qobjectTestProperty property int qobjectMethodTest: 2 property int qobjectMinorVersionTest: QtTestMinorVersionQObjectApi.qobjectTestProperty diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiCaching.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApiCaching.qml index f6ce2058a7..56a55e4e9b 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiCaching.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApiCaching.qml @@ -1,12 +1,10 @@ import QtQuick 2.0 import Qt.test 1.0 as QtTest // module API installed into existing uri -import Qt.test.scriptApi 1.0 as QtTestScriptApi // script module API installed into new uri import Qt.test.qobjectApiParented 1.0 as QtTestParentedQObjectApi // qobject (with parent) module API installed into a new uri QtObject { property int existingUriTest: QtTest.qobjectTestProperty - property int scriptTest: QtTestScriptApi.scriptTestProperty property int qobjectParentedTest: QtTestParentedQObjectApi.qobjectTestProperty } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApiEnums.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApiEnums.qml new file mode 100644 index 0000000000..da5ffd5e76 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApiEnums.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import Qt.test.qobjectApi 1.0 as QtTestQObjectApi // qobject module API installed into new uri + +QtObject { + property int enumValue: QtTestQObjectApi.EnumValue2; + property int enumMethod: QtTestQObjectApi.qobjectEnumTestMethod(QtTestQObjectApi.EnumValue1); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiWriting.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApiWriting.qml index 500c35e211..be647ca57f 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/moduleApiWriting.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/qobjectModuleApiWriting.qml @@ -1,6 +1,5 @@ import QtQuick 2.0 - -import Qt.test 1.0 as QtTest // module API installed into existing uri +import Qt.test 1.0 as QtTest // qobject module API installed into existing uri QtObject { property int firstProperty: 1 diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApi.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApi.qml new file mode 100644 index 0000000000..7c4e20489d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApi.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import Qt.test.scriptApi 1.0 as QtTestScriptApi // script module API installed into new uri + +QtObject { + property int scriptTest: QtTestScriptApi.scriptTestProperty // script module api's only provide properties. +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApiCaching.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApiCaching.qml new file mode 100644 index 0000000000..90974b5969 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApiCaching.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import Qt.test.scriptApi 1.0 as QtTestScriptApi // script module API installed into new uri + +QtObject { + property int scriptTest: QtTestScriptApi.scriptTestProperty +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApiWriting.qml b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApiWriting.qml new file mode 100644 index 0000000000..02461d59ed --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/moduleapi/scriptModuleApiWriting.qml @@ -0,0 +1,32 @@ +import QtQuick 2.0 +import Qt.test.scriptApi 1.0 as QtTestScriptApi +import Qt.test.scriptApi 2.0 as QtTestScriptApi2 + +QtObject { + property int firstProperty + property int readBack + + property int secondProperty + property int unchanged + + onFirstPropertyChanged: { + if (QtTestScriptApi.scriptTestProperty != firstProperty) { + QtTestScriptApi.scriptTestProperty = firstProperty; + readBack = QtTestScriptApi.scriptTestProperty; + } + } + + onSecondPropertyChanged: { + if (QtTestScriptApi2.scriptTestProperty != secondProperty) { + QtTestScriptApi2.scriptTestProperty = secondProperty; + unchanged = QtTestScriptApi2.scriptTestProperty; + } + } + + Component.onCompleted: { + firstProperty = QtTestScriptApi.scriptTestProperty; + readBack = QtTestScriptApi.scriptTestProperty; + secondProperty = QtTestScriptApi2.scriptTestProperty; + unchanged = QtTestScriptApi2.scriptTestProperty; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro index 4b7aff339c..5dfcfa6e1b 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro +++ b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro @@ -22,4 +22,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 160a57215b..05d5510033 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -111,6 +111,21 @@ static QJSValue script_api(QDeclarativeEngine *engine, QJSEngine *scriptEngine) return v; } +static QJSValue readonly_script_api(QDeclarativeEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + + static int testProperty = 42; + QJSValue v = scriptEngine->newObject(); + v.setProperty("scriptTestProperty", testProperty++); + + // now freeze it so that it's read-only + QJSValue freezeFunction = scriptEngine->evaluate("(function(obj) { return Object.freeze(obj); })"); + v = freezeFunction.call(QJSValue(), (QJSValueList() << v)); + + return v; +} + static QObject *qobject_api(QDeclarativeEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) @@ -166,6 +181,7 @@ void registerTypes() qmlRegisterModuleApi("Qt.test",1,0,script_api); // register (script) module API for an existing uri which contains elements qmlRegisterModuleApi("Qt.test",1,0,qobject_api); // register (qobject) for an existing uri for which another module API was previously regd. Should replace! qmlRegisterModuleApi("Qt.test.scriptApi",1,0,script_api); // register (script) module API for a uri which doesn't contain elements + qmlRegisterModuleApi("Qt.test.scriptApi",2,0,readonly_script_api); // register (script) module API for a uri which doesn't contain elements - will be made read-only qmlRegisterModuleApi("Qt.test.qobjectApi",1,0,qobject_api); // register (qobject) module API for a uri which doesn't contain elements qmlRegisterModuleApi("Qt.test.qobjectApi",1,3,qobject_api); // register (qobject) module API for a uri which doesn't contain elements, minor version set qmlRegisterModuleApi("Qt.test.qobjectApi",2,0,qobject_api); // register (qobject) module API for a uri which doesn't contain elements, major version set diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index afb361e2d7..2738ee3d60 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -934,6 +934,7 @@ private: class testQObjectApi : public QObject { Q_OBJECT + Q_ENUMS(MyEnum) Q_PROPERTY (int qobjectTestProperty READ qobjectTestProperty NOTIFY qobjectTestPropertyChanged) Q_PROPERTY (int qobjectTestWritableProperty READ qobjectTestWritableProperty WRITE setQObjectTestWritableProperty NOTIFY qobjectTestWritablePropertyChanged) @@ -945,7 +946,9 @@ public: ~testQObjectApi() {} - Q_INVOKABLE int qobjectTestMethod() { m_methodCallCount += 1; return m_methodCallCount; } + enum MyEnum { EnumValue1 = 25, EnumValue2 = 42 }; + Q_INVOKABLE int qobjectEnumTestMethod(MyEnum val) { return (static_cast<int>(val) + 5); } + Q_INVOKABLE int qobjectTestMethod(int increment = 1) { m_methodCallCount += increment; return m_methodCallCount; } int qobjectTestProperty() const { return m_testProperty; } void setQObjectTestProperty(int tp) { m_testProperty = tp; emit qobjectTestPropertyChanged(tp); } diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 3efe18909c..f14db0a330 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -145,6 +145,7 @@ private slots: void numberAssignment(); void propertySplicing(); void signalWithUnknownTypes(); + void moduleApi_data(); void moduleApi(); void importScripts(); void scarceResources(); @@ -2735,55 +2736,153 @@ void tst_qdeclarativeecmascript::signalWithUnknownTypes() delete object; } +void tst_qdeclarativeecmascript::moduleApi_data() +{ + QTest::addColumn<QUrl>("testfile"); + QTest::addColumn<QString>("errorMessage"); + QTest::addColumn<QStringList>("warningMessages"); + QTest::addColumn<QStringList>("readProperties"); + QTest::addColumn<QVariantList>("readExpectedValues"); + QTest::addColumn<QStringList>("writeProperties"); + QTest::addColumn<QVariantList>("writeValues"); + QTest::addColumn<QStringList>("readBackProperties"); + QTest::addColumn<QVariantList>("readBackExpectedValues"); + + QTest::newRow("qobject, register + read + method") + << TEST_FILE("moduleapi/qobjectModuleApi.qml") + << QString() + << QStringList() + << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest" + << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest") + << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26) + << QStringList() + << QVariantList() + << QStringList() + << QVariantList(); + + QTest::newRow("script, register + read") + << TEST_FILE("moduleapi/scriptModuleApi.qml") + << QString() + << QStringList() + << (QStringList() << "scriptTest") + << (QVariantList() << 13) + << QStringList() + << QVariantList() + << QStringList() + << QVariantList(); + + QTest::newRow("qobject, caching + read") + << TEST_FILE("moduleapi/qobjectModuleApiCaching.qml") + << QString() + << QStringList() + << (QStringList() << "existingUriTest" << "qobjectParentedTest") + << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27. + << QStringList() + << QVariantList() + << QStringList() + << QVariantList(); + + QTest::newRow("script, caching + read") + << TEST_FILE("moduleapi/scriptModuleApiCaching.qml") + << QString() + << QStringList() + << (QStringList() << "scriptTest") + << (QVariantList() << 13) // 13, shouldn't have incremented to 14. + << QStringList() + << QVariantList() + << QStringList() + << QVariantList(); + + QTest::newRow("qobject, writing + readonly constraints") + << TEST_FILE("moduleapi/qobjectModuleApiWriting.qml") + << QString() + << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\""))) + << (QStringList() << "readOnlyProperty" << "writableProperty") + << (QVariantList() << 20 << 50) + << (QStringList() << "firstProperty" << "writableProperty") + << (QVariantList() << 30 << 30) + << (QStringList() << "readOnlyProperty" << "writableProperty") + << (QVariantList() << 20 << 30); + + QTest::newRow("script, writing + readonly constraints") + << TEST_FILE("moduleapi/scriptModuleApiWriting.qml") + << QString() + << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\""))) + << (QStringList() << "readBack" << "unchanged") + << (QVariantList() << 13 << 42) + << (QStringList() << "firstProperty" << "secondProperty") + << (QVariantList() << 30 << 30) + << (QStringList() << "readBack" << "unchanged") + << (QVariantList() << 30 << 42); + + QTest::newRow("qobject module API enum values in JS") + << TEST_FILE("moduleapi/qobjectModuleApiEnums.qml") + << QString() + << QStringList() + << (QStringList() << "enumValue" << "enumMethod") + << (QVariantList() << 42 << 30) + << QStringList() + << QVariantList() + << QStringList() + << QVariantList(); + + QTest::newRow("qobject, invalid major version fail") + << TEST_FILE("moduleapi/moduleApiMajorVersionFail.qml") + << QString("QDeclarativeComponent: Component is not ready") + << QStringList() + << QStringList() + << QVariantList() + << QStringList() + << QVariantList() + << QStringList() + << QVariantList(); + + QTest::newRow("qobject, invalid minor version fail") + << TEST_FILE("moduleapi/moduleApiMinorVersionFail.qml") + << QString("QDeclarativeComponent: Component is not ready") + << QStringList() + << QStringList() + << QVariantList() + << QStringList() + << QVariantList() + << QStringList() + << QVariantList(); +} + void tst_qdeclarativeecmascript::moduleApi() { - QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); - QCOMPARE(object->property("existingUriTest").toInt(), 20); + QFETCH(QUrl, testfile); + QFETCH(QString, errorMessage); + QFETCH(QStringList, warningMessages); + QFETCH(QStringList, readProperties); + QFETCH(QVariantList, readExpectedValues); + QFETCH(QStringList, writeProperties); + QFETCH(QVariantList, writeValues); + QFETCH(QStringList, readBackProperties); + QFETCH(QVariantList, readBackExpectedValues); - QEXPECT_FAIL("", "QTBUG-17318", Continue); - QCOMPARE(object->property("scriptTest").toInt(), 13); - QCOMPARE(object->property("qobjectTest").toInt(), 20); - QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1. - QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20); - QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20); - QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); - delete object; + QDeclarativeComponent component(&engine, testfile); - // test that caching of module apis works correctly. - QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml")); - object = componentTwo.create(); - QVERIFY(object != 0); - QCOMPARE(object->property("existingUriTest").toInt(), 20); - QEXPECT_FAIL("", "QTBUG-17318", Continue); - QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented. - QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented. - delete object; + if (!errorMessage.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData()); - // test that writing to a property of module apis works correctly. - QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml")); - QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\""); - QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData()); - object = componentThree.create(); - QVERIFY(object != 0); - QCOMPARE(object->property("readOnlyProperty").toInt(), 20); - QCOMPARE(object->property("writableProperty").toInt(), 50); - QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty - QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty - QCOMPARE(object->property("readOnlyProperty").toInt(), 20); - QCOMPARE(object->property("writableProperty").toInt(), 30); - delete object; + if (warningMessages.size()) + foreach (const QString &warning, warningMessages) + QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData()); - QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml")); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready"); - object = failOne.create(); - QVERIFY(object == 0); // should have failed: invalid major version - - QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml")); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready"); - object = failTwo.create(); - QVERIFY(object == 0); // should have failed: invalid minor version + QObject *object = component.create(); + if (!errorMessage.isEmpty()) { + QVERIFY(object == 0); + } else { + QVERIFY(object != 0); + for (int i = 0; i < readProperties.size(); ++i) + QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i)); + for (int i = 0; i < writeProperties.size(); ++i) + QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i))); + for (int i = 0; i < readBackProperties.size(); ++i) + QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i)); + delete object; + } } void tst_qdeclarativeecmascript::importScripts() diff --git a/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf b/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf Binary files differnew file mode 100644 index 0000000000..aae50d5035 --- /dev/null +++ b/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf diff --git a/tests/auto/declarative/qdeclarativefontloader/data/dummy.ttf b/tests/auto/declarative/qdeclarativefontloader/data/dummy.ttf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativefontloader/data/dummy.ttf diff --git a/tests/auto/declarative/qdeclarativefontloader/data/tarzeau_ocr_a.ttf b/tests/auto/declarative/qdeclarativefontloader/data/tarzeau_ocr_a.ttf Binary files differnew file mode 100644 index 0000000000..cf93f9651f --- /dev/null +++ b/tests/auto/declarative/qdeclarativefontloader/data/tarzeau_ocr_a.ttf diff --git a/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro b/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro new file mode 100644 index 0000000000..946e5a8a16 --- /dev/null +++ b/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro @@ -0,0 +1,18 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative gui network +macx:CONFIG -= app_bundle + +HEADERS += ../../declarative/shared/testhttpserver.h +SOURCES += tst_qdeclarativefontloader.cpp ../../declarative/shared/testhttpserver.cpp + +symbian: { + importFiles.files = data + importFiles.path = . + DEPLOYMENT += importFiles +} else { + DEFINES += SRCDIR=\\\"$$PWD\\\" +} + +CONFIG += parallel_test + +QT += core-private gui-private declarative-private diff --git a/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp b/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp new file mode 100644 index 0000000000..29fe0329bb --- /dev/null +++ b/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <qtest.h> +#include <QtTest/QSignalSpy> +#include <QtDeclarative/qdeclarativeengine.h> +#include <QtDeclarative/qdeclarativecomponent.h> +#include <QtDeclarative/qdeclarativecontext.h> +#include <QtDeclarative/private/qdeclarativefontloader_p.h> +#include "../../../shared/util.h" +#include "../../declarative/shared/testhttpserver.h" + +#define SERVER_PORT 14448 + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +class tst_qdeclarativefontloader : public QObject +{ + Q_OBJECT +public: + tst_qdeclarativefontloader(); + +private slots: + void init(); + void noFont(); + void namedFont(); + void localFont(); + void failLocalFont(); + void webFont(); + void redirWebFont(); + void failWebFont(); + void changeFont(); + +private: + QDeclarativeEngine engine; + TestHTTPServer server; +}; + +tst_qdeclarativefontloader::tst_qdeclarativefontloader() : + server(SERVER_PORT) +{ + server.serveDirectory(SRCDIR "/data"); +} + +void tst_qdeclarativefontloader::init() +{ + QVERIFY(server.isValid()); +} + +void tst_qdeclarativefontloader::noFont() +{ + QString componentStr = "import QtQuick 2.0\nFontLoader { }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + QCOMPARE(fontObject->name(), QString("")); + QCOMPARE(fontObject->source(), QUrl("")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Null); + + delete fontObject; +} + +void tst_qdeclarativefontloader::namedFont() +{ + QString componentStr = "import QtQuick 2.0\nFontLoader { name: \"Helvetica\" }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + QCOMPARE(fontObject->source(), QUrl("")); + QCOMPARE(fontObject->name(), QString("Helvetica")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); +} + +void tst_qdeclarativefontloader::localFont() +{ + QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" SRCDIR "/data/tarzeau_ocr_a.ttf\" }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + QVERIFY(fontObject->source() != QUrl("")); + QTRY_COMPARE(fontObject->name(), QString("OCRA")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); +} + +void tst_qdeclarativefontloader::failLocalFont() +{ + QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + QUrl::fromLocalFile(SRCDIR "/data/dummy.ttf").toString() + "\" }"; + QTest::ignoreMessage(QtWarningMsg, QString("file::2:1: QML FontLoader: Cannot load font: \"" + QUrl::fromLocalFile(SRCDIR "/data/dummy.ttf").toString() + "\"").toUtf8().constData()); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + QVERIFY(fontObject->source() != QUrl("")); + QTRY_COMPARE(fontObject->name(), QString("")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Error); +} + +void tst_qdeclarativefontloader::webFont() +{ + QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/tarzeau_ocr_a.ttf\" }"; + QDeclarativeComponent component(&engine); + + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + QVERIFY(fontObject->source() != QUrl("")); + QTRY_COMPARE(fontObject->name(), QString("OCRA")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); +} + +void tst_qdeclarativefontloader::redirWebFont() +{ + server.addRedirect("olddir/oldname.ttf","../tarzeau_ocr_a.ttf"); + + QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/olddir/oldname.ttf\" }"; + QDeclarativeComponent component(&engine); + + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + QVERIFY(fontObject->source() != QUrl("")); + QTRY_COMPARE(fontObject->name(), QString("OCRA")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); +} + +void tst_qdeclarativefontloader::failWebFont() +{ + QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/nonexist.ttf\" }"; + QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML FontLoader: Cannot load font: \"http://localhost:14448/nonexist.ttf\""); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + QVERIFY(fontObject->source() != QUrl("")); + QTRY_COMPARE(fontObject->name(), QString("")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Error); +} + +void tst_qdeclarativefontloader::changeFont() +{ + QString componentStr = "import QtQuick 2.0\nFontLoader { source: font }"; + QDeclarativeContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("font", QUrl::fromLocalFile(SRCDIR "/data/tarzeau_ocr_a.ttf")); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast<QDeclarativeFontLoader*>(component.create()); + + QVERIFY(fontObject != 0); + + QSignalSpy nameSpy(fontObject, SIGNAL(nameChanged())); + QSignalSpy statusSpy(fontObject, SIGNAL(statusChanged())); + + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + QTRY_COMPARE(fontObject->name(), QString("OCRA")); + + ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf"); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Loading); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 1); + QCOMPARE(statusSpy.count(), 2); + QTRY_COMPARE(fontObject->name(), QString("Daniel")); + + ctxt->setContextProperty("font", QUrl::fromLocalFile(SRCDIR "/data/tarzeau_ocr_a.ttf")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 2); + QCOMPARE(statusSpy.count(), 2); + QTRY_COMPARE(fontObject->name(), QString("OCRA")); + + ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf"); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 3); + QCOMPARE(statusSpy.count(), 2); + QTRY_COMPARE(fontObject->name(), QString("Daniel")); +} + +QTEST_MAIN(tst_qdeclarativefontloader) + +#include "tst_qdeclarativefontloader.moc" diff --git a/tests/auto/declarative/qdeclarativeinstruction/qdeclarativeinstruction.pro b/tests/auto/declarative/qdeclarativeinstruction/qdeclarativeinstruction.pro index a4cdd81266..7cff542838 100644 --- a/tests/auto/declarative/qdeclarativeinstruction/qdeclarativeinstruction.pro +++ b/tests/auto/declarative/qdeclarativeinstruction/qdeclarativeinstruction.pro @@ -9,4 +9,4 @@ macx:CONFIG -= app_bundle CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativelanguage/data/empty.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/empty.errors.txt index d416e76ae2..620db2bbba 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/empty.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/empty.errors.txt @@ -1,2 +1,2 @@ -0:0:Expected token `numeric literal' -0:0:Expected a qualified name id +1:1:Expected token `numeric literal' +1:1:Expected a qualified name id diff --git a/tests/auto/declarative/qdeclarativelanguage/data/signal.2.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/signal.2.errors.txt index fce89285ec..0d4c33d750 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/signal.2.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/signal.2.errors.txt @@ -1 +1 @@ -4:21:Unexpected token `;' +4:21:Unexpected token `,' diff --git a/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro b/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro index 71d2066608..e6006aed00 100644 --- a/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro +++ b/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro @@ -20,4 +20,4 @@ symbian: { } CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro b/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro index 83ea7992ed..4575c581ae 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro +++ b/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private opengl-private +QT += core-private gui-private v8-private declarative-private opengl-private diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index 946a3a5692..0c3b75ac98 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -219,6 +219,11 @@ void tst_qdeclarativelistmodel::static_i18n_data() << QVariant(QString("hello")) << QString(); + QTest::newRow("QT_TRID_NOOP") + << QString::fromUtf8("ListElement { foo: QT_TRID_NOOP(\"qtn_1st_text\") }") + << QVariant(QString("qtn_1st_text")) + << QString(); + QTest::newRow("QT_TR_NOOP extra param") << QString::fromUtf8("ListElement { foo: QT_TR_NOOP(\"hello\",\"world\") }") << QVariant(QString()) @@ -228,6 +233,11 @@ void tst_qdeclarativelistmodel::static_i18n_data() << "ListElement { foo: QT_TRANSLATE_NOOP() }" << QVariant(QString()) << QString("ListElement: improperly specified QT_TRANSLATE_NOOP"); + + QTest::newRow("QT_TRID_NOOP missing param") + << QString::fromUtf8("ListElement { foo: QT_TRID_NOOP() }") + << QVariant(QString()) + << QString("ListElement: improperly specified QT_TRID_NOOP"); } void tst_qdeclarativelistmodel::static_i18n() diff --git a/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro b/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro index fd55ed5160..99291c1f2d 100644 --- a/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro +++ b/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro index 304e168e00..69ebb8e668 100644 --- a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro +++ b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro @@ -16,4 +16,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro b/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro index c8f8e9139b..27d2c0c1b2 100644 --- a/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro +++ b/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro b/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro index f2b5928915..63944117d6 100644 --- a/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro +++ b/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro b/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro index a51eaf34de..c22e8cc9e7 100644 --- a/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro +++ b/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro @@ -15,4 +15,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro b/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro index 9823c21836..d21c12ad42 100644 --- a/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro +++ b/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro @@ -13,4 +13,4 @@ symbian: { } CONFIG += parallel_test -QT += core-private gui-private declarative-private opengl-private +QT += core-private gui-private v8-private declarative-private opengl-private diff --git a/tests/auto/declarative/qdeclarativev4/qdeclarativev4.pro b/tests/auto/declarative/qdeclarativev4/qdeclarativev4.pro index 9b66edff41..0701d95902 100644 --- a/tests/auto/declarative/qdeclarativev4/qdeclarativev4.pro +++ b/tests/auto/declarative/qdeclarativev4/qdeclarativev4.pro @@ -16,4 +16,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro b/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro index f1c64398e9..79bac3998e 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro +++ b/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro @@ -17,4 +17,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro b/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro index d7dfe96c65..aae48ca14e 100644 --- a/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro +++ b/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro b/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro index 139d4b4e0b..6733d3595e 100644 --- a/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro +++ b/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro @@ -18,4 +18,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qjsengine/tst_qjsengine.cpp b/tests/auto/declarative/qjsengine/tst_qjsengine.cpp index d2f4b3b6ac..a6b4251c36 100644 --- a/tests/auto/declarative/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/declarative/qjsengine/tst_qjsengine.cpp @@ -325,6 +325,7 @@ private slots: void dateRoundtripQtJSQt(); void dateConversionJSQt(); void dateConversionQtJS(); + void functionPrototypeExtensions(); }; tst_QJSEngine::tst_QJSEngine() @@ -6478,6 +6479,24 @@ void tst_QJSEngine::scriptValueFromQMetaObject() } #endif +void tst_QJSEngine::functionPrototypeExtensions() +{ + // QJS adds connect and disconnect properties to Function.prototype. + QJSEngine eng; + QJSValue funProto = eng.globalObject().property("Function").property("prototype"); + QVERIFY(funProto.isFunction()); + QVERIFY(funProto.property("connect").isFunction()); + QCOMPARE(funProto.propertyFlags("connect"), QJSValue::SkipInEnumeration); + QVERIFY(funProto.property("disconnect").isFunction()); + QCOMPARE(funProto.propertyFlags("disconnect"), QJSValue::SkipInEnumeration); + + // No properties should appear in for-in statements. + QJSValue props = eng.evaluate("props = []; for (var p in Function.prototype) props.push(p); props"); + QVERIFY(!eng.hasUncaughtException()); + QVERIFY(props.isArray()); + QCOMPARE(props.property("length").toInt32(), 0); +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" diff --git a/tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro b/tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro index b32235aec0..1c2130d5cf 100644 --- a/tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro +++ b/tests/auto/declarative/qpacketprotocol/qpacketprotocol.pro @@ -7,4 +7,4 @@ SOURCES += tst_qpacketprotocol.cpp \ ../shared/debugutil.cpp CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qsgflickable/qsgflickable.pro b/tests/auto/declarative/qsgflickable/qsgflickable.pro index d5e5767e90..8aa66bacb8 100644 --- a/tests/auto/declarative/qsgflickable/qsgflickable.pro +++ b/tests/auto/declarative/qsgflickable/qsgflickable.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qsgflipable/qsgflipable.pro b/tests/auto/declarative/qsgflipable/qsgflipable.pro index c3998c1f9c..e28de1b610 100644 --- a/tests/auto/declarative/qsgflipable/qsgflipable.pro +++ b/tests/auto/declarative/qsgflipable/qsgflipable.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qsggridview/qsggridview.pro b/tests/auto/declarative/qsggridview/qsggridview.pro index a8b3484f0d..00c7d96529 100644 --- a/tests/auto/declarative/qsggridview/qsggridview.pro +++ b/tests/auto/declarative/qsggridview/qsggridview.pro @@ -14,5 +14,5 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private QT += opengl-private diff --git a/tests/auto/declarative/qsgitem/tst_qsgitem.cpp b/tests/auto/declarative/qsgitem/tst_qsgitem.cpp index 7a612c433b..05e59a69f0 100644 --- a/tests/auto/declarative/qsgitem/tst_qsgitem.cpp +++ b/tests/auto/declarative/qsgitem/tst_qsgitem.cpp @@ -127,6 +127,9 @@ private slots: void wheelEvent_data(); void wheelEvent(); + void hoverEvent_data(); + void hoverEvent(); + void hoverEventInParent(); private: void ensureFocus(QWidget *w) { @@ -894,6 +897,151 @@ void tst_qsgitem::wheelEvent() delete canvas; } +class HoverItem : public QSGItem +{ +Q_OBJECT +public: + HoverItem(QSGItem *parent = 0) + : QSGItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0) + { } + void resetCounters() { + hoverEnterCount = 0; + hoverMoveCount = 0; + hoverLeaveCount = 0; + } + int hoverEnterCount; + int hoverMoveCount; + int hoverLeaveCount; +protected: + virtual void hoverEnterEvent(QHoverEvent *event) { + event->accept(); + ++hoverEnterCount; + } + virtual void hoverMoveEvent(QHoverEvent *event) { + event->accept(); + ++hoverMoveCount; + } + virtual void hoverLeaveEvent(QHoverEvent *event) { + event->accept(); + ++hoverLeaveCount; + } +}; + +void tst_qsgitem::hoverEvent_data() +{ + QTest::addColumn<bool>("visible"); + QTest::addColumn<bool>("enabled"); + QTest::addColumn<bool>("acceptHoverEvents"); + + QTest::newRow("visible, enabled, accept hover") << true << true << true; + QTest::newRow("visible, disabled, accept hover") << true << false << true; + QTest::newRow("invisible, enabled, accept hover") << false << true << true; + QTest::newRow("invisible, disabled, accept hover") << false << false << true; + + QTest::newRow("visible, enabled, not accept hover") << true << true << false; + QTest::newRow("visible, disabled, not accept hover") << true << false << false; + QTest::newRow("invisible, enabled, not accept hover") << false << true << false; + QTest::newRow("invisible, disabled, not accept hover") << false << false << false; +} + +// ### For some unknown reason QTest::mouseMove() isn't working correctly. +static void sendMouseMove(QObject *object, const QPoint &position) +{ + QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0); + QApplication::sendEvent(object, &moveEvent); +} + +void tst_qsgitem::hoverEvent() +{ + QFETCH(bool, visible); + QFETCH(bool, enabled); + QFETCH(bool, acceptHoverEvents); + + QSGCanvas *canvas = new QSGCanvas(); + canvas->resize(200, 200); + canvas->show(); + + HoverItem *item = new HoverItem; + item->setSize(QSizeF(100, 100)); + item->setParentItem(canvas->rootItem()); + + item->setEnabled(enabled); + item->setVisible(visible); + item->setAcceptHoverEvents(acceptHoverEvents); + + const QPoint outside(150, 150); + const QPoint inside(50, 50); + const QPoint anotherInside(51, 51); + + sendMouseMove(canvas, outside); + item->resetCounters(); + + // Enter, then move twice inside, then leave. + sendMouseMove(canvas, inside); + sendMouseMove(canvas, anotherInside); + sendMouseMove(canvas, inside); + sendMouseMove(canvas, outside); + + const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents; + if (shouldReceiveHoverEvents) { + QCOMPARE(item->hoverEnterCount, 1); + QCOMPARE(item->hoverMoveCount, 2); + QCOMPARE(item->hoverLeaveCount, 1); + } else { + QCOMPARE(item->hoverEnterCount, 0); + QCOMPARE(item->hoverMoveCount, 0); + QCOMPARE(item->hoverLeaveCount, 0); + } + + delete canvas; +} + +void tst_qsgitem::hoverEventInParent() +{ + QSGCanvas *canvas = new QSGCanvas(); + canvas->resize(200, 200); + canvas->show(); + + HoverItem *parentItem = new HoverItem(canvas->rootItem()); + parentItem->setSize(QSizeF(200, 200)); + parentItem->setAcceptHoverEvents(true); + + HoverItem *leftItem = new HoverItem(parentItem); + leftItem->setSize(QSizeF(100, 200)); + leftItem->setAcceptHoverEvents(true); + + HoverItem *rightItem = new HoverItem(parentItem); + rightItem->setSize(QSizeF(100, 200)); + rightItem->setPos(QPointF(100, 0)); + rightItem->setAcceptHoverEvents(true); + + const QPoint insideLeft(50, 100); + const QPoint insideRight(150, 100); + + sendMouseMove(canvas, insideLeft); + parentItem->resetCounters(); + leftItem->resetCounters(); + rightItem->resetCounters(); + + sendMouseMove(canvas, insideRight); + QCOMPARE(parentItem->hoverEnterCount, 0); + QCOMPARE(parentItem->hoverLeaveCount, 0); + QCOMPARE(leftItem->hoverEnterCount, 0); + QCOMPARE(leftItem->hoverLeaveCount, 1); + QCOMPARE(rightItem->hoverEnterCount, 1); + QCOMPARE(rightItem->hoverLeaveCount, 0); + + sendMouseMove(canvas, insideLeft); + QCOMPARE(parentItem->hoverEnterCount, 0); + QCOMPARE(parentItem->hoverLeaveCount, 0); + QCOMPARE(leftItem->hoverEnterCount, 1); + QCOMPARE(leftItem->hoverLeaveCount, 1); + QCOMPARE(rightItem->hoverEnterCount, 1); + QCOMPARE(rightItem->hoverLeaveCount, 1); + + delete canvas; +} + QTEST_MAIN(tst_qsgitem) #include "tst_qsgitem.moc" diff --git a/tests/auto/declarative/qsglistview/qsglistview.pro b/tests/auto/declarative/qsglistview/qsglistview.pro index 3e18e9b467..4c781887ce 100644 --- a/tests/auto/declarative/qsglistview/qsglistview.pro +++ b/tests/auto/declarative/qsglistview/qsglistview.pro @@ -14,5 +14,5 @@ symbian: { } CONFIG += parallel_test -QT += core-private gui-private declarative-private widgets widgets-private +QT += core-private gui-private declarative-private widgets widgets-private v8-private QT += opengl-private diff --git a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp index 94d6cf3d45..1eecd58278 100644 --- a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp +++ b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp @@ -1124,6 +1124,7 @@ void tst_QSGListView::enforceRange_withoutHighlight() QSGView *canvas = createView(); canvas->show(); + QTest::qWaitForWindowShown(canvas); TestModel model; model.addItem("Item 0", "a"); diff --git a/tests/auto/declarative/qsgpathview/qsgpathview.pro b/tests/auto/declarative/qsgpathview/qsgpathview.pro index eb188666bb..ae0b1ed630 100644 --- a/tests/auto/declarative/qsgpathview/qsgpathview.pro +++ b/tests/auto/declarative/qsgpathview/qsgpathview.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qsgpositioners/qsgpositioners.pro b/tests/auto/declarative/qsgpositioners/qsgpositioners.pro index bf8110ffd4..ae470fa2fc 100644 --- a/tests/auto/declarative/qsgpositioners/qsgpositioners.pro +++ b/tests/auto/declarative/qsgpositioners/qsgpositioners.pro @@ -13,5 +13,5 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private QT += opengl-private diff --git a/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp b/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp index 137e6acd77..0a1c4dff77 100644 --- a/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp +++ b/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp @@ -160,7 +160,7 @@ void tst_qsgpositioners::test_horizontal_rtl() // Change the width of the row and check that items stay to the right row->setWidth(200); - QCOMPARE(one->x(), 150.0); + QTRY_COMPARE(one->x(), 150.0); QCOMPARE(one->y(), 0.0); QCOMPARE(two->x(), 130.0); QCOMPARE(two->y(), 0.0); @@ -580,7 +580,7 @@ void tst_qsgpositioners::test_grid_rightToLeft() // Change the width of the grid and check that items stay to the right grid->setWidth(200); - QCOMPARE(one->x(), 150.0); + QTRY_COMPARE(one->x(), 150.0); QCOMPARE(one->y(), 0.0); QCOMPARE(two->x(), 130.0); QCOMPARE(two->y(), 0.0); @@ -1086,16 +1086,16 @@ void tst_qsgpositioners::test_flow_resize() QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five"); QVERIFY(five != 0); - QCOMPARE(one->x(), 0.0); - QCOMPARE(one->y(), 0.0); - QCOMPARE(two->x(), 50.0); - QCOMPARE(two->y(), 0.0); - QCOMPARE(three->x(), 70.0); - QCOMPARE(three->y(), 0.0); - QCOMPARE(four->x(), 0.0); - QCOMPARE(four->y(), 50.0); - QCOMPARE(five->x(), 50.0); - QCOMPARE(five->y(), 50.0); + QTRY_COMPARE(one->x(), 0.0); + QTRY_COMPARE(one->y(), 0.0); + QTRY_COMPARE(two->x(), 50.0); + QTRY_COMPARE(two->y(), 0.0); + QTRY_COMPARE(three->x(), 70.0); + QTRY_COMPARE(three->y(), 0.0); + QTRY_COMPARE(four->x(), 0.0); + QTRY_COMPARE(four->y(), 50.0); + QTRY_COMPARE(five->x(), 50.0); + QTRY_COMPARE(five->y(), 50.0); delete canvas; } @@ -1110,7 +1110,7 @@ void tst_qsgpositioners::test_flow_resize_rightToLeft() root->setProperty("testRightToLeft", true); QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one"); - QVERIFY(one != 0); + QTRY_VERIFY(one != 0); QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two"); QVERIFY(two != 0); QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three"); @@ -1294,7 +1294,7 @@ void tst_qsgpositioners::test_mirroring() break; QSGItem *itemA = rootA->findChild<QSGItem*>(objectName); QSGItem *itemB = rootB->findChild<QSGItem*>(objectName); - QVERIFY(itemA->x() != itemB->x()); + QTRY_VERIFY(itemA->x() != itemB->x()); } QSGItemPrivate* rootPrivateB = QSGItemPrivate::get(rootB); @@ -1311,7 +1311,7 @@ void tst_qsgpositioners::test_mirroring() break; QSGItem *itemA = rootA->findChild<QSGItem*>(objectName); QSGItem *itemB = rootB->findChild<QSGItem*>(objectName); - QCOMPARE(itemA->x(), itemB->x()); + QTRY_COMPARE(itemA->x(), itemB->x()); } rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight @@ -1324,7 +1324,7 @@ void tst_qsgpositioners::test_mirroring() break; QSGItem *itemA = rootA->findChild<QSGItem*>(objectName); QSGItem *itemB = rootB->findChild<QSGItem*>(objectName); - QCOMPARE(itemA->x(), itemB->x()); + QTRY_COMPARE(itemA->x(), itemB->x()); } delete canvasA; delete canvasB; @@ -1428,12 +1428,9 @@ void tst_qsgpositioners::test_attachedproperties_dynamic() row->metaObject()->invokeMethod(row, "createSubRect"); - posIndex = rect1->property("index").toInt(); - QVERIFY(posIndex == 1); - isFirst = rect1->property("firstItem").toBool(); - QVERIFY(isFirst == false); - isLast = rect1->property("lastItem").toBool(); - QVERIFY(isLast == false); + QTRY_VERIFY(rect1->property("index").toInt() == 1); + QTRY_VERIFY(rect1->property("firstItem").toBool() == false); + QTRY_VERIFY(rect1->property("lastItem").toBool() == false); QSGRectangle *rect2 = canvas->rootObject()->findChild<QSGRectangle *>("rect2"); QVERIFY(rect2 != 0); @@ -1449,12 +1446,9 @@ void tst_qsgpositioners::test_attachedproperties_dynamic() qApp->processEvents(QEventLoop::DeferredDeletion); - posIndex = rect1->property("index").toInt(); - QVERIFY(posIndex == 1); - isFirst = rect1->property("firstItem").toBool(); - QVERIFY(isFirst == false); - isLast = rect1->property("lastItem").toBool(); - QVERIFY(isLast == true); + QTRY_VERIFY(rect1->property("index").toInt() == 1); + QTRY_VERIFY(rect1->property("firstItem").toBool() == false); + QTRY_VERIFY(rect1->property("lastItem").toBool() == true); delete canvas; } @@ -1464,6 +1458,8 @@ QSGView *tst_qsgpositioners::createView(const QString &filename) QSGView *canvas = new QSGView(0); canvas->setSource(QUrl::fromLocalFile(filename)); + canvas->show(); + QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn return canvas; } diff --git a/tests/auto/declarative/qsgtext/qsgtext.pro b/tests/auto/declarative/qsgtext/qsgtext.pro index 5254d1ebeb..4aa90f459c 100644 --- a/tests/auto/declarative/qsgtext/qsgtext.pro +++ b/tests/auto/declarative/qsgtext/qsgtext.pro @@ -19,5 +19,5 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private QT += opengl-private diff --git a/tests/auto/declarative/qsgtextedit/qsgtextedit.pro b/tests/auto/declarative/qsgtextedit/qsgtextedit.pro index 491bb2d3f3..4e233f3a10 100644 --- a/tests/auto/declarative/qsgtextedit/qsgtextedit.pro +++ b/tests/auto/declarative/qsgtextedit/qsgtextedit.pro @@ -12,7 +12,7 @@ symbian: { } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private QT += opengl-private qpa:CONFIG+=insignificant_test # QTBUG-21010, fails unstably diff --git a/tests/auto/declarative/qsgtextinput/qsgtextinput.pro b/tests/auto/declarative/qsgtextinput/qsgtextinput.pro index 56a811fa6d..fceef18487 100644 --- a/tests/auto/declarative/qsgtextinput/qsgtextinput.pro +++ b/tests/auto/declarative/qsgtextinput/qsgtextinput.pro @@ -12,5 +12,5 @@ symbian: { DEFINES += SRCDIR=\\\"$$PWD\\\" } -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private QT += opengl-private diff --git a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp index 3cc0dc196b..32e59c2a6d 100644 --- a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp +++ b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp @@ -2197,7 +2197,7 @@ public: virtual QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data) { nbPaint++; - return QSGTextInput::updatePaintNode(node, data); +// return QSGTextInput::updatePaintNode(node, data); } int nbPaint; }; diff --git a/tests/auto/declarative/qsgvisualdatamodel/qsgvisualdatamodel.pro b/tests/auto/declarative/qsgvisualdatamodel/qsgvisualdatamodel.pro index 8f433c1208..7770f8ff0f 100644 --- a/tests/auto/declarative/qsgvisualdatamodel/qsgvisualdatamodel.pro +++ b/tests/auto/declarative/qsgvisualdatamodel/qsgvisualdatamodel.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private +QT += core-private gui-private v8-private declarative-private diff --git a/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp b/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp index 7470153933..40fddef21b 100644 --- a/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp +++ b/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "../../../shared/util.h" #include <qtest.h> #include <QtTest/QSignalSpy> #include <QStandardItemModel> @@ -88,6 +89,13 @@ public: list << "one" << "two" << "three" << "four"; } + void emitMove(int sourceFirst, int sourceLast, int destinationChild) { + emit beginMoveRows(QModelIndex(), sourceFirst, sourceLast, QModelIndex(), destinationChild); + emit endMoveRows(); + } + + QStringList list; + public slots: void set(int idx, QString string) { list[idx] = string; @@ -103,9 +111,6 @@ protected: return list.at(index.row()); return QVariant(); } - -private: - QStringList list; }; @@ -125,6 +130,8 @@ private slots: void singleRole(); void modelProperties(); void noDelegate(); + void qaimRowsMoved(); + void qaimRowsMoved_data(); private: QDeclarativeEngine engine; @@ -538,6 +545,72 @@ void tst_qsgvisualdatamodel::noDelegate() } +void tst_qsgvisualdatamodel::qaimRowsMoved() +{ + // Test parameters passed in QAIM::rowsMoved() signal are converted correctly + // when translated and emitted as the QListModelInterface::itemsMoved() signal + QFETCH(int, sourceFirst); + QFETCH(int, sourceLast); + QFETCH(int, destinationChild); + QFETCH(int, expectFrom); + QFETCH(int, expectTo); + QFETCH(int, expectCount); + + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/visualdatamodel.qml")); + + SingleRoleModel model; + model.list.clear(); + for (int i=0; i<30; i++) + model.list << ("item " + i); + engine.rootContext()->setContextProperty("myModel", &model); + + QSGVisualDataModel *obj = qobject_cast<QSGVisualDataModel*>(c.create()); + QVERIFY(obj != 0); + + QSignalSpy spy(obj, SIGNAL(itemsMoved(int,int,int))); + model.emitMove(sourceFirst, sourceLast, destinationChild); + QTRY_COMPARE(spy.count(), 1); + + QCOMPARE(spy[0].count(), 3); + QCOMPARE(spy[0][0].toInt(), expectFrom); + QCOMPARE(spy[0][1].toInt(), expectTo); + QCOMPARE(spy[0][2].toInt(), expectCount); + + delete obj; +} + +void tst_qsgvisualdatamodel::qaimRowsMoved_data() +{ + QTest::addColumn<int>("sourceFirst"); + QTest::addColumn<int>("sourceLast"); + QTest::addColumn<int>("destinationChild"); + QTest::addColumn<int>("expectFrom"); + QTest::addColumn<int>("expectTo"); + QTest::addColumn<int>("expectCount"); + + QTest::newRow("move 1 forward") + << 1 << 1 << 6 + << 1 << 5 << 1; + + QTest::newRow("move 1 backwards") + << 4 << 4 << 1 + << 4 << 1 << 1; + + QTest::newRow("move multiple forwards") + << 0 << 2 << 13 + << 0 << 10 << 3; + + QTest::newRow("move multiple forwards, with same to") + << 0 << 1 << 3 + << 0 << 1 << 2; + + QTest::newRow("move multiple backwards") + << 10 << 14 << 1 + << 10 << 1 << 5; +} + + template<typename T> T *tst_qsgvisualdatamodel::findItem(QSGItem *parent, const QString &objectName, int index) { diff --git a/tests/auto/declarative/v8/Makefile.nonqt b/tests/auto/declarative/v8/Makefile.nonqt deleted file mode 100644 index 7ab695ba6a..0000000000 --- a/tests/auto/declarative/v8/Makefile.nonqt +++ /dev/null @@ -1,11 +0,0 @@ -release-m32: - g++ -o v8test_release_m32 -m32 -O2 v8main.cpp v8test.cpp -lpthread -L../../../../src/3rdparty/v8/ -lv8 - -debug-m32: - g++ -o v8test_debug_m32 -m32 -g v8main.cpp v8test.cpp -lpthread -L../../../../src/3rdparty/v8/ -lv8_g - -release: - g++ -o v8test_release -O2 v8main.cpp v8test.cpp -lpthread -L../../../../src/3rdparty/v8/ -lv8 - -debug: - g++ -o v8test_debug -g v8main.cpp v8test.cpp -lpthread -L../../../../src/3rdparty/v8/ -lv8_g diff --git a/tests/auto/declarative/v8/README.txt b/tests/auto/declarative/v8/README.txt deleted file mode 100644 index a5df6201be..0000000000 --- a/tests/auto/declarative/v8/README.txt +++ /dev/null @@ -1,13 +0,0 @@ -The v8 tests are actually implemented in v8test.[h|cpp]. There are also QtTest -(tst_v8.cpp) and non-Qt (v8main.cpp) stubs provided to run these tests. This -is done to allow the tests to be run both in the Qt CI system, and manually -without a build of Qt. The latter is necessary to run them against more exotic -build of V8, like the ARM simulator. - -To build the non-Qt version of the tests, first build a debug or release V8 -library under src/3rdparty/v8 using scons, and then use the Makefile.nonqt -makefile selecting one of the following targets: - release: Build the tests with -O2 and link against libv8 - debug: Build the tests with -g and link against libv8_g - release-m32: Build the tests with -O2 -m32 and link against libv8 - debug-m32: Build the tests with -g -m32 and link against libv8_g diff --git a/tests/auto/declarative/v8/tst_v8.cpp b/tests/auto/declarative/v8/tst_v8.cpp deleted file mode 100644 index 32d100e968..0000000000 --- a/tests/auto/declarative/v8/tst_v8.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <qtest.h> -#include "v8test.h" - -using namespace v8; - -class tst_v8 : public QObject -{ - Q_OBJECT -public: - tst_v8() {} - -private slots: - void initTestCase() {} - void cleanupTestCase() {} - - void eval(); - void userobjectcompare(); -}; - -void tst_v8::eval() -{ - QVERIFY(v8test_eval()); -} - -void tst_v8::userobjectcompare() -{ - QVERIFY(v8test_userobjectcompare()); -} - -int main(int argc, char *argv[]) -{ - V8::SetFlagsFromCommandLine(&argc, argv, true); - - QCoreApplication app(argc, argv); - tst_v8 tc; - return QTest::qExec(&tc, argc, argv); -} - -#include "tst_v8.moc" diff --git a/tests/auto/declarative/v8/v8.pro b/tests/auto/declarative/v8/v8.pro deleted file mode 100644 index bd6dfa9d5c..0000000000 --- a/tests/auto/declarative/v8/v8.pro +++ /dev/null @@ -1,10 +0,0 @@ -load(qttest_p4) -macx:CONFIG -= app_bundle - -SOURCES += tst_v8.cpp v8test.cpp -HEADERS += v8test.h - -CONFIG += parallel_test - -QT += declarative -DEFINES += USING_V8_SHARED diff --git a/tests/auto/declarative/v8/v8main.cpp b/tests/auto/declarative/v8/v8main.cpp deleted file mode 100644 index 5930f53f90..0000000000 --- a/tests/auto/declarative/v8/v8main.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "v8test.h" -#include <stdio.h> - -#define RUN_TEST(testname) { \ - if (!v8test_ ## testname()) \ - printf ("Test %s FAILED\n", # testname); \ -} - -int main(int argc, char *argv[]) -{ - v8::V8::SetFlagsFromCommandLine(&argc, argv, true); - - RUN_TEST(eval); - RUN_TEST(userobjectcompare); - - return -1; -} diff --git a/tests/auto/declarative/v8/v8test.cpp b/tests/auto/declarative/v8/v8test.cpp deleted file mode 100644 index 27d39c5970..0000000000 --- a/tests/auto/declarative/v8/v8test.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "v8test.h" - -using namespace v8; - -#define BEGINTEST() bool _testPassed = true; -#define ENDTEST() return _testPassed; - -#define VERIFY(expr) { \ - if (!(expr)) { \ - fprintf(stderr, "FAIL: %s:%d %s\n", __FILE__, __LINE__, # expr); \ - _testPassed = false; \ - goto cleanup; \ - } \ -} - - -bool v8test_eval() -{ - BEGINTEST(); - - HandleScope handle_scope; - Persistent<Context> context = Context::New(); - Context::Scope context_scope(context); - - Local<Object> qmlglobal = Object::New(); - qmlglobal->Set(String::New("a"), Integer::New(1922)); - - Local<Script> script = Script::Compile(String::New("eval(\"a\")"), NULL, NULL, - Handle<String>(), Script::QmlMode); - - TryCatch tc; - Local<Value> result = script->Run(qmlglobal); - - VERIFY(!tc.HasCaught()); - VERIFY(result->Int32Value() == 1922); - -cleanup: - context.Dispose(); - - ENDTEST(); -} - -static int userObjectComparisonCalled = 0; -static bool userObjectComparisonReturn = false; -static Local<Object> expectedLhs; -static Local<Object> expectedRhs; -static bool expectedObjectsCompared = false; - -#define SET_EXPECTED(lhs, rhs) { \ - expectedObjectsCompared = false; \ - expectedLhs = lhs; \ - expectedRhs = rhs; \ -} - -static bool UserObjectComparison(Local<Object> lhs, Local<Object> rhs) -{ - userObjectComparisonCalled++; - - expectedObjectsCompared = (lhs == expectedLhs && rhs == expectedRhs); - - return userObjectComparisonReturn; -} - -inline bool runscript(const char *source) { - Local<Script> script = Script::Compile(String::New(source)); - Local<Value> result = script->Run(); - return result->BooleanValue(); -} - -bool v8test_userobjectcompare() -{ - BEGINTEST(); - - HandleScope handle_scope; - Persistent<Context> context = Context::New(); - Context::Scope context_scope(context); - - V8::SetUserObjectComparisonCallbackFunction(UserObjectComparison); - - Local<ObjectTemplate> ot = ObjectTemplate::New(); - ot->MarkAsUseUserObjectComparison(); - - Local<Object> uoc1 = ot->NewInstance(); - Local<Object> uoc2 = ot->NewInstance(); - context->Global()->Set(String::New("uoc1a"), uoc1); - context->Global()->Set(String::New("uoc1b"), uoc1); - context->Global()->Set(String::New("uoc2"), uoc2); - Local<Object> obj1 = Object::New(); - context->Global()->Set(String::New("obj1a"), obj1); - context->Global()->Set(String::New("obj1b"), obj1); - context->Global()->Set(String::New("obj2"), Object::New()); - Local<String> string1 = String::New("Hello World"); - context->Global()->Set(String::New("string1a"), string1); - context->Global()->Set(String::New("string1b"), string1); - context->Global()->Set(String::New("string2"), v8::String::New("Goodbye World")); - - // XXX Opportunity for optimization - don't invoke user callback if objects are - // equal. -#if 0 - userObjectComparisonCalled = 0; userObjectComparisonReturn = false; - VERIFY(true == runscript("uoc1a == uoc1b")); - VERIFY(userObjectComparisonCalled == 0); -#endif - - // Comparing two uoc objects invokes uoc - userObjectComparisonCalled = 0; - userObjectComparisonReturn = false; - VERIFY(false == runscript("uoc1a == uoc2")); - VERIFY(userObjectComparisonCalled == 1); - - VERIFY(false == runscript("uoc2 == uoc1a")); - VERIFY(userObjectComparisonCalled == 2); - userObjectComparisonReturn = true; - VERIFY(true == runscript("uoc1a == uoc2")); - VERIFY(userObjectComparisonCalled == 3); - VERIFY(true == runscript("uoc2 == uoc1a")); - VERIFY(userObjectComparisonCalled == 4); - - // != on two uoc object invokes uoc - userObjectComparisonCalled = 0; - userObjectComparisonReturn = false; - VERIFY(true == runscript("uoc1a != uoc2")); - VERIFY(userObjectComparisonCalled == 1); - VERIFY(true == runscript("uoc2 != uoc1a")); - VERIFY(userObjectComparisonCalled == 2); - userObjectComparisonReturn = true; - VERIFY(false == runscript("uoc1a != uoc2")); - VERIFY(userObjectComparisonCalled == 3); - VERIFY(false == runscript("uoc2 != uoc1a")); - VERIFY(userObjectComparisonCalled == 4); - - // Comparison against a non-object doesn't invoke uoc - userObjectComparisonCalled = 0; - userObjectComparisonReturn = false; - VERIFY(false == runscript("uoc1a == string1a")); - VERIFY(userObjectComparisonCalled == 0); - VERIFY(false == runscript("string1a == uoc1a")); - VERIFY(userObjectComparisonCalled == 0); - VERIFY(false == runscript("2 == uoc1a")); - VERIFY(userObjectComparisonCalled == 0); - VERIFY(true == runscript("uoc1a != string1a")); - VERIFY(userObjectComparisonCalled == 0); - VERIFY(true == runscript("string1a != uoc1a")); - VERIFY(userObjectComparisonCalled == 0); - VERIFY(true == runscript("2 != uoc1a")); - VERIFY(userObjectComparisonCalled == 0); - - // Comparison against a non-uoc-object still invokes uoc - userObjectComparisonCalled = 0; - userObjectComparisonReturn = false; - VERIFY(false == runscript("uoc1a == obj1a")); - VERIFY(userObjectComparisonCalled == 1); - VERIFY(false == runscript("obj1a == uoc1a")); - VERIFY(userObjectComparisonCalled == 2); - userObjectComparisonReturn = true; - VERIFY(true == runscript("uoc1a == obj1a")); - VERIFY(userObjectComparisonCalled == 3); - VERIFY(true == runscript("obj1a == uoc1a")); - VERIFY(userObjectComparisonCalled == 4); - - // != comparison against a non-uoc-object still invokes uoc - userObjectComparisonCalled = 0; - userObjectComparisonReturn = false; - VERIFY(true == runscript("uoc1a != obj1a")); - VERIFY(userObjectComparisonCalled == 1); - VERIFY(true == runscript("obj1a != uoc1a")); - VERIFY(userObjectComparisonCalled == 2); - userObjectComparisonReturn = true; - VERIFY(false == runscript("uoc1a != obj1a")); - VERIFY(userObjectComparisonCalled == 3); - VERIFY(false == runscript("obj1a != uoc1a")); - VERIFY(userObjectComparisonCalled == 4); - - // Comparing two non-uoc objects does not invoke uoc - userObjectComparisonCalled = 0; - userObjectComparisonReturn = false; - VERIFY(true == runscript("obj1a == obj1a")); - VERIFY(true == runscript("obj1a == obj1b")); - VERIFY(false == runscript("obj1a == obj2")); - VERIFY(false == runscript("obj1a == string1a")); - VERIFY(true == runscript("string1a == string1a")); - VERIFY(true == runscript("string1a == string1b")); - VERIFY(false == runscript("string1a == string2")); - VERIFY(userObjectComparisonCalled == 0); - - // Correct lhs and rhs passed to uoc - userObjectComparisonCalled = 0; - userObjectComparisonReturn = false; - SET_EXPECTED(uoc1, uoc2); - VERIFY(false == runscript("uoc1a == uoc2")); - VERIFY(true == expectedObjectsCompared); - SET_EXPECTED(uoc2, uoc1); - VERIFY(false == runscript("uoc2 == uoc1a")); - VERIFY(true == expectedObjectsCompared); - SET_EXPECTED(uoc1, uoc2); - VERIFY(true == runscript("uoc1a != uoc2")); - VERIFY(true == expectedObjectsCompared); - SET_EXPECTED(uoc2, uoc1); - VERIFY(true == runscript("uoc2 != uoc1a")); - VERIFY(true == expectedObjectsCompared); - SET_EXPECTED(uoc1, obj1); - VERIFY(false == runscript("uoc1a == obj1a")); - VERIFY(true == expectedObjectsCompared); - SET_EXPECTED(obj1, uoc1); - VERIFY(false == runscript("obj1a == uoc1a")); - VERIFY(true == expectedObjectsCompared); - -cleanup: - V8::SetUserObjectComparisonCallbackFunction(0); - context.Dispose(); - - ENDTEST(); -} diff --git a/tests/auto/declarative/v8/v8test.h b/tests/auto/declarative/v8/v8test.h deleted file mode 100644 index 31acefc8b3..0000000000 --- a/tests/auto/declarative/v8/v8test.h +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef V8TEST_H -#define V8TEST_H - -#include "../../../../src/3rdparty/v8/include/v8.h" - -bool v8test_eval(); -bool v8test_userobjectcompare(); - -#endif // V8TEST_H - diff --git a/tests/auto/qtquick1/qdeclarativeanchors/qdeclarativeanchors.pro b/tests/auto/qtquick1/qdeclarativeanchors/qdeclarativeanchors.pro index 12b545811d..dc87f68769 100644 --- a/tests/auto/qtquick1/qdeclarativeanchors/qdeclarativeanchors.pro +++ b/tests/auto/qtquick1/qdeclarativeanchors/qdeclarativeanchors.pro @@ -13,4 +13,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativeanimations/qdeclarativeanimations.pro b/tests/auto/qtquick1/qdeclarativeanimations/qdeclarativeanimations.pro index 2daebc7a54..c6e87ca9ca 100644 --- a/tests/auto/qtquick1/qdeclarativeanimations/qdeclarativeanimations.pro +++ b/tests/auto/qtquick1/qdeclarativeanimations/qdeclarativeanimations.pro @@ -13,4 +13,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativebehaviors/qdeclarativebehaviors.pro b/tests/auto/qtquick1/qdeclarativebehaviors/qdeclarativebehaviors.pro index 4fd4ddd8b0..15512bd749 100644 --- a/tests/auto/qtquick1/qdeclarativebehaviors/qdeclarativebehaviors.pro +++ b/tests/auto/qtquick1/qdeclarativebehaviors/qdeclarativebehaviors.pro @@ -13,4 +13,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativeconnection/qdeclarativeconnection.pro b/tests/auto/qtquick1/qdeclarativeconnection/qdeclarativeconnection.pro index 6c3bec845a..3dc73e622c 100644 --- a/tests/auto/qtquick1/qdeclarativeconnection/qdeclarativeconnection.pro +++ b/tests/auto/qtquick1/qdeclarativeconnection/qdeclarativeconnection.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativeflickable/qdeclarativeflickable.pro b/tests/auto/qtquick1/qdeclarativeflickable/qdeclarativeflickable.pro index c01478380b..8c9d1872db 100644 --- a/tests/auto/qtquick1/qdeclarativeflickable/qdeclarativeflickable.pro +++ b/tests/auto/qtquick1/qdeclarativeflickable/qdeclarativeflickable.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativeflipable/qdeclarativeflipable.pro b/tests/auto/qtquick1/qdeclarativeflipable/qdeclarativeflipable.pro index 22d015c798..6ec02c54b5 100644 --- a/tests/auto/qtquick1/qdeclarativeflipable/qdeclarativeflipable.pro +++ b/tests/auto/qtquick1/qdeclarativeflipable/qdeclarativeflipable.pro @@ -14,5 +14,5 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private qpa:contains(QT_CONFIG,xcb):CONFIG+=insignificant_test # QTBUG-21012 fails on exit (X11-specific) diff --git a/tests/auto/qtquick1/qdeclarativegridview/qdeclarativegridview.pro b/tests/auto/qtquick1/qdeclarativegridview/qdeclarativegridview.pro index eb125599e1..48c4d21df7 100644 --- a/tests/auto/qtquick1/qdeclarativegridview/qdeclarativegridview.pro +++ b/tests/auto/qtquick1/qdeclarativegridview/qdeclarativegridview.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativeitem/qdeclarativeitem.pro b/tests/auto/qtquick1/qdeclarativeitem/qdeclarativeitem.pro index 459f80bec2..05bb55a4b2 100644 --- a/tests/auto/qtquick1/qdeclarativeitem/qdeclarativeitem.pro +++ b/tests/auto/qtquick1/qdeclarativeitem/qdeclarativeitem.pro @@ -14,5 +14,5 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private qpa:contains(QT_CONFIG,xcb):CONFIG+=insignificant_test # QTBUG-21012 fails on exit (X11-specific) diff --git a/tests/auto/qtquick1/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/qtquick1/qdeclarativeitem/tst_qdeclarativeitem.cpp index b244a24613..5b71f23f36 100644 --- a/tests/auto/qtquick1/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/qtquick1/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -91,6 +91,7 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); void qtbug_16871(); + void qtbug_21045(); private: QDeclarativeEngine engine; }; @@ -1365,6 +1366,18 @@ void tst_QDeclarativeItem::qtbug_16871() delete o; } +void tst_QDeclarativeItem::qtbug_21045() +{ + QDeclarativeComponent component(&engine); + QGraphicsScene scene; + component.setData("import QtQuick 1.1\nItem{visible: false; focus: true}", QUrl::fromLocalFile("file:")); + QObject *o = component.create(); + QDeclarativeItem* i = qobject_cast<QDeclarativeItem*>(o); + QVERIFY(i); + scene.addItem(i); + QVERIFY(!i->hasActiveFocus()); +} + QTEST_MAIN(tst_QDeclarativeItem) #include "tst_qdeclarativeitem.moc" diff --git a/tests/auto/qtquick1/qdeclarativelistview/qdeclarativelistview.pro b/tests/auto/qtquick1/qdeclarativelistview/qdeclarativelistview.pro index 5eb154dad2..8b3f848ff6 100644 --- a/tests/auto/qtquick1/qdeclarativelistview/qdeclarativelistview.pro +++ b/tests/auto/qtquick1/qdeclarativelistview/qdeclarativelistview.pro @@ -14,4 +14,4 @@ symbian: { } CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativepathview/qdeclarativepathview.pro b/tests/auto/qtquick1/qdeclarativepathview/qdeclarativepathview.pro index 4233096a2d..e37ad5c493 100644 --- a/tests/auto/qtquick1/qdeclarativepathview/qdeclarativepathview.pro +++ b/tests/auto/qtquick1/qdeclarativepathview/qdeclarativepathview.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativepositioners/qdeclarativepositioners.pro b/tests/auto/qtquick1/qdeclarativepositioners/qdeclarativepositioners.pro index cf4ebfbf39..b01f8a31d4 100644 --- a/tests/auto/qtquick1/qdeclarativepositioners/qdeclarativepositioners.pro +++ b/tests/auto/qtquick1/qdeclarativepositioners/qdeclarativepositioners.pro @@ -13,4 +13,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro b/tests/auto/qtquick1/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro index 99094cf101..1afe01ff4e 100644 --- a/tests/auto/qtquick1/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro +++ b/tests/auto/qtquick1/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativespringanimation/qdeclarativespringanimation.pro b/tests/auto/qtquick1/qdeclarativespringanimation/qdeclarativespringanimation.pro index 56f9c2df17..c3ceed0c84 100644 --- a/tests/auto/qtquick1/qdeclarativespringanimation/qdeclarativespringanimation.pro +++ b/tests/auto/qtquick1/qdeclarativespringanimation/qdeclarativespringanimation.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativestates/qdeclarativestates.pro b/tests/auto/qtquick1/qdeclarativestates/qdeclarativestates.pro index b80ab88f01..bdf151a849 100644 --- a/tests/auto/qtquick1/qdeclarativestates/qdeclarativestates.pro +++ b/tests/auto/qtquick1/qdeclarativestates/qdeclarativestates.pro @@ -13,4 +13,4 @@ symbian: { } CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro b/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro index ad9a667d57..6253806984 100644 --- a/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro +++ b/tests/auto/qtquick1/qdeclarativetext/qdeclarativetext.pro @@ -19,4 +19,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro b/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro index 2d5461ffc1..4e18222663 100644 --- a/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro +++ b/tests/auto/qtquick1/qdeclarativetextedit/qdeclarativetextedit.pro @@ -12,4 +12,4 @@ symbian: { } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativetextinput/qdeclarativetextinput.pro b/tests/auto/qtquick1/qdeclarativetextinput/qdeclarativetextinput.pro index d39da270a3..f18c054132 100644 --- a/tests/auto/qtquick1/qdeclarativetextinput/qdeclarativetextinput.pro +++ b/tests/auto/qtquick1/qdeclarativetextinput/qdeclarativetextinput.pro @@ -12,4 +12,4 @@ symbian: { DEFINES += SRCDIR=\\\"$$PWD\\\" } -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativeviewer/qdeclarativeviewer.pro b/tests/auto/qtquick1/qdeclarativeviewer/qdeclarativeviewer.pro index ca214b1210..67be35f510 100644 --- a/tests/auto/qtquick1/qdeclarativeviewer/qdeclarativeviewer.pro +++ b/tests/auto/qtquick1/qdeclarativeviewer/qdeclarativeviewer.pro @@ -17,4 +17,4 @@ symbian: { } CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private widgets-private +QT += core-private gui-private declarative-private qtquick1-private widgets-private v8-private diff --git a/tests/auto/qtquick1/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro b/tests/auto/qtquick1/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro index a5a0add30f..3f116e1f37 100644 --- a/tests/auto/qtquick1/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro +++ b/tests/auto/qtquick1/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro @@ -14,4 +14,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/auto/qtquick1/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro b/tests/auto/qtquick1/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro index 6acfe35dca..e8894a8564 100644 --- a/tests/auto/qtquick1/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro +++ b/tests/auto/qtquick1/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro @@ -18,4 +18,4 @@ symbian: { CONFIG += parallel_test -QT += core-private gui-private declarative-private qtquick1-private +QT += core-private gui-private v8-private declarative-private qtquick1-private diff --git a/tests/benchmarks/declarative/compilation/tst_compilation.cpp b/tests/benchmarks/declarative/compilation/tst_compilation.cpp index 98008d8bf8..9b4f9a70e8 100644 --- a/tests/benchmarks/declarative/compilation/tst_compilation.cpp +++ b/tests/benchmarks/declarative/compilation/tst_compilation.cpp @@ -44,10 +44,10 @@ #include <QtDeclarative/qdeclarativeengine.h> #include <QtDeclarative/qdeclarativecomponent.h> #include <QtDeclarative/private/qdeclarativejsengine_p.h> -#include <QtDeclarative/private/qdeclarativejsnodepool_p.h> +#include <QtDeclarative/private/qdeclarativejsmemorypool_p.h> #include <QtDeclarative/private/qdeclarativejsparser_p.h> #include <QtDeclarative/private/qdeclarativejslexer_p.h> -#include <QtDeclarative/private/qdeclarativescriptparser_p.h> +#include <QtDeclarative/private/qdeclarativescript_p.h> #include <QFile> #include <QDebug> @@ -154,7 +154,7 @@ void tst_compilation::scriptparser() QUrl url = QUrl::fromLocalFile(file); QBENCHMARK { - QDeclarativeScriptParser parser; + QDeclarativeScript::Parser parser; parser.parse(data, url); parser.tree(); } diff --git a/tests/benchmarks/declarative/creation/creation.pro b/tests/benchmarks/declarative/creation/creation.pro index 74cb47fb73..8241ace5a6 100644 --- a/tests/benchmarks/declarative/creation/creation.pro +++ b/tests/benchmarks/declarative/creation/creation.pro @@ -1,7 +1,7 @@ load(qttest_p4) TEMPLATE = app TARGET = tst_creation -QT += declarative +QT += declarative qtquick1 macx:CONFIG -= app_bundle SOURCES += tst_creation.cpp @@ -13,3 +13,5 @@ symbian { } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } + +QT += core-private gui-private declarative-private qtquick1-private diff --git a/tests/benchmarks/declarative/creation/tst_creation.cpp b/tests/benchmarks/declarative/creation/tst_creation.cpp index 4085688845..6659eb5989 100644 --- a/tests/benchmarks/declarative/creation/tst_creation.cpp +++ b/tests/benchmarks/declarative/creation/tst_creation.cpp @@ -48,7 +48,7 @@ #include <QGraphicsItem> #include <QDeclarativeItem> #include <QDeclarativeContext> -#include <private/qdeclarativetextinput_p.h> +#include <QtQuick1/private/qdeclarativetextinput_p.h> #include <private/qobject_p.h> #ifdef Q_OS_SYMBIAN @@ -111,7 +111,7 @@ tst_creation::tst_creation() qmlRegisterType<TestType>("Qt.test", 1, 0, "TestType"); //get rid of initialization effects - QDeclarativeTextInput te; + QDeclarative1TextInput te; } inline QUrl TEST_FILE(const QString &filename) @@ -206,7 +206,7 @@ void tst_creation::qobject_10tree_cpp() void tst_creation::qobject_qmltype() { - QDeclarativeType *t = QDeclarativeMetaType::qmlType("Qt/QtObject", 4, 7); + QDeclarativeType *t = QDeclarativeMetaType::qmlType("QtQuick/QtObject", 2, 0); QBENCHMARK { QObject *obj = t->create(); @@ -350,7 +350,7 @@ void tst_creation::elements_data() void tst_creation::elements() { QFETCH(QByteArray, type); - QDeclarativeType *t = QDeclarativeMetaType::qmlType(type, 4, 7); + QDeclarativeType *t = QDeclarativeMetaType::qmlType(type, 2, 0); if (!t || !t->isCreatable()) QSKIP("Non-creatable type", SkipSingle); diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index c553070123..c53fd3c7fd 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -540,6 +540,19 @@ int main(int argc, char *argv[]) engine.addImportPath(pluginImportPath); } + // load the QtQuick 1 plugin + { + QByteArray code("import QtQuick 1.0\nQtObject {}"); + QDeclarativeComponent c(&engine); + c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/loadqtquick1.qml")); + c.create(); + if (!c.errors().isEmpty()) { + foreach (const QDeclarativeError &error, c.errors()) + qWarning() << error.toString(); + return EXIT_IMPORTERROR; + } + } + // find all QMetaObjects reachable from the builtin module QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(); QList<QDeclarativeType *> defaultTypes = QDeclarativeMetaType::qmlTypes(); diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro index 0ac3a70c14..49134a05ab 100644 --- a/tools/qmlplugindump/qmlplugindump.pro +++ b/tools/qmlplugindump/qmlplugindump.pro @@ -2,7 +2,7 @@ TEMPLATE = app CONFIG += qt uic console DESTDIR = $$QT.declarative.bins -QT += declarative declarative-private core-private +QT += declarative declarative-private qtquick1 core-private TARGET = qmlplugindump diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index 0139f591a6..cd40ea5f8c 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -321,6 +321,7 @@ static void checkAndAdaptVersion(const QUrl &url) } QRegExp quick1("^\\s*import +QtQuick +1\\."); + QRegExp quick2("^\\s*import +QtQuick +2\\."); QRegExp qt47("^\\s*import +Qt +4\\.7"); QString envToWrite; @@ -328,16 +329,20 @@ static void checkAndAdaptVersion(const QUrl &url) QTextStream stream(&f); bool codeFound= false; - while (!codeFound && envToWrite.isEmpty()) { + while (!codeFound) { QString line = stream.readLine(); if (line.contains("{")) codeFound = true; - if (quick1.indexIn(line) >= 0) { + if (envToWrite.isEmpty() && quick1.indexIn(line) >= 0) { envToWrite = QLatin1String("quick1"); compat = QLatin1String("QtQuick 1.0"); - } else if (qt47.indexIn(line) >= 0) { + } else if (envToWrite.isEmpty() && qt47.indexIn(line) >= 0) { envToWrite = QLatin1String("qt"); compat = QLatin1String("Qt 4.7"); + } else if (quick2.indexIn(line) >= 0) { + envToWrite.clear(); + compat.clear(); + break; } } diff --git a/tools/qmlviewer/qml.pri b/tools/qmlviewer/qml.pri index f5d3f80feb..e84dfb5c9b 100644 --- a/tools/qmlviewer/qml.pri +++ b/tools/qmlviewer/qml.pri @@ -1,4 +1,4 @@ -QT += core-private gui-private declarative-private network sql +QT += core-private gui-private v8-private declarative-private network sql contains(QT_CONFIG, opengl) { QT += opengl DEFINES += GL_SUPPORTED |