aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--src/3rdparty/javascriptcore/COPYING.LIB488
-rw-r--r--src/3rdparty/javascriptcore/DateMath.cpp382
-rw-r--r--src/3rdparty/javascriptcore/DateMath.h190
-rw-r--r--src/3rdparty/javascriptcore/VERSION15
m---------src/3rdparty/v80
-rw-r--r--src/declarative/declarative.pro9
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.cpp76
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.h5
-rw-r--r--src/declarative/items/qsgitem.cpp74
-rw-r--r--src/declarative/items/qsgitem.h4
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp32
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeboundsignal.cpp1
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp13
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp119
-rw-r--r--src/declarative/qml/qdeclarativecomponent.h4
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h2
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp24
-rw-r--r--src/declarative/qml/qdeclarativecontext.h2
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h12
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass.cpp335
-rw-r--r--src/declarative/qml/qdeclarativedata_p.h11
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp1022
-rw-r--r--src/declarative/qml/qdeclarativeengine.h2
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h93
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp245
-rw-r--r--src/declarative/qml/qdeclarativeexpression.h3
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h19
-rw-r--r--src/declarative/qml/qdeclarativeglobalscriptclass.cpp147
-rw-r--r--src/declarative/qml/qdeclarativeinclude.cpp310
-rw-r--r--src/declarative/qml/qdeclarativeintegercache.cpp29
-rw-r--r--src/declarative/qml/qdeclarativeintegercache_p.h36
-rw-r--r--src/declarative/qml/qdeclarativelistscriptclass.cpp149
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp9
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp1226
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass_p.h166
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp2
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp68
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h52
-rw-r--r--src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp219
-rw-r--r--src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h163
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase.cpp585
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase_p.h8
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp11
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h8
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache.cpp29
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache_p.h38
-rw-r--r--src/declarative/qml/qdeclarativetypenamescriptclass.cpp195
-rw-r--r--src/declarative/qml/qdeclarativevaluetypescriptclass.cpp242
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp84
-rw-r--r--src/declarative/qml/qdeclarativevme_p.h5
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp71
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject_p.h13
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript.cpp409
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript_p.h8
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp1392
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest_p.h6
-rw-r--r--src/declarative/qml/qintrusivelist_p.h7
-rw-r--r--src/declarative/qml/qml.pri17
-rw-r--r--src/declarative/qml/v4/qdeclarativev4bindings.cpp3
-rw-r--r--src/declarative/qml/v4/qdeclarativev4irbuilder.cpp3
-rw-r--r--src/declarative/qml/v8/notes.txt4
-rw-r--r--src/declarative/qml/v8/qhashedstring.cpp103
-rw-r--r--src/declarative/qml/v8/qhashedstring_p.h572
-rw-r--r--src/declarative/qml/v8/qv8_p.h1
-rw-r--r--src/declarative/qml/v8/qv8contextwrapper.cpp425
-rw-r--r--src/declarative/qml/v8/qv8contextwrapper_p.h (renamed from src/declarative/qml/qdeclarativecontextscriptclass_p.h)73
-rw-r--r--src/declarative/qml/v8/qv8engine.cpp1423
-rw-r--r--src/declarative/qml/v8/qv8engine_p.h348
-rw-r--r--src/declarative/qml/v8/qv8include.cpp243
-rw-r--r--src/declarative/qml/v8/qv8include_p.h (renamed from src/declarative/qml/qdeclarativeinclude_p.h)48
-rw-r--r--src/declarative/qml/v8/qv8listwrapper.cpp178
-rw-r--r--src/declarative/qml/v8/qv8listwrapper_p.h96
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper.cpp1714
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper_p.h121
-rw-r--r--src/declarative/qml/v8/qv8stringwrapper.cpp94
-rw-r--r--src/declarative/qml/v8/qv8stringwrapper_p.h (renamed from src/declarative/qml/qdeclarativeglobalscriptclass_p.h)34
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp211
-rw-r--r--src/declarative/qml/v8/qv8typewrapper_p.h (renamed from src/declarative/qml/qdeclarativetypenamescriptclass_p.h)47
-rw-r--r--src/declarative/qml/v8/qv8valuetypewrapper.cpp289
-rw-r--r--src/declarative/qml/v8/qv8valuetypewrapper_p.h (renamed from src/declarative/qml/qdeclarativevaluetypescriptclass_p.h)46
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper.cpp190
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper_p.h101
-rw-r--r--src/declarative/qml/v8/qv8worker.cpp322
-rw-r--r--src/declarative/qml/v8/qv8worker_p.h (renamed from src/declarative/qml/qdeclarativelistscriptclass_p.h)34
-rw-r--r--src/declarative/qml/v8/v8.pri32
-rw-r--r--src/declarative/util/qdeclarativelistmodel.cpp2
-rw-r--r--src/src.pro2
-rw-r--r--src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch124
-rw-r--r--src/v8/0002-Add-a-bit-field-3-to-Map.patch118
-rw-r--r--src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch364
-rw-r--r--src/v8/0004-Generalize-external-object-resources.patch894
-rw-r--r--src/v8/0005-Introduce-a-QML-compilation-mode.patch1369
-rw-r--r--src/v8/0006-Allow-access-to-the-calling-script-data.patch48
-rw-r--r--src/v8/0007-Fix-warnings.patch46
-rw-r--r--src/v8/README1
-rw-r--r--src/v8/v8.pro263
-rw-r--r--src/v8/v8base.pri18
-rwxr-xr-xsrc/v8/wrapcc.pl48
-rw-r--r--tests/auto/declarative/declarative.pro3
-rw-r--r--tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp2
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml11
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/qtbug_11600.qml2
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml1
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp269
-rw-r--r--tests/auto/declarative/qdeclarativeitem/data/mapCoordinates.qml4
-rw-r--r--tests/auto/declarative/qdeclarativeqt/data/dateTimeConversion.qml14
-rw-r--r--tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp117
-rw-r--r--tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp3
-rw-r--r--tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp15
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/data/invalidMethodUsage.qml12
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp1
-rw-r--r--tests/auto/declarative/v8/tst_v8.cpp96
-rw-r--r--tests/auto/declarative/v8/v8.pro14
115 files changed, 13404 insertions, 6103 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000..183f5b46cc
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "src/3rdparty/v8"]
+ path = src/3rdparty/v8
+ url = git://github.com/aaronkennedy/v8.git
diff --git a/src/3rdparty/javascriptcore/COPYING.LIB b/src/3rdparty/javascriptcore/COPYING.LIB
new file mode 100644
index 0000000000..87c4a33dd8
--- /dev/null
+++ b/src/3rdparty/javascriptcore/COPYING.LIB
@@ -0,0 +1,488 @@
+
+
+NOTE! The LGPL below is copyrighted by the Free Software Foundation, but
+the instance of code that it refers to (the kde libraries) are copyrighted
+by the authors who actually wrote it.
+
+---------------------------------------------------------------------------
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor
+ Boston, MA 02110-1301, USA.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/3rdparty/javascriptcore/DateMath.cpp b/src/3rdparty/javascriptcore/DateMath.cpp
new file mode 100644
index 0000000000..11c224aebb
--- /dev/null
+++ b/src/3rdparty/javascriptcore/DateMath.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+
+ * Copyright 2006-2008 the V8 project authors. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DateMath.h"
+
+#include <algorithm>
+#include <limits.h>
+#include <limits>
+#include <stdint.h>
+#include <time.h>
+
+//#if HAVE(SYS_TIME_H)
+#if defined(EXISTS_SYS_TIME)
+#include <sys/time.h>
+#endif
+
+//#if HAVE(SYS_TIMEB_H)
+#if defined(EXISTS_SYS_TIMEB)
+#include <sys/timeb.h>
+#endif
+
+#define NaN std::numeric_limits<double>::quiet_NaN()
+
+using namespace QV8DateConverter::WTF;
+
+namespace QV8DateConverter {
+
+namespace WTF {
+
+/* Constants */
+
+static const double minutesPerDay = 24.0 * 60.0;
+static const double secondsPerDay = 24.0 * 60.0 * 60.0;
+static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0;
+
+static const double usecPerSec = 1000000.0;
+
+static const double maxUnixTime = 2145859200.0; // 12/31/2037
+// ECMAScript asks not to support for a date of which total
+// millisecond value is larger than the following value.
+// See 15.9.1.14 of ECMA-262 5th edition.
+static const double maxECMAScriptTime = 8.64E15;
+
+// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
+// First for non-leap years, then for leap years.
+static const int firstDayOfMonth[2][12] = {
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
+};
+
+static inline bool isLeapYear(int year)
+{
+ if (year % 4 != 0)
+ return false;
+ if (year % 400 == 0)
+ return true;
+ if (year % 100 == 0)
+ return false;
+ return true;
+}
+
+static inline int daysInYear(int year)
+{
+ return 365 + isLeapYear(year);
+}
+
+static inline double daysFrom1970ToYear(int year)
+{
+ // The Gregorian Calendar rules for leap years:
+ // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years.
+ // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years.
+ // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years.
+
+ static const int leapDaysBefore1971By4Rule = 1970 / 4;
+ static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100;
+ static const int leapDaysBefore1971By400Rule = 1970 / 400;
+
+ const double yearMinusOne = year - 1;
+ const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule;
+ const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule;
+ const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule;
+
+ return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
+}
+
+static inline double msToDays(double ms)
+{
+ return floor(ms / msPerDay);
+}
+
+int msToYear(double ms)
+{
+ int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
+ double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
+ if (msFromApproxYearTo1970 > ms)
+ return approxYear - 1;
+ if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms)
+ return approxYear + 1;
+ return approxYear;
+}
+
+int dayInYear(double ms, int year)
+{
+ return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
+}
+
+static inline double msToMilliseconds(double ms)
+{
+ double result = fmod(ms, msPerDay);
+ if (result < 0)
+ result += msPerDay;
+ return result;
+}
+
+// 0: Sunday, 1: Monday, etc.
+static inline int msToWeekDay(double ms)
+{
+ int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
+ if (wd < 0)
+ wd += 7;
+ return wd;
+}
+
+static inline int msToSeconds(double ms)
+{
+ double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
+ if (result < 0)
+ result += secondsPerMinute;
+ return static_cast<int>(result);
+}
+
+static inline int msToMinutes(double ms)
+{
+ double result = fmod(floor(ms / msPerMinute), minutesPerHour);
+ if (result < 0)
+ result += minutesPerHour;
+ return static_cast<int>(result);
+}
+
+static inline int msToHours(double ms)
+{
+ double result = fmod(floor(ms/msPerHour), hoursPerDay);
+ if (result < 0)
+ result += hoursPerDay;
+ return static_cast<int>(result);
+}
+
+int monthFromDayInYear(int dayInYear, bool leapYear)
+{
+ const int d = dayInYear;
+ int step;
+
+ if (d < (step = 31))
+ return 0;
+ step += (leapYear ? 29 : 28);
+ if (d < step)
+ return 1;
+ if (d < (step += 31))
+ return 2;
+ if (d < (step += 30))
+ return 3;
+ if (d < (step += 31))
+ return 4;
+ if (d < (step += 30))
+ return 5;
+ if (d < (step += 31))
+ return 6;
+ if (d < (step += 31))
+ return 7;
+ if (d < (step += 30))
+ return 8;
+ if (d < (step += 31))
+ return 9;
+ if (d < (step += 30))
+ return 10;
+ return 11;
+}
+
+static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth)
+{
+ startDayOfThisMonth = startDayOfNextMonth;
+ startDayOfNextMonth += daysInThisMonth;
+ return (dayInYear <= startDayOfNextMonth);
+}
+
+int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
+{
+ const int d = dayInYear;
+ int step;
+ int next = 30;
+
+ if (d <= next)
+ return d + 1;
+ const int daysInFeb = (leapYear ? 29 : 28);
+ if (checkMonth(d, step, next, daysInFeb))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ step = next;
+ return d - step;
+}
+
+static inline int monthToDayInYear(int month, bool isLeapYear)
+{
+ return firstDayOfMonth[isLeapYear][month];
+}
+
+static inline double timeToMS(double hour, double min, double sec, double ms)
+{
+ return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
+}
+
+double dateToDaysFrom1970(int year, int month, int day)
+{
+ year += month / 12;
+
+ month %= 12;
+ if (month < 0) {
+ month += 12;
+ --year;
+ }
+
+ double yearday = floor(daysFrom1970ToYear(year));
+ int monthday = monthToDayInYear(month, isLeapYear(year));
+
+ return yearday + monthday + day - 1;
+}
+
+static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
+{
+ double days = (day - 32075)
+ + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
+ + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
+ - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
+ - 2440588;
+ return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
+}
+
+// We follow the recommendation of RFC 2822 to consider all
+// obsolete time zones not listed here equivalent to "-0000".
+static const struct KnownZone {
+ const
+ char tzName[4];
+ int tzOffset;
+} known_zones[] = {
+ { "UT", 0 },
+ { "GMT", 0 },
+ { "EST", -300 },
+ { "EDT", -240 },
+ { "CST", -360 },
+ { "CDT", -300 },
+ { "MST", -420 },
+ { "MDT", -360 },
+ { "PST", -480 },
+ { "PDT", -420 }
+};
+
+double timeClip(double t)
+{
+ if (!isfinite(t))
+ return NaN;
+ if (fabs(t) > maxECMAScriptTime)
+ return NaN;
+ return trunc(t);
+}
+} // namespace WTF
+
+namespace JSC {
+
+double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds)
+{
+ double day = dateToDaysFrom1970(t.year + 1900, t.month, t.monthDay);
+ double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
+ double result = (day * WTF::msPerDay) + ms;
+
+ return result;
+}
+
+// input is UTC
+void msToGregorianDateTime(double ms, GregorianDateTime& tm)
+{
+ const int year = msToYear(ms);
+ tm.second = msToSeconds(ms);
+ tm.minute = msToMinutes(ms);
+ tm.hour = msToHours(ms);
+ tm.weekDay = msToWeekDay(ms);
+ tm.yearDay = dayInYear(ms, year);
+ tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
+ tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year));
+ tm.year = year - 1900;
+ tm.isDST = false;
+ tm.utcOffset = static_cast<long>(0); // no ExecState :. cannot calculate offset. Assume UTC output.
+ tm.timeZone = NULL;
+}
+
+} // namespace JSC
+
+} // namespace QV8DateConverter
+
diff --git a/src/3rdparty/javascriptcore/DateMath.h b/src/3rdparty/javascriptcore/DateMath.h
new file mode 100644
index 0000000000..5adb0d358c
--- /dev/null
+++ b/src/3rdparty/javascriptcore/DateMath.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ */
+
+#ifndef DateMath_h
+#define DateMath_h
+
+#include <math.h>
+#include <string.h>
+#include <time.h>
+
+namespace QV8DateConverter {
+
+namespace WTF {
+
+double timeClip(double);
+
+const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+const double hoursPerDay = 24.0;
+const double minutesPerHour = 60.0;
+const double secondsPerHour = 60.0 * 60.0;
+const double secondsPerMinute = 60.0;
+const double msPerSecond = 1000.0;
+const double msPerMinute = 60.0 * 1000.0;
+const double msPerHour = 60.0 * 60.0 * 1000.0;
+const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
+const double msPerMonth = 2592000000.0;
+
+// Returns the number of days from 1970-01-01 to the specified date.
+double dateToDaysFrom1970(int year, int month, int day);
+int msToYear(double ms);
+int dayInYear(double ms, int year);
+int monthFromDayInYear(int dayInYear, bool leapYear);
+int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
+
+} // namespace WTF
+
+using WTF::dateToDaysFrom1970;
+using WTF::dayInMonthFromDayInYear;
+using WTF::dayInYear;
+using WTF::minutesPerHour;
+using WTF::monthFromDayInYear;
+using WTF::msPerDay;
+using WTF::msPerSecond;
+using WTF::msToYear;
+using WTF::secondsPerMinute;
+
+namespace JSC {
+struct GregorianDateTime;
+
+void msToGregorianDateTime(double, GregorianDateTime&);
+double gregorianDateTimeToMS(const GregorianDateTime&, double);
+
+// Intentionally overridding the default tm of the system.
+// The members of tm differ on various operating systems.
+struct GregorianDateTime {
+ GregorianDateTime()
+ : second(0)
+ , minute(0)
+ , hour(0)
+ , weekDay(0)
+ , monthDay(0)
+ , yearDay(0)
+ , month(0)
+ , year(0)
+ , isDST(0)
+ , utcOffset(0)
+ , timeZone(0)
+ {
+ }
+
+ ~GregorianDateTime()
+ {
+ delete [] timeZone;
+ }
+
+ GregorianDateTime(const tm& inTm)
+ : second(inTm.tm_sec)
+ , minute(inTm.tm_min)
+ , hour(inTm.tm_hour)
+ , weekDay(inTm.tm_wday)
+ , monthDay(inTm.tm_mday)
+ , yearDay(inTm.tm_yday)
+ , month(inTm.tm_mon)
+ , year(inTm.tm_year)
+ , isDST(inTm.tm_isdst)
+ {
+ utcOffset = static_cast<int>(0);
+ timeZone = 0;
+ }
+
+ operator tm() const
+ {
+ tm ret;
+ memset(&ret, 0, sizeof(ret));
+
+ ret.tm_sec = second;
+ ret.tm_min = minute;
+ ret.tm_hour = hour;
+ ret.tm_wday = weekDay;
+ ret.tm_mday = monthDay;
+ ret.tm_yday = yearDay;
+ ret.tm_mon = month;
+ ret.tm_year = year;
+ ret.tm_isdst = isDST;
+ return ret;
+ }
+
+ void copyFrom(const GregorianDateTime& rhs)
+ {
+ second = rhs.second;
+ minute = rhs.minute;
+ hour = rhs.hour;
+ weekDay = rhs.weekDay;
+ monthDay = rhs.monthDay;
+ yearDay = rhs.yearDay;
+ month = rhs.month;
+ year = rhs.year;
+ isDST = rhs.isDST;
+ utcOffset = rhs.utcOffset;
+ if (rhs.timeZone) {
+ int inZoneSize = strlen(rhs.timeZone) + 1;
+ timeZone = new char[inZoneSize];
+ strncpy(timeZone, rhs.timeZone, inZoneSize);
+ } else
+ timeZone = 0;
+ }
+
+ int second;
+ int minute;
+ int hour;
+ int weekDay;
+ int monthDay;
+ int yearDay;
+ int month;
+ int year;
+ int isDST;
+ int utcOffset;
+ char* timeZone;
+};
+
+static inline int gmtoffset(const GregorianDateTime& t)
+{
+ return t.utcOffset;
+}
+
+} // namespace JSC
+
+} // namespace QV8DateConverter
+
+#endif // DateMath_h
diff --git a/src/3rdparty/javascriptcore/VERSION b/src/3rdparty/javascriptcore/VERSION
new file mode 100644
index 0000000000..af6229afcb
--- /dev/null
+++ b/src/3rdparty/javascriptcore/VERSION
@@ -0,0 +1,15 @@
+This is a snapshot of the files: DateMath.h and DateMath.cpp
+from a snapshot of JavaScriptCore from
+
+ git://gitorious.org/qtwebkit/qtwebkit.git
+
+The commit imported was from the
+
+ javascriptcore-snapshot-27012011 branch/tag
+
+and has the sha1 checksum
+
+ 3ab0f621048fbeb480b687a28ed31d92d8506150
+
+The two files were then modified slightly so that unneeded
+functionality was removed (mostly regarding timezone offset).
diff --git a/src/3rdparty/v8 b/src/3rdparty/v8
new file mode 160000
+Subproject 15eb9c6a9444307a867a854c742505c15bd8b86
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
index 0a1f76a251..354b5b6577 100644
--- a/src/declarative/declarative.pro
+++ b/src/declarative/declarative.pro
@@ -49,3 +49,12 @@ linux-g++-maemo:DEFINES += QDECLARATIVEVIEW_NOBACKGROUND
DEFINES += QT_NO_OPENTYPE
INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
+
+macx:CONFIG(debug, debug|release) {
+ LIBS += -L../v8/ -lv8_debug
+} else {
+ LIBS += -L../v8/ -lv8
+}
+
+# Prevent qmake adding v8 as a dependency
+CONFIG -= explicitlib
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp
index d3132deced..97014032e0 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp
@@ -63,6 +63,8 @@
#include <QtGui/qgraphicstransform.h>
#include <qlistmodelinterface_p.h>
+#include <private/qv8engine_p.h>
+
#include <float.h>
QT_BEGIN_NAMESPACE
@@ -2653,20 +2655,33 @@ void QDeclarativeItem::setKeepMouseGrab(bool keep)
If \a item is a \c null value, this maps the point from the coordinate
system of the root QML view.
*/
-QScriptValue QDeclarativeItem::mapFromItem(const QScriptValue &item, qreal x, qreal y) const
+void QDeclarativeItem::mapFromItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapFromItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
- // If QGraphicsItem::mapFromItem() is called with 0, behaves the same as mapFromScene()
- QPointF p = qobject_cast<QGraphicsItem*>(this)->mapFromItem(itemObj, x, y);
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QDeclarativeItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QDeclarativeItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapFromItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
+
+ QPointF p = QGraphicsItem::mapFromItem(itemObj, x, y);
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
/*!
@@ -2679,20 +2694,33 @@ QScriptValue QDeclarativeItem::mapFromItem(const QScriptValue &item, qreal x, qr
If \a item is a \c null value, this maps \a x and \a y to the coordinate
system of the root QML view.
*/
-QScriptValue QDeclarativeItem::mapToItem(const QScriptValue &item, qreal x, qreal y) const
+void QDeclarativeItem::mapToItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapToItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QDeclarativeItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QDeclarativeItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapToItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
- // If QGraphicsItem::mapToItem() is called with 0, behaves the same as mapToScene()
- QPointF p = qobject_cast<QGraphicsItem*>(this)->mapToItem(itemObj, x, y);
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QPointF p = QGraphicsItem::mapToItem(itemObj, x, y);
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
/*!
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.h b/src/declarative/graphicsitems/qdeclarativeitem.h
index 839b934903..90328fef24 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.h
+++ b/src/declarative/graphicsitems/qdeclarativeitem.h
@@ -64,6 +64,7 @@ class QDeclarativeTransition;
class QDeclarativeKeyEvent;
class QDeclarativeAnchors;
class QDeclarativeItemPrivate;
+class QDeclarativeV8Function;
class Q_DECLARATIVE_EXPORT QDeclarativeItem : public QGraphicsObject, public QDeclarativeParserStatus
{
Q_OBJECT
@@ -149,8 +150,8 @@ public:
bool keepMouseGrab() const;
void setKeepMouseGrab(bool);
- Q_INVOKABLE QScriptValue mapFromItem(const QScriptValue &item, qreal x, qreal y) const;
- Q_INVOKABLE QScriptValue mapToItem(const QScriptValue &item, qreal x, qreal y) const;
+ Q_INVOKABLE void mapFromItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void mapToItem(QDeclarativeV8Function*) const;
Q_INVOKABLE void forceActiveFocus();
Q_INVOKABLE QDeclarativeItem *childAt(qreal x, qreal y) const;
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index f2d26955aa..bb3ad8a2ca 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -1817,20 +1817,33 @@ void QSGItem::polish()
}
}
-QScriptValue QSGItem::mapFromItem(const QScriptValue &item, qreal x, qreal y) const
+void QSGItem::mapFromItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QSGItem *itemObj = qobject_cast<QSGItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapFromItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QSGItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QSGItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapFromItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
- // If QSGItem::mapFromItem() is called with 0, behaves the same as mapFromScene()
- QPointF p = mapFromItem(itemObj, QPointF(x, y));
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QPointF p = mapFromItem(itemObj, QPointF(x, y));
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
QTransform QSGItem::itemTransform(QSGItem *other, bool *ok) const
@@ -1847,20 +1860,33 @@ QTransform QSGItem::itemTransform(QSGItem *other, bool *ok) const
return t;
}
-QScriptValue QSGItem::mapToItem(const QScriptValue &item, qreal x, qreal y) const
+void QSGItem::mapToItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QSGItem *itemObj = qobject_cast<QSGItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapToItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QSGItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QSGItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapToItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
- // If QSGItem::mapToItem() is called with 0, behaves the same as mapToScene()
- QPointF p = mapToItem(itemObj, QPointF(x, y));
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QPointF p = mapToItem(itemObj, QPointF(x, y));
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
void QSGItem::forceActiveFocus()
diff --git a/src/declarative/items/qsgitem.h b/src/declarative/items/qsgitem.h
index 564d819000..a4420b2af5 100644
--- a/src/declarative/items/qsgitem.h
+++ b/src/declarative/items/qsgitem.h
@@ -287,8 +287,8 @@ public:
void polish();
- Q_INVOKABLE QScriptValue mapFromItem(const QScriptValue &item, qreal x, qreal y) const;
- Q_INVOKABLE QScriptValue mapToItem(const QScriptValue &item, qreal x, qreal y) const;
+ Q_INVOKABLE void mapFromItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void mapToItem(QDeclarativeV8Function*) const;
Q_INVOKABLE void forceActiveFocus();
Q_INVOKABLE QSGItem *childAt(qreal x, qreal y) const;
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index 3e93ce7266..02cdb2eb47 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -274,8 +274,17 @@ QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDecl
setNotifyOnValueChanged(true);
}
-QDeclarativeBinding::QDeclarativeBinding(const QScriptValue &func, QObject *obj, QDeclarativeContextData *ctxt, QObject *parent)
-: QDeclarativeExpression(ctxt, obj, func, *new QDeclarativeBindingPrivate)
+/*!
+ \internal
+
+ To avoid exposing v8 in the public API, functionPtr must be a pointer to a v8::Handle<v8::Function>.
+ For example:
+ v8::Handle<v8::Function> function;
+ new QDeclarativeBInding(&function, scope, ctxt);
+ */
+QDeclarativeBinding::QDeclarativeBinding(void *functionPtr, QObject *obj, QDeclarativeContextData *ctxt,
+ QObject *parent)
+: QDeclarativeExpression(ctxt, obj, functionPtr, *new QDeclarativeBindingPrivate)
{
setParent(parent);
setNotifyOnValueChanged(true);
@@ -362,25 +371,28 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
bool isUndefined = false;
QVariant value;
- QScriptValue scriptValue = d->scriptValue(0, &isUndefined);
+ v8::HandleScope handle_scope;
+ v8::Local<v8::Value> result = d->v8value(0, &isUndefined);
if (wasDeleted) {
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
return;
}
- if (d->property.propertyTypeCategory() == QDeclarativeProperty::List) {
- value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >());
- } else if (scriptValue.isNull() &&
- d->property.propertyTypeCategory() == QDeclarativeProperty::Object) {
+ if (isUndefined) {
+ } else if (d->property.propertyTypeCategory() == QDeclarativeProperty::List) {
+ value = ep->v8engine.toVariant(result, qMetaTypeId<QList<QObject *> >());
+ } else if (result->IsNull() && d->property.propertyTypeCategory() == QDeclarativeProperty::Object) {
value = QVariant::fromValue((QObject *)0);
} else {
- value = ep->scriptValueToVariant(scriptValue, d->property.propertyType());
+ value = ep->v8engine.toVariant(result, d->property.propertyType());
if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) {
// If the object is null, we extract the predicted type. While this isn't
// 100% reliable, in many cases it gives us better error messages if we
// assign this null-object to an incompatible property
- int type = ep->objectClass->objectType(scriptValue);
+ // XXX aakenned
+ // int type = ep->objectClass->objectType(scriptValue);
+ int type = QMetaType::QObjectStar;
QObject *o = 0;
value = QVariant(type, (void *)&o);
}
@@ -410,7 +422,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
QLatin1String(QMetaType::typeName(d->property.propertyType())) +
QLatin1String(" ") + d->property.name());
- } else if (!scriptValue.isRegExp() && scriptValue.isFunction()) {
+ } else if (result->IsFunction()) {
QUrl url = QUrl(d->url);
int line = d->line;
diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h
index 0260b95fb8..d723ade7b7 100644
--- a/src/declarative/qml/qdeclarativebinding_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p.h
@@ -154,7 +154,7 @@ public:
QDeclarativeBinding(const QString &, QObject *, QDeclarativeContextData *, QObject *parent=0);
QDeclarativeBinding(void *, QDeclarativeRefCount *, QObject *, QDeclarativeContextData *,
const QString &, int, QObject *parent);
- QDeclarativeBinding(const QScriptValue &, QObject *, QDeclarativeContextData *, QObject *parent=0);
+ QDeclarativeBinding(void *, QObject *, QDeclarativeContextData *, QObject *parent=0);
void setTarget(const QDeclarativeProperty &);
QDeclarativeProperty property() const;
diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp
index 47a15cb0ce..cedc5d55fa 100644
--- a/src/declarative/qml/qdeclarativeboundsignal.cpp
+++ b/src/declarative/qml/qdeclarativeboundsignal.cpp
@@ -227,7 +227,6 @@ QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMeta
} else {
QByteArray propType = type;
if (t >= QVariant::UserType || t == QVariant::Invalid) {
- //copy of QDeclarativeObjectScriptClass::enumType()
QByteArray scope;
QByteArray name;
int scopeIdx = propType.lastIndexOf("::");
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 3a686be9ec..21343b6567 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -64,7 +64,6 @@
#include "private/qdeclarativescriptparser_p.h"
#include "private/qdeclarativebinding_p.h"
#include "private/qdeclarativev4compiler_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include <QColor>
#include <QDebug>
@@ -2253,7 +2252,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop
}
} else {
// Otherwise we have to search the whole type
- // This matches the logic in QDeclarativeTypeNameScriptClass
+ // This matches the logic in QV8TypeWrapper
QByteArray enumName = enumValue.toUtf8();
const QMetaObject *metaObject = type->baseMetaObject();
for (int ii = metaObject->enumeratorCount() - 1; value == -1 && ii >= 0; --ii) {
@@ -2358,7 +2357,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
if (propName.at(0).isUpper())
COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
- if (enginePrivate->globalClass->illegalNames().contains(propName))
+ if (enginePrivate->v8engine.illegalNames().contains(propName))
COMPILE_EXCEPTION(&prop, tr("Illegal property name"));
propNames.insert(prop.name);
@@ -2371,7 +2370,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter"));
- if (enginePrivate->globalClass->illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine.illegalNames().contains(nameStr))
COMPILE_EXCEPTION(obj, tr("Illegal signal name"));
methodNames.insert(name);
}
@@ -2382,7 +2381,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter"));
- if (enginePrivate->globalClass->illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine.illegalNames().contains(nameStr))
COMPILE_EXCEPTION(obj, tr("Illegal method name"));
methodNames.insert(name);
}
@@ -2676,7 +2675,7 @@ bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QStr
}
- if (enginePrivate->globalClass->illegalNames().contains(val))
+ if (enginePrivate->v8engine.illegalNames().contains(val))
COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
return true;
@@ -2877,7 +2876,7 @@ int QDeclarativeCompiler::genContextCache()
if (compileState.ids.count() == 0)
return -1;
- QDeclarativeIntegerCache *cache = new QDeclarativeIntegerCache(engine);
+ QDeclarativeIntegerCache *cache = new QDeclarativeIntegerCache();
for (QHash<QString, QDeclarativeParser::Object *>::ConstIterator iter = compileState.ids.begin();
iter != compileState.ids.end();
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index 7126746078..b5704d17c7 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -660,49 +660,50 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q
Sets graphics object parent because forgetting to do this is a frequent
and serious problem.
*/
-QScriptValue QDeclarativeComponent::createObject(QObject* parent)
+void QDeclarativeComponent::createObject(QDeclarativeV8Function *args)
{
- Q_D(QDeclarativeComponent);
- return d->createObject(parent, QScriptValue(QScriptValue::NullValue));
-}
+ Q_ASSERT(args);
+
+#define RETURN(result) { args->returnValue((result)); return; }
-/*!
- \internal
- Overloadable method allows properties to be set during creation
-*/
-QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap)
-{
Q_D(QDeclarativeComponent);
- if (!valuemap.isObject() || valuemap.isArray()) {
- qmlInfo(this) << tr("createObject: value is not an object");
- return QScriptValue(QScriptValue::NullValue);
+ Q_ASSERT(d->engine);
+
+ QDeclarativeEngine *engine = d->engine;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QV8Engine *v8engine = &ep->v8engine;
+
+ QDeclarativeContext *ctxt = creationContext();
+ if (!ctxt) ctxt = engine->rootContext();
+
+ v8::Local<v8::Object> valuemap;
+ if (args->Length() >= 2) {
+ v8::Local<v8::Value> v = (*args)[1];
+ if (!v->IsObject() || v->IsArray()) {
+ qmlInfo(this) << tr("createObject: value is not an object");
+ RETURN(v8::Null());
+ }
+ valuemap = v8::Local<v8::Object>::Cast(v);
}
- return d->createObject(parent, valuemap);
-}
-QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap)
-{
- Q_Q(QDeclarativeComponent);
- QDeclarativeContext* ctxt = q->creationContext();
- if(!ctxt && engine)
- ctxt = engine->rootContext();
- if (!ctxt)
- return QScriptValue(QScriptValue::NullValue);
- QObject* ret = q->beginCreate(ctxt);
+ QObject *parent = args->Length()?v8engine->toQObject((*args)[0]):0;
+
+ QObject *ret = beginCreate(ctxt);
if (!ret) {
- q->completeCreate();
- return QScriptValue(QScriptValue::NullValue);
+ completeCreate();
+ RETURN(v8::Null());
}
- if (publicParent) {
- ret->setParent(publicParent);
+ if (parent) {
+ ret->setParent(parent);
+
QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
bool needParent = false;
for (int ii = 0; ii < functions.count(); ++ii) {
- QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent);
+ QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, parent);
if (res == QDeclarativePrivate::Parented) {
needParent = false;
break;
@@ -715,37 +716,41 @@ QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, c
qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
}
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
- QDeclarativeData::get(ret, true)->setImplicitDestructible();
- QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
-
- if (valuemap.isObject() && !valuemap.isArray()) {
- //Iterate through and assign properties
- QScriptValueIterator it(valuemap);
- while (it.hasNext()) {
- it.next();
- QScriptValue prop = newObject;
- QString propName = it.name();
- int index = propName.indexOf(QLatin1Char('.'));
- if (index > 0) {
- QString subProp = propName;
- int lastIndex = 0;
- while (index > 0) {
- subProp = propName.mid(lastIndex, index - lastIndex);
- prop = prop.property(subProp);
- lastIndex = index + 1;
- index = propName.indexOf(QLatin1Char('.'), index + 1);
- }
- prop.setProperty(propName.mid(propName.lastIndexOf(QLatin1Char('.')) + 1), it.value());
- } else {
- newObject.setProperty(propName, it.value());
- }
- }
+ v8::Handle<v8::Value> ov = v8engine->newQObject(ret);
+ Q_ASSERT(ov->IsObject());
+ v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
+
+ if (!valuemap.IsEmpty()) {
+
+#define SET_ARGS_SOURCE \
+ "(function(object, values) {"\
+ "try {"\
+ "for(var property in values) {"\
+ "try {"\
+ "var properties = property.split(\".\");"\
+ "var o = object;"\
+ "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
+ "o = o[properties[ii]];"\
+ "}"\
+ "o[properties[properties.length - 1]] = values[property];"\
+ "} catch(e) {}"\
+ "}"\
+ "} catch(e) {}"\
+ "})"
+
+ v8::Local<v8::Script> script = v8engine->qmlModeCompile(SET_ARGS_SOURCE);
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(script->Run(args->qmlGlobal()));
+
+ // Try catch isn't needed as the function itself is loaded with try/catch
+ v8::Handle<v8::Value> args[] = { object, valuemap };
+ function->Call(v8engine->global(), 2, args);
}
- q->completeCreate();
+ completeCreate();
+
+ RETURN(object);
- return newObject;
+#undef RETURN
}
/*!
diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h
index 6c05881f52..b9cc74d37c 100644
--- a/src/declarative/qml/qdeclarativecomponent.h
+++ b/src/declarative/qml/qdeclarativecomponent.h
@@ -60,6 +60,7 @@ class QByteArray;
class QDeclarativeComponentPrivate;
class QDeclarativeEngine;
class QDeclarativeComponentAttached;
+class QDeclarativeV8Function;
class Q_DECLARATIVE_EXPORT QDeclarativeComponent : public QObject
{
Q_OBJECT
@@ -110,8 +111,7 @@ Q_SIGNALS:
protected:
QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject* parent);
- Q_INVOKABLE QScriptValue createObject(QObject* parent);
- Q_INVOKABLE Q_REVISION(1) QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning
+ Q_INVOKABLE void createObject(QDeclarativeV8Function *);
private:
QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, QObject *parent);
diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h
index 9bfbba94e2..f5bbd20ef3 100644
--- a/src/declarative/qml/qdeclarativecomponent_p.h
+++ b/src/declarative/qml/qdeclarativecomponent_p.h
@@ -115,8 +115,6 @@ public:
ConstructionState *state);
static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state);
- QScriptValue createObject(QObject *publicParent, const QScriptValue valuemap);
-
QDeclarativeEngine *engine;
QDeclarativeGuardedContextData creationContext;
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index 4f0d704d95..1083409511 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -47,7 +47,6 @@
#include "private/qdeclarativeengine_p.h"
#include "qdeclarativeengine.h"
#include "qdeclarativeinfo.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include "private/qdeclarativev4bindings_p.h"
#include <qscriptengine.h>
@@ -313,7 +312,7 @@ void QDeclarativeContext::setContextProperty(const QString &name, const QVariant
}
}
- if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
+ if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache();
int idx = data->propertyNames->value(name);
if (idx == -1) {
@@ -350,7 +349,7 @@ void QDeclarativeContext::setContextProperty(const QString &name, QObject *value
return;
}
- if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
+ if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache();
int idx = data->propertyNames->value(name);
if (idx == -1) {
@@ -498,18 +497,18 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject
QDeclarativeContextData::QDeclarativeContextData()
-: parent(0), engine(0), isInternal(false), ownedByParent(false), publicContext(0), propertyNames(0), contextObject(0),
- imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
- contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
- componentAttached(0)
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), publicContext(0),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0),
+ linkedContext(0), componentAttached(0)
{
}
QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
-: parent(0), engine(0), isInternal(false), ownedByParent(false), publicContext(ctxt), propertyNames(0), contextObject(0),
- imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
- contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
- componentAttached(0)
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), publicContext(ctxt),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0),
+ linkedContext(0), componentAttached(0)
{
}
@@ -611,6 +610,9 @@ void QDeclarativeContextData::destroy()
if (optimizedBindings)
optimizedBindings->release();
+ for (int ii = 0; ii < importedScripts.count(); ++ii)
+ importedScripts[ii].Dispose();
+
delete [] idValues;
if (isInternal)
diff --git a/src/declarative/qml/qdeclarativecontext.h b/src/declarative/qml/qdeclarativecontext.h
index 66daca959d..21e1fc30de 100644
--- a/src/declarative/qml/qdeclarativecontext.h
+++ b/src/declarative/qml/qdeclarativecontext.h
@@ -94,8 +94,6 @@ private:
friend class QDeclarativeEnginePrivate;
friend class QDeclarativeExpression;
friend class QDeclarativeExpressionPrivate;
- friend class QDeclarativeContextScriptClass;
- friend class QDeclarativeObjectScriptClass;
friend class QDeclarativeComponent;
friend class QDeclarativeComponentPrivate;
friend class QDeclarativeScriptPrivate;
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index 29ca091fc2..11a4f1407b 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -69,6 +69,8 @@
#include <private/qobject_p.h>
#include "private/qdeclarativeguard_p.h"
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeContext;
@@ -137,7 +139,8 @@ public:
QDeclarativeContextPrivate *asQDeclarativeContextPrivate();
quint32 isInternal:1;
quint32 ownedByParent:1; // unrelated to isInternal; parent context deletes children if true.
- quint32 dummy:30;
+ quint32 isJSContext:1;
+ quint32 dummy:29;
QDeclarativeContext *publicContext;
// Property name cache
@@ -147,7 +150,9 @@ public:
QObject *contextObject;
// Any script blocks that exist on this context
- QList<QScriptValue> importedScripts;
+ // XXX aakenned
+ QList<v8::Persistent<v8::Object> > importedScripts;
+// QList<QScriptValue> importedScripts;
// Context base url
QUrl url;
@@ -216,9 +221,10 @@ public:
inline QDeclarativeGuardedContextData(QDeclarativeContextData *);
inline ~QDeclarativeGuardedContextData();
+ inline QDeclarativeContextData *contextData();
inline void setContextData(QDeclarativeContextData *);
- inline QDeclarativeContextData *contextData();
+ inline bool isNull() const { return !m_contextData; }
inline operator QDeclarativeContextData*() const { return m_contextData; }
inline QDeclarativeContextData* operator->() const { return m_contextData; }
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
deleted file mode 100644
index 3abd78794a..0000000000
--- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp
+++ /dev/null
@@ -1,335 +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$
-** 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 "private/qdeclarativecontextscriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
-#include "private/qdeclarativeguard_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct ContextData : public QScriptDeclarativeClass::Object {
- ContextData() : overrideObject(0), isSharedContext(true) {}
- ContextData(QDeclarativeContextData *c, QObject *o)
- : context(c), scopeObject(o), overrideObject(0), isSharedContext(false), isUrlContext(false) {}
- QDeclarativeGuardedContextData context;
- QDeclarativeGuard<QObject> scopeObject;
- QObject *overrideObject;
- bool isSharedContext:1;
- bool isUrlContext:1;
-
- QDeclarativeContextData *getContext(QDeclarativeEngine *engine) {
- if (isSharedContext) {
- return QDeclarativeEnginePrivate::get(engine)->sharedContext;
- } else {
- return context.contextData();
- }
- }
-
- QObject *getScope(QDeclarativeEngine *engine) {
- if (isSharedContext) {
- return QDeclarativeEnginePrivate::get(engine)->sharedScope;
- } else {
- return scopeObject.data();
- }
- }
-};
-
-struct UrlContextData : public ContextData {
- UrlContextData(QDeclarativeContextData *c, QObject *o, const QString &u)
- : ContextData(c, o), url(u) {
- isUrlContext = true;
- }
- UrlContextData(const QString &u)
- : ContextData(0, 0), url(u) {
- isUrlContext = true;
- }
- QString url;
-};
-
-/*
- The QDeclarativeContextScriptClass handles property access for a QDeclarativeContext
- via QtScript.
- */
-QDeclarativeContextScriptClass::QDeclarativeContextScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
- lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1)
-{
-}
-
-QDeclarativeContextScriptClass::~QDeclarativeContextScriptClass()
-{
-}
-
-QScriptValue QDeclarativeContextScriptClass::newContext(QDeclarativeContextData *context, QObject *scopeObject)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new ContextData(context, scopeObject));
-}
-
-QScriptValue QDeclarativeContextScriptClass::newUrlContext(QDeclarativeContextData *context, QObject *scopeObject,
- const QString &url)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new UrlContextData(context, scopeObject, url));
-}
-
-QScriptValue QDeclarativeContextScriptClass::newUrlContext(const QString &url)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new UrlContextData(url));
-}
-
-QScriptValue QDeclarativeContextScriptClass::newSharedContext()
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new ContextData());
-}
-
-QDeclarativeContextData *QDeclarativeContextScriptClass::contextFromValue(const QScriptValue &v)
-{
- if (scriptClass(v) != this)
- return 0;
-
- ContextData *data = (ContextData *)object(v);
- return data->getContext(engine);
-}
-
-QUrl QDeclarativeContextScriptClass::urlFromValue(const QScriptValue &v)
-{
- if (scriptClass(v) != this)
- return QUrl();
-
- ContextData *data = (ContextData *)object(v);
- if (data->isUrlContext) {
- return QUrl(static_cast<UrlContextData *>(data)->url);
- } else {
- return QUrl();
- }
-}
-
-QObject *QDeclarativeContextScriptClass::setOverrideObject(QScriptValue &v, QObject *override)
-{
- if (scriptClass(v) != this)
- return 0;
-
- ContextData *data = (ContextData *)object(v);
- QObject *rv = data->overrideObject;
- data->overrideObject = override;
- return rv;
-}
-
-QScriptClass::QueryFlags
-QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(flags);
-
- lastScopeObject = 0;
- lastContext = 0;
- lastData = 0;
- lastPropertyIndex = -1;
-
- QDeclarativeContextData *bindContext = ((ContextData *)object)->getContext(engine);
- QObject *scopeObject = ((ContextData *)object)->getScope(engine);
- if (!bindContext)
- return 0;
-
- QObject *overrideObject = ((ContextData *)object)->overrideObject;
- if (overrideObject) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptClass::QueryFlags rv =
- ep->objectClass->queryProperty(overrideObject, name, flags, bindContext,
- QDeclarativeObjectScriptClass::ImplicitObject |
- QDeclarativeObjectScriptClass::SkipAttachedProperties);
- if (rv) {
- lastScopeObject = overrideObject;
- lastContext = bindContext;
- return rv;
- }
- }
-
- bool includeTypes = true;
- while (bindContext) {
- QScriptClass::QueryFlags rv =
- queryProperty(bindContext, scopeObject, name, flags, includeTypes);
- scopeObject = 0; // Only applies to the first context
- includeTypes = false; // Only applies to the first context
- if (rv) return rv;
- bindContext = bindContext->parent;
- }
-
- return 0;
-}
-
-QScriptClass::QueryFlags
-QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindContext, QObject *scopeObject,
- const Identifier &name,
- QScriptClass::QueryFlags flags,
- bool includeTypes)
-{
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- lastPropertyIndex = bindContext->propertyNames?bindContext->propertyNames->value(name):-1;
- if (lastPropertyIndex != -1) {
- lastContext = bindContext;
- return QScriptClass::HandlesReadAccess;
- }
-
- if (includeTypes && bindContext->imports) {
- QDeclarativeTypeNameCache::Data *data = bindContext->imports->data(name);
-
- if (data) {
- lastData = data;
- lastContext = bindContext;
- lastScopeObject = scopeObject;
- return QScriptClass::HandlesReadAccess;
- }
- }
-
- if (scopeObject) {
- QScriptClass::QueryFlags rv =
- ep->objectClass->queryProperty(scopeObject, name, flags, bindContext,
- QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
- if (rv) {
- lastScopeObject = scopeObject;
- lastContext = bindContext;
- return rv;
- }
- }
-
- if (bindContext->contextObject) {
- QScriptClass::QueryFlags rv =
- ep->objectClass->queryProperty(bindContext->contextObject, name, flags, bindContext,
- QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
-
- if (rv) {
- lastScopeObject = bindContext->contextObject;
- lastContext = bindContext;
- return rv;
- }
- }
-
- return 0;
-}
-
-QDeclarativeContextScriptClass::Value
-QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
-{
- Q_UNUSED(object);
-
- QDeclarativeContextData *bindContext = lastContext;
- Q_ASSERT(bindContext);
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (lastData) {
-
- if (lastData->type) {
- return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->type));
- } else if (lastData->typeNamespace) {
- return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->typeNamespace));
- } else {
- int index = lastData->importedScriptIndex;
- if (index < bindContext->importedScripts.count()) {
- return Value(scriptEngine, bindContext->importedScripts.at(index));
- } else {
- return Value();
- }
- }
-
- } else if (lastScopeObject) {
-
- return ep->objectClass->property(lastScopeObject, name);
-
- } else if (lastPropertyIndex != -1) {
-
- QScriptValue rv;
- if (lastPropertyIndex < bindContext->idValueCount) {
- rv = ep->objectClass->newQObject(bindContext->idValues[lastPropertyIndex].data());
-
- if (ep->captureProperties)
- ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(&bindContext->idValues[lastPropertyIndex].bindings);
- } else {
- QDeclarativeContextPrivate *cp = bindContext->asQDeclarativeContextPrivate();
- const QVariant &value = cp->propertyValues.at(lastPropertyIndex);
- if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
- rv = ep->listClass->newList(QDeclarativeListProperty<QObject>(bindContext->asQDeclarativeContext(), (void*)lastPropertyIndex, 0, QDeclarativeContextPrivate::context_count, QDeclarativeContextPrivate::context_at), qMetaTypeId<QDeclarativeListProperty<QObject> >());
- } else {
- rv = ep->scriptValueFromVariant(value);
- }
-
- if (ep->captureProperties)
- ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext->asQDeclarativeContext(), -1, lastPropertyIndex + cp->notifyIndex);
- }
-
- return Value(scriptEngine, rv);
-
- } else {
-
- return Value(scriptEngine, lastFunction);
-
- }
-}
-
-void QDeclarativeContextScriptClass::setProperty(Object *object, const Identifier &name,
- const QScriptValue &value)
-{
- Q_UNUSED(object);
- Q_ASSERT(lastScopeObject);
-
- QDeclarativeContextData *bindContext = lastContext;
- Q_ASSERT(bindContext);
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- ep->objectClass->setProperty(lastScopeObject, name, value, context(), bindContext);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h
index 33458dc2f4..2516f4a8e1 100644
--- a/src/declarative/qml/qdeclarativedata_p.h
+++ b/src/declarative/qml/qdeclarativedata_p.h
@@ -57,6 +57,8 @@
#include <private/qobject_p.h>
#include "private/qdeclarativeguard_p.h"
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeCompiledData;
@@ -76,8 +78,8 @@ public:
QDeclarativeData()
: ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0),
- bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0),
- scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), extendedData(0) {
+ bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), propertyCache(0),
+ guards(0), extendedData(0) {
init();
}
@@ -128,10 +130,7 @@ public:
QDeclarativeCompiledData *deferredComponent; // Can't this be found from the context?
unsigned int deferredIdx;
- // ### Can we make this QScriptValuePrivate so we incur no additional allocation
- // cost?
- QScriptValue *scriptValue;
- quint32 objectDataRefCount;
+ v8::Persistent<v8::Object> v8object;
QDeclarativePropertyCache *propertyCache;
QDeclarativeGuard<QObject> *guards;
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 073e1d4119..c4e9d0e432 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -44,7 +44,6 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativecompiler_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include "qdeclarative.h"
#include "qdeclarativecontext.h"
#include "qdeclarativeexpression.h"
@@ -55,9 +54,6 @@
#include "private/qdeclarativestringconverters_p.h"
#include "private/qdeclarativexmlhttprequest_p.h"
#include "private/qdeclarativesqldatabase_p.h"
-#include "private/qdeclarativescarceresourcescriptclass_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
#include "qdeclarativescriptstring.h"
#include "private/qdeclarativeglobal_p.h"
#include "private/qdeclarativeworkerscript_p.h"
@@ -68,13 +64,11 @@
#include "qdeclarativeextensioninterface.h"
#include "private/qdeclarativelist_p.h"
#include "private/qdeclarativetypenamecache_p.h"
-#include "private/qdeclarativeinclude_p.h"
#include "private/qdeclarativenotifier_p.h"
#include "private/qdeclarativedebugtrace_p.h"
#include "private/qdeclarativeapplication_p.h"
#include <QtCore/qmetaobject.h>
-#include <QScriptClass>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
@@ -343,16 +337,16 @@ The \c status property will be updated as the operation progresses.
If provided, \a callback is invoked when the operation completes. The callback is passed
the same object as is returned from the Qt.include() call.
*/
-// Qt.include() is implemented in qdeclarativeinclude.cpp
+// Qt.include() is implemented in qv8include.cpp
QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
: captureProperties(false), rootContext(0), isDebugging(false),
- outputWarningsToStdErr(true), contextClass(0), sharedContext(0), sharedScope(0),
- objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0),
- inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0),
- inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0),
- scarceResources(0), scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
+ outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
+ cleanup(0), erroredBindings(0), inProgressCreations(0), scriptEngine(this),
+ workerScriptEngine(0), componentAttached(0), inBeginCreate(false),
+ networkAccessManager(0), networkAccessManagerFactory(0),
+ scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
sgContext(0)
{
if (!qt_QmlQtModule_registered) {
@@ -363,102 +357,18 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
QSGItemsModule::defineModule();
QDeclarativeValueTypeFactory::registerValueTypes();
}
- globalClass = new QDeclarativeGlobalScriptClass(&scriptEngine);
-}
-
-/*!
- \qmlmethod url Qt::resolvedUrl(url url)
- Returns \a url resolved relative to the URL of the caller.
-*/
-QUrl QDeclarativeScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url)
-{
- if (p) {
- QDeclarativeContextData *ctxt = p->getContext(context);
- if (ctxt)
- return ctxt->resolvedUrl(url);
- else
- return p->getUrl(context).resolved(url);
- }
- return baseUrl.resolved(url);
}
QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *priv)
-: p(priv), sqlQueryClass(0), namedNodeMapClass(0), nodeListClass(0)
+: p(priv)
{
// Note that all documentation for stuff put on the global object goes in
// doc/src/declarative/globalobject.qdoc
- bool mainthread = priv != 0;
-
QScriptValue qtObject =
newQMetaObject(StaticQtMetaObject::get());
globalObject().setProperty(QLatin1String("Qt"), qtObject);
-#ifndef QT_NO_DESKTOPSERVICES
- offlineStoragePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation).replace(QLatin1Char('/'), QDir::separator())
- + QDir::separator() + QLatin1String("QML")
- + QDir::separator() + QLatin1String("OfflineStorage");
-#endif
-
-#ifndef QT_NO_XMLSTREAMREADER
- qt_add_qmlxmlhttprequest(this);
-#endif
- qt_add_qmlsqldatabase(this);
- // XXX A Multimedia "Qt.Sound" class also needs to be made available,
- // XXX but we don't want a dependency in that cirection.
- // XXX When the above a done some better way, that way should also be
- // XXX used to add Qt.Sound class.
-
- //types
- if (mainthread)
- qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::include, 2));
- else
- qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::worker_include, 2));
-
- qtObject.setProperty(QLatin1String("isQtObject"), newFunction(QDeclarativeEnginePrivate::isQtObject, 1));
- qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4));
- qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4));
- qtObject.setProperty(QLatin1String("rect"), newFunction(QDeclarativeEnginePrivate::rect, 4));
- qtObject.setProperty(QLatin1String("point"), newFunction(QDeclarativeEnginePrivate::point, 2));
- qtObject.setProperty(QLatin1String("size"), newFunction(QDeclarativeEnginePrivate::size, 2));
- qtObject.setProperty(QLatin1String("vector3d"), newFunction(QDeclarativeEnginePrivate::vector3d, 3));
-
- if (mainthread) {
- //color helpers
- qtObject.setProperty(QLatin1String("lighter"), newFunction(QDeclarativeEnginePrivate::lighter, 1));
- qtObject.setProperty(QLatin1String("darker"), newFunction(QDeclarativeEnginePrivate::darker, 1));
- qtObject.setProperty(QLatin1String("tint"), newFunction(QDeclarativeEnginePrivate::tint, 2));
- }
-
-#ifndef QT_NO_DATESTRING
- //date/time formatting
- qtObject.setProperty(QLatin1String("formatDate"),newFunction(QDeclarativeEnginePrivate::formatDate, 2));
- qtObject.setProperty(QLatin1String("formatTime"),newFunction(QDeclarativeEnginePrivate::formatTime, 2));
- qtObject.setProperty(QLatin1String("formatDateTime"),newFunction(QDeclarativeEnginePrivate::formatDateTime, 2));
-#endif
-
- //misc methods
- qtObject.setProperty(QLatin1String("openUrlExternally"),newFunction(QDeclarativeEnginePrivate::desktopOpenUrl, 1));
- qtObject.setProperty(QLatin1String("fontFamilies"),newFunction(QDeclarativeEnginePrivate::fontFamilies, 0));
- qtObject.setProperty(QLatin1String("md5"),newFunction(QDeclarativeEnginePrivate::md5, 1));
- qtObject.setProperty(QLatin1String("btoa"),newFunction(QDeclarativeEnginePrivate::btoa, 1));
- qtObject.setProperty(QLatin1String("atob"),newFunction(QDeclarativeEnginePrivate::atob, 1));
- qtObject.setProperty(QLatin1String("quit"), newFunction(QDeclarativeEnginePrivate::quit, 0));
- qtObject.setProperty(QLatin1String("resolvedUrl"),newFunction(QDeclarativeScriptEngine::resolvedUrl, 1));
-
- if (mainthread) {
- qtObject.setProperty(QLatin1String("createQmlObject"),
- newFunction(QDeclarativeEnginePrivate::createQmlObject, 1));
- qtObject.setProperty(QLatin1String("createComponent"),
- newFunction(QDeclarativeEnginePrivate::createComponent, 1));
- }
-
- //firebug/webkit compat
- QScriptValue consoleObject = newObject();
- consoleObject.setProperty(QLatin1String("log"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1));
- consoleObject.setProperty(QLatin1String("debug"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1));
- globalObject().setProperty(QLatin1String("console"), consoleObject);
-
// translation functions need to be installed
// before the global script class is constructed (QTBUG-6437)
installTranslatorFunctions();
@@ -466,16 +376,6 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr
QDeclarativeScriptEngine::~QDeclarativeScriptEngine()
{
- delete sqlQueryClass;
- delete nodeListClass;
- delete namedNodeMapClass;
-}
-
-QScriptValue QDeclarativeScriptEngine::resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine)
-{
- QString arg = ctxt->argument(0).toString();
- QUrl r = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt,QUrl(arg));
- return QScriptValue(r.toString());
}
QNetworkAccessManager *QDeclarativeScriptEngine::networkAccessManager()
@@ -500,20 +400,6 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
delete rootContext;
rootContext = 0;
- delete contextClass;
- contextClass = 0;
- delete objectClass;
- objectClass = 0;
- delete scarceResourceClass;
- scarceResourceClass = 0;
- delete valueTypeClass;
- valueTypeClass = 0;
- delete typeNameClass;
- typeNameClass = 0;
- delete listClass;
- listClass = 0;
- delete globalClass;
- globalClass = 0;
for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
(*iter)->release();
@@ -579,16 +465,10 @@ void QDeclarativeEnginePrivate::init()
QDeclarativeData::init();
- contextClass = new QDeclarativeContextScriptClass(q);
- objectClass = new QDeclarativeObjectScriptClass(q);
- scarceResourceClass = new QDeclarativeScarceResourceScriptClass(q);
- valueTypeClass = new QDeclarativeValueTypeScriptClass(q);
- typeNameClass = new QDeclarativeTypeNameScriptClass(q);
- listClass = new QDeclarativeListScriptClass(q);
- rootContext = new QDeclarativeContext(q,true);
+ // Init V8 data
+ v8engine.init(q);
- QScriptValue applicationObject = objectClass->newQObject(new QDeclarativeApplication(q));
- scriptEngine.globalObject().property(QLatin1String("Qt")).setProperty(QLatin1String("application"), applicationObject);
+ rootContext = new QDeclarativeContext(q,true);
if (QCoreApplication::instance()->thread() == q->thread() &&
QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
@@ -938,6 +818,15 @@ void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
}
/*!
+ Attempt to free unused memory.
+*/
+void QDeclarativeEngine::collectGarbage()
+{
+ v8::V8::LowMemoryNotification();
+ while (!v8::V8::IdleNotification()) {}
+}
+
+/*!
Returns the QDeclarativeContext for the \a object, or 0 if no
context has been set.
@@ -1186,19 +1075,19 @@ void QDeclarativeData::destroyed(QObject *object)
guard->objectDestroyed(object);
}
- if (scriptValue)
- delete scriptValue;
-
if (extendedData)
delete extendedData;
+ v8object.Dispose();
+
if (ownMemory)
delete this;
}
void QDeclarativeData::parentChanged(QObject *, QObject *parent)
{
- if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; }
+ // XXX aakenned
+// if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; }
}
void QDeclarativeData::objectNameChanged(QObject *)
@@ -1242,44 +1131,6 @@ void QDeclarativeData::setBindingBit(QObject *obj, int bit)
bindingBits[bit / 32] |= (1 << (bit % 32));
}
-/*!
- Creates a QScriptValue allowing you to use \a object in QML script.
- \a engine is the QDeclarativeEngine it is to be created in.
-
- The QScriptValue returned is a QtScript Object, not a QtScript QObject, due
- to the special needs of QML requiring more functionality than a standard
- QtScript QObject.
-*/
-QScriptValue QDeclarativeEnginePrivate::qmlScriptObject(QObject* object,
- QDeclarativeEngine* engine)
-{
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
- return enginePriv->objectClass->newQObject(object);
-}
-
-/*!
- Returns the QDeclarativeContext for the executing QScript \a ctxt.
-*/
-QDeclarativeContextData *QDeclarativeEnginePrivate::getContext(QScriptContext *ctxt)
-{
- QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
- Q_ASSERT(scopeNode.isValid());
- Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
- return contextClass->contextFromValue(scopeNode);
-}
-
-/*!
- Returns the QUrl associated with the script \a ctxt for the case that there is
- no QDeclarativeContext.
-*/
-QUrl QDeclarativeEnginePrivate::getUrl(QScriptContext *ctxt)
-{
- QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
- Q_ASSERT(scopeNode.isValid());
- Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
- return contextClass->urlFromValue(scopeNode);
-}
-
QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
{
if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
@@ -1290,651 +1141,6 @@ QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
return url.toLocalFile();
}
-/*!
-\qmlmethod object Qt::createComponent(url)
-
-Returns a \l Component object created using the QML file at the specified \a url,
-or \c null if an empty string was given.
-
-The returned component's \l Component::status property indicates whether the
-component was successfully created. If the status is \c Component.Error,
-see \l Component::errorString() for an error description.
-
-Call \l {Component::createObject()}{Component.createObject()} on the returned
-component to create an object instance of the component.
-
-For example:
-
-\snippet doc/src/snippets/declarative/createComponent-simple.qml 0
-
-See \l {Dynamic Object Management in QML} for more information on using this function.
-
-To create a QML object from an arbitrary string of QML (instead of a file),
-use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *activeEnginePriv =
- static_cast<QDeclarativeScriptEngine*>(engine)->p;
- QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
-
- if(ctxt->argumentCount() != 1) {
- return ctxt->throwError(QLatin1String("Qt.createComponent(): Invalid arguments"));
- } else {
-
- QString arg = ctxt->argument(0).toString();
- if (arg.isEmpty())
- return engine->nullValue();
- QUrl url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt, QUrl(arg));
- QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
- QDeclarativeComponent *c = new QDeclarativeComponent(activeEngine, url, activeEngine);
- QDeclarativeComponentPrivate::get(c)->creationContext = context;
- QDeclarativeData::get(c, true)->setImplicitDestructible();
- return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QDeclarativeComponent*>());
- }
-}
-
-/*!
-\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
-
-Returns a new object created from the given \a string of QML which will have the specified \a parent,
-or \c null if there was an error in creating the object.
-
-If \a filepath is specified, it will be used for error reporting for the created object.
-
-Example (where \c parentItem is the id of an existing QML item):
-
-\snippet doc/src/snippets/declarative/createQmlObject.qml 0
-
-In the case of an error, a QtScript Error object is thrown. This object has an additional property,
-\c qmlErrors, which is an array of the errors encountered.
-Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
-For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
-{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
-
-Note that this function returns immediately, and therefore may not work if
-the \a qml string loads new components (that is, external QML files that have not yet been loaded).
-If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
-
-See \l {Dynamic Object Management in QML} for more information on using this function.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *activeEnginePriv =
- static_cast<QDeclarativeScriptEngine*>(engine)->p;
- QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
-
- if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3)
- return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Invalid arguments"));
-
- QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
- Q_ASSERT(context);
-
- QString qml = ctxt->argument(0).toString();
- if (qml.isEmpty())
- return engine->nullValue();
-
- QUrl url;
- if(ctxt->argumentCount() > 2)
- url = QUrl(ctxt->argument(2).toString());
- else
- url = QUrl(QLatin1String("inline"));
-
- if (url.isValid() && url.isRelative())
- url = context->resolvedUrl(url);
-
- QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
- if(!parentArg)
- return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Missing parent object"));
-
- QDeclarativeComponent component(activeEngine);
- component.setData(qml.toUtf8(), url);
-
- if(component.isError()) {
- QList<QDeclarativeError> errors = component.errors();
- QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
- QScriptValue arr = ctxt->engine()->newArray(errors.length());
- int i = 0;
- foreach (const QDeclarativeError &error, errors){
- errstr += QLatin1String("\n ") + error.toString();
- QScriptValue qmlErrObject = ctxt->engine()->newObject();
- qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
- qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
- qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
- qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
- arr.setProperty(i++, qmlErrObject);
- }
- QScriptValue err = ctxt->throwError(errstr);
- err.setProperty(QLatin1String("qmlErrors"),arr);
- return err;
- }
-
- if (!component.isReady())
- return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Component is not ready"));
-
- QObject *obj = component.beginCreate(context->asQDeclarativeContext());
- if(obj)
- QDeclarativeData::get(obj, true)->setImplicitDestructible();
- component.completeCreate();
-
- if(component.isError()) {
- QList<QDeclarativeError> errors = component.errors();
- QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
- QScriptValue arr = ctxt->engine()->newArray(errors.length());
- int i = 0;
- foreach (const QDeclarativeError &error, errors){
- errstr += QLatin1String("\n ") + error.toString();
- QScriptValue qmlErrObject = ctxt->engine()->newObject();
- qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
- qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
- qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
- qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
- arr.setProperty(i++, qmlErrObject);
- }
- QScriptValue err = ctxt->throwError(errstr);
- err.setProperty(QLatin1String("qmlErrors"),arr);
- return err;
- }
-
- Q_ASSERT(obj);
-
- obj->setParent(parentArg);
-
- QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
- for (int ii = 0; ii < functions.count(); ++ii) {
- if (QDeclarativePrivate::Parented == functions.at(ii)(obj, parentArg))
- break;
- }
-
- QDeclarativeData::get(obj, true)->setImplicitDestructible();
- return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar);
-}
-
-/*!
-\qmlmethod bool Qt::isQtObject(object)
-Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
-*/
-QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if (ctxt->argumentCount() == 0)
- return QScriptValue(engine, false);
-
- return QScriptValue(engine, 0 != ctxt->argument(0).toQObject());
-}
-
-/*!
-\qmlmethod Qt::vector3d(real x, real y, real z)
-Returns a Vector3D with the specified \c x, \c y and \c z.
-*/
-QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 3)
- return ctxt->throwError(QLatin1String("Qt.vector(): Invalid arguments"));
- qsreal x = ctxt->argument(0).toNumber();
- qsreal y = ctxt->argument(1).toNumber();
- qsreal z = ctxt->argument(2).toNumber();
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QVector3D(x, y, z)));
-}
-
-/*!
-\qmlmethod string Qt::formatDate(datetime date, variant format)
-
-Returns a string representation of \c date, optionally formatted according
-to \c format.
-
-The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
-property, a QDate, or QDateTime value. The \a format parameter may be any of
-the possible format values as described for
-\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
-
-If \a format is not specified, \a date is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
-*/
-#ifndef QT_NO_DATESTRING
-QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount == 0 || argCount > 2)
- return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid arguments"));
-
- QDate date = ctxt->argument(0).toDateTime().date();
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- if (argCount == 2) {
- QScriptValue formatArg = ctxt->argument(1);
- if (formatArg.isString()) {
- QString format = formatArg.toString();
- return engine->newVariant(QVariant::fromValue(date.toString(format)));
- } else if (formatArg.isNumber()) {
- enumFormat = Qt::DateFormat(formatArg.toUInt32());
- } else {
- return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format"));
- }
- }
- return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
-}
-
-/*!
-\qmlmethod string Qt::formatTime(datetime time, variant format)
-
-Returns a string representation of \c time, optionally formatted according to
-\c format.
-
-The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
-value. The \a format parameter may be any of the possible format values as
-described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
-
-If \a format is not specified, \a time is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
-*/
-QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount == 0 || argCount > 2)
- return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid arguments"));
-
- QTime time;
- QScriptValue sv = ctxt->argument(0);
- if (sv.isDate())
- time = sv.toDateTime().time();
- else if (sv.toVariant().type() == QVariant::Time)
- time = sv.toVariant().toTime();
-
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- if (argCount == 2) {
- QScriptValue formatArg = ctxt->argument(1);
- if (formatArg.isString()) {
- QString format = formatArg.toString();
- return engine->newVariant(QVariant::fromValue(time.toString(format)));
- } else if (formatArg.isNumber()) {
- enumFormat = Qt::DateFormat(formatArg.toUInt32());
- } else {
- return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format"));
- }
- }
- return engine->newVariant(QVariant::fromValue(time.toString(enumFormat)));
-}
-
-/*!
-\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
-
-Returns a string representation of \c datetime, optionally formatted according to
-\c format.
-
-The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
-property, a QDate, QTime, or QDateTime value.
-
-If \a format is not provided, \a dateTime is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
-\a format should be either.
-
-\list
-\o One of the Qt::DateFormat enumeration values, such as
- \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
-\o A string that specifies the format of the returned string, as detailed below.
-\endlist
-
-If \a format specifies a format string, it should use the following expressions
-to specify the date:
-
- \table
- \header \i Expression \i Output
- \row \i d \i the day as number without a leading zero (1 to 31)
- \row \i dd \i the day as number with a leading zero (01 to 31)
- \row \i ddd
- \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
- Uses QDate::shortDayName().
- \row \i dddd
- \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
- Uses QDate::longDayName().
- \row \i M \i the month as number without a leading zero (1-12)
- \row \i MM \i the month as number with a leading zero (01-12)
- \row \i MMM
- \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
- Uses QDate::shortMonthName().
- \row \i MMMM
- \i the long localized month name (e.g. 'January' to 'December').
- Uses QDate::longMonthName().
- \row \i yy \i the year as two digit number (00-99)
- \row \i yyyy \i the year as four digit number
- \endtable
-
-In addition the following expressions can be used to specify the time:
-
- \table
- \header \i Expression \i Output
- \row \i h
- \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
- \row \i hh
- \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
- \row \i m \i the minute without a leading zero (0 to 59)
- \row \i mm \i the minute with a leading zero (00 to 59)
- \row \i s \i the second without a leading zero (0 to 59)
- \row \i ss \i the second with a leading zero (00 to 59)
- \row \i z \i the milliseconds without leading zeroes (0 to 999)
- \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
- \row \i AP
- \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
- \row \i ap
- \i use am/pm display. \e ap will be replaced by either "am" or "pm".
- \endtable
-
- All other input characters will be ignored. Any sequence of characters that
- are enclosed in single quotes will be treated as text and not be used as an
- expression. Two consecutive single quotes ("''") are replaced by a single quote
- in the output.
-
-For example, if the following date/time value was specified:
-
- \code
- // 21 May 2001 14:13:09
- var dateTime = new Date(2001, 5, 21, 14, 13, 09)
- \endcode
-
-This \a dateTime value could be passed to \c Qt.formatDateTime(),
-\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
-with the \a format values below to produce the following results:
-
- \table
- \header \i Format \i Result
- \row \i "dd.MM.yyyy" \i 21.05.2001
- \row \i "ddd MMMM d yy" \i Tue May 21 01
- \row \i "hh:mm:ss.zzz" \i 14:13:09.042
- \row \i "h:m:s ap" \i 2:13:9 pm
- \endtable
-*/
-QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount == 0 || argCount > 2)
- return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid arguments"));
-
- QDateTime date = ctxt->argument(0).toDateTime();
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- if (argCount == 2) {
- QScriptValue formatArg = ctxt->argument(1);
- if (formatArg.isString()) {
- QString format = formatArg.toString();
- return engine->newVariant(QVariant::fromValue(date.toString(format)));
- } else if (formatArg.isNumber()) {
- enumFormat = Qt::DateFormat(formatArg.toUInt32());
- } else {
- return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format"));
- }
- }
- return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
-}
-#endif // QT_NO_DATESTRING
-
-/*!
-\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
-
-Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
-All components should be in the range 0-1 inclusive.
-*/
-QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount < 3 || argCount > 4)
- return ctxt->throwError(QLatin1String("Qt.rgba(): Invalid arguments"));
- qsreal r = ctxt->argument(0).toNumber();
- qsreal g = ctxt->argument(1).toNumber();
- qsreal b = ctxt->argument(2).toNumber();
- qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
-
- if (r < 0.0) r=0.0;
- if (r > 1.0) r=1.0;
- if (g < 0.0) g=0.0;
- if (g > 1.0) g=1.0;
- if (b < 0.0) b=0.0;
- if (b > 1.0) b=1.0;
- if (a < 0.0) a=0.0;
- if (a > 1.0) a=1.0;
-
- return engine->toScriptValue(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
-}
-
-/*!
-\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
-
-Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
-All components should be in the range 0-1 inclusive.
-*/
-QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine *engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount < 3 || argCount > 4)
- return ctxt->throwError(QLatin1String("Qt.hsla(): Invalid arguments"));
- qsreal h = ctxt->argument(0).toNumber();
- qsreal s = ctxt->argument(1).toNumber();
- qsreal l = ctxt->argument(2).toNumber();
- qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
-
- if (h < 0.0) h=0.0;
- if (h > 1.0) h=1.0;
- if (s < 0.0) s=0.0;
- if (s > 1.0) s=1.0;
- if (l < 0.0) l=0.0;
- if (l > 1.0) l=1.0;
- if (a < 0.0) a=0.0;
- if (a > 1.0) a=1.0;
-
- return engine->toScriptValue(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
-}
-
-/*!
-\qmlmethod rect Qt::rect(int x, int y, int width, int height)
-
-Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
-
-The returned object has \c x, \c y, \c width and \c height attributes with the given values.
-*/
-QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 4)
- return ctxt->throwError(QLatin1String("Qt.rect(): Invalid arguments"));
-
- qsreal x = ctxt->argument(0).toNumber();
- qsreal y = ctxt->argument(1).toNumber();
- qsreal w = ctxt->argument(2).toNumber();
- qsreal h = ctxt->argument(3).toNumber();
-
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
-}
-
-/*!
-\qmlmethod point Qt::point(int x, int y)
-Returns a Point with the specified \c x and \c y coordinates.
-*/
-QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments"));
- qsreal x = ctxt->argument(0).toNumber();
- qsreal y = ctxt->argument(1).toNumber();
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y)));
-}
-
-/*!
-\qmlmethod Qt::size(int width, int height)
-Returns a Size with the specified \c width and \c height.
-*/
-QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments"));
- qsreal w = ctxt->argument(0).toNumber();
- qsreal h = ctxt->argument(1).toNumber();
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h)));
-}
-
-/*!
-\qmlmethod color Qt::lighter(color baseColor, real factor)
-Returns a color lighter than \c baseColor by the \c factor provided.
-
-If the factor is greater than 1.0, this functions returns a lighter color.
-Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
-the return color is darker, but we recommend using the Qt.darker() function for this purpose.
-If the factor is 0 or negative, the return value is unspecified.
-
-The function converts the current RGB color to HSV, multiplies the value (V) component
-by factor and converts the color back to RGB.
-
-If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
-*/
-QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.lighter(): Invalid arguments"));
- QVariant v = ctxt->argument(0).toVariant();
- QColor color;
- if (v.userType() == QVariant::Color)
- color = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
- qsreal factor = 1.5;
- if (ctxt->argumentCount() == 2)
- factor = ctxt->argument(1).toNumber();
- color = color.lighter(int(qRound(factor*100.)));
- return engine->toScriptValue(QVariant::fromValue(color));
-}
-
-/*!
-\qmlmethod color Qt::darker(color baseColor, real factor)
-Returns a color darker than \c baseColor by the \c factor provided.
-
-If the factor is greater than 1.0, this function returns a darker color.
-Setting factor to 3.0 returns a color that has one-third the brightness.
-If the factor is less than 1.0, the return color is lighter, but we recommend using
-the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
-value is unspecified.
-
-The function converts the current RGB color to HSV, divides the value (V) component
-by factor and converts the color back to RGB.
-
-If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
-*/
-QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.darker(): Invalid arguments"));
- QVariant v = ctxt->argument(0).toVariant();
- QColor color;
- if (v.userType() == QVariant::Color)
- color = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
- qsreal factor = 2.0;
- if (ctxt->argumentCount() == 2)
- factor = ctxt->argument(1).toNumber();
- color = color.darker(int(qRound(factor*100.)));
- return engine->toScriptValue(QVariant::fromValue(color));
-}
-
-/*!
-\qmlmethod bool Qt::openUrlExternally(url target)
-Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
-*/
-QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
-{
- if(ctxt->argumentCount() < 1)
- return QScriptValue(e, false);
- bool ret = false;
-#ifndef QT_NO_DESKTOPSERVICES
- ret = QDesktopServices::openUrl(QDeclarativeScriptEngine::get(e)->resolvedUrl(ctxt, QUrl(ctxt->argument(0).toString())));
-#endif
- return QScriptValue(e, ret);
-}
-
-/*!
-\qmlmethod list<string> Qt::fontFamilies()
-Returns a list of the font families available to the application.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::fontFamilies(QScriptContext *ctxt, QScriptEngine *e)
-{
- if(ctxt->argumentCount() != 0)
- return ctxt->throwError(QLatin1String("Qt.fontFamilies(): Invalid arguments"));
-
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(e);
- QFontDatabase database;
- return p->scriptValueFromVariant(database.families());
-}
-
-/*!
-\qmlmethod string Qt::md5(data)
-Returns a hex string of the md5 hash of \c data.
-*/
-QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *)
-{
- if (ctxt->argumentCount() != 1)
- return ctxt->throwError(QLatin1String("Qt.md5(): Invalid arguments"));
-
- QByteArray data = ctxt->argument(0).toString().toUtf8();
- QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
-
- return QScriptValue(QLatin1String(result.toHex()));
-}
-
-/*!
-\qmlmethod string Qt::btoa(data)
-Binary to ASCII - this function returns a base64 encoding of \c data.
-*/
-QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
-{
- if (ctxt->argumentCount() != 1)
- return ctxt->throwError(QLatin1String("Qt.btoa(): Invalid arguments"));
-
- QByteArray data = ctxt->argument(0).toString().toUtf8();
-
- return QScriptValue(QLatin1String(data.toBase64()));
-}
-
-/*!
-\qmlmethod string Qt::atob(data)
-ASCII to binary - this function returns a base64 decoding of \c data.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
-{
- if (ctxt->argumentCount() != 1)
- return ctxt->throwError(QLatin1String("Qt.atob(): Invalid arguments"));
-
- QByteArray data = ctxt->argument(0).toString().toUtf8();
-
- return QScriptValue(QLatin1String(QByteArray::fromBase64(data)));
-}
-
-QScriptValue QDeclarativeEnginePrivate::consoleLog(QScriptContext *ctxt, QScriptEngine *e)
-{
- if(ctxt->argumentCount() < 1)
- return e->newVariant(QVariant(false));
-
- QByteArray msg;
-
- for (int i=0; i<ctxt->argumentCount(); ++i) {
- if (!msg.isEmpty()) msg += ' ';
- msg += ctxt->argument(i).toString().toLocal8Bit();
- // does not support firebug "%[a-z]" formatting, since firebug really
- // does just ignore the format letter, which makes it pointless.
- }
-
- qDebug("%s",msg.constData());
-
- return e->newVariant(QVariant(true));
-}
-
void QDeclarativeEnginePrivate::sendQuit()
{
Q_Q(QDeclarativeEngine);
@@ -2003,145 +1209,6 @@ void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const
dumpwarning(error);
}
-/*!
-\qmlmethod Qt::quit()
-This function causes the QDeclarativeEngine::quit() signal to be emitted.
-Within the \l {QML Viewer}, this causes the launcher application to exit;
-to quit a C++ application when this method is called, connect the
-QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
-{
- QDeclarativeEnginePrivate *qe = get (e);
- qe->sendQuit();
- return QScriptValue();
-}
-
-/*!
- \qmlmethod color Qt::tint(color baseColor, color tintColor)
- This function allows tinting one color with another.
-
- The tint color should usually be mostly transparent, or you will not be
- able to see the underlying color. The below example provides a slight red
- tint by having the tint color be pure red which is only 1/16th opaque.
-
- \qml
- Item {
- Rectangle {
- x: 0; width: 80; height: 80
- color: "lightsteelblue"
- }
- Rectangle {
- x: 100; width: 80; height: 80
- color: Qt.tint("lightsteelblue", "#10FF0000")
- }
- }
- \endqml
- \image declarative-rect_tint.png
-
- Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
-*/
-QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.tint(): Invalid arguments"));
- //get color
- QVariant v = ctxt->argument(0).toVariant();
- QColor color;
- if (v.userType() == QVariant::Color)
- color = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
-
- //get tint color
- v = ctxt->argument(1).toVariant();
- QColor tintColor;
- if (v.userType() == QVariant::Color)
- tintColor = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
-
- //tint
- QColor finalColor;
- int a = tintColor.alpha();
- if (a == 0xFF)
- finalColor = tintColor;
- else if (a == 0x00)
- finalColor = color;
- else {
- qreal a = tintColor.alphaF();
- qreal inv_a = 1.0 - a;
-
- finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
- tintColor.greenF() * a + color.greenF() * inv_a,
- tintColor.blueF() * a + color.blueF() * inv_a,
- a + inv_a * color.alphaF());
- }
-
- return engine->toScriptValue(QVariant::fromValue(finalColor));
-}
-
-QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)
-{
- if (variantIsScarceResource(val)) {
- return scarceResourceClass->newScarceResource(val);
- } else if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) {
- QDeclarativeListReferencePrivate *p =
- QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData());
- if (p->object) {
- return listClass->newList(p->property, p->propertyType);
- } else {
- return scriptEngine.nullValue();
- }
- } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) {
- const QList<QObject *> &list = *(QList<QObject *>*)val.constData();
- QScriptValue rv = scriptEngine.newArray(list.count());
- for (int ii = 0; ii < list.count(); ++ii) {
- QObject *object = list.at(ii);
- rv.setProperty(ii, objectClass->newQObject(object));
- }
- return rv;
- } else if (QDeclarativeValueType *vt = valueTypes[val.userType()]) {
- return valueTypeClass->newObject(val, vt);
- }
-
- bool objOk;
- QObject *obj = QDeclarativeMetaType::toQObject(val, &objOk);
- if (objOk) {
- return objectClass->newQObject(obj);
- } else {
- return scriptEngine.toScriptValue(val);
- }
-}
-
-/*
- If the variant is a scarce resource (consumes a large amount of memory, or
- only a limited number of them can be held in memory at any given time without
- exhausting supply for future use) we need to release the scarce resource
- after evaluation of the javascript binding is complete.
- */
-bool QDeclarativeEnginePrivate::variantIsScarceResource(const QVariant& val)
-{
- if (val.type() == QVariant::Pixmap) {
- return true;
- } else if (val.type() == QVariant::Image) {
- return true;
- }
-
- return false;
-}
-
/*
This function should be called prior to evaluation of any js expression,
so that scarce resources are not freed prematurely (eg, if there is a
@@ -2169,45 +1236,13 @@ void QDeclarativeEnginePrivate::dereferenceScarceResources()
// note that the actual SRD is owned by the JS engine,
// so we cannot delete the SRD; but we can free the
// memory used by the variant in the SRD.
- ScarceResourceData *srd = 0;
- while (scarceResources) {
- srd = scarceResources; // srd points to the "old" (current) head of the list
- scarceResources = srd->next; // srd->next is the "new" head of the list
- if (srd->next) srd->next->prev = &scarceResources; // newHead->prev = listptr.
- srd->next = 0;
- srd->prev = 0;
- srd->releaseResource(); // release the old head node.
+ while (ScarceResourceData *sr = scarceResources.first()) {
+ sr->data = QVariant();
+ scarceResources.remove(sr);
}
}
}
-QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint)
-{
- QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
- if (dc == objectClass)
- return QVariant::fromValue(objectClass->toQObject(val));
- else if (dc == scarceResourceClass)
- return scarceResourceClass->toVariant(val);
- else if (dc == valueTypeClass)
- return valueTypeClass->toVariant(val);
- else if (dc == contextClass)
- return QVariant();
-
- // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted
- if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) {
- QList<QObject *> list;
- int length = val.property(QLatin1String("length")).toInt32();
- for (int ii = 0; ii < length; ++ii) {
- QScriptValue arrayItem = val.property(ii);
- QObject *d = arrayItem.toQObject();
- list << d;
- }
- return QVariant::fromValue(list);
- }
-
- return val.toVariant();
-}
-
/*!
Adds \a path as a directory where the engine searches for
installed modules in a URL-based directory structure.
@@ -2311,7 +1346,6 @@ void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
d->importDatabase.setPluginPathList(paths);
}
-
/*!
Imports the plugin named \a filePath with the \a uri provided.
Returns true if the plugin was successfully imported; otherwise returns false.
@@ -2371,13 +1405,13 @@ bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &ur
void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
{
Q_D(QDeclarativeEngine);
- d->scriptEngine.offlineStoragePath = dir;
+ qt_qmlsqldatabase_setOfflineStoragePath(&d->v8engine, dir);
}
QString QDeclarativeEngine::offlineStoragePath() const
{
Q_D(const QDeclarativeEngine);
- return d->scriptEngine.offlineStoragePath;
+ return qt_qmlsqldatabase_getOfflineStoragePath(&d->v8engine);
}
static void voidptr_destructor(void *v)
diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h
index 8db3db8096..4f1ecdc8f1 100644
--- a/src/declarative/qml/qdeclarativeengine.h
+++ b/src/declarative/qml/qdeclarativeengine.h
@@ -107,6 +107,8 @@ public:
bool outputWarningsToStandardError() const;
void setOutputWarningsToStandardError(bool);
+ void collectGarbage();
+
static QDeclarativeContext *contextForObject(const QObject *);
static void setContextForObject(QObject *, QDeclarativeContext *);
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index fadedf41dd..f3943db454 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -66,14 +66,10 @@
#include "qdeclarativeimageprovider.h"
#include "private/qdeclarativeproperty_p.h"
#include "private/qdeclarativepropertycache_p.h"
-#include "private/qdeclarativeobjectscriptclass_p.h"
-#include "private/qdeclarativescarceresourcescriptclass_p.h"
-#include "private/qdeclarativecontextscriptclass_p.h"
-#include "private/qdeclarativevaluetypescriptclass_p.h"
#include "private/qdeclarativemetatype_p.h"
#include "private/qdeclarativedirparser_p.h"
+#include "private/qintrusivelist_p.h"
-#include <QtScript/QScriptClass>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptString>
#include <QtCore/qstring.h>
@@ -85,33 +81,27 @@
#include <private/qobject_p.h>
+#include <private/qv8engine_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeContext;
class QDeclarativeEngine;
class QDeclarativeContextPrivate;
class QDeclarativeExpression;
-class QDeclarativeContextScriptClass;
class QDeclarativeImportDatabase;
-class QDeclarativeObjectScriptClass;
-class QDeclarativeScarceResourceScriptClass;
class ScarceResourceData;
-class QDeclarativeTypeNameScriptClass;
-class QDeclarativeValueTypeScriptClass;
class QScriptEngineDebugger;
class QNetworkReply;
class QNetworkAccessManager;
class QDeclarativeNetworkAccessManagerFactory;
class QDeclarativeAbstractBinding;
class QScriptDeclarativeClass;
-class QDeclarativeTypeNameScriptClass;
class QDeclarativeTypeNameCache;
class QDeclarativeComponentAttached;
-class QDeclarativeListScriptClass;
class QDeclarativeCleanup;
class QDeclarativeDelayedError;
class QDeclarativeWorkerScriptEngine;
-class QDeclarativeGlobalScriptClass;
class QDir;
class QSGTexture;
class QSGContext;
@@ -122,21 +112,10 @@ public:
QDeclarativeScriptEngine(QDeclarativeEnginePrivate *priv);
virtual ~QDeclarativeScriptEngine();
- QUrl resolvedUrl(QScriptContext *context, const QUrl& url); // resolved against p's context, or baseUrl if no p
- static QScriptValue resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine);
-
static QDeclarativeScriptEngine *get(QScriptEngine* e) { return static_cast<QDeclarativeScriptEngine*>(e); }
QDeclarativeEnginePrivate *p;
- // User by SQL API
- QScriptClass *sqlQueryClass;
- QString offlineStoragePath;
-
- // Used by DOM Core 3 API
- QScriptClass *namedNodeMapClass;
- QScriptClass *nodeListClass;
-
QUrl baseUrl;
virtual QNetworkAccessManager *networkAccessManager();
@@ -170,16 +149,8 @@ public:
bool outputWarningsToStdErr;
- QDeclarativeContextScriptClass *contextClass;
QDeclarativeContextData *sharedContext;
QObject *sharedScope;
- QDeclarativeObjectScriptClass *objectClass;
- QDeclarativeScarceResourceScriptClass *scarceResourceClass;
- QDeclarativeValueTypeScriptClass *valueTypeClass;
- QDeclarativeTypeNameScriptClass *typeNameClass;
- QDeclarativeListScriptClass *listClass;
- // Global script class
- QDeclarativeGlobalScriptClass *globalClass;
// Registered cleanup handlers
QDeclarativeCleanup *cleanup;
@@ -188,6 +159,9 @@ public:
QDeclarativeDelayedError *erroredBindings;
int inProgressCreations;
+ // V8 Engine
+ QV8Engine v8engine;
+
QDeclarativeScriptEngine scriptEngine;
QDeclarativeWorkerScriptEngine *getWorkerScriptEngine();
@@ -243,15 +217,20 @@ public:
QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
- /*
- A scarce resource (like a large pixmap or texture) will be cached in a
- JavaScript wrapper object when accessed in a binding or other js expression.
- We need some way to automatically release that scarce resource prior to normal
- garbage collection (unless the user explicitly preserves the resource).
- */
- ScarceResourceData* scarceResources;
+ // Scarce resources are "exceptionally high cost" QVariant types where allowing the
+ // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
+ // out-of-resource situations. When such a resource is passed into JavaScript we
+ // add it to the scarceResources list and it is destroyed when we return from the
+ // JavaScript execution that created it. The user can prevent this behavior by
+ // calling preserve() on the object which removes it from this scarceResource list.
+ class ScarceResourceData {
+ public:
+ ScarceResourceData(const QVariant &data) : data(data) {}
+ QVariant data;
+ QIntrusiveListNode node;
+ };
+ QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
int scarceResourcesRefCount;
- static bool variantIsScarceResource(const QVariant& val);
void referenceScarceResources();
void dereferenceScarceResources();
@@ -291,9 +270,6 @@ public:
QHash<int, int> m_qmlLists;
QHash<int, QDeclarativeCompiledData *> m_compositeTypes;
- QScriptValue scriptValueFromVariant(const QVariant &);
- QVariant scriptValueToVariant(const QScriptValue &, int hint = QVariant::Invalid);
-
void sendQuit();
void warning(const QDeclarativeError &);
void warning(const QList<QDeclarativeError> &);
@@ -302,35 +278,6 @@ public:
static void warning(QDeclarativeEnginePrivate *, const QDeclarativeError &);
static void warning(QDeclarativeEnginePrivate *, const QList<QDeclarativeError> &);
- static QScriptValue qmlScriptObject(QObject*, QDeclarativeEngine*);
-
- static QScriptValue createComponent(QScriptContext*, QScriptEngine*);
- static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*);
- static QScriptValue isQtObject(QScriptContext*, QScriptEngine*);
- static QScriptValue vector3d(QScriptContext*, QScriptEngine*);
- static QScriptValue rgba(QScriptContext*, QScriptEngine*);
- static QScriptValue hsla(QScriptContext*, QScriptEngine*);
- static QScriptValue point(QScriptContext*, QScriptEngine*);
- static QScriptValue size(QScriptContext*, QScriptEngine*);
- static QScriptValue rect(QScriptContext*, QScriptEngine*);
-
- static QScriptValue lighter(QScriptContext*, QScriptEngine*);
- static QScriptValue darker(QScriptContext*, QScriptEngine*);
- static QScriptValue tint(QScriptContext*, QScriptEngine*);
-
- static QScriptValue desktopOpenUrl(QScriptContext*, QScriptEngine*);
- static QScriptValue fontFamilies(QScriptContext*, QScriptEngine*);
- static QScriptValue md5(QScriptContext*, QScriptEngine*);
- static QScriptValue btoa(QScriptContext*, QScriptEngine*);
- static QScriptValue atob(QScriptContext*, QScriptEngine*);
- static QScriptValue consoleLog(QScriptContext*, QScriptEngine*);
- static QScriptValue quit(QScriptContext*, QScriptEngine*);
-
-#ifndef QT_NO_DATESTRING
- static QScriptValue formatDate(QScriptContext*, QScriptEngine*);
- static QScriptValue formatTime(QScriptContext*, QScriptEngine*);
- static QScriptValue formatDateTime(QScriptContext*, QScriptEngine*);
-#endif
static QScriptEngine *getScriptEngine(QDeclarativeEngine *e) { return &e->d_func()->scriptEngine; }
static QDeclarativeEngine *getEngine(QScriptEngine *e) { return static_cast<QDeclarativeScriptEngine*>(e)->p->q_func(); }
static QDeclarativeEnginePrivate *get(QDeclarativeEngine *e) { return e->d_func(); }
@@ -338,8 +285,6 @@ public:
static QDeclarativeEnginePrivate *get(QDeclarativeContextData *c) { return (c && c->engine) ? QDeclarativeEnginePrivate::get(c->engine) : 0; }
static QDeclarativeEnginePrivate *get(QScriptEngine *e) { return static_cast<QDeclarativeScriptEngine*>(e)->p; }
static QDeclarativeEngine *get(QDeclarativeEnginePrivate *p) { return p->q_func(); }
- QDeclarativeContextData *getContext(QScriptContext *);
- QUrl getUrl(QScriptContext *);
static QString urlToLocalFileOrQrc(const QUrl& url);
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index afd1be1025..a210e4e1d7 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -46,7 +46,6 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativerewrite_p.h"
#include "private/qdeclarativecompiler_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include <QtCore/qdebug.h>
#include <QtScript/qscriptprogram.h>
@@ -79,6 +78,11 @@ QDeclarativeQtScriptExpression::QDeclarativeQtScriptExpression()
QDeclarativeQtScriptExpression::~QDeclarativeQtScriptExpression()
{
+ v8function.Dispose();
+ v8qmlscope.Dispose();
+ v8function = v8::Persistent<v8::Function>();
+ v8qmlscope = v8::Persistent<v8::Function>();
+
if (guardList) { delete [] guardList; guardList = 0; }
if (dataRef) dataRef->release();
if (deleted) *deleted = true;
@@ -103,15 +107,16 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QS
expressionFunctionValid = false;
}
-void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QScriptValue &func,
+void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, v8::Handle<v8::Function> func,
QObject *me)
{
- expression = func.toString();
+ // XXX aakenned
+ // expression = func.toString();
QDeclarativeAbstractExpression::setContext(ctxt);
scopeObject = me;
- expressionFunction = func;
+ v8function = v8::Persistent<v8::Function>::New(func);
expressionFunctionMode = ExplicitContext;
expressionFunctionValid = true;
}
@@ -123,7 +128,8 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex
url = srcUrl;
line = lineNumber;
- if (dataRef) dataRef->release();
+ Q_ASSERT(!dataRef);
+
dataRef = rc;
if (dataRef) dataRef->addref();
@@ -136,45 +142,42 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex
bool isSharedProgram = progIdx & 0x80000000;
progIdx &= 0x7FFFFFFF;
- QDeclarativeEngine *engine = ctxt->engine;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (isSharedProgram) {
-
- if (!dd->cachedClosures.at(progIdx)) {
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- scriptContext->pushScope(ep->contextClass->newSharedContext());
- scriptContext->pushScope(ep->globalClass->staticGlobalObject());
- dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(expression, url, line));
- scriptEngine->popContext();
- }
-
- expressionFunction = *dd->cachedClosures.at(progIdx);
- expressionFunctionMode = SharedContext;
- expressionFunctionValid = true;
+ v8function = evalFunction(ctxt, me, expression, url, line, &v8qmlscope);
- } else {
+ expressionFunctionMode = ExplicitContext;
+ expressionFunctionValid = true;
- if (!dd->cachedPrograms.at(progIdx)) {
- dd->cachedPrograms[progIdx] = new QScriptProgram(expression, url, line);
- }
+ QDeclarativeAbstractExpression::setContext(ctxt);
+ scopeObject = me;
+}
- expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx),
- &expressionContext);
+// Callee owns the persistent handle
+v8::Persistent<v8::Function>
+QDeclarativeExpressionPrivate::evalFunction(QDeclarativeContextData *ctxt, QObject *scope,
+ const QString &code, const QString &filename, int line,
+ v8::Persistent<v8::Object> *qmlscope)
+{
+ QDeclarativeEngine *engine = ctxt->engine;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- expressionFunctionMode = ExplicitContext;
- expressionFunctionValid = true;
- }
+ // XXX aakenned optimize
+ v8::HandleScope handle_scope;
+ v8::Context::Scope ctxtscope(ep->v8engine.context());
+
+ // XXX try/catch?
- QDeclarativeAbstractExpression::setContext(ctxt);
- scopeObject = me;
+ v8::Local<v8::Object> scopeobject = ep->v8engine.qmlScope(ctxt, scope);
+ v8::Local<v8::Script> script = ep->v8engine.qmlModeCompile(code, filename, line);
+ v8::Local<v8::Value> result = script->Run(scopeobject);
+ if (qmlscope) *qmlscope = v8::Persistent<v8::Object>::New(scopeobject);
+ return v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(result));
}
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object,
const QString &program, const QString &fileName,
int lineNumber, QScriptValue *contextObject)
{
+#if 0
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
if (contextObject) {
@@ -187,12 +190,16 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex
QScriptValue rv = ep->scriptEngine.evaluate(program, fileName, lineNumber);
ep->scriptEngine.popContext();
return rv;
+#else
+ qFatal("Not impl");
+#endif
}
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object,
const QScriptProgram &program,
QScriptValue *contextObject)
{
+#if 0
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
if (contextObject) {
@@ -205,6 +212,9 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex
QScriptValue rv = ep->scriptEngine.evaluate(program);
ep->scriptEngine.popContext();
return rv;
+#else
+ qFatal("Not impl");
+#endif
}
/*!
@@ -317,16 +327,26 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
-/*! \internal */
-QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, const QScriptValue &func,
+/*!
+ \internal
+
+ To avoid exposing v8 in the public API, functionPtr must be a pointer to a v8::Handle<v8::Function>.
+ For example:
+ v8::Handle<v8::Function> function;
+ new QDeclarativeExpression(ctxt, scope, &function, ...);
+ */
+QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, void *functionPtr,
QDeclarativeExpressionPrivate &dd)
: QObject(dd, 0)
{
+ v8::Handle<v8::Function> function = *(v8::Handle<v8::Function> *)functionPtr;
+
Q_D(QDeclarativeExpression);
- d->init(ctxt, func, scope);
+ d->init(ctxt, function, scope);
if (QDeclarativeExpression_notifyIdx == -1)
QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
+
d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
@@ -377,34 +397,43 @@ void QDeclarativeExpression::setExpression(const QString &expression)
d->resetNotifyOnChange();
d->expression = expression;
d->expressionFunctionValid = false;
- d->expressionFunction = QScriptValue();
+ d->v8function.Dispose();
+ d->v8qmlscope.Dispose();
+ d->v8function = v8::Persistent<v8::Function>();
+ d->v8qmlscope = v8::Persistent<v8::Function>();
}
-void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
- QDeclarativeError &error)
+void QDeclarativeExpressionPrivate::exceptionToError(v8::Handle<v8::Message> message,
+ QDeclarativeError &error)
{
- if (scriptEngine->hasUncaughtException() &&
- scriptEngine->uncaughtException().isError()) {
+ Q_ASSERT(!message.IsEmpty());
- QString fileName;
- int lineNumber = scriptEngine->uncaughtExceptionLineNumber();
+ v8::Handle<v8::Value> name = message->GetScriptResourceName();
+ v8::Handle<v8::String> description = message->Get();
+ int lineNumber = message->GetLineNumber();
- QScriptValue exception = scriptEngine->uncaughtException();
- QLatin1String fileNameProp("fileName");
+ Q_ASSERT(name->IsString());
- if (!exception.property(fileNameProp).toString().isEmpty()){
- fileName = exception.property(fileNameProp).toString();
- } else {
- fileName = QLatin1String("<Unknown File>");
- }
+ v8::Local<v8::String> file = name->ToString();
+ if (file->Length() == 0)
+ error.setUrl(QUrl(QLatin1String("<Unknown File>")));
+ else
+ error.setUrl(QUrl(QV8Engine::toStringStatic(file)));
- error.setUrl(QUrl(fileName));
- error.setLine(lineNumber);
- error.setColumn(-1);
- error.setDescription(exception.toString());
- } else {
- error = QDeclarativeError();
- }
+ error.setLine(lineNumber);
+ error.setColumn(-1);
+
+ QString qDescription = QV8Engine::toStringStatic(description);
+ if (qDescription.startsWith(QLatin1String("Uncaught ")))
+ qDescription = qDescription.mid(9 /* strlen("Uncaught ") */);
+
+ error.setDescription(qDescription);
+}
+
+void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
+ QDeclarativeError &error)
+{
+ qFatal("Not implemented - we use v8 now");
}
bool QDeclarativeQtScriptExpression::notifyOnValueChange() const
@@ -448,14 +477,14 @@ QDeclarativeQtScriptExpression::EvaluateFlags QDeclarativeQtScriptExpression::ev
return evalFlags;
}
-QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope, bool *isUndefined)
+v8::Local<v8::Value> QDeclarativeQtScriptExpression::v8value(QObject *secondaryScope, bool *isUndefined)
{
Q_ASSERT(context() && context()->engine);
Q_ASSERT(!trackChange || (guardObject && guardObjectNotifyIndex != -1));
- if (!expressionFunction.isValid()) {
+ if (v8function.IsEmpty() || v8function->IsUndefined()) {
if (isUndefined) *isUndefined = true;
- return QScriptValue();
+ return v8::Local<v8::Value>();
}
DeleteWatcher watcher(this);
@@ -467,7 +496,7 @@ QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope
ep->captureProperties = trackChange;
ep->capturedProperties.copyAndClear(lastCapturedProperties);
- QScriptValue value = eval(secondaryScope, isUndefined);
+ v8::Local<v8::Value> value = eval(secondaryScope, isUndefined);
if (!watcher.wasDeleted() && trackChange) {
if (ep->capturedProperties.count() == 0) {
@@ -487,59 +516,52 @@ QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope
return value;
}
-QScriptValue QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool *isUndefined)
+v8::Local<v8::Value> QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool *isUndefined)
{
Q_ASSERT(context() && context()->engine);
-
DeleteWatcher watcher(this);
QDeclarativeEngine *engine = context()->engine;
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
+ QObject *restoreSecondaryScope = 0;
+ if (secondaryScope)
+ restoreSecondaryScope = ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
- QDeclarativeContextData *oldSharedContext = 0;
- QObject *oldSharedScope = 0;
- QObject *oldOverride = 0;
- bool isShared = (expressionFunctionMode == SharedContext);
+ v8::TryCatch try_catch;
+ v8::Context::Scope scope(ep->v8engine.context()); // XXX is this needed?
- if (isShared) {
- oldSharedContext = ep->sharedContext;
- oldSharedScope = ep->sharedScope;
- ep->sharedContext = context();
- ep->sharedScope = scopeObject;
- } else {
- oldOverride = ep->contextClass->setOverrideObject(expressionContext, secondaryScope);
+ v8::Handle<v8::Object> This;
+
+ if (evaluateFlags() & RequiresThisObject) {
+ v8::Handle<v8::Value> value = ep->v8engine.newQObject(scopeObject);
+ if (value->IsObject()) This = v8::Handle<v8::Object>::Cast(value);
+ }
+ if (This.IsEmpty()) {
+ This = ep->v8engine.global();
}
- QScriptValue thisObject;
- if (evalFlags & RequiresThisObject)
- thisObject = ep->objectClass->newQObject(scopeObject);
- QScriptValue svalue = expressionFunction.call(thisObject); // This could cause this c++ object to be deleted
+ v8::Local<v8::Value> result = v8function->Call(This, 0, 0);
- if (isShared) {
- ep->sharedContext = oldSharedContext;
- ep->sharedScope = oldSharedScope;
- } else if (!watcher.wasDeleted()) {
- ep->contextClass->setOverrideObject(expressionContext, oldOverride);
- }
+ if (secondaryScope)
+ ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
if (isUndefined)
- *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException();
+ *isUndefined = try_catch.HasCaught() || result->IsUndefined();
- // Handle exception
- if (scriptEngine->hasUncaughtException()) {
- if (!watcher.wasDeleted())
- QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
-
- scriptEngine->clearExceptions();
- return QScriptValue();
- } else {
- if (!watcher.wasDeleted())
+ if (watcher.wasDeleted()) {
+ } else if (try_catch.HasCaught()) {
+ v8::Local<v8::Message> message = try_catch.Message();
+ if (!message.IsEmpty()) {
+ QDeclarativeExpressionPrivate::exceptionToError(message, error);
+ } else {
error = QDeclarativeError();
-
- return svalue;
+ }
+ } else {
+ error = QDeclarativeError();
}
+
+ return result;
}
void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties)
@@ -625,31 +647,23 @@ void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeE
}
}
-QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined)
+// Must be called with a valid handle scope
+v8::Local<v8::Value> QDeclarativeExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
{
if (!expressionFunctionValid) {
QDeclarativeEngine *engine = context()->engine;
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- expressionContext = ep->contextClass->newContext(context(), scopeObject);
- scriptContext->pushScope(expressionContext);
- scriptContext->pushScope(ep->globalClass->staticGlobalObject());
QDeclarativeRewrite::RewriteBinding rewriteBinding;
rewriteBinding.setName(name);
bool ok = true;
const QString code = rewriteBinding(expression, &ok);
- if (ok)
- expressionFunction = scriptEngine->evaluate(code, url, line);
-
- scriptEngine->popContext();
+ if (ok) v8function = evalFunction(context(), scopeObject, code, url, line, &v8qmlscope);
expressionFunctionMode = ExplicitContext;
expressionFunctionValid = true;
}
- return QDeclarativeQtScriptExpression::scriptValue(secondaryScope, isUndefined);
+ return QDeclarativeQtScriptExpression::v8value(secondaryScope, isUndefined);
}
QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
@@ -662,10 +676,19 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU
}
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
+ QVariant rv;
+
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- QVariant retn(ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId<QList<QObject*> >()));
+
+ {
+ v8::HandleScope handle_scope;
+ v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
+ rv = ep->v8engine.toVariant(result, qMetaTypeId<QList<QObject*> >());
+ }
+
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
- return retn;
+
+ return rv;
}
/*!
diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h
index d40094b669..ae0aba6a4b 100644
--- a/src/declarative/qml/qdeclarativeexpression.h
+++ b/src/declarative/qml/qdeclarativeexpression.h
@@ -59,7 +59,6 @@ class QDeclarativeEngine;
class QDeclarativeContext;
class QDeclarativeExpressionPrivate;
class QDeclarativeContextData;
-class QScriptValue;
class Q_DECLARATIVE_EXPORT QDeclarativeExpression : public QObject
{
Q_OBJECT
@@ -95,7 +94,7 @@ Q_SIGNALS:
protected:
QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QString &,
QDeclarativeExpressionPrivate &dd);
- QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QScriptValue &,
+ QDeclarativeExpression(QDeclarativeContextData *, QObject *, void *,
QDeclarativeExpressionPrivate &dd);
QDeclarativeExpression(QDeclarativeContextData *, void *, QDeclarativeRefCount *rc,
QObject *me, const QString &, int, QDeclarativeExpressionPrivate &dd);
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index 51cae0f9d4..04cbdad415 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -60,6 +60,8 @@
#include <QtScript/qscriptvalue.h>
+#include <private/qv8engine_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeAbstractExpression
@@ -124,7 +126,8 @@ public:
QString expression;
Mode expressionFunctionMode;
- QScriptValue expressionFunction;
+ v8::Persistent<v8::Function> v8function;
+ v8::Persistent<v8::Object> v8qmlscope;
QScriptValue expressionContext; // Only used in ExplicitContext
QObject *scopeObject; // Only used in SharedContext
@@ -137,7 +140,7 @@ public:
void setEvaluateFlags(EvaluateFlags flags);
EvaluateFlags evaluateFlags() const;
- QScriptValue scriptValue(QObject *secondaryScope, bool *isUndefined);
+ v8::Local<v8::Value> v8value(QObject *secondaryScope, bool *isUndefined);
class DeleteWatcher {
public:
@@ -152,7 +155,7 @@ public:
private:
void clearGuards();
- QScriptValue eval(QObject *secondaryScope, bool *isUndefined);
+ v8::Local<v8::Value> eval(QObject *secondaryScope, bool *isUndefined);
void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties);
bool trackChange;
@@ -180,11 +183,12 @@ public:
~QDeclarativeExpressionPrivate();
void init(QDeclarativeContextData *, const QString &, QObject *);
- void init(QDeclarativeContextData *, const QScriptValue &, QObject *);
+ void init(QDeclarativeContextData *, v8::Handle<v8::Function>, QObject *);
void init(QDeclarativeContextData *, void *, QDeclarativeRefCount *, QObject *, const QString &, int);
QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
- QScriptValue scriptValue(QObject *secondaryScope = 0, bool *isUndefined = 0);
+
+ v8::Local<v8::Value> v8value(QObject *secondaryScope = 0, bool *isUndefined = 0);
static QDeclarativeExpressionPrivate *get(QDeclarativeExpression *expr) {
return static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr));
@@ -197,11 +201,16 @@ public:
virtual void emitValueChanged();
static void exceptionToError(QScriptEngine *, QDeclarativeError &);
+ static void exceptionToError(v8::Handle<v8::Message>, QDeclarativeError &);
static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QString &, const QString &,
int, QScriptValue *);
static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &,
QScriptValue *);
+ static v8::Persistent<v8::Function> evalFunction(QDeclarativeContextData *ctxt, QObject *scope,
+ const QString &code, const QString &filename, int line,
+ v8::Persistent<v8::Object> *qmlscope = 0);
+
bool expressionFunctionValid:1;
QString url; // This is a QString for a reason. QUrls are slooooooow...
diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp b/src/declarative/qml/qdeclarativeglobalscriptclass.cpp
deleted file mode 100644
index 4bdfdd9b9e..0000000000
--- a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp
+++ /dev/null
@@ -1,147 +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$
-** 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 "private/qdeclarativeglobalscriptclass_p.h"
-
-#include <QtCore/qstringlist.h>
-#include <QtCore/qvector.h>
-#include <QtScript/qscriptstring.h>
-#include <QtScript/qscriptengine.h>
-#include <QtScript/qscriptvalueiterator.h>
-
-#include <private/qscriptdeclarativeclass_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*
- Used to prevent any writes to the global object.
-*/
-QDeclarativeGlobalScriptClass::QDeclarativeGlobalScriptClass(QScriptEngine *engine)
-: QScriptClass(engine)
-{
- QString eval = QLatin1String("eval");
- QString version = QLatin1String("version");
-
- QScriptValue originalGlobalObject = engine->globalObject();
-
- QScriptValue newGlobalObject = engine->newObject();
-
- {
- QScriptValueIterator iter(originalGlobalObject);
- QVector<QString> names;
- QVector<QScriptValue> values;
- QVector<QScriptValue::PropertyFlags> flags;
- while (iter.hasNext()) {
- iter.next();
-
- QString name = iter.name();
-
- if (name == version)
- continue;
-
- if (name != eval) {
- names.append(name);
- values.append(iter.value());
- flags.append(iter.flags() | QScriptValue::Undeletable);
- }
- newGlobalObject.setProperty(iter.scriptName(), iter.value());
-
- m_illegalNames.insert(name);
- }
- m_staticGlobalObject = QScriptDeclarativeClass::newStaticScopeObject(
- engine, names.size(), names.constData(), values.constData(), flags.constData());
- }
-
- newGlobalObject.setScriptClass(this);
- engine->setGlobalObject(newGlobalObject);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeGlobalScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(object);
- Q_UNUSED(name);
- Q_UNUSED(flags);
- Q_UNUSED(id);
- return HandlesWriteAccess;
-}
-
-void QDeclarativeGlobalScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id, const QScriptValue &value)
-{
- Q_UNUSED(object);
- Q_UNUSED(id);
- Q_UNUSED(value);
- QString error = QLatin1String("Invalid write to global property \"") +
- name.toString() + QLatin1Char('\"');
- engine()->currentContext()->throwError(error);
-}
-
-/* This method is for the use of tst_qdeclarativeecmascript::callQtInvokables() only */
-void QDeclarativeGlobalScriptClass::explicitSetProperty(const QStringList &names, const QList<QScriptValue> &values)
-{
- Q_ASSERT(names.count() == values.count());
- QScriptValue globalObject = engine()->globalObject();
-
- QScriptValue v = engine()->newObject();
-
- QScriptValueIterator iter(v);
- while (iter.hasNext()) {
- iter.next();
- v.setProperty(iter.scriptName(), iter.value());
- }
-
- for (int ii = 0; ii < names.count(); ++ii) {
- const QString &name = names.at(ii);
- const QScriptValue &value = values.at(ii);
- v.setProperty(name, value);
- }
-
- v.setScriptClass(this);
-
- engine()->setGlobalObject(v);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativeinclude.cpp b/src/declarative/qml/qdeclarativeinclude.cpp
deleted file mode 100644
index 7102209126..0000000000
--- a/src/declarative/qml/qdeclarativeinclude.cpp
+++ /dev/null
@@ -1,310 +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$
-** 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 "qdeclarativeinclude_p.h"
-
-#include <QtScript/qscriptengine.h>
-#include <QtNetwork/qnetworkrequest.h>
-#include <QtNetwork/qnetworkreply.h>
-#include <QtCore/qfile.h>
-
-#include <private/qdeclarativeengine_p.h>
-#include <private/qdeclarativeglobalscriptclass_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QDeclarativeInclude::QDeclarativeInclude(const QUrl &url,
- QDeclarativeEngine *engine,
- QScriptContext *ctxt)
-: QObject(engine), m_engine(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0)
-{
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- m_context = ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));
-
- m_scope[0] = QScriptDeclarativeClass::scopeChainValue(ctxt, -4);
- m_scope[1] = QScriptDeclarativeClass::scopeChainValue(ctxt, -5);
-
- m_scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- m_network = QDeclarativeScriptEngine::get(m_scriptEngine)->networkAccessManager();
-
- m_result = resultValue(m_scriptEngine);
-
- QNetworkRequest request;
- request.setUrl(url);
-
- m_reply = m_network->get(request);
- QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
-}
-
-QDeclarativeInclude::~QDeclarativeInclude()
-{
- delete m_reply;
-}
-
-QScriptValue QDeclarativeInclude::resultValue(QScriptEngine *engine, Status status)
-{
- QScriptValue result = engine->newObject();
- result.setProperty(QLatin1String("OK"), QScriptValue(engine, Ok));
- result.setProperty(QLatin1String("LOADING"), QScriptValue(engine, Loading));
- result.setProperty(QLatin1String("NETWORK_ERROR"), QScriptValue(engine, NetworkError));
- result.setProperty(QLatin1String("EXCEPTION"), QScriptValue(engine, Exception));
-
- result.setProperty(QLatin1String("status"), QScriptValue(engine, status));
- return result;
-}
-
-QScriptValue QDeclarativeInclude::result() const
-{
- return m_result;
-}
-
-void QDeclarativeInclude::setCallback(const QScriptValue &c)
-{
- m_callback = c;
-}
-
-QScriptValue QDeclarativeInclude::callback() const
-{
- return m_callback;
-}
-
-#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
-void QDeclarativeInclude::finished()
-{
- m_redirectCount++;
-
- if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) {
- QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
- if (redirect.isValid()) {
- m_url = m_url.resolved(redirect.toUrl());
- delete m_reply;
-
- QNetworkRequest request;
- request.setUrl(m_url);
-
- m_reply = m_network->get(request);
- QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
- return;
- }
- }
-
- if (m_reply->error() == QNetworkReply::NoError) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine);
-
- QByteArray data = m_reply->readAll();
-
- QString code = QString::fromUtf8(data);
-
- QString urlString = m_url.toString();
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(m_scriptEngine);
- scriptContext->pushScope(ep->contextClass->newUrlContext(m_context, 0, urlString));
- scriptContext->pushScope(m_scope[0]);
-
- scriptContext->pushScope(m_scope[1]);
- scriptContext->setActivationObject(m_scope[1]);
- QDeclarativeScriptParser::extractPragmas(code);
-
- m_scriptEngine->evaluate(code, urlString, 1);
-
- m_scriptEngine->popContext();
-
- if (m_scriptEngine->hasUncaughtException()) {
- m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Exception));
- m_result.setProperty(QLatin1String("exception"), m_scriptEngine->uncaughtException());
- m_scriptEngine->clearExceptions();
- } else {
- m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Ok));
- }
- } else {
- m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, NetworkError));
- }
-
- callback(m_scriptEngine, m_callback, m_result);
-
- disconnect();
- deleteLater();
-}
-
-void QDeclarativeInclude::callback(QScriptEngine *engine, QScriptValue &callback, QScriptValue &status)
-{
- if (callback.isValid()) {
- QScriptValue args = engine->newArray(1);
- args.setProperty(0, status);
- callback.call(QScriptValue(), args);
- }
-}
-
-/*
- Documented in qdeclarativeengine.cpp
-*/
-QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if (ctxt->argumentCount() == 0)
- return engine->undefinedValue();
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- QUrl contextUrl = ep->contextClass->urlFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));
- if (contextUrl.isEmpty())
- return ctxt->throwError(QLatin1String("Qt.include(): Can only be called from JavaScript files"));
-
- QString urlString = ctxt->argument(0).toString();
- QUrl url(urlString);
- if (url.isRelative()) {
- url = QUrl(contextUrl).resolved(url);
- urlString = url.toString();
- }
-
- QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
-
- QScriptValue func = ctxt->argument(1);
- if (!func.isFunction())
- func = QScriptValue();
-
- QScriptValue result;
- if (localFile.isEmpty()) {
- QDeclarativeInclude *i =
- new QDeclarativeInclude(url, QDeclarativeEnginePrivate::getEngine(engine), ctxt);
-
- if (func.isValid())
- i->setCallback(func);
-
- result = i->result();
- } else {
-
- QFile f(localFile);
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray data = f.readAll();
- QString code = QString::fromUtf8(data);
-
- QDeclarativeContextData *context =
- ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));
-
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine);
- scriptContext->pushScope(ep->contextClass->newUrlContext(context, 0, urlString));
- scriptContext->pushScope(ep->globalClass->staticGlobalObject());
- QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -5);
- scriptContext->pushScope(scope);
- scriptContext->setActivationObject(scope);
- QDeclarativeScriptParser::extractPragmas(code);
-
- engine->evaluate(code, urlString, 1);
-
- engine->popContext();
-
- if (engine->hasUncaughtException()) {
- result = resultValue(engine, Exception);
- result.setProperty(QLatin1String("exception"), engine->uncaughtException());
- engine->clearExceptions();
- } else {
- result = resultValue(engine, Ok);
- }
- callback(engine, func, result);
- } else {
- result = resultValue(engine, NetworkError);
- callback(engine, func, result);
- }
- }
-
- return result;
-}
-
-QScriptValue QDeclarativeInclude::worker_include(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if (ctxt->argumentCount() == 0)
- return engine->undefinedValue();
-
- QString urlString = ctxt->argument(0).toString();
- QUrl url(ctxt->argument(0).toString());
- if (url.isRelative()) {
- QString contextUrl = QScriptDeclarativeClass::scopeChainValue(ctxt, -3).data().toString();
- Q_ASSERT(!contextUrl.isEmpty());
-
- url = QUrl(contextUrl).resolved(url);
- urlString = url.toString();
- }
-
- QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
-
- QScriptValue func = ctxt->argument(1);
- if (!func.isFunction())
- func = QScriptValue();
-
- QScriptValue result;
- if (!localFile.isEmpty()) {
-
- QFile f(localFile);
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray data = f.readAll();
- QString code = QString::fromUtf8(data);
-
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine);
- QScriptValue urlContext = engine->newObject();
- urlContext.setData(QScriptValue(engine, urlString));
- scriptContext->pushScope(urlContext);
-
- QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -4);
- scriptContext->pushScope(scope);
- scriptContext->setActivationObject(scope);
- QDeclarativeScriptParser::extractPragmas(code);
-
- engine->evaluate(code, urlString, 1);
-
- engine->popContext();
-
- if (engine->hasUncaughtException()) {
- result = resultValue(engine, Exception);
- result.setProperty(QLatin1String("exception"), engine->uncaughtException());
- engine->clearExceptions();
- } else {
- result = resultValue(engine, Ok);
- }
- callback(engine, func, result);
- } else {
- result = resultValue(engine, NetworkError);
- callback(engine, func, result);
- }
- }
-
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeintegercache.cpp b/src/declarative/qml/qdeclarativeintegercache.cpp
index cbeb16842f..ae2fbfca87 100644
--- a/src/declarative/qml/qdeclarativeintegercache.cpp
+++ b/src/declarative/qml/qdeclarativeintegercache.cpp
@@ -41,34 +41,21 @@
#include "private/qdeclarativeintegercache_p.h"
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativemetatype_p.h"
-
QT_BEGIN_NAMESPACE
-QDeclarativeIntegerCache::QDeclarativeIntegerCache(QDeclarativeEngine *e)
-: QDeclarativeCleanup(e), engine(e)
+QDeclarativeIntegerCache::QDeclarativeIntegerCache()
{
}
QDeclarativeIntegerCache::~QDeclarativeIntegerCache()
{
- clear();
-}
-
-void QDeclarativeIntegerCache::clear()
-{
- qDeleteAll(stringCache);
- stringCache.clear();
- identifierCache.clear();
- engine = 0;
}
QString QDeclarativeIntegerCache::findId(int value) const
{
for (StringCache::ConstIterator iter = stringCache.begin();
iter != stringCache.end(); ++iter) {
- if (iter.value() && iter.value()->value == value)
+ if (iter.value() == value)
return iter.key();
}
return QString();
@@ -78,19 +65,13 @@ void QDeclarativeIntegerCache::add(const QString &id, int value)
{
Q_ASSERT(!stringCache.contains(id));
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- // ### use contextClass
- Data *d = new Data(enginePriv->objectClass->createPersistentIdentifier(id), value);
-
- stringCache.insert(id, d);
- identifierCache.insert(d->identifier, d);
+ stringCache.insert(id, value);
}
int QDeclarativeIntegerCache::value(const QString &id)
{
- Data *d = stringCache.value(id);
- return d?d->value:-1;
+ int *rv = stringCache.value(id);
+ return rv?*rv:-1;
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeintegercache_p.h b/src/declarative/qml/qdeclarativeintegercache_p.h
index 686880e0d7..33dd2485ff 100644
--- a/src/declarative/qml/qdeclarativeintegercache_p.h
+++ b/src/declarative/qml/qdeclarativeintegercache_p.h
@@ -54,51 +54,35 @@
//
#include "private/qdeclarativerefcount_p.h"
-#include "private/qdeclarativecleanup_p.h"
-
-#include <QtCore/qhash.h>
-
-#include <private/qscriptdeclarativeclass_p.h>
+#include "private/qhashedstring_p.h"
QT_BEGIN_NAMESPACE
class QDeclarativeType;
class QDeclarativeEngine;
-class QDeclarativeIntegerCache : public QDeclarativeRefCount, public QDeclarativeCleanup
+class QDeclarativeIntegerCache : public QDeclarativeRefCount
{
public:
- QDeclarativeIntegerCache(QDeclarativeEngine *);
+ QDeclarativeIntegerCache();
virtual ~QDeclarativeIntegerCache();
inline int count() const;
void add(const QString &, int);
+
int value(const QString &);
- QString findId(int value) const;
- inline int value(const QScriptDeclarativeClass::Identifier &id) const;
+ inline int value(v8::Handle<v8::String>);
-protected:
- virtual void clear();
+ QString findId(int value) const;
private:
- struct Data : public QScriptDeclarativeClass::PersistentIdentifier {
- Data(const QScriptDeclarativeClass::PersistentIdentifier &i, int v)
- : QScriptDeclarativeClass::PersistentIdentifier(i), value(v) {}
-
- int value;
- };
-
- typedef QHash<QString, Data *> StringCache;
- typedef QHash<QScriptDeclarativeClass::Identifier, Data *> IdentifierCache;
-
+ typedef QStringHash<int> StringCache;
StringCache stringCache;
- IdentifierCache identifierCache;
- QDeclarativeEngine *engine;
};
-int QDeclarativeIntegerCache::value(const QScriptDeclarativeClass::Identifier &id) const
+int QDeclarativeIntegerCache::value(v8::Handle<v8::String> name)
{
- Data *d = identifierCache.value(id);
- return d?d->value:-1;
+ int *result = stringCache.value(name);
+ return result?*result:-1;
}
int QDeclarativeIntegerCache::count() const
diff --git a/src/declarative/qml/qdeclarativelistscriptclass.cpp b/src/declarative/qml/qdeclarativelistscriptclass.cpp
deleted file mode 100644
index ace777e6ff..0000000000
--- a/src/declarative/qml/qdeclarativelistscriptclass.cpp
+++ /dev/null
@@ -1,149 +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$
-** 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 "private/qdeclarativelistscriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativeguard_p.h"
-#include "private/qdeclarativelist_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct ListData : public QScriptDeclarativeClass::Object {
- QDeclarativeGuard<QObject> object;
- QDeclarativeListProperty<QObject> property;
- int propertyType;
-};
-
-QDeclarativeListScriptClass::QDeclarativeListScriptClass(QDeclarativeEngine *e)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(e)), engine(e)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- Q_UNUSED(scriptEngine);
-
- m_lengthId = createPersistentIdentifier(QLatin1String("length"));
-}
-
-QDeclarativeListScriptClass::~QDeclarativeListScriptClass()
-{
-}
-
-QScriptValue QDeclarativeListScriptClass::newList(QObject *object, int propId, int propType)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (!object || propId == -1)
- return scriptEngine->nullValue();
-
- ListData *data = new ListData;
- data->object = object;
- data->propertyType = propType;
- void *args[] = { &data->property, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
-
- return newObject(scriptEngine, this, data);
-}
-
-QScriptValue QDeclarativeListScriptClass::newList(const QDeclarativeListProperty<QObject> &prop, int propType)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- ListData *data = new ListData;
- data->object = prop.object;
- data->property = prop;
- data->propertyType = propType;
-
- return newObject(scriptEngine, this, data);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeListScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(object);
- Q_UNUSED(flags);
- if (name == m_lengthId.identifier)
- return QScriptClass::HandlesReadAccess;
-
- bool ok = false;
- quint32 idx = toArrayIndex(name, &ok);
-
- if (ok) {
- lastIndex = idx;
- return QScriptClass::HandlesReadAccess;
- } else {
- return 0;
- }
-}
-
-QDeclarativeListScriptClass::Value QDeclarativeListScriptClass::property(Object *obj, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- ListData *data = (ListData *)obj;
- if (!data->object)
- return Value();
-
- quint32 count = data->property.count?data->property.count(&data->property):0;
-
- if (name == m_lengthId.identifier)
- return Value(scriptEngine, count);
- else if (lastIndex < count && data->property.at)
- return Value(scriptEngine, enginePriv->objectClass->newQObject(data->property.at(&data->property, lastIndex)));
- else
- return Value();
-}
-
-QVariant QDeclarativeListScriptClass::toVariant(Object *obj, bool *ok)
-{
- ListData *data = (ListData *)obj;
-
- if (!data->object) {
- if (ok) *ok = false;
- return QVariant();
- }
-
- return QVariant::fromValue(QDeclarativeListReferencePrivate::init(data->property, data->propertyType, engine));
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index ede02e9f30..d00a28eb2d 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -1099,8 +1099,10 @@ QT_END_NAMESPACE
#include <QtGui/qvector3d.h>
#include <QtGui/qvector4d.h>
#include <QtGui/qquaternion.h>
+#include <private/qv8engine_p.h>
Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QDeclarativeV8Handle);
QT_BEGIN_NAMESPACE
@@ -1181,6 +1183,7 @@ bool QDeclarativeMetaType::canCopy(int type)
default:
if (type == qMetaTypeId<QVariant>() ||
type == qMetaTypeId<QScriptValue>() ||
+ type == qMetaTypeId<QDeclarativeV8Handle>() ||
typeCategory(type) != Unknown) {
return true;
}
@@ -1403,6 +1406,9 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
} else if (type == qMetaTypeId<QScriptValue>()) {
*static_cast<NS(QScriptValue) *>(data) = *static_cast<const NS(QScriptValue)*>(copy);
return true;
+ } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
+ *static_cast<NS(QDeclarativeV8Handle) *>(data) = *static_cast<const NS(QDeclarativeV8Handle)*>(copy);
+ return true;
} else if (typeCategory(type) != Unknown) {
*static_cast<void **>(data) = *static_cast<void* const *>(copy);
return true;
@@ -1610,6 +1616,9 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
} else if (type == qMetaTypeId<QScriptValue>()) {
*static_cast<NS(QScriptValue) *>(data) = NS(QScriptValue)();
return true;
+ } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
+ *static_cast<NS(QDeclarativeV8Handle) *>(data) = NS(QDeclarativeV8Handle)();
+ return true;
} else if (typeCategory(type) != Unknown) {
*static_cast<void **>(data) = 0;
return true;
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
deleted file mode 100644
index edc1755a72..0000000000
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ /dev/null
@@ -1,1226 +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$
-** 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 "private/qdeclarativeobjectscriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativedata_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeguard_p.h"
-#include "private/qdeclarativevmemetaobject_p.h"
-
-#include <QtCore/qtimer.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtScript/qscriptcontextinfo.h>
-
-Q_DECLARE_METATYPE(QScriptValue)
-
-#if defined(__GNUC__)
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
-// The code in this file does not violate strict aliasing, but GCC thinks it does
-// so turn off the warnings for us to have a clean build
-# pragma GCC diagnostic ignored "-Wstrict-aliasing"
-# endif
-#endif
-
-QT_BEGIN_NAMESPACE
-
-struct ObjectData : public QScriptDeclarativeClass::Object {
- ObjectData(QObject *o, int t) : object(o), type(t) {
- if (o) {
- QDeclarativeData *ddata = QDeclarativeData::get(object, true);
- if (ddata) ddata->objectDataRefCount++;
- }
- }
-
- virtual ~ObjectData() {
- if (object && !object->parent()) {
- QDeclarativeData *ddata = QDeclarativeData::get(object, false);
- if (ddata && !ddata->indestructible && 0 == --ddata->objectDataRefCount)
- object->deleteLater();
- }
- }
-
- QDeclarativeGuard<QObject> object;
- int type;
-};
-
-/*
- The QDeclarativeObjectScriptClass handles property access for QObjects
- via QtScript. It is also used to provide a more useful API in
- QtScript for QML.
- */
-QDeclarativeObjectScriptClass::QDeclarativeObjectScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- methods(bindEngine), lastData(0), engine(bindEngine)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- m_destroy = scriptEngine->newFunction(destroy);
- m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
- m_toString = scriptEngine->newFunction(tostring);
- m_toStringId = createPersistentIdentifier(QLatin1String("toString"));
-}
-
-QDeclarativeObjectScriptClass::~QDeclarativeObjectScriptClass()
-{
-}
-
-QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (!object)
- return scriptEngine->nullValue();
-// return newObject(scriptEngine, this, new ObjectData(object, type));
-
- if (QObjectPrivate::get(object)->wasDeleted)
- return scriptEngine->undefinedValue();
-
- QDeclarativeData *ddata = QDeclarativeData::get(object, true);
-
- if (!ddata) {
- return scriptEngine->undefinedValue();
- } else if (!ddata->indestructible && !object->parent()) {
- return newObject(scriptEngine, this, new ObjectData(object, type));
- } else if (!ddata->scriptValue) {
- ddata->scriptValue = new QScriptValue(newObject(scriptEngine, this, new ObjectData(object, type)));
- return *ddata->scriptValue;
- } else if (ddata->scriptValue->engine() == QDeclarativeEnginePrivate::getScriptEngine(engine)) {
- return *ddata->scriptValue;
- } else {
- return newObject(scriptEngine, this, new ObjectData(object, type));
- }
-}
-
-QObject *QDeclarativeObjectScriptClass::toQObject(const QScriptValue &value) const
-{
- return value.toQObject();
-}
-
-int QDeclarativeObjectScriptClass::objectType(const QScriptValue &value) const
-{
- if (scriptClass(value) != this)
- return QVariant::Invalid;
-
- Object *o = object(value);
- return ((ObjectData*)(o))->type;
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- return queryProperty(toQObject(object), name, flags, 0);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
- QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext,
- QueryHints hints)
-{
- Q_UNUSED(flags);
- lastData = 0;
- lastTNData = 0;
-
- if (name == m_destroyId.identifier ||
- name == m_toStringId.identifier)
- return QScriptClass::HandlesReadAccess;
-
- if (!obj)
- return 0;
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
- lastData = QDeclarativePropertyCache::property(engine, obj, name, local);
- if ((hints & ImplicitObject) && lastData && lastData->revision != 0) {
-
- QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData))
- return 0;
- }
-
- if (lastData)
- return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
-
- if (!(hints & SkipAttachedProperties)) {
- if (!evalContext && context()) {
- // Global object, QScriptContext activation object, QDeclarativeContext object
- QScriptValue scopeNode = scopeChainValue(context(), -3);
- if (scopeNode.isValid()) {
- Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);
-
- evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
- }
- }
-
- if (evalContext && evalContext->imports) {
- QDeclarativeTypeNameCache::Data *data = evalContext->imports->data(name);
- if (data) {
- lastTNData = data;
- return QScriptClass::HandlesReadAccess;
- }
- }
- }
-
- if (!(hints & ImplicitObject)) {
- local.coreIndex = -1;
- lastData = &local;
- return QScriptClass::HandlesWriteAccess;
- }
-
- return 0;
-}
-
-QDeclarativeObjectScriptClass::Value
-QDeclarativeObjectScriptClass::property(Object *object, const Identifier &name)
-{
- return property(toQObject(object), name);
-}
-
-QDeclarativeObjectScriptClass::Value
-QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (name == m_destroyId.identifier)
- return Value(scriptEngine, m_destroy);
- else if (name == m_toStringId.identifier)
- return Value(scriptEngine, m_toString);
-
- if (lastData && !lastData->isValid())
- return Value();
-
- Q_ASSERT(obj);
-
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- if (lastTNData) {
-
- if (lastTNData->type)
- return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->type));
- else
- return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace));
-
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsFunction) {
- if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
- return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
- } else {
- // Uncomment to use QtScript method call logic
- // QScriptValue sobj = scriptEngine->newQObject(obj);
- // return Value(scriptEngine, sobj.property(toString(name)));
- return Value(scriptEngine, methods.newMethod(obj, lastData));
- }
- } else {
- if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) {
- if (lastData->coreIndex == 0) {
- enginePriv->capturedProperties <<
- QDeclarativeEnginePrivate::CapturedProperty(QDeclarativeData::get(obj, true)->objectNameNotifier());
- } else {
- enginePriv->capturedProperties <<
- QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
- }
- }
-
- if (QDeclarativeValueTypeFactory::isValueType((uint)lastData->propType)) {
- QDeclarativeValueType *valueType = enginePriv->valueTypes[lastData->propType];
- if (valueType)
- return Value(scriptEngine, enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType));
- }
-
- if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) {
- return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, lastData->propType));
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
- QObject *rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, newQObject(rv, lastData->propType));
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQScriptValue) {
- QScriptValue rv = scriptEngine->nullValue();
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::QReal) {
- qreal rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Int || lastData->flags & QDeclarativePropertyCache::Data::IsEnumType) {
- int rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Bool) {
- bool rv = false;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::QString) {
- QString rv;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::UInt) {
- uint rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Float) {
- float rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Double) {
- double rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else {
- QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
- return Value(scriptEngine, enginePriv->scriptValueFromVariant(var));
- }
- }
-}
-
-void QDeclarativeObjectScriptClass::setProperty(Object *object,
- const Identifier &name,
- const QScriptValue &value)
-{
- return setProperty(toQObject(object), name, value, context());
-}
-
-void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
- const Identifier &name,
- const QScriptValue &value,
- QScriptContext *context,
- QDeclarativeContextData *evalContext)
-{
- Q_UNUSED(name);
-
- Q_ASSERT(obj);
- Q_ASSERT(lastData);
- Q_ASSERT(context);
-
- if (!lastData->isValid()) {
- QString error = QLatin1String("Cannot assign to non-existent property \"") +
- toString(name) + QLatin1Char('\"');
- context->throwError(error);
- return;
- }
-
- if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) &&
- !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) {
- QString error = QLatin1String("Cannot assign to read-only property \"") +
- toString(name) + QLatin1Char('\"');
- context->throwError(error);
- return;
- }
-
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- if (!evalContext) {
- // Global object, QScriptContext activation object, QDeclarativeContext object
- QScriptValue scopeNode = scopeChainValue(context, -3);
- if (scopeNode.isValid()) {
- Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);
-
- evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
- }
- }
-
- QDeclarativeBinding *newBinding = 0;
- if (value.isFunction() && !value.isRegExp()) {
- QScriptContextInfo ctxtInfo(context);
- QDeclarativePropertyCache::ValueTypeData valueTypeData;
-
- newBinding = new QDeclarativeBinding(value, obj, evalContext);
- newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
- newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext));
- if (newBinding->expression().contains(QLatin1String("this")))
- newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
- }
-
- QDeclarativeAbstractBinding *delBinding =
- QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding);
- if (delBinding)
- delBinding->destroy();
-
- if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
- QObject *o = 0;
- int status = -1;
- int flags = 0;
- void *argv[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv);
- } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
- void *a[] = { 0 };
- QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
- } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) {
- QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext);
- } else if (value.isUndefined()) {
- QString error = QLatin1String("Cannot assign [undefined] to ") +
- QLatin1String(QMetaType::typeName(lastData->propType));
- context->throwError(error);
- } else if (value.isFunction() && !value.isRegExp()) {
- // this is handled by the binding creation above
- } else {
- //### expand optimization for other known types
- if (lastData->propType == QMetaType::Int && value.isNumber()) {
- int rawValue = qRound(value.toNumber());
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- } else if (lastData->propType == QMetaType::QReal && value.isNumber()) {
- qreal rawValue = qreal(value.toNumber());
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- } else if (lastData->propType == QMetaType::QString && value.isString()) {
- const QString &rawValue = value.toString();
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- }
-
- QVariant v;
- if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
- v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
- else
- v = enginePriv->scriptValueToVariant(value, lastData->propType);
-
- if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) {
- const char *valueType = 0;
- if (v.userType() == QVariant::Invalid) valueType = "null";
- else valueType = QMetaType::typeName(v.userType());
-
- QString error = QLatin1String("Cannot assign ") +
- QLatin1String(valueType) +
- QLatin1String(" to ") +
- QLatin1String(QMetaType::typeName(lastData->propType));
- context->throwError(error);
- }
- }
-}
-
-bool QDeclarativeObjectScriptClass::isQObject() const
-{
- return true;
-}
-
-QObject *QDeclarativeObjectScriptClass::toQObject(Object *object, bool *ok)
-{
- if (ok) *ok = true;
-
- ObjectData *data = (ObjectData*)object;
- return data->object.data();
-}
-
-QScriptValue QDeclarativeObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *)
-{
- QObject* obj = context->thisObject().toQObject();
-
- QString ret;
- if(obj){
- QString objectName = obj->objectName();
-
- ret += QString::fromUtf8(obj->metaObject()->className());
- ret += QLatin1String("(0x");
- ret += QString::number((quintptr)obj,16);
-
- if (!objectName.isEmpty()) {
- ret += QLatin1String(", \"");
- ret += objectName;
- ret += QLatin1Char('\"');
- }
-
- ret += QLatin1Char(')');
- }else{
- ret += QLatin1String("null");
- }
- return QScriptValue(ret);
-}
-
-QScriptValue QDeclarativeObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
- QScriptValue that = context->thisObject();
-
- if (scriptClass(that) != p->objectClass)
- return engine->undefinedValue();
-
- ObjectData *data = (ObjectData *)p->objectClass->object(that);
- if (!data->object)
- return engine->undefinedValue();
-
- QDeclarativeData *ddata = QDeclarativeData::get(data->object, false);
- if (!ddata || ddata->indestructible)
- return engine->currentContext()->throwError(QLatin1String("Invalid attempt to destroy() an indestructible object"));
-
- QObject *obj = data->object;
- int delay = 0;
- if (context->argumentCount() > 0)
- delay = context->argument(0).toInt32();
- if (delay > 0)
- QTimer::singleShot(delay, obj, SLOT(deleteLater()));
- else
- obj->deleteLater();
-
- return engine->undefinedValue();
-}
-
-QStringList QDeclarativeObjectScriptClass::propertyNames(Object *object)
-{
- QObject *obj = toQObject(object);
- if (!obj)
- return QStringList();
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
-
- QDeclarativePropertyCache *cache = 0;
- QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata)
- cache = ddata->propertyCache;
- if (!cache) {
- cache = enginePrivate->cache(obj);
- if (cache) {
- if (ddata) { cache->addref(); ddata->propertyCache = cache; }
- } else {
- // Not cachable - fall back to QMetaObject (eg. dynamic meta object)
- // XXX QDeclarativeOpenMetaObject has a cache, so this is suboptimal.
- // XXX This is a workaround for QTBUG-9420.
- const QMetaObject *mo = obj->metaObject();
- QStringList r;
- int pc = mo->propertyCount();
- int po = mo->propertyOffset();
- for (int i=po; i<pc; ++i)
- r += QString::fromUtf8(mo->property(i).name());
- return r;
- }
- }
- return cache->propertyNames();
-}
-
-bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2)
-{
- ObjectData *d1 = (ObjectData *)o1;
- ObjectData *d2 = (ObjectData *)o2;
-
- return d1 == d2 || d1->object == d2->object;
-}
-
-struct MethodData : public QScriptDeclarativeClass::Object {
- MethodData(QObject *o, const QDeclarativePropertyCache::Data &d) : object(o), data(d) {}
-
- QDeclarativeGuard<QObject> object;
- QDeclarativePropertyCache::Data data;
-};
-
-QDeclarativeObjectMethodScriptClass::QDeclarativeObjectMethodScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- engine(bindEngine)
-{
- qRegisterMetaType<QList<QObject *> >("QList<QObject *>");
-
- setSupportsCall(true);
-
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- m_connect = scriptEngine->newFunction(connect);
- m_connectId = createPersistentIdentifier(QLatin1String("connect"));
- m_disconnect = scriptEngine->newFunction(disconnect);
- m_disconnectId = createPersistentIdentifier(QLatin1String("disconnect"));
-}
-
-QDeclarativeObjectMethodScriptClass::~QDeclarativeObjectMethodScriptClass()
-{
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::newMethod(QObject *object, const QDeclarativePropertyCache::Data *method)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new MethodData(object, *method));
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::connect(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
-
- QScriptValue that = context->thisObject();
- if (&p->objectClass->methods != scriptClass(that))
- return engine->undefinedValue();
-
- MethodData *data = (MethodData *)object(that);
-
- if (!data->object || context->argumentCount() == 0)
- return engine->undefinedValue();
-
- QByteArray signal("2");
- signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
-
- if (context->argumentCount() == 1) {
- qScriptConnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
- } else {
- qScriptConnect(data->object, signal.constData(), context->argument(0), context->argument(1));
- }
-
- return engine->undefinedValue();
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::disconnect(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
-
- QScriptValue that = context->thisObject();
- if (&p->objectClass->methods != scriptClass(that))
- return engine->undefinedValue();
-
- MethodData *data = (MethodData *)object(that);
-
- if (!data->object || context->argumentCount() == 0)
- return engine->undefinedValue();
-
- QByteArray signal("2");
- signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
-
- if (context->argumentCount() == 1) {
- qScriptDisconnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
- } else {
- qScriptDisconnect(data->object, signal.constData(), context->argument(0), context->argument(1));
- }
-
- return engine->undefinedValue();
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectMethodScriptClass::queryProperty(Object *, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(flags);
- if (name == m_connectId.identifier || name == m_disconnectId.identifier)
- return QScriptClass::HandlesReadAccess;
- else
- return 0;
-
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::property(Object *, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (name == m_connectId.identifier)
- return Value(scriptEngine, m_connect);
- else if (name == m_disconnectId.identifier)
- return Value(scriptEngine, m_disconnect);
- else
- return Value();
-}
-
-namespace {
-struct MetaCallArgument {
- inline MetaCallArgument();
- inline ~MetaCallArgument();
- inline void *dataPtr();
-
- inline void initAsType(int type, QDeclarativeEngine *);
- void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &);
- inline QScriptDeclarativeClass::Value toValue(QDeclarativeEngine *);
-
-private:
- MetaCallArgument(const MetaCallArgument &);
-
- inline void cleanup();
-
- char data[4 * sizeof(void *)];
- int type;
- bool isObjectType;
-};
-}
-
-MetaCallArgument::MetaCallArgument()
-: type(QVariant::Invalid), isObjectType(false)
-{
-}
-
-MetaCallArgument::~MetaCallArgument()
-{
- cleanup();
-}
-
-void MetaCallArgument::cleanup()
-{
- if (type == QMetaType::QString) {
- ((QString *)&data)->~QString();
- } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- ((QVariant *)&data)->~QVariant();
- } else if (type == qMetaTypeId<QScriptValue>()) {
- ((QScriptValue *)&data)->~QScriptValue();
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
- ((QList<QObject *> *)&data)->~QList<QObject *>();
- }
-}
-
-void *MetaCallArgument::dataPtr()
-{
- if (type == -1)
- return ((QVariant *)data)->data();
- else
- return (void *)&data;
-}
-
-void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e)
-{
- if (type != 0) { cleanup(); type = 0; }
- if (callType == 0) return;
-
- QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e);
-
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue(engine->undefinedValue());
- type = callType;
- } else if (callType == QMetaType::Int ||
- callType == QMetaType::UInt ||
- callType == QMetaType::Bool ||
- callType == QMetaType::Double ||
- callType == QMetaType::Float) {
- type = callType;
- } else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = 0;
- type = callType;
- } else if (callType == QMetaType::QString) {
- new (&data) QString();
- type = callType;
- } else if (callType == qMetaTypeId<QVariant>()) {
- type = callType;
- new (&data) QVariant();
- } else if (callType == qMetaTypeId<QList<QObject *> >()) {
- type = callType;
- new (&data) QList<QObject *>();
- } else {
- type = -1;
- new (&data) QVariant(callType, (void *)0);
- }
-}
-
-void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, const QScriptValue &value)
-{
- if (type != 0) { cleanup(); type = 0; }
-
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue(value);
- type = qMetaTypeId<QScriptValue>();
- } else if (callType == QMetaType::Int) {
- *((int *)&data) = int(value.toInt32());
- type = callType;
- } else if (callType == QMetaType::UInt) {
- *((uint *)&data) = uint(value.toUInt32());
- type = callType;
- } else if (callType == QMetaType::Bool) {
- *((bool *)&data) = value.toBool();
- type = callType;
- } else if (callType == QMetaType::Double) {
- *((double *)&data) = double(value.toNumber());
- type = callType;
- } else if (callType == QMetaType::Float) {
- *((float *)&data) = float(value.toNumber());
- type = callType;
- } else if (callType == QMetaType::QString) {
- if (value.isNull() || value.isUndefined())
- new (&data) QString();
- else
- new (&data) QString(value.toString());
- type = callType;
- } else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = value.toQObject();
- type = callType;
- } else if (callType == qMetaTypeId<QVariant>()) {
- new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value));
- type = callType;
- } else if (callType == qMetaTypeId<QList<QObject*> >()) {
- QList<QObject *> *list = new (&data) QList<QObject *>();
- if (value.isArray()) {
- int length = value.property(QLatin1String("length")).toInt32();
- for (int ii = 0; ii < length; ++ii) {
- QScriptValue arrayItem = value.property(ii);
- QObject *d = arrayItem.toQObject();
- list->append(d);
- }
- } else if (QObject *d = value.toQObject()) {
- list->append(d);
- }
- type = callType;
- } else {
- new (&data) QVariant();
- type = -1;
-
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
- QVariant v = priv->scriptValueToVariant(value);
- if (v.userType() == callType) {
- *((QVariant *)&data) = v;
- } else if (v.canConvert((QVariant::Type)callType)) {
- *((QVariant *)&data) = v;
- ((QVariant *)&data)->convert((QVariant::Type)callType);
- } else if (const QMetaObject *mo = priv->rawMetaObjectForType(callType)) {
- QObject *obj = priv->toQObject(v);
-
- if (obj) {
- const QMetaObject *objMo = obj->metaObject();
- while (objMo && objMo != mo) objMo = objMo->superClass();
- if (!objMo) obj = 0;
- }
-
- *((QVariant *)&data) = QVariant(callType, &obj);
- } else {
- *((QVariant *)&data) = QVariant(callType, (void *)0);
- }
- }
-}
-
-QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e)
-{
- QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e);
-
- if (type == qMetaTypeId<QScriptValue>()) {
- return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)&data));
- } else if (type == QMetaType::Int) {
- return QScriptDeclarativeClass::Value(engine, *((int *)&data));
- } else if (type == QMetaType::UInt) {
- return QScriptDeclarativeClass::Value(engine, *((uint *)&data));
- } else if (type == QMetaType::Bool) {
- return QScriptDeclarativeClass::Value(engine, *((bool *)&data));
- } else if (type == QMetaType::Double) {
- return QScriptDeclarativeClass::Value(engine, *((double *)&data));
- } else if (type == QMetaType::Float) {
- return QScriptDeclarativeClass::Value(engine, *((float *)&data));
- } else if (type == QMetaType::QString) {
- return QScriptDeclarativeClass::Value(engine, *((QString *)&data));
- } else if (type == QMetaType::QObjectStar) {
- QObject *object = *((QObject **)&data);
- if (object)
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
- return QScriptDeclarativeClass::Value(engine, priv->objectClass->newQObject(object));
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
- QList<QObject *> &list = *(QList<QObject *>*)&data;
- QScriptValue rv = engine->newArray(list.count());
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
- for (int ii = 0; ii < list.count(); ++ii) {
- QObject *object = list.at(ii);
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- rv.setProperty(ii, priv->objectClass->newQObject(object));
- }
- return QScriptDeclarativeClass::Value(engine, rv);
- } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(e);
- QScriptValue rv = ep->scriptValueFromVariant(*((QVariant *)&data));
- if (rv.isQObject()) {
- QObject *object = rv.toQObject();
- if (object)
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- }
- return QScriptDeclarativeClass::Value(engine, rv);
- } else {
- return QScriptDeclarativeClass::Value();
- }
-}
-
-int QDeclarativeObjectMethodScriptClass::enumType(const QMetaObject *meta, const QString &strname)
-{
- QByteArray str = strname.toUtf8();
- QByteArray scope;
- QByteArray name;
- int scopeIdx = str.lastIndexOf("::");
- if (scopeIdx != -1) {
- scope = str.left(scopeIdx);
- name = str.mid(scopeIdx + 2);
- } else {
- name = str;
- }
- for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
- QMetaEnum m = meta->enumerator(i);
- if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
- return QVariant::Int;
- }
- return QVariant::Invalid;
-}
-
-QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::call(Object *o, QScriptContext *ctxt)
-{
- MethodData *method = static_cast<MethodData *>(o);
-
- if (method->data.relatedIndex == -1)
- return callPrecise(method->object, method->data, ctxt);
- else
- return callOverloaded(method, ctxt);
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
- QScriptContext *ctxt)
-{
- if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
-
- QMetaMethod m = object->metaObject()->method(data.coreIndex);
- QList<QByteArray> argTypeNames = m.parameterTypes();
- QVarLengthArray<int, 9> argTypes(argTypeNames.count());
-
- // ### Cache
- for (int ii = 0; ii < argTypeNames.count(); ++ii) {
- argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
- if (argTypes[ii] == QVariant::Invalid)
- argTypes[ii] = enumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
- if (argTypes[ii] == QVariant::Invalid)
- return Value(ctxt, ctxt->throwError(QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)))));
- }
-
- if (argTypes.count() > ctxt->argumentCount())
- return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments")));
-
- return callMethod(object, data.coreIndex, data.propType, argTypes.count(), argTypes.data(), ctxt);
-
- } else {
-
- return callMethod(object, data.coreIndex, data.propType, 0, 0, ctxt);
-
- }
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index,
- int returnType, int argCount, int *argTypes,
- QScriptContext *ctxt)
-{
- if (argCount > 0) {
-
- QVarLengthArray<MetaCallArgument, 9> args(argCount + 1);
- args[0].initAsType(returnType, engine);
-
- for (int ii = 0; ii < argCount; ++ii)
- args[ii + 1].fromScriptValue(argTypes[ii], engine, ctxt->argument(ii));
-
- QVarLengthArray<void *, 9> argData(args.count());
- for (int ii = 0; ii < args.count(); ++ii)
- argData[ii] = args[ii].dataPtr();
-
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
-
- return args[0].toValue(engine);
-
- } else if (returnType != 0) {
-
- MetaCallArgument arg;
- arg.initAsType(returnType, engine);
-
- void *args[] = { arg.dataPtr() };
-
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
-
- return arg.toValue(engine);
-
- } else {
-
- void *args[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
- return Value();
-
- }
-}
-
-/*!
-Resolve the overloaded method to call. The algorithm works conceptually like this:
- 1. Resolve the set of overloads it is *possible* to call.
- Impossible overloads include those that have too many parameters or have parameters
- of unknown type.
- 2. Filter the set of overloads to only contain those with the closest number of
- parameters.
- For example, if we are called with 3 parameters and there are 2 overloads that
- take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
- 3. Find the best remaining overload based on its match score.
- If two or more overloads have the same match score, call the last one. The match
- score is constructed by adding the matchScore() result for each of the parameters.
-*/
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callOverloaded(MethodData *method, QScriptContext *ctxt)
-{
- int argumentCount = ctxt->argumentCount();
-
- QDeclarativePropertyCache::Data *best = 0;
- int bestParameterScore = INT_MAX;
- int bestMatchScore = INT_MAX;
-
- QDeclarativePropertyCache::Data dummy;
- QDeclarativePropertyCache::Data *attempt = &method->data;
-
- do {
- QList<QByteArray> methodArgTypeNames;
-
- if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
- methodArgTypeNames = method->object->metaObject()->method(attempt->coreIndex).parameterTypes();
-
- int methodArgumentCount = methodArgTypeNames.count();
-
- if (methodArgumentCount > argumentCount)
- continue; // We don't have sufficient arguments to call this method
-
- int methodParameterScore = argumentCount - methodArgumentCount;
- if (methodParameterScore > bestParameterScore)
- continue; // We already have a better option
-
- int methodMatchScore = 0;
- QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
-
- bool unknownArgument = false;
- for (int ii = 0; ii < methodArgumentCount; ++ii) {
- methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
- if (methodArgTypes[ii] == QVariant::Invalid)
- methodArgTypes[ii] = enumType(method->object->metaObject(),
- QString::fromLatin1(methodArgTypeNames.at(ii)));
- if (methodArgTypes[ii] == QVariant::Invalid) {
- unknownArgument = true;
- break;
- }
- methodMatchScore += matchScore(ctxt->argument(ii), methodArgTypes[ii], methodArgTypeNames.at(ii));
- }
- if (unknownArgument)
- continue; // We don't understand all the parameters
-
- if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
- best = attempt;
- bestParameterScore = methodParameterScore;
- bestMatchScore = methodMatchScore;
- }
-
- if (bestParameterScore == 0 && bestMatchScore == 0)
- break; // We can't get better than that
-
- } while((attempt = relatedMethod(method->object, attempt, dummy)) != 0);
-
- if (best) {
- return callPrecise(method->object, *best, ctxt);
- } else {
- QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
- QDeclarativePropertyCache::Data *candidate = &method->data;
- while (candidate) {
- error += QLatin1String("\n ") + QString::fromUtf8(method->object->metaObject()->method(candidate->coreIndex).signature());
- candidate = relatedMethod(method->object, candidate, dummy);
- }
- return Value(ctxt, ctxt->throwError(error));
- }
-}
-
-/*!
- Returns the match score for converting \a actual to be of type \a conversionType. A
- zero score means "perfect match" whereas a higher score is worse.
-
- The conversion table is copied out of the QtScript callQtMethod() function.
-*/
-int QDeclarativeObjectMethodScriptClass::matchScore(const QScriptValue &actual, int conversionType,
- const QByteArray &conversionTypeName)
-{
- if (actual.isNumber()) {
- switch (conversionType) {
- case QMetaType::Double:
- return 0;
- case QMetaType::Float:
- return 1;
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- return 2;
- case QMetaType::Long:
- case QMetaType::ULong:
- return 3;
- case QMetaType::Int:
- case QMetaType::UInt:
- return 4;
- case QMetaType::Short:
- case QMetaType::UShort:
- return 5;
- break;
- case QMetaType::Char:
- case QMetaType::UChar:
- return 6;
- default:
- return 10;
- }
- } else if (actual.isString()) {
- switch (conversionType) {
- case QMetaType::QString:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isBoolean()) {
- switch (conversionType) {
- case QMetaType::Bool:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isDate()) {
- switch (conversionType) {
- case QMetaType::QDateTime:
- return 0;
- case QMetaType::QDate:
- return 1;
- case QMetaType::QTime:
- return 2;
- default:
- return 10;
- }
- } else if (actual.isRegExp()) {
- switch (conversionType) {
- case QMetaType::QRegExp:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isVariant()) {
- if (conversionType == qMetaTypeId<QVariant>())
- return 0;
- else if (actual.toVariant().userType() == conversionType)
- return 0;
- else
- return 10;
- } else if (actual.isArray()) {
- switch (conversionType) {
- case QMetaType::QStringList:
- case QMetaType::QVariantList:
- return 5;
- default:
- return 10;
- }
- } else if (actual.isQObject()) {
- switch (conversionType) {
- case QMetaType::QObjectStar:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isNull()) {
- switch (conversionType) {
- case QMetaType::VoidStar:
- case QMetaType::QObjectStar:
- return 0;
- default:
- if (!conversionTypeName.endsWith('*'))
- return 10;
- else
- return 0;
- }
- } else {
- return 10;
- }
-}
-
-static inline int QMetaObject_methods(const QMetaObject *metaObject)
-{
- struct Private
- {
- int revision;
- int className;
- int classInfoCount, classInfoData;
- int methodCount, methodData;
- };
-
- return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
-}
-
-static QByteArray QMetaMethod_name(const QMetaMethod &m)
-{
- QByteArray sig = m.signature();
- int paren = sig.indexOf('(');
- if (paren == -1)
- return sig;
- else
- return sig.left(paren);
-}
-
-/*!
-Returns the next related method, if one, or 0.
-*/
-QDeclarativePropertyCache::Data *
-QDeclarativeObjectMethodScriptClass::relatedMethod(QObject *object, QDeclarativePropertyCache::Data *current,
- QDeclarativePropertyCache::Data &dummy)
-{
- QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
- if (current->relatedIndex == -1)
- return 0;
-
- if (cache) {
- return cache->method(current->relatedIndex);
- } else {
- const QMetaObject *mo = object->metaObject();
- int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
-
- while (methodOffset > current->relatedIndex) {
- mo = mo->superClass();
- methodOffset -= QMetaObject_methods(mo);
- }
-
- QMetaMethod method = mo->method(current->relatedIndex);
- dummy.load(method);
-
- // Look for overloaded methods
- QByteArray methodName = QMetaMethod_name(method);
- for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
- if (methodName == QMetaMethod_name(mo->method(ii))) {
- dummy.relatedIndex = ii;
- return &dummy;
- }
- }
-
- return &dummy;
- }
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
deleted file mode 100644
index 850a94f364..0000000000
--- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
+++ /dev/null
@@ -1,166 +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$
-** 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 QDECLARATIVEOBJECTSCRIPTCLASS_P_H
-#define QDECLARATIVEOBJECTSCRIPTCLASS_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 "private/qdeclarativepropertycache_p.h"
-#include "private/qdeclarativetypenamecache_p.h"
-
-#include <private/qscriptdeclarativeclass_p.h>
-#include <QtScript/qscriptengine.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDeclarativeEngine;
-class QScriptContext;
-class QScriptEngine;
-class QDeclarativeContextData;
-class MethodData;
-
-class Q_AUTOTEST_EXPORT QDeclarativeObjectMethodScriptClass : public QScriptDeclarativeClass
-{
-public:
- QDeclarativeObjectMethodScriptClass(QDeclarativeEngine *);
- ~QDeclarativeObjectMethodScriptClass();
-
- QScriptValue newMethod(QObject *, const QDeclarativePropertyCache::Data *);
-
-protected:
- virtual Value call(Object *, QScriptContext *);
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
-
-private:
- int enumType(const QMetaObject *, const QString &);
-
- Value callPrecise(QObject *, const QDeclarativePropertyCache::Data &, QScriptContext *);
- Value callOverloaded(MethodData *, QScriptContext *);
- Value callMethod(QObject *, int index, int returnType, int argCount, int *argTypes, QScriptContext *ctxt);
-
- int matchScore(const QScriptValue &, int, const QByteArray &);
- QDeclarativePropertyCache::Data *relatedMethod(QObject *, QDeclarativePropertyCache::Data *current,
- QDeclarativePropertyCache::Data &dummy);
-
- PersistentIdentifier m_connectId;
- PersistentIdentifier m_disconnectId;
- QScriptValue m_connect;
- QScriptValue m_disconnect;
-
- static QScriptValue connect(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue disconnect(QScriptContext *context, QScriptEngine *engine);
-
- QDeclarativeEngine *engine;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeObjectScriptClass : public QScriptDeclarativeClass
-{
-public:
- QDeclarativeObjectScriptClass(QDeclarativeEngine *);
- ~QDeclarativeObjectScriptClass();
-
- QScriptValue newQObject(QObject *, int type = QMetaType::QObjectStar);
-
- QObject *toQObject(const QScriptValue &) const;
- int objectType(const QScriptValue &) const;
-
- enum QueryHint {
- ImplicitObject = 0x01,
- SkipAttachedProperties = 0x02
- };
- Q_DECLARE_FLAGS(QueryHints, QueryHint)
-
- QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &,
- QScriptClass::QueryFlags flags,
- QDeclarativeContextData *evalContext,
- QueryHints hints = 0);
-
- Value property(QObject *, const Identifier &);
-
- void setProperty(QObject *, const Identifier &name, const QScriptValue &,
- QScriptContext *context, QDeclarativeContextData *evalContext = 0);
- virtual QStringList propertyNames(Object *);
- virtual bool compare(Object *, Object *);
-
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
-
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
- virtual bool isQObject() const;
- virtual QObject *toQObject(Object *, bool *ok = 0);
-
-private:
- friend class QDeclarativeObjectMethodScriptClass;
- QDeclarativeObjectMethodScriptClass methods;
-
- QDeclarativeTypeNameCache::Data *lastTNData;
- QDeclarativePropertyCache::Data *lastData;
- QDeclarativePropertyCache::Data local;
-
- PersistentIdentifier m_destroyId;
- PersistentIdentifier m_toStringId;
- QScriptValue m_destroy;
- QScriptValue m_toString;
-
- static QScriptValue tostring(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine);
-
- QDeclarativeEngine *engine;
-};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeObjectScriptClass::QueryHints);
-
-QT_END_NAMESPACE
-
-#endif // QDECLARATIVEOBJECTSCRIPTCLASS_P_H
-
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index b91b820e0f..427e00e8fb 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -1503,7 +1503,7 @@ QDeclarativePropertyPrivate::restore(const QDeclarativePropertyCache::Data &data
prop.d = new QDeclarativePropertyPrivate;
prop.d->object = object;
prop.d->context = ctxt;
- prop.d->engine = ctxt->engine;
+ prop.d->engine = ctxt?ctxt->engine:0;
prop.d->core = data;
prop.d->valueType = valueType;
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 9cbb4fa8cc..7e6f130c27 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -43,9 +43,11 @@
#include "private/qdeclarativeengine_p.h"
#include "private/qdeclarativebinding_p.h"
+#include "private/qv8engine_p.h"
#include <QtCore/qdebug.h>
Q_DECLARE_METATYPE(QScriptValue)
+Q_DECLARE_METATYPE(QDeclarativeV8Handle);
QT_BEGIN_NAMESPACE
@@ -68,6 +70,8 @@ QDeclarativePropertyCache::Data::Flags QDeclarativePropertyCache::Data::flagsFor
flags |= Data::IsQmlBinding;
} else if (propType == qMetaTypeId<QScriptValue>()) {
flags |= Data::IsQScriptValue;
+ } else if (propType == qMetaTypeId<QDeclarativeV8Handle>()) {
+ flags |= Data::IsV8Handle;
} else if (p.isEnumType()) {
flags |= Data::IsEnumType;
} else {
@@ -107,8 +111,13 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m)
propType = QMetaType::type(returnType);
QList<QByteArray> params = m.parameterTypes();
- if (!params.isEmpty())
+ if (!params.isEmpty()) {
flags |= Data::HasArguments;
+ if (params.at(0).length() == 23 &&
+ 0 == qstrcmp(params.at(0).constData(), "QDeclarativeV8Function*")) {
+ flags |= Data::IsV8Function;
+ }
+ }
revision = m.revision();
}
@@ -156,16 +165,11 @@ void QDeclarativePropertyCache::clear()
data->release();
}
- for (IdentifierCache::ConstIterator iter = identifierCache.begin();
- iter != identifierCache.end(); ++iter) {
- RData *data = (*iter);
- data->release();
- }
-
indexCache.clear();
methodIndexCache.clear();
stringCache.clear();
- identifierCache.clear();
+ constructor.Dispose();
+ constructor = v8::Persistent<v8::Function>();
}
QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObject *metaObject,
@@ -219,7 +223,6 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const
cache->indexCache = indexCache;
cache->methodIndexCache = methodIndexCache;
cache->stringCache = stringCache;
- cache->identifierCache = identifierCache;
cache->allowedRevisionCache = allowedRevisionCache;
for (int ii = 0; ii < indexCache.count(); ++ii) {
@@ -230,8 +233,8 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const
}
for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
(*iter)->addref();
- for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter)
- (*iter)->addref();
+
+ // We specifically do *NOT* copy the constructor
return cache;
}
@@ -248,6 +251,9 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
{
Q_UNUSED(revision);
+ constructor.Dispose(); // Now invalid
+ constructor = v8::Persistent<v8::Function>();
+
allowedRevisionCache.append(0);
QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
@@ -267,7 +273,6 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
methodName = methodName.left(parenIdx);
RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
methodIndexCache[ii] = data;
data->load(m);
@@ -286,12 +291,9 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
data->overrideIndex = old->coreIndex;
stringCache[methodName]->release();
- identifierCache[data->identifier.identifier]->release();
}
stringCache.insert(methodName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
data->addref();
}
@@ -307,7 +309,6 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
QString propName = QString::fromUtf8(p.name());
RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
indexCache[ii] = data;
data->load(p, engine);
@@ -320,12 +321,9 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
data->overrideIndex = old->coreIndex;
stringCache[propName]->release();
- identifierCache[data->identifier.identifier]->release();
}
stringCache.insert(propName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
data->addref();
}
}
@@ -375,7 +373,8 @@ QDeclarativePropertyCache::method(int index) const
QDeclarativePropertyCache::Data *
QDeclarativePropertyCache::property(const QString &str) const
{
- return stringCache.value(str);
+ QDeclarativePropertyCache::RData **rv = stringCache.value(str);
+ return rv?*rv:0;
}
QString QDeclarativePropertyCache::Data::name(QObject *object)
@@ -407,29 +406,35 @@ QString QDeclarativePropertyCache::Data::name(const QMetaObject *metaObject)
QStringList QDeclarativePropertyCache::propertyNames() const
{
- return stringCache.keys();
+ QStringList keys;
+ for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
+ keys.append(iter.key());
+ return keys;
}
-QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
- const QScriptDeclarativeClass::Identifier &name, Data &local)
+QDeclarativePropertyCache::Data *
+QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
+ v8::Handle<v8::String> name, Data &local)
{
- QDeclarativePropertyCache::Data *rv = 0;
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
+ Q_ASSERT(engine);
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
QDeclarativePropertyCache *cache = 0;
QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
+ if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine) // XXX aakenend
cache = ddata->propertyCache;
if (!cache) {
- cache = enginePrivate->cache(obj);
+ cache = ep->cache(obj);
if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
}
+ QDeclarativePropertyCache::Data *rv = 0;
+
if (cache) {
rv = cache->property(name);
} else {
- local = QDeclarativePropertyCache::create(obj->metaObject(), enginePrivate->objectClass->toString(name));
+ QString strname = ep->v8engine.toString(name);
+ local = QDeclarativePropertyCache::create(obj->metaObject(), strname);
if (local.isValid())
rv = &local;
}
@@ -437,8 +442,9 @@ QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativ
return rv;
}
-QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
- const QString &name, Data &local)
+QDeclarativePropertyCache::Data *
+QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
+ const QString &name, Data &local)
{
QDeclarativePropertyCache::Data *rv = 0;
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 65a8725b8f..968ea51dda 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -57,6 +57,7 @@
#include "private/qdeclarativecleanup_p.h"
#include "private/qdeclarativenotifier_p.h"
+#include "private/qhashedstring_p.h"
#include <QtCore/qvector.h>
#include <QtScript/private/qscriptdeclarativeclass_p.h>
@@ -64,6 +65,8 @@ QT_BEGIN_NAMESPACE
class QDeclarativeEngine;
class QMetaProperty;
+class QV8Engine;
+class QV8QObjectWrapper;
class Q_AUTOTEST_EXPORT QDeclarativePropertyCache : public QDeclarativeRefCount, public QDeclarativeCleanup
{
@@ -93,16 +96,30 @@ public:
IsQList = 0x00000100,
IsQmlBinding = 0x00000200,
IsQScriptValue = 0x00000400,
+ IsV8Handle = 0x00000800,
// Apply only to IsFunctions
- IsVMEFunction = 0x00000800,
- HasArguments = 0x00001000,
- IsSignal = 0x00002000,
- IsVMESignal = 0x00004000
+ IsVMEFunction = 0x00001000,
+ HasArguments = 0x00002000,
+ IsSignal = 0x00004000,
+ IsVMESignal = 0x00008000,
+ IsV8Function = 0x00010000
};
Q_DECLARE_FLAGS(Flags, Flag)
bool isValid() const { return coreIndex != -1; }
+ bool isConstant() const { return flags & IsConstant; }
+ bool isWritable() const { return flags & IsWritable; }
+ bool isResettable() const { return flags & IsResettable; }
+ bool isAlias() const { return flags & IsAlias; }
+ bool isFinal() const { return flags & IsFinal; }
+ bool isFunction() const { return flags & IsFunction; }
+ bool isQObject() const { return flags & IsQObjectDerived; }
+ bool isEnum() const { return flags & IsEnumType; }
+ bool isQList() const { return flags & IsQList; }
+ bool isQmlBinding() const { return flags & IsQmlBinding; }
+ bool isQScriptValue() const { return flags & IsQScriptValue; }
+ bool isV8Handle() const { return flags & IsV8Handle; }
Flags flags;
int propType;
@@ -141,7 +158,7 @@ public:
static Data create(const QMetaObject *, const QString &);
- inline Data *property(const QScriptDeclarativeClass::Identifier &id) const;
+ inline Data *property(v8::Handle<v8::String>) const;
Data *property(const QString &) const;
Data *property(int) const;
Data *method(int) const;
@@ -151,22 +168,25 @@ public:
inline bool isAllowedInRevision(Data *) const;
inline QDeclarativeEngine *qmlEngine() const;
- static Data *property(QDeclarativeEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &);
static Data *property(QDeclarativeEngine *, QObject *, const QString &, Data &);
+ static Data *property(QDeclarativeEngine *, QObject *, v8::Handle<v8::String>, Data &);
protected:
virtual void clear();
private:
friend class QDeclarativeEnginePrivate;
+ friend class QV8QObjectWrapper;
+ // Implemented in v8/qv8qobjectwrapper.cpp
+ v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
+
+ // XXX is this worth it anymore?
struct RData : public Data, public QDeclarativeRefCount {
- QScriptDeclarativeClass::PersistentIdentifier identifier;
};
typedef QVector<RData *> IndexCache;
- typedef QHash<QString, RData *> StringCache;
- typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+ typedef QStringHash<RData *> StringCache;
typedef QVector<int> AllowedRevisionCache;
void updateRecur(QDeclarativeEngine *, const QMetaObject *);
@@ -175,8 +195,8 @@ private:
IndexCache indexCache;
IndexCache methodIndexCache;
StringCache stringCache;
- IdentifierCache identifierCache;
AllowedRevisionCache allowedRevisionCache;
+ v8::Persistent<v8::Function> constructor;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyCache::Data::Flags);
@@ -207,12 +227,6 @@ QDeclarativePropertyCache::overrideData(Data *data) const
return methodIndexCache.at(data->overrideIndex);
}
-QDeclarativePropertyCache::Data *
-QDeclarativePropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const
-{
- return identifierCache.value(id);
-}
-
QDeclarativePropertyCache::ValueTypeData::ValueTypeData()
: flags(QDeclarativePropertyCache::Data::NoFlags), valueTypeCoreIdx(-1), valueTypePropType(0)
{
@@ -236,6 +250,12 @@ QDeclarativeEngine *QDeclarativePropertyCache::qmlEngine() const
return engine;
}
+QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(v8::Handle<v8::String> str) const
+{
+ QDeclarativePropertyCache::RData **rv = stringCache.value(str);
+ return rv?*rv:0;
+}
+
QT_END_NAMESPACE
#endif // QDECLARATIVEPROPERTYCACHE_P_H
diff --git a/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp b/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp
deleted file mode 100644
index d94e2d9332..0000000000
--- a/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp
+++ /dev/null
@@ -1,219 +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$
-** 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 "private/qdeclarativescarceresourcescriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativedata_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeguard_p.h"
-#include "private/qdeclarativevmemetaobject_p.h"
-
-#include <QtCore/qtimer.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtScript/qscriptcontextinfo.h>
-
-Q_DECLARE_METATYPE(QScriptValue);
-
-QT_BEGIN_NAMESPACE
-
-QDeclarativeScarceResourceScriptClass::QDeclarativeScarceResourceScriptClass(QDeclarativeEngine *bindEngine)
- : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- // Properties of this type can be explicitly preserved by clients,
- // which prevents the scarce resource from being automatically
- // released after the binding has been evaluated.
- m_preserve = scriptEngine->newFunction(preserve);
- m_preserveId = createPersistentIdentifier(QLatin1String("preserve"));
-
- // Similarly, they can be explicitly destroyed by clients,
- // which releases the scarce resource.
- m_destroy = scriptEngine->newFunction(destroy);
- m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
-}
-
-QDeclarativeScarceResourceScriptClass::~QDeclarativeScarceResourceScriptClass()
-{
-}
-
-/*
- Returns a JavaScript object whose instance data is a new scarce resource data.
- The scarce resource is added to the doubly-linked-list of scarce resources in the engine
- so that the scarce resource can be released after evaluation completes.
- */
-QScriptValue QDeclarativeScarceResourceScriptClass::newScarceResource(const QVariant &v)
-{
- // create the scarce resource
- ScarceResourceData *srd = new ScarceResourceData(v);
-
- // insert into the linked list
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
- srd->insertInto(&enginePrivate->scarceResources);
- Q_ASSERT(enginePrivate->scarceResourcesRefCount > 0);
-
- // return the javascript object with the scarce resource instance data
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return QScriptDeclarativeClass::newObject(scriptEngine, this, srd); // JSC takes ownership of srd.
-}
-
-QVariant QDeclarativeScarceResourceScriptClass::toVariant(Object *object, bool *ok)
-{
- ScarceResourceData *obj = static_cast<ScarceResourceData*>(object);
- if (ok) *ok = true;
- return obj->resource;
-}
-
-QVariant QDeclarativeScarceResourceScriptClass::toVariant(const QScriptValue &value)
-{
- Q_ASSERT(scriptClass(value) == this);
-
- return toVariant(object(value), 0);
-}
-
-// The destroy() and preserve() function properties are readable.
-QScriptClass::QueryFlags
-QDeclarativeScarceResourceScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(object)
- Q_UNUSED(flags)
-
- if (name == m_destroyId.identifier || name == m_preserveId.identifier)
- return (QScriptClass::HandlesReadAccess);
- return 0;
-}
-
-// Return the (function) values which may be evaluated by clients.
-QDeclarativeScarceResourceScriptClass::Value
-QDeclarativeScarceResourceScriptClass::property(Object *object, const Identifier &name)
-{
- Q_UNUSED(object)
-
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- // functions
- if (name == m_preserveId.identifier)
- return Value(scriptEngine, m_preserve);
- else if (name == m_destroyId.identifier)
- return Value(scriptEngine, m_destroy);
-
- return Value();
-}
-
-/*
- This method is called when the user explicitly calls the "preserve" method of a scarce resource in JavaScript
- within the specified evaluation context \a context of the script engine \a engine.
- Calling this function signifies that the user explicitly wants to preserve the resource rather than let it
- be automatically released once evaluation of the expression is complete.
- This function removes the internal scarce resource from the declarative engine's linked list of scarce resources
- to release after evaluation of the expression completes. This means that the resource will only be truly
- released when the JavaScript engine's garbage collector is run.
-
- Example:
- \qml
- function getIcon(model) {
- var icon = model.avatar; // a pixmap property
- icon.preserve(); // explicitly preserves the resource
- return icon; // a valid variant will be returned
- }
- \endqml
- */
-QScriptValue QDeclarativeScarceResourceScriptClass::preserve(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
- QScriptValue that = context->thisObject();
-
- if (scriptClass(that) != p->scarceResourceClass)
- return engine->undefinedValue();
-
- // The client wishes to preserve the resource in this SRD.
- ScarceResourceData *data = static_cast<ScarceResourceData *>(p->scarceResourceClass->object(that));
- if (!data)
- return engine->undefinedValue();
-
- // remove node from list, without releasing the resource.
- data->removeNode();
-
- return engine->undefinedValue();
-}
-
-/*
- This method is called when the user explicitly calls the "destroy" method of a scarce resource in JavaScript
- within the specified evaluation context \a context of the script engine \a engine.
- Calling this function signifies that the user explicitly wants to release the resource.
- This function sets the internal scarce resource variant to the invalid variant, in order to release the original resource,
- and then removes the resource from the declarative engine's linked-list of scarce resources to
- to release after evaluation of the expression completes, as it has already been released.
-
- Example:
- \qml
- function getIcon(model) {
- var icon = model.avatar; // a pixmap property
- icon.destroy(); // explicitly releases the resource
- return icon; // an invalid variant will be returned
- }
- \endqml
- */
-QScriptValue QDeclarativeScarceResourceScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
- QScriptValue that = context->thisObject();
-
- if (scriptClass(that) != p->scarceResourceClass)
- return engine->undefinedValue();
-
- // the client wishes to release the resource in this SRD.
- ScarceResourceData *data = static_cast<ScarceResourceData *>(p->scarceResourceClass->object(that));
- if (!data)
- return engine->undefinedValue();
-
- // release the resource and remove the node from the list.
- data->releaseResource();
-
- return engine->undefinedValue();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h b/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h
deleted file mode 100644
index 2a1390a230..0000000000
--- a/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h
+++ /dev/null
@@ -1,163 +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$
-** 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 QDECLARATIVESCARCERESOURCESCRIPTCLASS_P_H
-#define QDECLARATIVESCARCERESOURCESCRIPTCLASS_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 "private/qdeclarativepropertycache_p.h"
-#include "private/qdeclarativetypenamecache_p.h"
-
-#include <private/qscriptdeclarativeclass_p.h>
-#include <QtScript/qscriptengine.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDeclarativeEngine;
-
-/*
- Scarce resources (like pixmaps and textures) are managed manually
- in that the variant will be set to the invalid variant once the
- JavaScript engine has finished using the JavaScript object whose
- instance data is the ScarceResourceData (but before the garbage
- collector frees the JavaScript object itself).
-
- The engine stores a doubly-linked-list of scarce resources which
- will to be cleaned up after a binding is successfully evaluated
- (unless the user explicitly preserves the scarce resource).
-
- A ScarceResourceData pointer should not be deleted manually, as
- all instances of a ScarceResourceData should be owned by the
- JavaScript engine.
- */
-struct ScarceResourceData : public QScriptDeclarativeClass::Object {
- ScarceResourceData(const QVariant &v) : resource(v), prev(0), next(0)
- {
- }
-
- virtual ~ScarceResourceData()
- {
- releaseResource();
- }
-
- // Insert this resource into the given list of resources.
- void insertInto(ScarceResourceData **list)
- {
- // This node becomes the head of the list.
- next = *list; // so our next = old list head
- *list = this; // list now points to us (we're the head)
- prev = list; // as we're the head, our prev ptr becomes the list ptr.
-
- // and the next node's prev pointer must contain a ptr to our next ptr,
- // since per definition, prev always contains a pointer to the previous node's "next" ptr,
- // and the "this" node is the "this->next" node's "prev" node.
- if (next) next->prev = &next;
- }
-
- // Remove this resource from the list of resources, without releasing the resource.
- void removeNode()
- {
- // whatever previously pointed to this node (ie, as that node's "next" node)
- // should now point to our next node (since we no longer exist in the list).
- // and the next node's prev ptr should point to our prev node.
- if (prev) *prev = next;
- if (next) next->prev = prev;
- prev = 0;
- next = 0;
- }
-
- // Release this resource, and remove from the list.
- void releaseResource()
- {
- resource = QVariant();
- removeNode();
- }
-
- QVariant resource;
-
- // prev always contains a pointer to the previous node's "next" ptr.
- // :. for the head node, [*prev] will be engine->scarceResources
- // :. for every other node, [*prev] will be the previous node's "next" ptr.
- ScarceResourceData **prev;
- ScarceResourceData *next;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeScarceResourceScriptClass : public QScriptDeclarativeClass
-{
-public:
- QDeclarativeScarceResourceScriptClass(QDeclarativeEngine *);
- ~QDeclarativeScarceResourceScriptClass();
-
- // Creates a new JavaScript object whose instance data is the scarce resource v
- QScriptValue newScarceResource(const QVariant &v);
-
- // inherited from QScriptDeclarativeClass
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual QVariant toVariant(Object *, bool *ok = 0);
- QVariant toVariant(const QScriptValue &value);
-
-private:
- PersistentIdentifier m_preserveId;
- PersistentIdentifier m_destroyId;
- QScriptValue m_preserve;
- QScriptValue m_destroy;
-
- static QScriptValue preserve(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine);
-
- QDeclarativeEngine *engine;
-};
-
-QT_END_NAMESPACE
-
-#endif // QDECLARATIVESCARCERESOURCESCRIPTCLASS_P_H
diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp
index 4ed2bba525..d4452e766d 100644
--- a/src/declarative/qml/qdeclarativesqldatabase.cpp
+++ b/src/declarative/qml/qdeclarativesqldatabase.cpp
@@ -47,101 +47,21 @@
#include "private/qdeclarativeengine_p.h"
#include <QtCore/qobject.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptvalueiterator.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
-#include <QtScript/qscriptclasspropertyiterator.h>
#include <QtSql/qsqldatabase.h>
#include <QtSql/qsqlquery.h>
#include <QtSql/qsqlerror.h>
#include <QtSql/qsqlrecord.h>
+#include <QtGui/qdesktopservices.h>
#include <QtCore/qstack.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qsettings.h>
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>
-Q_DECLARE_METATYPE(QSqlDatabase)
-Q_DECLARE_METATYPE(QSqlQuery)
+#include <private/qv8engine_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeSqlQueryScriptClass: public QScriptClass {
-public:
- QDeclarativeSqlQueryScriptClass(QScriptEngine *engine) : QScriptClass(engine)
- {
- str_length = engine->toStringHandle(QLatin1String("length"));
- str_forwardOnly = engine->toStringHandle(QLatin1String("forwardOnly")); // not in HTML5 (an optimization)
- }
-
- QueryFlags queryProperty(const QScriptValue &,
- const QScriptString &name,
- QueryFlags flags, uint *)
- {
- if (flags & HandlesReadAccess) {
- if (name == str_length) {
- return HandlesReadAccess;
- } else if (name == str_forwardOnly) {
- return flags;
- }
- }
- if (flags & HandlesWriteAccess)
- if (name == str_forwardOnly)
- return flags;
- return 0;
- }
-
- QScriptValue property(const QScriptValue &object,
- const QScriptString &name, uint)
- {
- QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
- if (name == str_length) {
- int s = query.size();
- if (s<0) {
- // Inefficient.
- if (query.last()) {
- return query.at()+1;
- } else {
- return 0;
- }
- } else {
- return s;
- }
- } else if (name == str_forwardOnly) {
- return query.isForwardOnly();
- }
- return engine()->undefinedValue();
- }
-
- void setProperty(QScriptValue &object,
- const QScriptString &name, uint, const QScriptValue & value)
- {
- if (name == str_forwardOnly) {
- QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
- query.setForwardOnly(value.toBool());
- }
- }
-
- QScriptValue::PropertyFlags propertyFlags(const QScriptValue &/*object*/, const QScriptString &name, uint /*id*/)
- {
- if (name == str_length) {
- return QScriptValue::Undeletable
- | QScriptValue::SkipInEnumeration;
- }
- return QScriptValue::Undeletable;
- }
-
-private:
- QScriptString str_length;
- QScriptString str_forwardOnly;
-};
-
-// If the spec changes to allow iteration, check git history...
-// class QDeclarativeSqlQueryScriptClassPropertyIterator : public QScriptClassPropertyIterator
-
-
-
enum SqlException {
UNKNOWN_ERR,
DATABASE_ERR,
@@ -165,90 +85,227 @@ static const char* sqlerror[] = {
0
};
-#define THROW_SQL(error, desc) \
+#define THROW_SQL(error, desc)
+
+#define V8THROW_SQL(error, desc) \
{ \
- QScriptValue errorValue = context->throwError(desc); \
- errorValue.setProperty(QLatin1String("code"), error); \
- return errorValue; \
+ v8::Local<v8::Value> v = v8::Exception::Error(engine->toString(desc)); \
+ v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \
+ v8::ThrowException(v); \
+ return v8::Handle<v8::Value>(); \
+}
+
+#define V8THROW_REFERENCE(string) { \
+ v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \
+ return v8::Handle<v8::Value>(); \
+}
+
+#define V8THROW_REFERENCE_VOID(string) { \
+ v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \
+ return; \
}
-static QString qmlsqldatabase_databasesPath(QScriptEngine *engine)
+struct QDeclarativeSqlDatabaseData {
+ QDeclarativeSqlDatabaseData(QV8Engine *engine);
+ ~QDeclarativeSqlDatabaseData();
+
+ QString offlineStoragePath;
+ v8::Persistent<v8::Function> constructor;
+ v8::Persistent<v8::Function> queryConstructor;
+ v8::Persistent<v8::Function> rowsConstructor;
+
+ static inline QDeclarativeSqlDatabaseData *data(QV8Engine *e) {
+ return (QDeclarativeSqlDatabaseData *)e->sqlDatabaseData();
+ }
+ static inline QDeclarativeSqlDatabaseData *data(void *d) {
+ return (QDeclarativeSqlDatabaseData *)d;
+ }
+};
+
+class QV8SqlDatabaseResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(SQLDatabaseType)
+
+public:
+ enum Type { Database, Query, Rows };
+
+ QV8SqlDatabaseResource(QV8Engine *e)
+ : QV8ObjectResource(e), type(Database), inTransaction(false), readonly(false), forwardOnly(false) {}
+
+ Type type;
+ QSqlDatabase database;
+
+ QString version; // type == Database
+
+ bool inTransaction; // type == Query
+ bool readonly; // type == Query
+
+ QSqlQuery query; // type == Rows
+ bool forwardOnly; // type == Rows
+};
+
+static v8::Handle<v8::Value> qmlsqldatabase_version(v8::Local<v8::String> property, const v8::AccessorInfo& info)
{
- QDeclarativeScriptEngine *qmlengine = static_cast<QDeclarativeScriptEngine*>(engine);
- return qmlengine->offlineStoragePath
- + QDir::separator() + QLatin1String("Databases");
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Database)
+ V8THROW_REFERENCE("Not a SQLDatabase object");
+
+ return r->engine->toString(r->version);
}
-static void qmlsqldatabase_initDatabasesPath(QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_length(v8::Local<v8::String> property, const v8::AccessorInfo& info)
{
- QDir().mkpath(qmlsqldatabase_databasesPath(engine));
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ int s = r->query.size();
+ if (s < 0) {
+ // Inefficient
+ if (r->query.last()) {
+ s = r->query.at() + 1;
+ } else {
+ s = 0;
+ }
+ }
+ return v8::Integer::New(s);
}
-static QString qmlsqldatabase_databaseFile(const QString& connectionName, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_forwardOnly(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- return qmlsqldatabase_databasesPath(engine) + QDir::separator()
- + connectionName;
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ return v8::Boolean::New(r->query.isForwardOnly());
}
+static void qmlsqldatabase_rows_setForwardOnly(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info)
+{
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE_VOID("Not a SQLDatabase::Rows object");
+
+ r->query.setForwardOnly(value->BooleanValue());
+}
-static QScriptValue qmlsqldatabase_item(QScriptContext *context, QScriptEngine *engine)
+QDeclarativeSqlDatabaseData::~QDeclarativeSqlDatabaseData()
{
- QSqlQuery query = qscriptvalue_cast<QSqlQuery>(context->thisObject().data());
- int i = context->argument(0).toNumber();
- if (query.at() == i || query.seek(i)) { // Qt 4.6 doesn't optimize seek(at())
- QSqlRecord r = query.record();
- QScriptValue row = engine->newObject();
- for (int j=0; j<r.count(); ++j) {
- row.setProperty(r.fieldName(j), QScriptValue(engine,r.value(j).toString()));
+ constructor.Dispose(); constructor = v8::Persistent<v8::Function>();
+ queryConstructor.Dispose(); queryConstructor = v8::Persistent<v8::Function>();
+}
+
+static QString qmlsqldatabase_databasesPath(QV8Engine *engine)
+{
+ return QDeclarativeSqlDatabaseData::data(engine)->offlineStoragePath +
+ QDir::separator() + QLatin1String("Databases");
+}
+
+static void qmlsqldatabase_initDatabasesPath(QV8Engine *engine)
+{
+ QDir().mkpath(qmlsqldatabase_databasesPath(engine));
+}
+
+static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV8Engine *engine)
+{
+ return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName;
+}
+
+static v8::Handle<v8::Value> qmlsqldatabase_rows_index(QV8SqlDatabaseResource *r, uint32_t index)
+{
+ if (r->query.at() == index || r->query.seek(index)) {
+
+ QSqlRecord record = r->query.record();
+ // XXX optimize
+ v8::Local<v8::Object> row = v8::Object::New();
+ for (int ii = 0; ii < record.count(); ++ii) {
+ row->Set(r->engine->toString(record.fieldName(ii)),
+ r->engine->toString(record.value(ii).toString()));
}
return row;
+ } else {
+ return v8::Undefined();
}
- return engine->undefinedValue();
}
-static QScriptValue qmlsqldatabase_executeSql_outsidetransaction(QScriptContext *context, QScriptEngine * /*engine*/)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_index(uint32_t index, const v8::AccessorInfo& info)
{
- THROW_SQL(DATABASE_ERR,QDeclarativeEngine::tr("executeSql called outside transaction()"));
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ return qmlsqldatabase_rows_index(r, index);
}
-static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_item(const v8::Arguments& args)
{
- QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
- QString sql = context->argument(0).toString();
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ return qmlsqldatabase_rows_index(r, args.Length()?args[0]->Uint32Value():0);
+}
+
+static v8::Handle<v8::Value> qmlsqldatabase_executeSql(const v8::Arguments& args)
+{
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Query)
+ V8THROW_REFERENCE("Not a SQLDatabase::Query object");
+
+ QV8Engine *engine = r->engine;
+
+ if (!r->inTransaction)
+ V8THROW_SQL(DATABASE_ERR,QDeclarativeEngine::tr("executeSql called outside transaction()"));
+
+ QSqlDatabase db = r->database;
+
+ QString sql = engine->toString(args[0]);
+
+ if (r->readonly && !sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) {
+ V8THROW_SQL(SYNTAX_ERR, QDeclarativeEngine::tr("Read-only Transaction"));
+ }
+
QSqlQuery query(db);
bool err = false;
- QScriptValue result;
+ v8::Handle<v8::Value> result = v8::Undefined();
if (query.prepare(sql)) {
- if (context->argumentCount() > 1) {
- QScriptValue values = context->argument(1);
- if (values.isObject()) {
- if (values.isArray()) {
- int size = values.property(QLatin1String("length")).toInt32();
- for (int i = 0; i < size; ++i)
- query.bindValue(i, values.property(i).toVariant());
- } else {
- for (QScriptValueIterator it(values); it.hasNext();) {
- it.next();
- query.bindValue(it.name(),it.value().toVariant());
- }
- }
+ if (args.Length() > 1) {
+ v8::Local<v8::Value> values = args[1];
+ if (values->IsArray()) {
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(values);
+ uint32_t size = array->Length();
+ for (uint32_t ii = 0; ii < size; ++ii)
+ query.bindValue(ii, engine->toVariant(array->Get(ii), -1));
+ } else if (values->IsObject() && !values->ToObject()->GetExternalResource()) {
+ v8::Local<v8::Object> object = values->ToObject();
+ v8::Local<v8::Array> names = object->GetPropertyNames();
+ uint32_t size = names->Length();
+ for (uint32_t ii = 0; ii < size; ++ii)
+ query.bindValue(engine->toString(names->Get(ii)),
+ engine->toVariant(object->Get(names->Get(ii)), -1));
} else {
- query.bindValue(0,values.toVariant());
+ query.bindValue(0, engine->toVariant(values, -1));
}
}
if (query.exec()) {
- result = engine->newObject();
- QDeclarativeScriptEngine *qmlengine = static_cast<QDeclarativeScriptEngine*>(engine);
- if (!qmlengine->sqlQueryClass)
- qmlengine->sqlQueryClass = new QDeclarativeSqlQueryScriptClass(engine);
- QScriptValue rows = engine->newObject(qmlengine->sqlQueryClass);
- rows.setData(engine->newVariant(QVariant::fromValue(query)));
- rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration);
- result.setProperty(QLatin1String("rows"),rows);
- result.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected());
- result.setProperty(QLatin1String("insertId"),query.lastInsertId().toString());
+ v8::Handle<v8::Object> rows = QDeclarativeSqlDatabaseData::data(engine)->rowsConstructor->NewInstance();
+ QV8SqlDatabaseResource *r = new QV8SqlDatabaseResource(engine);
+ r->type = QV8SqlDatabaseResource::Rows;
+ r->database = db;
+ r->query = query;
+ rows->SetExternalResource(r);
+
+ v8::Local<v8::Object> resultObject = v8::Object::New();
+ result = resultObject;
+ // XXX optimize
+ resultObject->Set(v8::String::New("rowsAffected"), v8::Integer::New(query.numRowsAffected()));
+ resultObject->Set(v8::String::New("insertId"), engine->toString(query.lastInsertId().toString()));
+ resultObject->Set(v8::String::New("rows"), rows);
} else {
err = true;
}
@@ -256,117 +313,138 @@ static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEn
err = true;
}
if (err)
- THROW_SQL(DATABASE_ERR,query.lastError().text());
+ V8THROW_SQL(DATABASE_ERR,query.lastError().text());
+
return result;
}
-static QScriptValue qmlsqldatabase_executeSql_readonly(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_changeVersion(const v8::Arguments& args)
{
- QString sql = context->argument(0).toString();
- if (sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) {
- return qmlsqldatabase_executeSql(context,engine);
- } else {
- THROW_SQL(SYNTAX_ERR,QDeclarativeEngine::tr("Read-only Transaction"))
- }
-}
+ if (args.Length() < 2)
+ return v8::Undefined();
-static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScriptEngine *engine)
-{
- if (context->argumentCount() < 2)
- return engine->undefinedValue();
-
- QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
- QString from_version = context->argument(0).toString();
- QString to_version = context->argument(1).toString();
- QScriptValue callback = context->argument(2);
-
- QScriptValue instance = engine->newObject();
- instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,1));
- QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db));
-
- QString foundvers = context->thisObject().property(QLatin1String("version")).toString();
- if (from_version!=foundvers) {
- THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(foundvers));
- return engine->undefinedValue();
- }
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Database)
+ V8THROW_REFERENCE("Not a SQLDatabase object");
+
+ QV8Engine *engine = r->engine;
+
+ QSqlDatabase db = r->database;
+ QString from_version = engine->toString(args[0]);
+ QString to_version = engine->toString(args[1]);
+ v8::Handle<v8::Value> callback = args[2];
+
+ if (from_version != r->version)
+ V8THROW_SQL(VERSION_ERR, QDeclarativeEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->version));
+
+ v8::Local<v8::Object> instance = QDeclarativeSqlDatabaseData::data(engine)->queryConstructor->NewInstance();
+ QV8SqlDatabaseResource *r2 = new QV8SqlDatabaseResource(engine);
+ r2->type = QV8SqlDatabaseResource::Query;
+ r2->database = db;
+ r2->version = r->version;
+ r2->inTransaction = true;
+ instance->SetExternalResource(r2);
bool ok = true;
- if (callback.isFunction()) {
+ if (callback->IsFunction()) {
ok = false;
db.transaction();
- callback.call(QScriptValue(), QScriptValueList() << tx);
- if (engine->hasUncaughtException()) {
+
+ v8::TryCatch tc;
+ v8::Handle<v8::Value> callbackArgs[] = { instance };
+ v8::Handle<v8::Function>::Cast(callback)->Call(engine->global(), 1, callbackArgs);
+
+ if (tc.HasCaught()) {
+ db.rollback();
+ tc.ReThrow();
+ return v8::Handle<v8::Value>();
+ } else if (!db.commit()) {
db.rollback();
+ V8THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("SQL transaction failed"));
} else {
- if (!db.commit()) {
- db.rollback();
- THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("SQL transaction failed"));
- } else {
- ok = true;
- }
+ ok = true;
}
}
+ r2->inTransaction = false;
+
if (ok) {
- context->thisObject().setProperty(QLatin1String("version"), to_version, QScriptValue::ReadOnly);
+ r2->version = to_version;
#ifndef QT_NO_SETTINGS
QSettings ini(qmlsqldatabase_databaseFile(db.connectionName(),engine) + QLatin1String(".ini"), QSettings::IniFormat);
ini.setValue(QLatin1String("Version"), to_version);
#endif
}
- return engine->undefinedValue();
+ return v8::Undefined();
}
-static QScriptValue qmlsqldatabase_transaction_shared(QScriptContext *context, QScriptEngine *engine, bool readOnly)
+static v8::Handle<v8::Value> qmlsqldatabase_transaction_shared(const v8::Arguments& args, bool readOnly)
{
- QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
- QScriptValue callback = context->argument(0);
- if (!callback.isFunction())
- THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("transaction: missing callback"));
-
- QScriptValue instance = engine->newObject();
- instance.setProperty(QLatin1String("executeSql"),
- engine->newFunction(readOnly ? qmlsqldatabase_executeSql_readonly : qmlsqldatabase_executeSql,1));
- QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db));
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Database)
+ V8THROW_REFERENCE("Not a SQLDatabase object");
+
+ QV8Engine *engine = r->engine;
+
+ if (args.Length() == 0 || !args[0]->IsFunction())
+ V8THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("transaction: missing callback"));
+
+ QSqlDatabase db = r->database;
+ v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(args[0]);
+
+ v8::Local<v8::Object> instance = QDeclarativeSqlDatabaseData::data(engine)->queryConstructor->NewInstance();
+ QV8SqlDatabaseResource *q = new QV8SqlDatabaseResource(engine);
+ q->type = QV8SqlDatabaseResource::Query;
+ q->database = db;
+ q->readonly = readOnly;
+ q->inTransaction = true;
+ instance->SetExternalResource(q);
db.transaction();
- callback.call(QScriptValue(), QScriptValueList() << tx);
- instance.setProperty(QLatin1String("executeSql"),
- engine->newFunction(qmlsqldatabase_executeSql_outsidetransaction));
- if (engine->hasUncaughtException()) {
+ v8::TryCatch tc;
+ v8::Handle<v8::Value> callbackArgs[] = { instance };
+ callback->Call(engine->global(), 1, callbackArgs);
+
+ q->inTransaction = false;
+
+ if (tc.HasCaught()) {
+ db.rollback();
+ tc.ReThrow();
+ return v8::Handle<v8::Value>();
+ } else if (!db.commit()) {
db.rollback();
- } else {
- if (!db.commit())
- db.rollback();
}
- return engine->undefinedValue();
+
+ return v8::Undefined();
}
-static QScriptValue qmlsqldatabase_transaction(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_transaction(const v8::Arguments& args)
{
- return qmlsqldatabase_transaction_shared(context,engine,false);
+ return qmlsqldatabase_transaction_shared(args, false);
}
-static QScriptValue qmlsqldatabase_read_transaction(QScriptContext *context, QScriptEngine *engine)
+
+static v8::Handle<v8::Value> qmlsqldatabase_read_transaction(const v8::Arguments& args)
{
- return qmlsqldatabase_transaction_shared(context,engine,true);
+ return qmlsqldatabase_transaction_shared(args, true);
}
/*
Currently documented in doc/src/declarative/globalobject.qdoc
*/
-static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_open_sync(const v8::Arguments& args)
{
#ifndef QT_NO_SETTINGS
+ QV8Engine *engine = V8ENGINE();
qmlsqldatabase_initDatabasesPath(engine);
QSqlDatabase database;
- QString dbname = context->argument(0).toString();
- QString dbversion = context->argument(1).toString();
- QString dbdescription = context->argument(2).toString();
- int dbestimatedsize = context->argument(3).toNumber();
- QScriptValue dbcreationCallback = context->argument(4);
+ QString dbname = engine->toString(args[0]);
+ QString dbversion = engine->toString(args[1]);
+ QString dbdescription = engine->toString(args[2]);
+ int dbestimatedsize = args[3]->Int32Value();
+ v8::Handle<v8::Value> dbcreationCallback = args[4];
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(dbname.toUtf8());
@@ -383,13 +461,13 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng
database = QSqlDatabase::database(dbid);
version = ini.value(QLatin1String("Version")).toString();
if (version != dbversion && !dbversion.isEmpty() && !version.isEmpty())
- THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("SQL: database version mismatch"));
+ V8THROW_SQL(VERSION_ERR, QDeclarativeEngine::tr("SQL: database version mismatch"));
} else {
created = !QFile::exists(basename+QLatin1String(".sqlite"));
database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
if (created) {
ini.setValue(QLatin1String("Name"), dbname);
- if (dbcreationCallback.isFunction())
+ if (dbcreationCallback->IsFunction())
version = QString();
ini.setValue(QLatin1String("Version"), version);
ini.setValue(QLatin1String("Description"), dbdescription);
@@ -398,7 +476,7 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng
} else {
if (!dbversion.isEmpty() && ini.value(QLatin1String("Version")) != dbversion) {
// Incompatible
- THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("SQL: database version mismatch"));
+ V8THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("SQL: database version mismatch"));
}
version = ini.value(QLatin1String("Version")).toString();
}
@@ -408,35 +486,96 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng
database.open();
}
- QScriptValue instance = engine->newObject();
- instance.setProperty(QLatin1String("transaction"), engine->newFunction(qmlsqldatabase_transaction,1));
- instance.setProperty(QLatin1String("readTransaction"), engine->newFunction(qmlsqldatabase_read_transaction,1));
- instance.setProperty(QLatin1String("version"), version, QScriptValue::ReadOnly);
- instance.setProperty(QLatin1String("changeVersion"), engine->newFunction(qmlsqldatabase_change_version,3));
-
- QScriptValue result = engine->newVariant(instance,QVariant::fromValue(database));
-
- if (created && dbcreationCallback.isFunction()) {
- dbcreationCallback.call(QScriptValue(), QScriptValueList() << result);
+ v8::Local<v8::Object> instance = QDeclarativeSqlDatabaseData::data(engine)->constructor->NewInstance();
+ QV8SqlDatabaseResource *r = new QV8SqlDatabaseResource(engine);
+ r->database = database;
+ r->version = version;
+ instance->SetExternalResource(r);
+
+ if (created && dbcreationCallback->IsFunction()) {
+ v8::TryCatch tc;
+ v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(dbcreationCallback);
+ v8::Handle<v8::Value> args[] = { instance };
+ callback->Call(engine->global(), 1, args);
+ if (tc.HasCaught()) {
+ tc.ReThrow();
+ return v8::Handle<v8::Value>();
+ }
}
- return result;
+ return instance;
#else
- return engine->undefinedValue();
+ return v8::Undefined();
#endif // QT_NO_SETTINGS
}
-void qt_add_qmlsqldatabase(QScriptEngine *engine)
+QDeclarativeSqlDatabaseData::QDeclarativeSqlDatabaseData(QV8Engine *engine)
{
- QScriptValue openDatabase = engine->newFunction(qmlsqldatabase_open_sync, 4);
- engine->globalObject().setProperty(QLatin1String("openDatabaseSync"), openDatabase);
+ QString dataLocation = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
+ offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
+ QDir::separator() + QLatin1String("QML") +
+ QDir::separator() + QLatin1String("OfflineStorage");
- QScriptValue sqlExceptionPrototype = engine->newObject();
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("transaction"),
+ V8FUNCTION(qmlsqldatabase_transaction, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("readTransaction"),
+ V8FUNCTION(qmlsqldatabase_read_transaction, engine));
+ ft->PrototypeTemplate()->SetAccessor(v8::String::New("version"), qmlsqldatabase_version);
+ ft->PrototypeTemplate()->Set(v8::String::New("changeVersion"),
+ V8FUNCTION(qmlsqldatabase_changeVersion, engine));
+ constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("executeSql"),
+ V8FUNCTION(qmlsqldatabase_executeSql, engine));
+ queryConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("item"), V8FUNCTION(qmlsqldatabase_rows_item, engine));
+ ft->PrototypeTemplate()->SetAccessor(v8::String::New("length"), qmlsqldatabase_rows_length);
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("forwardOnly"), qmlsqldatabase_rows_forwardOnly,
+ qmlsqldatabase_rows_setForwardOnly);
+ ft->InstanceTemplate()->SetIndexedPropertyHandler(qmlsqldatabase_rows_index);
+ rowsConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+}
+
+void *qt_add_qmlsqldatabase(QV8Engine *engine)
+{
+ v8::Local<v8::Function> openDatabase = V8FUNCTION(qmlsqldatabase_open_sync, engine);
+ engine->global()->Set(v8::String::New("openDatabaseSync"), openDatabase);
+
+ v8::PropertyAttribute attributes = (v8::PropertyAttribute)(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
+ v8::Local<v8::Object> sqlExceptionPrototype = v8::Object::New();
for (int i=0; sqlerror[i]; ++i)
- sqlExceptionPrototype.setProperty(QLatin1String(sqlerror[i]),
- i,QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ sqlExceptionPrototype->Set(v8::String::New(sqlerror[i]), v8::Integer::New(i), attributes);
+ engine->global()->Set(v8::String::New("SQLException"), sqlExceptionPrototype);
+
+ return (void *)new QDeclarativeSqlDatabaseData(engine);
+}
+
+void qt_rem_qmlsqldatabase(QV8Engine *engine, void *d)
+{
+ QDeclarativeSqlDatabaseData *data = (QDeclarativeSqlDatabaseData *)d;
+ delete data;
+}
- engine->globalObject().setProperty(QLatin1String("SQLException"), sqlExceptionPrototype);
+void qt_qmlsqldatabase_setOfflineStoragePath(QV8Engine *engine, const QString &path)
+{
+ QDeclarativeSqlDatabaseData::data(engine)->offlineStoragePath = path;
+}
+
+QString qt_qmlsqldatabase_getOfflineStoragePath(const QV8Engine *engine)
+{
+ return QDeclarativeSqlDatabaseData::data(const_cast<QV8Engine *>(engine))->offlineStoragePath;
}
/*
diff --git a/src/declarative/qml/qdeclarativesqldatabase_p.h b/src/declarative/qml/qdeclarativesqldatabase_p.h
index 671bd3062c..85b2b111e2 100644
--- a/src/declarative/qml/qdeclarativesqldatabase_p.h
+++ b/src/declarative/qml/qdeclarativesqldatabase_p.h
@@ -58,8 +58,12 @@
QT_BEGIN_NAMESPACE
-class QScriptEngine;
-void qt_add_qmlsqldatabase(QScriptEngine *engine);
+class QV8Engine;
+
+void *qt_add_qmlsqldatabase(QV8Engine *engine);
+void qt_rem_qmlsqldatabase(QV8Engine *engine, void *);
+void qt_qmlsqldatabase_setOfflineStoragePath(QV8Engine *engine, const QString &);
+QString qt_qmlsqldatabase_getOfflineStoragePath(const QV8Engine *);
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp
index 1c1eeee2cf..27d0fc6e67 100644
--- a/src/declarative/qml/qdeclarativetypeloader.cpp
+++ b/src/declarative/qml/qdeclarativetypeloader.cpp
@@ -1090,6 +1090,9 @@ void QDeclarativeScriptData::clear()
for (int ii = 0; ii < scripts.count(); ++ii)
scripts.at(ii)->release();
scripts.clear();
+
+ m_program.Dispose();
+ m_value.Dispose();
}
QDeclarativeScriptBlob::QDeclarativeScriptBlob(const QUrl &url, QDeclarativeTypeLoader *loader)
@@ -1218,7 +1221,13 @@ void QDeclarativeScriptBlob::done()
m_imports.populateCache(m_scriptData->importCache, engine);
m_scriptData->pragmas = m_pragmas;
- m_scriptData->m_program = QScriptProgram(m_source, finalUrl().toString());
+
+ // XXX aakenned - what about error handling?
+ QV8Engine *v8engine = &QDeclarativeEnginePrivate::get(engine)->v8engine;
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(v8engine->context());
+ v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_source, finalUrl().toString(), 1);
+ m_scriptData->m_program = v8::Persistent<v8::Script>::New(program);
}
QDeclarativeQmldirData::QDeclarativeQmldirData(const QUrl &url)
diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h
index 1c0798d67b..9bda579b45 100644
--- a/src/declarative/qml/qdeclarativetypeloader_p.h
+++ b/src/declarative/qml/qdeclarativetypeloader_p.h
@@ -64,6 +64,8 @@
#include <private/qdeclarativedirparser_p.h>
#include <private/qdeclarativeimport_p.h>
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeScriptData;
@@ -307,8 +309,10 @@ private:
friend class QDeclarativeScriptBlob;
bool m_loaded;
- QScriptProgram m_program;
- QScriptValue m_value;
+ v8::Persistent<v8::Script> m_program;
+ v8::Persistent<v8::Object> m_value;
+// QScriptProgram m_program;
+// QScriptValue m_value;
};
class Q_AUTOTEST_EXPORT QDeclarativeScriptBlob : public QDeclarativeDataBlob
diff --git a/src/declarative/qml/qdeclarativetypenamecache.cpp b/src/declarative/qml/qdeclarativetypenamecache.cpp
index b9577c17fa..214cb4d9d1 100644
--- a/src/declarative/qml/qdeclarativetypenamecache.cpp
+++ b/src/declarative/qml/qdeclarativetypenamecache.cpp
@@ -57,9 +57,7 @@ QDeclarativeTypeNameCache::~QDeclarativeTypeNameCache()
void QDeclarativeTypeNameCache::clear()
{
- qDeleteAll(stringCache);
stringCache.clear();
- identifierCache.clear();
m_moduleApi = 0;
engine = 0;
}
@@ -69,14 +67,9 @@ void QDeclarativeTypeNameCache::add(const QString &name, int importedScriptIndex
if (stringCache.contains(name))
return;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- RData *data = new RData;
- // ### Use typename class
- data->identifier = ep->objectClass->createPersistentIdentifier(name);
- data->importedScriptIndex = importedScriptIndex;
+ Data data;
+ data.importedScriptIndex = importedScriptIndex;
stringCache.insert(name, data);
- identifierCache.insert(data->identifier.identifier, data);
}
void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type)
@@ -84,14 +77,9 @@ void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type)
if (stringCache.contains(name))
return;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- RData *data = new RData;
- // ### Use typename class
- data->identifier = ep->objectClass->createPersistentIdentifier(name);
- data->type = type;
+ Data data;
+ data.type = type;
stringCache.insert(name, data);
- identifierCache.insert(data->identifier.identifier, data);
}
void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeTypeNameCache *typeNamespace)
@@ -101,13 +89,10 @@ void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeTypeNameCac
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- RData *data = new RData;
- // ### Use typename class
- data->identifier = ep->objectClass->createPersistentIdentifier(name);
- data->typeNamespace = typeNamespace;
- stringCache.insert(name, data);
- identifierCache.insert(data->identifier.identifier, data);
+ Data data;
typeNamespace->addref();
+ data.typeNamespace = typeNamespace;
+ stringCache.insert(name, data);
}
QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QString &id) const
diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h
index bcca41f4d5..7d2c1a604d 100644
--- a/src/declarative/qml/qdeclarativetypenamecache_p.h
+++ b/src/declarative/qml/qdeclarativetypenamecache_p.h
@@ -59,6 +59,8 @@
#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qhashedstring_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeType;
@@ -71,7 +73,9 @@ public:
struct Data {
inline Data();
+ inline Data(const Data &);
inline ~Data();
+ inline Data &operator=(const Data &);
QDeclarativeType *type;
QDeclarativeTypeNameCache *typeNamespace;
int importedScriptIndex;
@@ -82,7 +86,7 @@ public:
void add(const QString &, QDeclarativeTypeNameCache *);
Data *data(const QString &) const;
- inline Data *data(const QScriptDeclarativeClass::Identifier &id) const;
+ inline Data *data(v8::Handle<v8::String>) const;
inline bool isEmpty() const;
inline QDeclarativeMetaType::ModuleApiInstance *moduleApi() const;
@@ -92,14 +96,10 @@ protected:
virtual void clear();
private:
- struct RData : public Data {
- QScriptDeclarativeClass::PersistentIdentifier identifier;
- };
- typedef QHash<QString, RData *> StringCache;
- typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+ typedef QStringHash<Data> StringCache;
StringCache stringCache;
- IdentifierCache identifierCache;
+
QDeclarativeEngine *engine;
QDeclarativeMetaType::ModuleApiInstance *m_moduleApi;
};
@@ -114,14 +114,25 @@ QDeclarativeTypeNameCache::Data::~Data()
if (typeNamespace) typeNamespace->release();
}
-QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QScriptDeclarativeClass::Identifier &id) const
+bool QDeclarativeTypeNameCache::isEmpty() const
{
- return identifierCache.value(id);
+ return stringCache.isEmpty();
}
-bool QDeclarativeTypeNameCache::isEmpty() const
+QDeclarativeTypeNameCache::Data::Data(const QDeclarativeTypeNameCache::Data &o)
+: type(o.type), typeNamespace(o.typeNamespace), importedScriptIndex(o.importedScriptIndex)
+{
+ if (typeNamespace) typeNamespace->addref();
+}
+
+QDeclarativeTypeNameCache::Data &QDeclarativeTypeNameCache::Data::operator=(const QDeclarativeTypeNameCache::Data &o)
{
- return identifierCache.isEmpty();
+ 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
@@ -129,6 +140,11 @@ QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi()
return m_moduleApi;
}
+QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(v8::Handle<v8::String> name) const
+{
+ return stringCache.value(name);
+}
+
QT_END_NAMESPACE
#endif // QDECLARATIVETYPENAMECACHE_P_H
diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp
deleted file mode 100644
index d628b7065a..0000000000
--- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp
+++ /dev/null
@@ -1,195 +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$
-** 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 "private/qdeclarativetypenamescriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativetypenamecache_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct TypeNameData : public QScriptDeclarativeClass::Object {
- TypeNameData(QObject *o, QDeclarativeType *t, QDeclarativeTypeNameScriptClass::TypeNameMode m) : object(o), type(t), typeNamespace(0), mode(m) {}
- TypeNameData(QObject *o, QDeclarativeTypeNameCache *n, QDeclarativeTypeNameScriptClass::TypeNameMode m) : object(o), type(0), typeNamespace(n), mode(m) {
- if (typeNamespace) typeNamespace->addref();
- }
- ~TypeNameData() {
- if (typeNamespace) typeNamespace->release();
- }
-
- QObject *object;
- QDeclarativeType *type;
- QDeclarativeTypeNameCache *typeNamespace;
- QDeclarativeTypeNameScriptClass::TypeNameMode mode;
-};
-
-QDeclarativeTypeNameScriptClass::QDeclarativeTypeNameScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- engine(bindEngine), object(0), type(0), api(0)
-{
-}
-
-QDeclarativeTypeNameScriptClass::~QDeclarativeTypeNameScriptClass()
-{
-}
-
-QScriptValue QDeclarativeTypeNameScriptClass::newObject(QObject *object, QDeclarativeType *type, TypeNameMode mode)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type, mode));
-}
-
-QScriptValue QDeclarativeTypeNameScriptClass::newObject(QObject *object, QDeclarativeTypeNameCache *ns, TypeNameMode mode)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns, mode));
-}
-
-QScriptClass::QueryFlags
-QDeclarativeTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(flags);
-
- TypeNameData *data = (TypeNameData *)obj;
-
- object = 0;
- type = 0;
- api = 0;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- if (data->typeNamespace) {
- QDeclarativeTypeNameCache::Data *d = data->typeNamespace->data(name);
- if (d && d->type) {
- type = d->type;
- return QScriptClass::HandlesReadAccess;
- } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = data->typeNamespace->moduleApi()) {
- if (moduleApi->scriptCallback) {
- moduleApi->scriptApi = moduleApi->scriptCallback(engine, &ep->scriptEngine);
- moduleApi->scriptCallback = 0;
- moduleApi->qobjectCallback = 0;
- } else if (moduleApi->qobjectCallback) {
- moduleApi->qobjectApi = moduleApi->qobjectCallback(engine, &ep->scriptEngine);
- moduleApi->scriptCallback = 0;
- moduleApi->qobjectCallback = 0;
- }
-
- api = moduleApi;
- if (api->qobjectApi) {
- return ep->objectClass->queryProperty(api->qobjectApi, name, flags, 0,
- QDeclarativeObjectScriptClass::SkipAttachedProperties);
- } else {
- return QScriptClass::HandlesReadAccess;
- }
-
- return 0;
-
- } else {
- return 0;
- }
-
- } else if (data->type) {
-
- if (startsWithUpper(name)) {
- QString strName = toString(name);
- // Must be an enum
- if (data->mode == IncludeEnums) {
- // ### Optimize
- QByteArray enumName = strName.toUtf8();
- const QMetaObject *metaObject = data->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) {
- enumValue = value;
- return QScriptClass::HandlesReadAccess;
- }
- }
- }
- return 0;
- } else if (data->object) {
- // Must be an attached property
- object = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), data->object);
- if (!object) return 0;
- return ep->objectClass->queryProperty(object, name, flags, 0);
- }
-
- }
-
- return 0;
-}
-
-QDeclarativeTypeNameScriptClass::Value
-QDeclarativeTypeNameScriptClass::property(Object *obj, const Identifier &name)
-{
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- if (type) {
- return Value(scriptEngine, newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode));
- } else if (object) {
- return ep->objectClass->property(object, name);
- } else if (api && api->qobjectApi) {
- return ep->objectClass->property(api->qobjectApi, name);
- } else if (api) {
- return propertyValue(api->scriptApi, name);
- } else {
- return Value(scriptEngine, enumValue);
- }
-}
-
-void QDeclarativeTypeNameScriptClass::setProperty(Object *, const Identifier &n, const QScriptValue &v)
-{
- Q_ASSERT(!type);
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- if (api) {
- Q_ASSERT(api->qobjectApi);
- ep->objectClass->setProperty(api->qobjectApi, n, v, context());
- } else {
- Q_ASSERT(object);
- ep->objectClass->setProperty(object, n, v, context());
- }
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp
deleted file mode 100644
index 4c312b52a8..0000000000
--- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp
+++ /dev/null
@@ -1,242 +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$
-** 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 "private/qdeclarativevaluetypescriptclass_p.h"
-
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeproperty_p.h"
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativeguard_p.h"
-
-#include <QtScript/qscriptcontextinfo.h>
-
-QT_BEGIN_NAMESPACE
-
-struct QDeclarativeValueTypeObject : public QScriptDeclarativeClass::Object {
- enum Type { Reference, Copy };
- QDeclarativeValueTypeObject(Type t) : objectType(t) {}
- Type objectType;
- QDeclarativeValueType *type;
-};
-
-struct QDeclarativeValueTypeReference : public QDeclarativeValueTypeObject {
- QDeclarativeValueTypeReference() : QDeclarativeValueTypeObject(Reference) {}
- QDeclarativeGuard<QObject> object;
- int property;
-};
-
-struct QDeclarativeValueTypeCopy : public QDeclarativeValueTypeObject {
- QDeclarativeValueTypeCopy() : QDeclarativeValueTypeObject(Copy) {}
- QVariant value;
-};
-
-QDeclarativeValueTypeScriptClass::QDeclarativeValueTypeScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
-{
-}
-
-QDeclarativeValueTypeScriptClass::~QDeclarativeValueTypeScriptClass()
-{
-}
-
-QScriptValue QDeclarativeValueTypeScriptClass::newObject(QObject *object, int coreIndex, QDeclarativeValueType *type)
-{
- QDeclarativeValueTypeReference *ref = new QDeclarativeValueTypeReference;
- ref->type = type;
- ref->object = object;
- ref->property = coreIndex;
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return QScriptDeclarativeClass::newObject(scriptEngine, this, ref);
-}
-
-QScriptValue QDeclarativeValueTypeScriptClass::newObject(const QVariant &v, QDeclarativeValueType *type)
-{
- QDeclarativeValueTypeCopy *copy = new QDeclarativeValueTypeCopy;
- copy->type = type;
- copy->value = v;
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return QScriptDeclarativeClass::newObject(scriptEngine, this, copy);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeValueTypeScriptClass::queryProperty(Object *obj, const Identifier &name,
- QScriptClass::QueryFlags)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- m_lastIndex = -1;
-
- QByteArray propName = toString(name).toUtf8();
-
- m_lastIndex = o->type->metaObject()->indexOfProperty(propName.constData());
- if (m_lastIndex == -1)
- return 0;
-
- QScriptClass::QueryFlags rv = 0;
-
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(o);
-
- if (!ref->object)
- return 0;
-
- QMetaProperty prop = ref->object->metaObject()->property(m_lastIndex);
-
- rv = QScriptClass::HandlesReadAccess;
- if (prop.isWritable())
- rv |= QScriptClass::HandlesWriteAccess;
- } else {
- rv = QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
- }
-
- return rv;
-}
-
-QDeclarativeValueTypeScriptClass::Value QDeclarativeValueTypeScriptClass::property(Object *obj, const Identifier &)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- QVariant rv;
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
-
- QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
- ref->type->read(ref->object, ref->property);
- rv = p.read(ref->type);
- } else {
- QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
-
- QMetaProperty p = copy->type->metaObject()->property(m_lastIndex);
- copy->type->setValue(copy->value);
- rv = p.read(copy->type);
- }
-
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return Value(scriptEngine, static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv));
-}
-
-void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier &,
- const QScriptValue &value)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value);
-
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
-
- ref->type->read(ref->object, ref->property);
- QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
-
- QDeclarativeBinding *newBinding = 0;
- if (value.isFunction() && !value.isRegExp()) {
- QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(engine)->getContext(context());
-
- QDeclarativePropertyCache::Data cacheData;
- cacheData.flags = QDeclarativePropertyCache::Data::IsWritable;
- cacheData.propType = ref->object->metaObject()->property(ref->property).userType();
- cacheData.coreIndex = ref->property;
-
- QDeclarativePropertyCache::ValueTypeData valueTypeData;
- valueTypeData.valueTypeCoreIdx = m_lastIndex;
- valueTypeData.valueTypePropType = p.userType();
-
- newBinding = new QDeclarativeBinding(value, ref->object, ctxt);
- QScriptContextInfo ctxtInfo(context());
- newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
- QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt);
- newBinding->setTarget(prop);
- if (newBinding->expression().contains(QLatin1String("this")))
- newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
- }
-
- QDeclarativeAbstractBinding *delBinding =
- QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, newBinding);
- if (delBinding)
- delBinding->destroy();
-
- if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
- v = v.toInt();
- p.write(ref->type, v);
- ref->type->write(ref->object, ref->property, 0);
-
- } else {
- QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
- copy->type->setValue(copy->value);
- QMetaProperty p = copy->type->metaObject()->property(m_lastIndex);
- p.write(copy->type, v);
- copy->value = copy->type->value();
- }
-}
-
-QVariant QDeclarativeValueTypeScriptClass::toVariant(Object *obj, bool *ok)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
-
- if (ok) *ok = true;
-
- if (ref->object) {
- ref->type->read(ref->object, ref->property);
- return ref->type->value();
- }
- } else {
- QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
-
- if (ok) *ok = true;
-
- return copy->value;
- }
-
- return QVariant();
-}
-
-QVariant QDeclarativeValueTypeScriptClass::toVariant(const QScriptValue &value)
-{
- Q_ASSERT(scriptClass(value) == this);
-
- return toVariant(object(value), 0);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 13539a0f1f..5e35f6020b 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -59,7 +59,6 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativev4bindings_p.h"
#include "private/qdeclarativeglobal_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include "qdeclarativescriptstring.h"
#include <QStack>
@@ -962,68 +961,67 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData
}
}
-QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
+v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
{
if (script->m_loaded)
- return script->m_value;
+ return v8::Persistent<v8::Object>::New(script->m_value);
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
+ QV8Engine *v8engine = &ep->v8engine;
bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
// Create the script context if required
- QDeclarativeContextData *ctxt = 0;
- if (!shared) {
- ctxt = new QDeclarativeContextData;
- ctxt->isInternal = true;
- ctxt->url = script->url;
-
- // For backward compatibility, if there are no imports, we need to use the
- // imports from the parent context. See QTBUG-17518.
- if (!script->importCache->isEmpty()) {
- ctxt->imports = script->importCache;
- } else {
- ctxt->imports = parentCtxt->imports;
- }
-
- if (ctxt->imports) {
- ctxt->imports->addref();
- }
-
- ctxt->setParent(parentCtxt, true);
+ QDeclarativeContextData *ctxt = new QDeclarativeContextData;
+ ctxt->isInternal = true;
+ ctxt->isJSContext = true;
+ ctxt->url = script->url;
+
+ // For backward compatibility, if there are no imports, we need to use the
+ // imports from the parent context. See QTBUG-17518.
+ if (!script->importCache->isEmpty()) {
+ ctxt->imports = script->importCache;
+ } else {
+ ctxt->imports = parentCtxt->imports;
+ }
- for (int ii = 0; ii < script->scripts.count(); ++ii)
- ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
+ if (ctxt->imports) {
+ ctxt->imports->addref();
}
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- if (shared) {
- scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
- } else {
- scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
+ ctxt->setParent(parentCtxt, true);
+
+ for (int ii = 0; ii < script->scripts.count(); ++ii) {
+ ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
}
- scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
- QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
- scriptContext->pushScope(scope);
+ // XXX aakenned optimize
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(v8engine->context());
- scriptEngine->evaluate(script->m_program);
+ v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
- if (scriptEngine->hasUncaughtException()) {
- QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
- enginePriv->warning(error);
- }
+ v8::TryCatch try_catch;
+ script->m_program->Run(qmlglobal);
- scriptEngine->popContext();
+ v8::Persistent<v8::Object> rv;
+
+ if (try_catch.HasCaught()) {
+ v8::Local<v8::Message> message = try_catch.Message();
+ if (!message.IsEmpty()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(message, error);
+ ep->warning(error);
+ }
+ }
+ rv = v8::Persistent<v8::Object>::New(qmlglobal);
if (shared) {
+ script->m_value = v8::Persistent<v8::Object>::New(qmlglobal);
script->m_loaded = true;
- script->m_value = scope;
}
- return scope;
+ return rv;
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevme_p.h b/src/declarative/qml/qdeclarativevme_p.h
index 40343b2f19..14f85e57a3 100644
--- a/src/declarative/qml/qdeclarativevme_p.h
+++ b/src/declarative/qml/qdeclarativevme_p.h
@@ -59,6 +59,8 @@
#include <QtCore/QString>
#include <QtCore/QStack>
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QObject;
@@ -103,7 +105,6 @@ public:
QObject *run(QDeclarativeContextData *, QDeclarativeCompiledData *,
int start = -1, const QBitField & = QBitField());
- QScriptValue run(QDeclarativeContextData *, QDeclarativeScriptData *);
void runDeferred(QObject *);
@@ -111,6 +112,8 @@ public:
QList<QDeclarativeError> errors() const;
private:
+ v8::Persistent<v8::Object> run(QDeclarativeContextData *, QDeclarativeScriptData *);
+
QObject *run(QDeclarativeVMEStack<QObject *> &,
QDeclarativeContextData *, QDeclarativeCompiledData *,
int start, const QBitField &);
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index 6eb74b3bad..a272c180c2 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -383,7 +383,7 @@ QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj,
const QDeclarativeVMEMetaData *meta,
QDeclarativeCompiledData *cdata)
: object(obj), compiledData(cdata), ctxt(QDeclarativeData::get(obj, true)->outerContext),
- metaData(meta), data(0), methods(0), parent(0)
+ metaData(meta), data(0), v8methods(0), parent(0)
{
compiledData->addref();
@@ -418,7 +418,9 @@ QDeclarativeVMEMetaObject::~QDeclarativeVMEMetaObject()
compiledData->release();
delete parent;
delete [] data;
- delete [] methods;
+
+ for (int ii = 0; v8methods && ii < metaData->methodCount; ++ii)
+ v8methods[ii].Dispose();
}
int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
@@ -649,27 +651,35 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- QScriptValue function = method(id);
-
- QScriptValueList args;
+ // XXX aakenned
+ v8::Handle<v8::Function> function = method(id);
QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + id;
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(ep->v8engine.context());
+ v8::Handle<v8::Value> *args = 0;
+
if (data->parameterCount) {
- for (int ii = 0; ii < data->parameterCount; ++ii) {
- args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]);
- }
+ args = new v8::Handle<v8::Value>[data->parameterCount];
+ for (int ii = 0; ii < data->parameterCount; ++ii)
+ args[ii] = ep->v8engine.fromVariant(*(QVariant *)a[ii + 1]);
}
- QScriptValue rv = function.call(ep->objectClass->newQObject(object), args);
- if (ep->scriptEngine.hasUncaughtException()) {
+ v8::TryCatch try_catch;
+
+ v8::Local<v8::Value> result = function->Call(ep->v8engine.global(), data->parameterCount, args);
+
+ QVariant rv;
+ if (try_catch.HasCaught()) {
QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(&ep->scriptEngine, error);
- if (error.isValid()) {
+ QDeclarativeExpressionPrivate::exceptionToError(try_catch.Message(), error);
+ if (error.isValid())
ep->warning(error);
- }
+ if (a[0]) *(QVariant *)a[0] = QVariant();
+ } else {
+ if (a[0]) *(QVariant *)a[0] = ep->v8engine.toVariant(result, 0);
}
- if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv);
-
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
return -1;
}
@@ -683,12 +693,12 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
return object->qt_metacall(c, _id, a);
}
-QScriptValue QDeclarativeVMEMetaObject::method(int index)
+v8::Handle<v8::Function> QDeclarativeVMEMetaObject::method(int index)
{
- if (!methods)
- methods = new QScriptValue[metaData->methodCount];
+ if (!v8methods)
+ v8methods = new v8::Persistent<v8::Function>[metaData->methodCount];
- if (!methods[index].isValid()) {
+ if (v8methods[index].IsEmpty()) {
QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + index;
const QChar *body =
@@ -696,17 +706,17 @@ QScriptValue QDeclarativeVMEMetaObject::method(int index)
QString code = QString::fromRawData(body, data->bodyLength);
- // XXX Use QScriptProgram
// XXX We should evaluate all methods in a single big script block to
// improve the call time between dynamic methods defined on the same
// object
- methods[index] = QDeclarativeExpressionPrivate::evalInObjectScope(ctxt, object, code, ctxt->url.toString(),
- data->lineNumber, 0);
+ v8methods[index] = QDeclarativeExpressionPrivate::evalFunction(ctxt, object, code, ctxt->url.toString(),
+ data->lineNumber);
}
- return methods[index];
+ return v8methods[index];
}
+#if 0
QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
{
if (data[id].dataType() == qMetaTypeId<QScriptValue>())
@@ -716,22 +726,28 @@ QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
else
return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueFromVariant(data[id].asQVariant());
}
+#endif
QVariant QDeclarativeVMEMetaObject::readVarPropertyAsVariant(int id)
{
+#if 0
if (data[id].dataType() == qMetaTypeId<QScriptValue>())
return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQScriptValue());
- else if (data[id].dataType() == QMetaType::QObjectStar)
+ else
+#endif
+ if (data[id].dataType() == QMetaType::QObjectStar)
return QVariant::fromValue(data[id].asQObject());
else
return data[id].asQVariant();
}
+#if 0
void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &value)
{
data[id].setValue(value);
activate(object, methodOffset + id, 0);
}
+#endif
void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QVariant &value)
{
@@ -803,7 +819,7 @@ int QDeclarativeVMEMetaObject::vmeMethodLineNumber(int index)
return data->lineNumber;
}
-QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
+v8::Handle<v8::Function> QDeclarativeVMEMetaObject::vmeMethod(int index)
{
if (index < methodOffset) {
Q_ASSERT(parent);
@@ -814,6 +830,7 @@ QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
return method(index - methodOffset - plainSignals);
}
+// Used by debugger
void QDeclarativeVMEMetaObject::setVmeMethod(int index, const QScriptValue &value)
{
if (index < methodOffset) {
@@ -823,11 +840,14 @@ void QDeclarativeVMEMetaObject::setVmeMethod(int index, const QScriptValue &valu
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+#if 0
if (!methods)
methods = new QScriptValue[metaData->methodCount];
methods[index - methodOffset - plainSignals] = value;
+#endif
}
+#if 0
QScriptValue QDeclarativeVMEMetaObject::vmeProperty(int index)
{
if (index < propOffset) {
@@ -845,6 +865,7 @@ void QDeclarativeVMEMetaObject::setVMEProperty(int index, const QScriptValue &v)
}
return writeVarProperty(index - propOffset, v);
}
+#endif
bool QDeclarativeVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
{
diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h
index 318ac4aa77..7e8b38df4c 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject_p.h
+++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h
@@ -69,6 +69,8 @@
#include "private/qdeclarativecompiler_p.h"
#include "private/qdeclarativecontext_p.h"
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
#define QML_ALIAS_FLAG_PTR 0x00000001
@@ -140,11 +142,13 @@ public:
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
void registerInterceptor(int index, int valueIndex, QDeclarativePropertyValueInterceptor *interceptor);
- QScriptValue vmeMethod(int index);
+ v8::Handle<v8::Function> vmeMethod(int index);
int vmeMethodLineNumber(int index);
void setVmeMethod(int index, const QScriptValue &);
+#if 0
QScriptValue vmeProperty(int index);
void setVMEProperty(int index, const QScriptValue &);
+#endif
void connectAliasSignal(int index);
@@ -168,11 +172,14 @@ private:
QHash<int, QPair<int, QDeclarativePropertyValueInterceptor*> > interceptors;
QScriptValue *methods;
- QScriptValue method(int);
+ v8::Persistent<v8::Function> *v8methods;
+ v8::Handle<v8::Function> method(int);
+#if 0
QScriptValue readVarProperty(int);
- QVariant readVarPropertyAsVariant(int);
void writeVarProperty(int, const QScriptValue &);
+#endif
+ QVariant readVarPropertyAsVariant(int);
void writeVarProperty(int, const QVariant &);
QAbstractDynamicMetaObject *parent;
diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp
index db8a2ae81b..0d5582f11e 100644
--- a/src/declarative/qml/qdeclarativeworkerscript.cpp
+++ b/src/declarative/qml/qdeclarativeworkerscript.cpp
@@ -58,6 +58,8 @@
#include <QtDeclarative/qdeclarativeinfo.h>
#include "qdeclarativenetworkaccessmanagerfactory.h"
+#include <private/qv8engine_p.h>
+#include <private/qv8worker_p.h>
QT_BEGIN_NAMESPACE
@@ -66,15 +68,15 @@ class WorkerDataEvent : public QEvent
public:
enum Type { WorkerData = QEvent::User };
- WorkerDataEvent(int workerId, const QVariant &data);
+ WorkerDataEvent(int workerId, const QByteArray &data);
virtual ~WorkerDataEvent();
int workerId() const;
- QVariant data() const;
+ QByteArray data() const;
private:
int m_id;
- QVariant m_data;
+ QByteArray m_data;
};
class WorkerLoadEvent : public QEvent
@@ -128,27 +130,28 @@ public:
QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *eng);
- struct ScriptEngine : public QDeclarativeScriptEngine
+ class WorkerEngine : public QV8Engine
{
- ScriptEngine(QDeclarativeWorkerScriptEnginePrivate *parent) : QDeclarativeScriptEngine(0), p(parent), accessManager(0) {}
- ~ScriptEngine() { delete accessManager; }
+ public:
+ WorkerEngine(QDeclarativeWorkerScriptEnginePrivate *parent);
+ ~WorkerEngine();
+
+ void init();
+ virtual QNetworkAccessManager *networkAccessManager();
+
QDeclarativeWorkerScriptEnginePrivate *p;
- QNetworkAccessManager *accessManager;
- virtual QNetworkAccessManager *networkAccessManager() {
- if (!accessManager) {
- if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
- accessManager = p->qmlengine->networkAccessManagerFactory()->create(this);
- } else {
- accessManager = new QNetworkAccessManager(this);
- }
- }
- return accessManager;
- }
+ v8::Local<v8::Function> sendFunction(int id);
+ void callOnMessage(v8::Handle<v8::Object> object, v8::Handle<v8::Value> arg);
+ private:
+ v8::Persistent<v8::Function> onmessage;
+ v8::Persistent<v8::Function> createsend;
+ QNetworkAccessManager *accessManager;
};
- ScriptEngine *workerEngine;
- static QDeclarativeWorkerScriptEnginePrivate *get(QScriptEngine *e) {
- return static_cast<ScriptEngine *>(e)->p;
+
+ WorkerEngine *workerEngine;
+ static QDeclarativeWorkerScriptEnginePrivate *get(QV8Engine *e) {
+ return static_cast<WorkerEngine *>(e)->p;
}
QDeclarativeEngine *qmlengine;
@@ -158,26 +161,21 @@ public:
struct WorkerScript {
WorkerScript();
+ ~WorkerScript();
int id;
QUrl source;
bool initialized;
QDeclarativeWorkerScript *owner;
- QScriptValue object;
-
- QScriptValue callback;
+ v8::Persistent<v8::Object> object;
};
QHash<int, WorkerScript *> workers;
- QScriptValue getWorker(int);
+ v8::Handle<v8::Object> getWorker(WorkerScript *);
int m_nextId;
- static QVariant scriptValueToVariant(const QScriptValue &);
- static QScriptValue variantToScriptValue(const QVariant &, QScriptEngine *);
-
- static QScriptValue onMessage(QScriptContext *ctxt, QScriptEngine *engine);
- static QScriptValue sendMessage(QScriptContext *ctxt, QScriptEngine *engine);
+ static v8::Handle<v8::Value> sendMessage(const v8::Arguments &args);
signals:
void stopThread();
@@ -186,75 +184,133 @@ protected:
virtual bool event(QEvent *);
private:
- void processMessage(int, const QVariant &);
+ void processMessage(int, const QByteArray &);
void processLoad(int, const QUrl &);
- void reportScriptException(WorkerScript *);
+ void reportScriptException(WorkerScript *, const QDeclarativeError &error);
};
-QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine)
-: workerEngine(0), qmlengine(engine), m_nextId(0)
+QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QDeclarativeWorkerScriptEnginePrivate *parent)
+: p(parent), accessManager(0)
{
}
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::onMessage(QScriptContext *ctxt, QScriptEngine *engine)
+QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
+{
+ createsend.Dispose(); createsend.Clear();
+ onmessage.Dispose(); onmessage.Clear();
+ delete accessManager;
+}
+
+void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::init()
{
- QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(engine);
+ QV8Engine::init(0);
- int id = ctxt->thisObject().data().toVariant().toInt();
+#define CALL_ONMESSAGE_SCRIPT \
+ "(function(object, message) { "\
+ "var isfunction = false; "\
+ "try { "\
+ "isfunction = object.WorkerScript.onMessage instanceof Function; "\
+ "} catch (e) {}" \
+ "if (isfunction) "\
+ "object.WorkerScript.onMessage(message); "\
+ "})"
- WorkerScript *script = p->workers.value(id);
- if (!script)
- return engine->undefinedValue();
+#define SEND_MESSAGE_CREATE_SCRIPT \
+ "(function(method, engine) { "\
+ "return (function(id) { "\
+ "return (function(message) { "\
+ "if (arguments.length) method(engine, id, message); "\
+ "}); "\
+ "}); "\
+ "})"
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(context());
- if (ctxt->argumentCount() >= 1)
- script->callback = ctxt->argument(0);
+ {
+ v8::Local<v8::Script> onmessagescript = v8::Script::New(v8::String::New(CALL_ONMESSAGE_SCRIPT));
+ onmessage = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(onmessagescript->Run()));
+ }
+ {
+ v8::Local<v8::Script> createsendscript = v8::Script::New(v8::String::New(SEND_MESSAGE_CREATE_SCRIPT));
+ v8::Local<v8::Function> createsendconstructor = v8::Local<v8::Function>::Cast(createsendscript->Run());
- return script->callback;
+ v8::Handle<v8::Value> args[] = {
+ V8FUNCTION(QDeclarativeWorkerScriptEnginePrivate::sendMessage, this)
+ };
+ v8::Local<v8::Value> createsendvalue = createsendconstructor->Call(global(), 1, args);
+
+ createsend = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(createsendvalue));
+ }
}
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::sendMessage(QScriptContext *ctxt, QScriptEngine *engine)
+// Requires handle and context scope
+v8::Local<v8::Function> QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id)
{
- if (!ctxt->argumentCount())
- return engine->undefinedValue();
+ v8::Handle<v8::Value> args[] = { v8::Integer::New(id) };
+ return v8::Local<v8::Function>::Cast(createsend->Call(global(), 1, args));
+}
- QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(engine);
+// Requires handle and context scope
+void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::callOnMessage(v8::Handle<v8::Object> object,
+ v8::Handle<v8::Value> arg)
+{
+ v8::Handle<v8::Value> args[] = { object, arg };
+ onmessage->Call(global(), 2, args);
+}
- int id = ctxt->thisObject().data().toVariant().toInt();
+QNetworkAccessManager *QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager()
+{
+ if (!accessManager) {
+ if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
+ accessManager = p->qmlengine->networkAccessManagerFactory()->create(p);
+ } else {
+ accessManager = new QNetworkAccessManager(p);
+ }
+ }
+ return accessManager;
+}
- WorkerScript *script = p->workers.value(id);
- if (!script)
- return engine->undefinedValue();
+QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine)
+: workerEngine(0), qmlengine(engine), m_nextId(0)
+{
+}
- QMutexLocker(&p->m_lock);
+v8::Handle<v8::Value> QDeclarativeWorkerScriptEnginePrivate::sendMessage(const v8::Arguments &args)
+{
+ WorkerEngine *engine = (WorkerEngine*)V8ENGINE();
+
+ int id = args[1]->Int32Value();
+
+ QByteArray data = QV8Worker::serialize(args[2], engine);
+
+ QMutexLocker(&engine->p->m_lock);
+ WorkerScript *script = engine->p->workers.value(id);
+ if (!script)
+ return v8::Undefined();
if (script->owner)
- QCoreApplication::postEvent(script->owner,
- new WorkerDataEvent(0, scriptValueToVariant(ctxt->argument(0))));
+ QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data));
- return engine->undefinedValue();
+ return v8::Undefined();
}
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::getWorker(int id)
+// Requires handle scope and context scope
+v8::Handle<v8::Object> QDeclarativeWorkerScriptEnginePrivate::getWorker(WorkerScript *script)
{
- QHash<int, WorkerScript *>::ConstIterator iter = workers.find(id);
-
- if (iter == workers.end())
- return workerEngine->nullValue();
-
- WorkerScript *script = *iter;
if (!script->initialized) {
-
script->initialized = true;
- script->object = workerEngine->newObject();
- QScriptValue api = workerEngine->newObject();
- api.setData(script->id);
+ script->object = v8::Persistent<v8::Object>::New(workerEngine->contextWrapper()->urlScope(script->source));
- api.setProperty(QLatin1String("onMessage"), workerEngine->newFunction(onMessage),
- QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- api.setProperty(QLatin1String("sendMessage"), workerEngine->newFunction(sendMessage));
+ workerEngine->contextWrapper()->setReadOnly(script->object, false);
- script->object.setProperty(QLatin1String("WorkerScript"), api);
+ v8::Local<v8::Object> api = v8::Object::New();
+ api->Set(v8::String::New("sendMessage"), workerEngine->sendFunction(script->id));
+
+ script->object->Set(v8::String::New("WorkerScript"), api);
+
+ workerEngine->contextWrapper()->setReadOnly(script->object, true);
}
return script->object;
@@ -262,6 +318,7 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::getWorker(int id)
bool QDeclarativeWorkerScriptEnginePrivate::event(QEvent *event)
{
+ // XXX must handle remove request
if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
processMessage(workerEvent->workerId(), workerEvent->data());
@@ -278,22 +335,24 @@ bool QDeclarativeWorkerScriptEnginePrivate::event(QEvent *event)
}
}
-void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QVariant &data)
+void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &data)
{
WorkerScript *script = workers.value(id);
if (!script)
return;
- if (script->callback.isFunction()) {
- QScriptValue args = workerEngine->newArray(1);
- args.setProperty(0, variantToScriptValue(data, workerEngine));
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(workerEngine->context());
- script->callback.call(script->object, args);
+ v8::Handle<v8::Value> value = QV8Worker::deserialize(data, workerEngine);
- if (workerEngine->hasUncaughtException()) {
- reportScriptException(script);
- workerEngine->clearExceptions();
- }
+ v8::TryCatch tc;
+ workerEngine->callOnMessage(script->object, value);
+
+ if (tc.HasCaught()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(tc.Message(), error);
+ reportScriptException(script, error);
}
}
@@ -308,44 +367,41 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
if (f.open(QIODevice::ReadOnly)) {
QByteArray data = f.readAll();
QString sourceCode = QString::fromUtf8(data);
-
- QScriptValue activation = getWorker(id);
-
- QScriptContext *ctxt = QScriptDeclarativeClass::pushCleanContext(workerEngine);
- QScriptValue urlContext = workerEngine->newObject();
- urlContext.setData(QScriptValue(workerEngine, url.toString()));
- ctxt->pushScope(urlContext);
- ctxt->pushScope(activation);
- ctxt->setActivationObject(activation);
QDeclarativeScriptParser::extractPragmas(sourceCode);
- workerEngine->baseUrl = url;
- workerEngine->evaluate(sourceCode);
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(workerEngine->context());
WorkerScript *script = workers.value(id);
- if (script) {
- script->source = url;
- if (workerEngine->hasUncaughtException()) {
- reportScriptException(script);
- workerEngine->clearExceptions();
- }
+ if (!script)
+ return;
+ script->source = url;
+ v8::Handle<v8::Object> activation = getWorker(script);
+ if (activation.IsEmpty())
+ return;
+
+ // XXX ???
+ // workerEngine->baseUrl = url;
+
+ v8::TryCatch tc;
+ v8::Local<v8::Script> program = workerEngine->qmlModeCompile(sourceCode, url.toString());
+
+ if (!tc.HasCaught())
+ program->Run(activation);
+
+ if (tc.HasCaught()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(tc.Message(), error);
+ reportScriptException(script, error);
}
-
- workerEngine->popContext();
} else {
qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString();
}
}
-void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script)
+void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script,
+ const QDeclarativeError &error)
{
- if (!script || !workerEngine->hasUncaughtException())
- return;
-
- QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(workerEngine, error);
- error.setUrl(script->source);
-
QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(workerEngine);
QMutexLocker(&p->m_lock);
@@ -353,109 +409,7 @@ void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *
QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error));
}
-QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value)
-{
- if (value.isBool()) {
- return QVariant(value.toBool());
- } else if (value.isString()) {
- return QVariant(value.toString());
- } else if (value.isNumber()) {
- return QVariant((qreal)value.toNumber());
- } else if (value.isDate()) {
- return QVariant(value.toDateTime());
-#ifndef QT_NO_REGEXP
- } else if (value.isRegExp()) {
- return QVariant(value.toRegExp());
-#endif
- } else if (value.isArray()) {
- QVariantList list;
-
- quint32 length = (quint32)value.property(QLatin1String("length")).toNumber();
-
- for (quint32 ii = 0; ii < length; ++ii) {
- QVariant v = scriptValueToVariant(value.property(ii));
- list << v;
- }
-
- return QVariant(list);
- } else if (value.isQObject()) {
- QDeclarativeListModel *lm = qobject_cast<QDeclarativeListModel *>(value.toQObject());
- if (lm) {
- QDeclarativeListModelWorkerAgent *agent = lm->agent();
- if (agent) {
- QDeclarativeListModelWorkerAgent::VariantRef v(agent);
- return QVariant::fromValue(v);
- } else {
- return QVariant();
- }
- } else {
- // No other QObject's are allowed to be sent
- return QVariant();
- }
- } else if (value.isObject()) {
- QVariantHash hash;
-
- QScriptValueIterator iter(value);
-
- while (iter.hasNext()) {
- iter.next();
- hash.insert(iter.name(), scriptValueToVariant(iter.value()));
- }
-
- return QVariant(hash);
- }
-
- return QVariant();
-
-}
-
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(const QVariant &value, QScriptEngine *engine)
-{
- if (value.userType() == QVariant::Bool) {
- return QScriptValue(value.toBool());
- } else if (value.userType() == QVariant::String) {
- return QScriptValue(value.toString());
- } else if (value.userType() == QMetaType::QReal) {
- return QScriptValue(value.toReal());
- } else if (value.userType() == QVariant::DateTime) {
- return engine->newDate(value.toDateTime());
-#ifndef QT_NO_REGEXP
- } else if (value.userType() == QVariant::RegExp) {
- return engine->newRegExp(value.toRegExp());
-#endif
- } else if (value.userType() == qMetaTypeId<QDeclarativeListModelWorkerAgent::VariantRef>()) {
- QDeclarativeListModelWorkerAgent::VariantRef vr = qvariant_cast<QDeclarativeListModelWorkerAgent::VariantRef>(value);
- if (vr.a->scriptEngine() == 0)
- vr.a->setScriptEngine(engine);
- else if (vr.a->scriptEngine() != engine)
- return engine->nullValue();
- QScriptValue o = engine->newQObject(vr.a);
- o.setData(engine->newVariant(value)); // Keeps the agent ref so that it is cleaned up on gc
- return o;
- } else if (value.userType() == QMetaType::QVariantList) {
- QVariantList list = qvariant_cast<QVariantList>(value);
- QScriptValue rv = engine->newArray(list.count());
-
- for (quint32 ii = 0; ii < quint32(list.count()); ++ii)
- rv.setProperty(ii, variantToScriptValue(list.at(ii), engine));
-
- return rv;
- } else if (value.userType() == QMetaType::QVariantHash) {
-
- QVariantHash hash = qvariant_cast<QVariantHash>(value);
-
- QScriptValue rv = engine->newObject();
-
- for (QVariantHash::ConstIterator iter = hash.begin(); iter != hash.end(); ++iter)
- rv.setProperty(iter.key(), variantToScriptValue(iter.value(), engine));
-
- return rv;
- } else {
- return engine->nullValue();
- }
-}
-
-WorkerDataEvent::WorkerDataEvent(int workerId, const QVariant &data)
+WorkerDataEvent::WorkerDataEvent(int workerId, const QByteArray &data)
: QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data)
{
}
@@ -469,7 +423,7 @@ int WorkerDataEvent::workerId() const
return m_id;
}
-QVariant WorkerDataEvent::data() const
+QByteArray WorkerDataEvent::data() const
{
return m_data;
}
@@ -537,9 +491,16 @@ QDeclarativeWorkerScriptEnginePrivate::WorkerScript::WorkerScript()
{
}
+QDeclarativeWorkerScriptEnginePrivate::WorkerScript::~WorkerScript()
+{
+ object.Dispose(); object.Clear();
+}
+
int QDeclarativeWorkerScriptEngine::registerWorkerScript(QDeclarativeWorkerScript *owner)
{
- QDeclarativeWorkerScriptEnginePrivate::WorkerScript *script = new QDeclarativeWorkerScriptEnginePrivate::WorkerScript;
+ typedef QDeclarativeWorkerScriptEnginePrivate::WorkerScript WorkerScript;
+ WorkerScript *script = new WorkerScript;
+
script->id = d->m_nextId++;
script->owner = owner;
@@ -560,7 +521,7 @@ void QDeclarativeWorkerScriptEngine::executeUrl(int id, const QUrl &url)
QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url));
}
-void QDeclarativeWorkerScriptEngine::sendMessage(int id, const QVariant &data)
+void QDeclarativeWorkerScriptEngine::sendMessage(int id, const QByteArray &data)
{
QCoreApplication::postEvent(d, new WorkerDataEvent(id, data));
}
@@ -569,7 +530,11 @@ void QDeclarativeWorkerScriptEngine::run()
{
d->m_lock.lock();
- d->workerEngine = new QDeclarativeWorkerScriptEnginePrivate::ScriptEngine(d);
+ v8::Isolate *isolate = v8::Isolate::New();
+ isolate->Enter();
+
+ d->workerEngine = new QDeclarativeWorkerScriptEnginePrivate::WorkerEngine(d);
+ d->workerEngine->init();
d->m_wait.wakeAll();
@@ -578,6 +543,9 @@ void QDeclarativeWorkerScriptEngine::run()
exec();
delete d->workerEngine; d->workerEngine = 0;
+
+ isolate->Exit();
+ isolate->Dispose();
}
@@ -677,14 +645,18 @@ void QDeclarativeWorkerScript::setSource(const QUrl &source)
of ListModel objects, any modifications by the other thread to an object
passed in \c message will not be reflected in the original object.
*/
-void QDeclarativeWorkerScript::sendMessage(const QScriptValue &message)
+void QDeclarativeWorkerScript::sendMessage(QDeclarativeV8Function *args)
{
if (!engine()) {
qWarning("QDeclarativeWorkerScript: Attempt to send message before WorkerScript establishment");
return;
}
- m_engine->sendMessage(m_scriptId, QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(message));
+ v8::Handle<v8::Value> argument = v8::Undefined();
+ if (args->Length() != 0)
+ argument = (*args)[0];
+
+ m_engine->sendMessage(m_scriptId, QV8Worker::serialize(argument, args->engine()));
}
void QDeclarativeWorkerScript::classBegin()
@@ -731,11 +703,12 @@ bool QDeclarativeWorkerScript::event(QEvent *event)
if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
QDeclarativeEngine *engine = qmlEngine(this);
if (engine) {
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
- QScriptValue value =
- QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(workerEvent->data(), scriptEngine);
- emit message(value);
+ QV8Engine *v8engine = &QDeclarativeEnginePrivate::get(engine)->v8engine;
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(v8engine->context());
+ v8::Handle<v8::Value> value = QV8Worker::deserialize(workerEvent->data(), v8engine);
+ emit message(QDeclarativeV8Handle::fromHandle(value));
}
return true;
} else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) {
diff --git a/src/declarative/qml/qdeclarativeworkerscript_p.h b/src/declarative/qml/qdeclarativeworkerscript_p.h
index 70fdeb4d0d..54c9644efc 100644
--- a/src/declarative/qml/qdeclarativeworkerscript_p.h
+++ b/src/declarative/qml/qdeclarativeworkerscript_p.h
@@ -78,7 +78,7 @@ public:
int registerWorkerScript(QDeclarativeWorkerScript *);
void removeWorkerScript(int);
void executeUrl(int, const QUrl &);
- void sendMessage(int, const QVariant &);
+ void sendMessage(int, const QByteArray &);
protected:
virtual void run();
@@ -87,6 +87,8 @@ private:
QDeclarativeWorkerScriptEnginePrivate *d;
};
+class QDeclarativeV8Function;
+class QDeclarativeV8Handle;
class Q_AUTOTEST_EXPORT QDeclarativeWorkerScript : public QObject, public QDeclarativeParserStatus
{
Q_OBJECT
@@ -101,11 +103,11 @@ public:
void setSource(const QUrl &);
public slots:
- void sendMessage(const QScriptValue &);
+ void sendMessage(QDeclarativeV8Function*);
signals:
void sourceChanged();
- void message(const QScriptValue &messageObject);
+ void message(const QDeclarativeV8Handle &messageObject);
protected:
virtual void classBegin();
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
index 930d345285..0a3cbe5c7e 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp
+++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
@@ -41,6 +41,8 @@
#include "private/qdeclarativexmlhttprequest_p.h"
+#include <private/qv8engine_p.h>
+
#include "qdeclarativeengine.h"
#include "private/qdeclarativeengine_p.h"
#include "private/qdeclarativerefcount_p.h"
@@ -82,17 +84,17 @@
#define VALIDATION_ERR 16
#define TYPE_MISMATCH_ERR 17
-#define THROW_DOM(error, desc) \
-{ \
- QScriptValue errorValue = context->throwError(QLatin1String(desc)); \
- errorValue.setProperty(QLatin1String("code"), error); \
- return errorValue; \
-}
+#define V8THROW_DOM(error, string) { \
+ v8::Local<v8::Value> v = v8::Exception::Error(v8::String::New(string)); \
+ v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \
+ v8::ThrowException(v); \
+ return v8::Handle<v8::Value>(); \
+}
-#define THROW_SYNTAX(desc) \
- return context->throwError(QScriptContext::SyntaxError, QLatin1String(desc));
-#define THROW_REFERENCE(desc) \
- return context->throwError(QScriptContext::ReferenceError, QLatin1String(desc));
+#define V8THROW_REFERENCE(string) { \
+ v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \
+ return v8::Handle<v8::Value>(); \
+}
#define D(arg) (arg)->release()
#define A(arg) (arg)->addref()
@@ -101,6 +103,59 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(xhrDump, QML_XHR_DUMP);
+struct QDeclarativeXMLHttpRequestData {
+ QDeclarativeXMLHttpRequestData();
+ ~QDeclarativeXMLHttpRequestData();
+
+ v8::Persistent<v8::Function> nodeFunction;
+
+ v8::Persistent<v8::Object> namedNodeMapPrototype;
+ v8::Persistent<v8::Object> nodeListPrototype;
+ v8::Persistent<v8::Object> nodePrototype;
+ v8::Persistent<v8::Object> elementPrototype;
+ v8::Persistent<v8::Object> attrPrototype;
+ v8::Persistent<v8::Object> characterDataPrototype;
+ v8::Persistent<v8::Object> textPrototype;
+ v8::Persistent<v8::Object> cdataPrototype;
+ v8::Persistent<v8::Object> documentPrototype;
+
+ v8::Local<v8::Object> newNode();
+};
+
+static inline QDeclarativeXMLHttpRequestData *xhrdata(QV8Engine *engine)
+{
+ return (QDeclarativeXMLHttpRequestData *)engine->xmlHttpRequestData();
+}
+
+QDeclarativeXMLHttpRequestData::QDeclarativeXMLHttpRequestData()
+{
+}
+
+QDeclarativeXMLHttpRequestData::~QDeclarativeXMLHttpRequestData()
+{
+ nodeFunction.Dispose(); nodeFunction.Clear();
+ namedNodeMapPrototype.Dispose(); namedNodeMapPrototype.Clear();
+ nodeListPrototype.Dispose(); nodeListPrototype.Clear();
+ nodePrototype.Dispose(); nodePrototype.Clear();
+ elementPrototype.Dispose(); elementPrototype.Clear();
+ attrPrototype.Dispose(); attrPrototype.Clear();
+ characterDataPrototype.Dispose(); characterDataPrototype.Clear();
+ textPrototype.Dispose(); textPrototype.Clear();
+ cdataPrototype.Dispose(); cdataPrototype.Clear();
+ documentPrototype.Dispose(); documentPrototype.Clear();
+}
+
+v8::Local<v8::Object> QDeclarativeXMLHttpRequestData::newNode()
+{
+ if (nodeFunction.IsEmpty()) {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ nodeFunction = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+
+ return nodeFunction->NewInstance();
+}
+
namespace {
class DocumentImpl;
@@ -169,86 +224,53 @@ class NamedNodeMap
{
public:
// JS API
- static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> length(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> indexed(uint32_t index, const v8::AccessorInfo& info);
+ static v8::Handle<v8::Value> named(v8::Local<v8::String> property, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue create(QScriptEngine *, NodeImpl *, QList<NodeImpl *> *);
-
- NamedNodeMap();
- NamedNodeMap(const NamedNodeMap &);
- ~NamedNodeMap();
- bool isNull();
-
- NodeImpl *d;
- QList<NodeImpl *> *list;
-private:
- NamedNodeMap &operator=(const NamedNodeMap &);
-};
-
-class NamedNodeMapClass : public QScriptClass
-{
-public:
- NamedNodeMapClass(QScriptEngine *engine) : QScriptClass(engine) {}
-
- virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> create(QV8Engine *, NodeImpl *, QList<NodeImpl *> *);
};
class NodeList
{
public:
// JS API
- static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> length(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> indexed(uint32_t index, const v8::AccessorInfo& info);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue create(QScriptEngine *, NodeImpl *);
-
- NodeList();
- NodeList(const NodeList &);
- ~NodeList();
- bool isNull();
-
- NodeImpl *d;
-private:
- NodeList &operator=(const NodeList &);
-};
-
-class NodeListClass : public QScriptClass
-{
-public:
- NodeListClass(QScriptEngine *engine) : QScriptClass(engine) {}
- virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> create(QV8Engine *, NodeImpl *);
};
class Node
{
public:
// JS API
- static QScriptValue nodeName(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue nodeValue(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue nodeType(QScriptContext *context, QScriptEngine *engine);
-
- static QScriptValue parentNode(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue childNodes(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue firstChild(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue lastChild(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue previousSibling(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue nextSibling(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue attributes(QScriptContext *context, QScriptEngine *engine);
-
- //static QScriptValue ownerDocument(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue namespaceURI(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue prefix(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue localName(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue baseURI(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue textContent(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> nodeName(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> nodeValue(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> nodeType(v8::Local<v8::String>, const v8::AccessorInfo& args);
+
+ static v8::Handle<v8::Value> parentNode(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> childNodes(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> firstChild(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> lastChild(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> previousSibling(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> nextSibling(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> attributes(v8::Local<v8::String>, const v8::AccessorInfo& args);
+
+ //static v8::Handle<v8::Value> ownerDocument(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> namespaceURI(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> prefix(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> localName(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> baseURI(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> textContent(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue create(QScriptEngine *, NodeImpl *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> create(QV8Engine *, NodeImpl *);
Node();
Node(const Node &o);
@@ -265,68 +287,82 @@ class Element : public Node
{
public:
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class Attr : public Node
{
public:
// JS API
- static QScriptValue name(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue specified(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue value(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue ownerElement(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue schemaTypeInfo(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue isId(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> name(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> specified(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> value(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> ownerElement(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> schemaTypeInfo(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> isId(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class CharacterData : public Node
{
public:
// JS API
- static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> length(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class Text : public CharacterData
{
public:
// JS API
- static QScriptValue isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue wholeText(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> isElementContentWhitespace(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> wholeText(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class CDATA : public Text
{
public:
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class Document : public Node
{
public:
// JS API
- static QScriptValue xmlVersion(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue xmlEncoding(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue xmlStandalone(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue documentElement(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> xmlVersion(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> xmlEncoding(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> xmlStandalone(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> documentElement(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue load(QScriptEngine *engine, const QByteArray &data);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> load(QV8Engine *engine, const QByteArray &data);
};
}
+class QDeclarativeDOMNodeResource : public QV8ObjectResource, public Node
+{
+ V8_RESOURCE_TYPE(DOMNodeType);
+public:
+ QDeclarativeDOMNodeResource(QV8Engine *e);
+
+ QList<NodeImpl *> *list; // Only used in NamedNodeMap
+};
+
+QDeclarativeDOMNodeResource::QDeclarativeDOMNodeResource(QV8Engine *e)
+: QV8ObjectResource(e), list(0)
+{
+}
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Node)
@@ -345,152 +381,174 @@ void NodeImpl::release()
D(document);
}
-QScriptValue Node::nodeName(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nodeName(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- switch (node.d->type) {
+ switch (r->d->type) {
case NodeImpl::Document:
- return QScriptValue(QLatin1String("#document"));
+ return v8::String::New("#document");
case NodeImpl::CDATA:
- return QScriptValue(QLatin1String("#cdata-section"));
+ return v8::String::New("#cdata-section");
case NodeImpl::Text:
- return QScriptValue(QLatin1String("#text"));
+ return v8::String::New("#text");
default:
- return QScriptValue(node.d->name);
+ return engine->toString(r->d->name);
}
}
-QScriptValue Node::nodeValue(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nodeValue(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->type == NodeImpl::Document ||
- node.d->type == NodeImpl::DocumentFragment ||
- node.d->type == NodeImpl::DocumentType ||
- node.d->type == NodeImpl::Element ||
- node.d->type == NodeImpl::Entity ||
- node.d->type == NodeImpl::EntityReference ||
- node.d->type == NodeImpl::Notation)
- return engine->nullValue();
+ if (r->d->type == NodeImpl::Document ||
+ r->d->type == NodeImpl::DocumentFragment ||
+ r->d->type == NodeImpl::DocumentType ||
+ r->d->type == NodeImpl::Element ||
+ r->d->type == NodeImpl::Entity ||
+ r->d->type == NodeImpl::EntityReference ||
+ r->d->type == NodeImpl::Notation)
+ return v8::Null();
- return QScriptValue(node.d->data);
+ return engine->toString(r->d->data);
}
-QScriptValue Node::nodeType(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nodeType(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
- return QScriptValue(node.d->type);
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ return v8::Integer::New(r->d->type);
}
-QScriptValue Node::parentNode(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::parentNode(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->parent) return Node::create(engine, node.d->parent);
- else return engine->nullValue();
+ if (r->d->parent) return Node::create(engine, r->d->parent);
+ else return v8::Null();
}
-QScriptValue Node::childNodes(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::childNodes(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return NodeList::create(engine, node.d);
+ return NodeList::create(engine, r->d);
}
-QScriptValue Node::firstChild(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::firstChild(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->children.isEmpty()) return engine->nullValue();
- else return Node::create(engine, node.d->children.first());
+ if (r->d->children.isEmpty()) return v8::Null();
+ else return Node::create(engine, r->d->children.first());
}
-QScriptValue Node::lastChild(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::lastChild(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->children.isEmpty()) return engine->nullValue();
- else return Node::create(engine, node.d->children.last());
+ if (r->d->children.isEmpty()) return v8::Null();
+ else return Node::create(engine, r->d->children.last());
}
-QScriptValue Node::previousSibling(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::previousSibling(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (!node.d->parent) return engine->nullValue();
+ if (!r->d->parent) return v8::Null();
- for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
- if (node.d->parent->children.at(ii) == node.d) {
- if (ii == 0) return engine->nullValue();
- else return Node::create(engine, node.d->parent->children.at(ii - 1));
+ for (int ii = 0; ii < r->d->parent->children.count(); ++ii) {
+ if (r->d->parent->children.at(ii) == r->d) {
+ if (ii == 0) return v8::Null();
+ else return Node::create(engine, r->d->parent->children.at(ii - 1));
}
}
- return engine->nullValue();
+ return v8::Null();
}
-QScriptValue Node::nextSibling(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nextSibling(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (!node.d->parent) return engine->nullValue();
+ if (!r->d->parent) return v8::Null();
- for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
- if (node.d->parent->children.at(ii) == node.d) {
- if ((ii + 1) == node.d->parent->children.count()) return engine->nullValue();
- else return Node::create(engine, node.d->parent->children.at(ii + 1));
+ for (int ii = 0; ii < r->d->parent->children.count(); ++ii) {
+ if (r->d->parent->children.at(ii) == r->d) {
+ if ((ii + 1) == r->d->parent->children.count()) return v8::Null();
+ else return Node::create(engine, r->d->parent->children.at(ii + 1));
}
}
- return engine->nullValue();
+ return v8::Null();
}
-QScriptValue Node::attributes(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::attributes(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->type != NodeImpl::Element)
- return engine->nullValue();
+ if (r->d->type != NodeImpl::Element)
+ return v8::Null();
else
- return NamedNodeMap::create(engine, node.d, &node.d->attributes);
-}
-
-QScriptValue Node::prototype(QScriptEngine *engine)
-{
- QScriptValue proto = engine->newObject();
-
- proto.setProperty(QLatin1String("nodeName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("nodeValue"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("nodeType"), engine->newFunction(nodeType), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("parentNode"), engine->newFunction(parentNode), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("childNodes"), engine->newFunction(childNodes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("firstChild"), engine->newFunction(firstChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("lastChild"), engine->newFunction(lastChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("previousSibling"), engine->newFunction(previousSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("nextSibling"), engine->newFunction(nextSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("attributes"), engine->newFunction(attributes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return NamedNodeMap::create(engine, r->d, &r->d->attributes);
+}
+
+v8::Handle<v8::Object> Node::prototype(QV8Engine *engine)
+{
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->nodePrototype.IsEmpty()) {
+ d->nodePrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->nodePrototype->SetAccessor(v8::String::New("nodeName"), nodeName,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("nodeValue"), nodeValue,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("nodeType"), nodeType,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("parentNode"), parentNode,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("childNodes"), childNodes,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("firstChild"), firstChild,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("lastChild"), lastChild,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("previousSibling"), previousSibling,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("nextSibling"), nextSibling,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("attributes"), attributes,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->nodePrototype;
}
-QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
+v8::Handle<v8::Value> Node::create(QV8Engine *engine, NodeImpl *data)
{
- QScriptValue instance = engine->newObject();
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ v8::Local<v8::Object> instance = d->newNode();
switch (data->type) {
case NodeImpl::Attr:
- instance.setPrototype(Attr::prototype(engine));
+ instance->SetPrototype(Attr::prototype(engine));
break;
case NodeImpl::Comment:
case NodeImpl::Document:
@@ -500,138 +558,171 @@ QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
case NodeImpl::EntityReference:
case NodeImpl::Notation:
case NodeImpl::ProcessingInstruction:
- return QScriptValue();
+ return v8::Undefined();
case NodeImpl::CDATA:
- instance.setPrototype(CDATA::prototype(engine));
+ instance->SetPrototype(CDATA::prototype(engine));
break;
case NodeImpl::Text:
- instance.setPrototype(Text::prototype(engine));
+ instance->SetPrototype(Text::prototype(engine));
break;
case NodeImpl::Element:
- instance.setPrototype(Element::prototype(engine));
+ instance->SetPrototype(Element::prototype(engine));
break;
}
- Node node;
- node.d = data;
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = data;
if (data) A(data);
+ instance->SetExternalResource(r);
- return engine->newVariant(instance, QVariant::fromValue(node));
-}
-
-QScriptValue Element::prototype(QScriptEngine *engine)
-{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
-
- proto.setProperty(QLatin1String("tagName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
-}
-
-QScriptValue Attr::prototype(QScriptEngine *engine)
-{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
-
- proto.setProperty(QLatin1String("name"), engine->newFunction(name), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("value"), engine->newFunction(value), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("ownerElement"), engine->newFunction(ownerElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return instance;
}
-QScriptValue Attr::name(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Object> Element::prototype(QV8Engine *engine)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
-
- return QScriptValue(node.d->name);
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->elementPrototype.IsEmpty()) {
+ d->elementPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->elementPrototype->SetPrototype(Node::prototype(engine));
+ d->elementPrototype->SetAccessor(v8::String::New("tagName"), nodeName,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->elementPrototype;
+}
+
+v8::Handle<v8::Object> Attr::prototype(QV8Engine *engine)
+{
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->attrPrototype.IsEmpty()) {
+ d->attrPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->attrPrototype->SetPrototype(Node::prototype(engine));
+ d->attrPrototype->SetAccessor(v8::String::New("name"), name,
+ 0, v8::External::Wrap(engine));
+ d->attrPrototype->SetAccessor(v8::String::New("value"), value,
+ 0, v8::External::Wrap(engine));
+ d->attrPrototype->SetAccessor(v8::String::New("ownerElement"), ownerElement,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->attrPrototype;
}
-QScriptValue Attr::value(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Attr::name(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(node.d->data);
+ return engine->toString(r->d->name);
}
-QScriptValue Attr::ownerElement(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Attr::value(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return Node::create(engine, node.d->parent);
+ return engine->toString(r->d->data);
}
-QScriptValue CharacterData::length(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Attr::ownerElement(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(node.d->data.length());
+ return Node::create(engine, r->d->parent);
}
-QScriptValue CharacterData::prototype(QScriptEngine *engine)
+v8::Handle<v8::Value> CharacterData::length(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- proto.setProperty(QLatin1String("data"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return v8::Integer::New(r->d->data.length());
}
-QScriptValue Text::isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Object> CharacterData::prototype(QV8Engine *engine)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
-
- return node.d->data.trimmed().isEmpty();
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->characterDataPrototype.IsEmpty()) {
+ d->characterDataPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->characterDataPrototype->SetPrototype(Node::prototype(engine));
+ d->characterDataPrototype->SetAccessor(v8::String::New("data"), nodeValue,
+ 0, v8::External::Wrap(engine));
+ d->characterDataPrototype->SetAccessor(v8::String::New("length"), length,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->characterDataPrototype;
}
-QScriptValue Text::wholeText(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Text::isElementContentWhitespace(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return node.d->data;
+ return v8::Boolean::New(r->d->data.trimmed().isEmpty());
}
-QScriptValue Text::prototype(QScriptEngine *engine)
+v8::Handle<v8::Value> Text::wholeText(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(CharacterData::prototype(engine));
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- proto.setProperty(QLatin1String("isElementContentWhitespace"), engine->newFunction(isElementContentWhitespace), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("wholeText"), engine->newFunction(wholeText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return engine->toString(r->d->data);
}
-QScriptValue CDATA::prototype(QScriptEngine *engine)
+v8::Handle<v8::Object> Text::prototype(QV8Engine *engine)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Text::prototype(engine));
- return proto;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->textPrototype.IsEmpty()) {
+ d->textPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->textPrototype->SetPrototype(CharacterData::prototype(engine));
+ d->textPrototype->SetAccessor(v8::String::New("isElementContentWhitespace"), isElementContentWhitespace,
+ 0, v8::External::Wrap(engine));
+ d->textPrototype->SetAccessor(v8::String::New("wholeText"), wholeText,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->textPrototype;
}
-QScriptValue Document::prototype(QScriptEngine *engine)
+v8::Handle<v8::Object> CDATA::prototype(QV8Engine *engine)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
-
- proto.setProperty(QLatin1String("xmlVersion"), engine->newFunction(xmlVersion), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("xmlEncoding"), engine->newFunction(xmlEncoding), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("xmlStandalone"), engine->newFunction(xmlStandalone), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("documentElement"), engine->newFunction(documentElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->cdataPrototype.IsEmpty()) {
+ d->cdataPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->cdataPrototype->SetPrototype(Text::prototype(engine));
+ // XXX freeze
+ }
+ return d->cdataPrototype;
+}
+
+v8::Handle<v8::Object> Document::prototype(QV8Engine *engine)
+{
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->documentPrototype.IsEmpty()) {
+ d->documentPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->documentPrototype->SetPrototype(Node::prototype(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("xmlVersion"), xmlVersion,
+ 0, v8::External::Wrap(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("xmlEncoding"), xmlEncoding,
+ 0, v8::External::Wrap(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("xmlStandalone"), xmlStandalone,
+ 0, v8::External::Wrap(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("documentElement"), documentElement,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->documentPrototype;
}
-QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data)
+v8::Handle<v8::Value> Document::load(QV8Engine *engine, const QByteArray &data)
{
Q_ASSERT(engine);
@@ -709,14 +800,15 @@ QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data)
if (!document || reader.hasError()) {
if (document) D(document);
- return engine->nullValue();
+ return v8::Null();
}
- QScriptValue instance = engine->newObject();
- instance.setPrototype(Document::prototype(engine));
- Node documentNode;
- documentNode.d = document;
- return engine->newVariant(instance, QVariant::fromValue(documentNode));
+ v8::Local<v8::Object> instance = xhrdata(engine)->newNode();
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = document;
+ instance->SetExternalResource(r);
+ instance->SetPrototype(Document::prototype(engine));
+ return instance;
}
Node::Node()
@@ -740,221 +832,165 @@ bool Node::isNull() const
return d == 0;
}
-QScriptValue NamedNodeMap::length(QScriptContext *context, QScriptEngine *engine)
-{
- NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(context->thisObject().data());
- if (map.isNull()) return engine->undefinedValue();
-
- return QScriptValue(map.list->count());
-}
-
-QScriptValue NamedNodeMap::prototype(QScriptEngine *engine)
+v8::Handle<v8::Value> NamedNodeMap::length(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- QScriptValue proto = engine->newObject();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return v8::Integer::New(r->list->count());
}
-QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<NodeImpl *> *list)
+v8::Handle<v8::Value> NamedNodeMap::indexed(uint32_t index, const v8::AccessorInfo& args)
{
- QScriptValue instance = engine->newObject();
- instance.setPrototype(NamedNodeMap::prototype(engine));
-
- NamedNodeMap map;
- map.d = data;
- map.list = list;
- if (data) A(data);
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || !r->list) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- instance.setData(engine->newVariant(QVariant::fromValue(map)));
-
- if (!QDeclarativeScriptEngine::get(engine)->namedNodeMapClass)
- QDeclarativeScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine);
-
- instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->namedNodeMapClass);
-
- return instance;
-}
-
-NamedNodeMap::NamedNodeMap()
-: d(0), list(0)
-{
-}
-
-NamedNodeMap::NamedNodeMap(const NamedNodeMap &o)
-: d(o.d), list(o.list)
-{
- if (d) A(d);
-}
-
-NamedNodeMap::~NamedNodeMap()
-{
- if (d) D(d);
+ if (index < r->list->count()) {
+ return Node::create(engine, r->list->at(index));
+ } else {
+ return v8::Undefined();
+ }
}
-bool NamedNodeMap::isNull()
+v8::Handle<v8::Value> NamedNodeMap::named(v8::Local<v8::String> property, const v8::AccessorInfo& args)
{
- return d == 0;
-}
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || !r->list) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
-QScriptValue NodeList::length(QScriptContext *context, QScriptEngine *engine)
-{
- NodeList list = qscriptvalue_cast<NodeList>(context->thisObject().data());
- if (list.isNull()) return engine->undefinedValue();
+ QString str = engine->toString(property);
+ for (int ii = 0; ii < r->list->count(); ++ii) {
+ if (r->list->at(ii)->name == str) {
+ return Node::create(engine, r->list->at(ii));
+ }
+ }
- return QScriptValue(list.d->children.count());
+ return v8::Undefined();
}
-QScriptValue NodeList::prototype(QScriptEngine *engine)
+v8::Handle<v8::Object> NamedNodeMap::prototype(QV8Engine *engine)
{
- QScriptValue proto = engine->newObject();
-
- proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->namedNodeMapPrototype.IsEmpty()) {
+ v8::Local<v8::ObjectTemplate> ot = v8::ObjectTemplate::New();
+ ot->SetAccessor(v8::String::New("length"), length, 0, v8::External::Wrap(engine));
+ ot->SetIndexedPropertyHandler(indexed, 0, 0, 0, 0, v8::External::Wrap(engine));
+ ot->SetFallbackPropertyHandler(named, 0, 0, 0, 0, v8::External::Wrap(engine));
+ d->namedNodeMapPrototype = v8::Persistent<v8::Object>::New(ot->NewInstance());
+ // XXX freeze
+ }
+ return d->namedNodeMapPrototype;
}
-QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data)
+v8::Handle<v8::Value> NamedNodeMap::create(QV8Engine *engine, NodeImpl *data, QList<NodeImpl *> *list)
{
- QScriptValue instance = engine->newObject();
- instance.setPrototype(NodeList::prototype(engine));
-
- NodeList list;
- list.d = data;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ v8::Local<v8::Object> instance = d->newNode();
+ instance->SetPrototype(NamedNodeMap::prototype(engine));
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = data;
+ r->list = list;
if (data) A(data);
-
- instance.setData(engine->newVariant(QVariant::fromValue(list)));
-
- if (!QDeclarativeScriptEngine::get(engine)->nodeListClass)
- QDeclarativeScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine);
-
- instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->nodeListClass);
-
+ instance->SetExternalResource(r);
return instance;
}
-NodeList::NodeList()
-: d(0)
-{
-}
-
-NodeList::NodeList(const NodeList &o)
-: d(o.d)
-{
- if (d) A(d);
-}
-
-NodeList::~NodeList()
-{
- if (d) D(d);
-}
-
-bool NodeList::isNull()
+v8::Handle<v8::Value> NodeList::indexed(uint32_t index, const v8::AccessorInfo& args)
{
- return d == 0;
-}
-
-NamedNodeMapClass::QueryFlags NamedNodeMapClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
-{
- if (!(flags & HandlesReadAccess))
- return 0;
-
- NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
- Q_ASSERT(!map.isNull());
-
- bool ok = false;
- QString nameString = name.toString();
- uint index = nameString.toUInt(&ok);
- if (ok) {
- if ((uint)map.list->count() <= index)
- return 0;
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- *id = index;
- return HandlesReadAccess;
+ if (index < r->d->children.count()) {
+ return Node::create(engine, r->d->children.at(index));
} else {
- for (int ii = 0; ii < map.list->count(); ++ii) {
- if (map.list->at(ii) && map.list->at(ii)->name == nameString) {
- *id = ii;
- return HandlesReadAccess;
- }
- }
+ // XXX RangeError exception?
+ return v8::Undefined();
}
-
- return 0;
}
-QScriptValue NamedNodeMapClass::property(const QScriptValue &object, const QScriptString &, uint id)
+v8::Handle<v8::Value> NodeList::length(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
- return Node::create(engine(), map.list->at(id));
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
+
+ return v8::Integer::New(r->d->children.count());
}
-NodeListClass::QueryFlags NodeListClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
+v8::Handle<v8::Object> NodeList::prototype(QV8Engine *engine)
{
- if (!(flags & HandlesReadAccess))
- return 0;
-
- bool ok = false;
- uint index = name.toString().toUInt(&ok);
- if (!ok)
- return 0;
-
- NodeList list = qscriptvalue_cast<NodeList>(object.data());
- if (list.isNull() || (uint)list.d->children.count() <= index)
- return 0; // ### I think we're meant to raise an exception
-
- *id = index;
- return HandlesReadAccess;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->nodeListPrototype.IsEmpty()) {
+ v8::Local<v8::ObjectTemplate> ot = v8::ObjectTemplate::New();
+ ot->SetAccessor(v8::String::New("length"), length, 0, v8::External::Wrap(engine));
+ ot->SetIndexedPropertyHandler(indexed, 0, 0, 0, 0, v8::External::Wrap(engine));
+ d->nodeListPrototype = v8::Persistent<v8::Object>::New(ot->NewInstance());
+ // XXX freeze
+ }
+ return d->nodeListPrototype;
}
-QScriptValue NodeListClass::property(const QScriptValue &object, const QScriptString &, uint id)
+v8::Handle<v8::Value> NodeList::create(QV8Engine *engine, NodeImpl *data)
{
- NodeList list = qscriptvalue_cast<NodeList>(object.data());
- return Node::create(engine(), list.d->children.at(id));
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ v8::Local<v8::Object> instance = d->newNode();
+ instance->SetPrototype(NodeList::prototype(engine));
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = data;
+ if (data) A(data);
+ instance->SetExternalResource(r);
+ return instance;
}
-QScriptValue Document::documentElement(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::documentElement(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return Node::create(engine, static_cast<DocumentImpl *>(document.d)->root);
+ return Node::create(engine, static_cast<DocumentImpl *>(r->d)->root);
}
-QScriptValue Document::xmlStandalone(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::xmlStandalone(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(static_cast<DocumentImpl *>(document.d)->isStandalone);
+ return v8::Boolean::New(static_cast<DocumentImpl *>(r->d)->isStandalone);
}
-QScriptValue Document::xmlVersion(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::xmlVersion(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(static_cast<DocumentImpl *>(document.d)->version);
+ return engine->toString(static_cast<DocumentImpl *>(r->d)->version);
}
-QScriptValue Document::xmlEncoding(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::xmlEncoding(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(static_cast<DocumentImpl *>(document.d)->encoding);
+ return engine->toString(static_cast<DocumentImpl *>(r->d)->encoding);
}
-class QDeclarativeXMLHttpRequest : public QObject
+class QDeclarativeXMLHttpRequest : public QObject, public QV8ObjectResource
{
Q_OBJECT
+V8_RESOURCE_TYPE(XMLHttpRequestType)
public:
enum State { Unsent = 0,
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
- QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager);
+ QDeclarativeXMLHttpRequest(QV8Engine *engine, QNetworkAccessManager *manager);
virtual ~QDeclarativeXMLHttpRequest();
bool sendFlag() const;
@@ -963,13 +999,14 @@ public:
int replyStatus() const;
QString replyStatusText() const;
- QScriptValue open(QScriptValue *me, const QString &, const QUrl &);
+ v8::Handle<v8::Value> open(v8::Handle<v8::Object> me, const QString &, const QUrl &);
+ v8::Handle<v8::Value> send(v8::Handle<v8::Object> me, const QByteArray &);
+ v8::Handle<v8::Value> abort(v8::Handle<v8::Object> me);
void addHeader(const QString &, const QString &);
QString header(const QString &name);
QString headers();
- QScriptValue send(QScriptValue *me, const QByteArray &);
- QScriptValue abort(QScriptValue *me);
+
QString responseBody();
const QByteArray & rawResponseBody() const;
@@ -1005,10 +1042,12 @@ private:
#endif
void readEncoding();
- QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback)
+ v8::Handle<v8::Object> getMe() const;
+ void setMe(v8::Handle<v8::Object> me);
+ v8::Persistent<v8::Object> m_me;
- QScriptValue dispatchCallback(QScriptValue *me);
- void printError(const QScriptValue&);
+ void dispatchCallback(v8::Handle<v8::Object> me);
+ void printError(v8::Handle<v8::Message>);
int m_status;
QString m_statusText;
@@ -1020,8 +1059,8 @@ private:
QNetworkAccessManager *networkAccessManager() { return m_nam; }
};
-QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager)
-: m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
+QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QV8Engine *engine, QNetworkAccessManager *manager)
+: QV8ObjectResource(engine), m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
{
}
@@ -1056,7 +1095,8 @@ QString QDeclarativeXMLHttpRequest::replyStatusText() const
return m_statusText;
}
-QScriptValue QDeclarativeXMLHttpRequest::open(QScriptValue *me, const QString &method, const QUrl &url)
+v8::Handle<v8::Value> QDeclarativeXMLHttpRequest::open(v8::Handle<v8::Object> me, const QString &method,
+ const QUrl &url)
{
destroyNetwork();
m_sendFlag = false;
@@ -1065,7 +1105,8 @@ QScriptValue QDeclarativeXMLHttpRequest::open(QScriptValue *me, const QString &m
m_method = method;
m_url = url;
m_state = Opened;
- return dispatchCallback(me);
+ dispatchCallback(me);
+ return v8::Undefined();
}
void QDeclarativeXMLHttpRequest::addHeader(const QString &name, const QString &value)
@@ -1176,20 +1217,21 @@ void QDeclarativeXMLHttpRequest::requestFromUrl(const QUrl &url)
this, SLOT(finished()));
}
-QScriptValue QDeclarativeXMLHttpRequest::send(QScriptValue *me, const QByteArray &data)
+v8::Handle<v8::Value> QDeclarativeXMLHttpRequest::send(v8::Handle<v8::Object> me, const QByteArray &data)
{
m_errorFlag = false;
m_sendFlag = true;
m_redirectCount = 0;
m_data = data;
- m_me = *me;
+
+ setMe(me);
requestFromUrl(m_url);
- return QScriptValue();
+ return v8::Undefined();
}
-QScriptValue QDeclarativeXMLHttpRequest::abort(QScriptValue *me)
+v8::Handle<v8::Value> QDeclarativeXMLHttpRequest::abort(v8::Handle<v8::Object> me)
{
destroyNetwork();
m_responseEntityBody = QByteArray();
@@ -1202,16 +1244,32 @@ QScriptValue QDeclarativeXMLHttpRequest::abort(QScriptValue *me)
m_state = Done;
m_sendFlag = false;
- QScriptValue cbv = dispatchCallback(me);
- if (cbv.isError()) return cbv;
+ dispatchCallback(me);
}
m_state = Unsent;
- return QScriptValue();
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Object> QDeclarativeXMLHttpRequest::getMe() const
+{
+ return m_me;
+}
+
+void QDeclarativeXMLHttpRequest::setMe(v8::Handle<v8::Object> me)
+{
+ m_me.Dispose();
+ m_me = v8::Persistent<v8::Object>();
+
+ if (!me.IsEmpty())
+ m_me = v8::Persistent<v8::Object>::New(me);
}
void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes)
{
+ v8::HandleScope handle_scope;
+
Q_UNUSED(bytes)
m_status =
m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -1222,16 +1280,18 @@ void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes)
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
bool wasEmpty = m_responseEntityBody.isEmpty();
m_responseEntityBody.append(m_network->readAll());
if (wasEmpty && !m_responseEntityBody.isEmpty()) {
m_state = Loading;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
}
@@ -1249,6 +1309,8 @@ static const char *errorToString(QNetworkReply::NetworkError error)
void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error)
{
+ v8::HandleScope handle_scope;
+
Q_UNUSED(error)
m_status =
m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -1272,20 +1334,25 @@ void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error)
error == QNetworkReply::AuthenticationRequiredError ||
error == QNetworkReply::ContentReSendError) {
m_state = Loading;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
} else {
m_errorFlag = true;
}
m_state = Done;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
void QDeclarativeXMLHttpRequest::finished()
{
+ v8::HandleScope handle_scope;
+
m_redirectCount++;
if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) {
QVariant redirect = m_network->attribute(QNetworkRequest::RedirectionTargetAttribute);
@@ -1305,8 +1372,9 @@ void QDeclarativeXMLHttpRequest::finished()
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
m_responseEntityBody.append(m_network->readAll());
readEncoding();
@@ -1324,14 +1392,17 @@ void QDeclarativeXMLHttpRequest::finished()
destroyNetwork();
if (m_state < Loading) {
m_state = Loading;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
m_state = Done;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
- m_me = QScriptValue();
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
+
+ setMe(v8::Handle<v8::Object>());
}
@@ -1409,17 +1480,25 @@ const QByteArray &QDeclarativeXMLHttpRequest::rawResponseBody() const
return m_responseEntityBody;
}
-QScriptValue QDeclarativeXMLHttpRequest::dispatchCallback(QScriptValue *me)
+// Requires a TryCatch scope
+void QDeclarativeXMLHttpRequest::dispatchCallback(v8::Handle<v8::Object> me)
{
- QScriptValue v = me->property(QLatin1String("callback"));
- return v.call();
+ v8::Local<v8::Value> callback = me->Get(v8::String::New("onreadystatechange"));
+ if (callback->IsFunction()) {
+ v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(callback);
+
+ f->Call(me, 0, 0);
+ }
}
-void QDeclarativeXMLHttpRequest::printError(const QScriptValue& sv)
+// Must have a handle scope
+void QDeclarativeXMLHttpRequest::printError(v8::Handle<v8::Message> message)
{
+ v8::Context::Scope scope(engine->context());
+
QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(sv.engine(), error);
- QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(sv.engine()), error);
+ QDeclarativeExpressionPrivate::exceptionToError(message, error);
+ QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(engine->engine()), error);
}
void QDeclarativeXMLHttpRequest::destroyNetwork()
@@ -1432,71 +1511,68 @@ void QDeclarativeXMLHttpRequest::destroyNetwork()
}
// XMLHttpRequest methods
-static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_open(const v8::Arguments &args)
{
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (context->argumentCount() < 2 || context->argumentCount() > 5)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ if (args.Length() < 2 || args.Length() > 5)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+
+ QV8Engine *engine = r->engine;
// Argument 0 - Method
- QString method = context->argument(0).toString().toUpper();
+ QString method = engine->toString(args[0]).toUpper();
if (method != QLatin1String("GET") &&
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
method != QLatin1String("POST"))
- THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
-
+ V8THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
- QUrl url = QUrl::fromEncoded(context->argument(1).toString().toUtf8());
+ QUrl url = QUrl::fromEncoded(engine->toString(args[1]).toUtf8());
- if (url.isRelative()) {
- url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(context,url);
- }
+ if (url.isRelative())
+ url = engine->callingContext()->resolvedUrl(url);
// Argument 2 - async (optional)
- if (context->argumentCount() > 2 && !context->argument(2).toBoolean())
- THROW_DOM(NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
-
+ if (args.Length() > 2 && !args[2]->BooleanValue())
+ V8THROW_DOM(NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
// Argument 3/4 - user/pass (optional)
QString username, password;
- if (context->argumentCount() > 3)
- username = context->argument(3).toString();
- if (context->argumentCount() > 4)
- password = context->argument(4).toString();
-
+ if (args.Length() > 3)
+ username = engine->toString(args[3]);
+ if (args.Length() > 4)
+ password = engine->toString(args[4]);
// Clear the fragment (if any)
url.setFragment(QString());
+
// Set username/password
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- return request->open(&dataObject, method, url);
+ return r->open(args.This(), method, url);
}
-static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_setRequestHeader(const v8::Arguments &args)
{
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
-
- if (context->argumentCount() != 2)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
+ if (args.Length() != 2)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
- if (request->readyState() != QDeclarativeXMLHttpRequest::Opened ||
- request->sendFlag())
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Opened || r->sendFlag())
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ QV8Engine *engine = r->engine;
- QString name = context->argument(0).toString();
- QString value = context->argument(1).toString();
+ QString name = engine->toString(args[0]);
+ QString value = engine->toString(args[1]);
// ### Check that name and value are well formed
@@ -1521,237 +1597,243 @@ static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context,
nameUpper == QLatin1String("VIA") ||
nameUpper.startsWith(QLatin1String("PROXY-")) ||
nameUpper.startsWith(QLatin1String("SEC-")))
- return engine->undefinedValue();
+ return v8::Undefined();
- request->addHeader(nameUpper, value);
+ r->addHeader(nameUpper, value);
- return engine->undefinedValue();
+ return v8::Undefined();
}
-static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngine *)
+static v8::Handle<v8::Value> qmlxmlhttprequest_send(const v8::Arguments &args)
{
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (request->readyState() != QDeclarativeXMLHttpRequest::Opened)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ QV8Engine *engine = r->engine;
- if (request->sendFlag())
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Opened ||
+ r->sendFlag())
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
QByteArray data;
- if (context->argumentCount() > 0)
- data = context->argument(0).toString().toUtf8();
+ if (args.Length() > 0)
+ data = engine->toString(args[0]).toUtf8();
- return request->send(&dataObject, data);
+ return r->send(args.This(), data);
}
-static QScriptValue qmlxmlhttprequest_abort(QScriptContext *context, QScriptEngine *)
+static v8::Handle<v8::Value> qmlxmlhttprequest_abort(const v8::Arguments &args)
{
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- return request->abort(&dataObject);
+ return r->abort(args.This());
}
-static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_getResponseHeader(const v8::Arguments &args)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (context->argumentCount() != 1)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ QV8Engine *engine = r->engine;
- if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done &&
- request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (args.Length() != 1)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
- QString headerName = context->argument(0).toString();
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done &&
+ r->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
- return QScriptValue(request->header(headerName));
+ return engine->toString(r->header(engine->toString(args[0])));
}
-static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_getAllResponseHeaders(const v8::Arguments &args)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ QV8Engine *engine = r->engine;
- if (context->argumentCount() != 0)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ if (args.Length() != 0)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
- if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done &&
- request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done &&
+ r->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
- return QScriptValue(request->headers());
+ return engine->toString(r->headers());
}
// XMLHttpRequest properties
-static QScriptValue qmlxmlhttprequest_readyState(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_readyState(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- return QScriptValue(request->readyState());
+ return v8::Integer::NewFromUnsigned(r->readyState());
}
-static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_status(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
- request->readyState() == QDeclarativeXMLHttpRequest::Opened)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
+ r->readyState() == QDeclarativeXMLHttpRequest::Opened)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
- if (request->errorFlag())
- return QScriptValue(0);
+ if (r->errorFlag())
+ return v8::Integer::New(0);
else
- return QScriptValue(request->replyStatus());
+ return v8::Integer::New(r->replyStatus());
}
-static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_statusText(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
- request->readyState() == QDeclarativeXMLHttpRequest::Opened)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ QV8Engine *engine = r->engine;
- if (request->errorFlag())
- return QScriptValue(0);
+ if (r->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
+ r->readyState() == QDeclarativeXMLHttpRequest::Opened)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ if (r->errorFlag())
+ return engine->toString(QString());
else
- return QScriptValue(request->replyStatusText());
+ return engine->toString(r->replyStatusText());
}
-static QScriptValue qmlxmlhttprequest_responseText(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_responseText(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ QV8Engine *engine = r->engine;
- if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done)
- return QScriptValue(QString());
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done)
+ return engine->toString(QString());
else
- return QScriptValue(request->responseBody());
+ return engine->toString(r->responseBody());
}
-static QScriptValue qmlxmlhttprequest_responseXML(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_responseXML(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (!request->receivedXml() ||
- (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done))
- return engine->nullValue();
- else
- return Document::load(engine, request->rawResponseBody());
+ if (!r->receivedXml() ||
+ (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done)) {
+ return v8::Null();
+ } else {
+ return Document::load(r->engine, r->rawResponseBody());
+ }
}
-static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_new(const v8::Arguments &args)
{
- Q_UNUSED(engine);
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ if (args.IsConstructCall()) {
+ QV8Engine *engine = V8ENGINE();
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+
+ QDeclarativeXMLHttpRequest *r = new QDeclarativeXMLHttpRequest(engine, engine->networkAccessManager());
+ args.This()->SetExternalResource(r);
- if (context->argumentCount()) {
- QScriptValue v = context->argument(0);
- dataObject.setProperty(QLatin1String("callback"), v);
- return v;
+ return args.This();
} else {
- return dataObject.property(QLatin1String("callback"));
+ return v8::Undefined();
}
}
-// Constructor
-static QScriptValue qmlxmlhttprequest_new(QScriptContext *context, QScriptEngine *engine)
+#define NEWFUNCTION(function) v8::FunctionTemplate::New(function)->GetFunction()
+
+void qt_rem_qmlxmlhttprequest(QV8Engine *engine, void *d)
{
- if (context->isCalledAsConstructor()) {
- context->thisObject().setData(engine->newQObject(new QDeclarativeXMLHttpRequest(QDeclarativeScriptEngine::get(engine)->networkAccessManager()), QScriptEngine::ScriptOwnership));
- }
- return engine->undefinedValue();
+ QDeclarativeXMLHttpRequestData *data = (QDeclarativeXMLHttpRequestData *)d;
+ delete data;
}
-void qt_add_qmlxmlhttprequest(QScriptEngine *engine)
+void *qt_add_qmlxmlhttprequest(QV8Engine *engine)
{
- QScriptValue prototype = engine->newObject();
+ v8::PropertyAttribute attributes = (v8::PropertyAttribute)(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
+
+ // XMLHttpRequest
+ v8::Local<v8::FunctionTemplate> xmlhttprequest = v8::FunctionTemplate::New(qmlxmlhttprequest_new,
+ v8::External::Wrap(engine));
+ xmlhttprequest->InstanceTemplate()->SetHasExternalResource(true);
// Methods
- prototype.setProperty(QLatin1String("open"), engine->newFunction(qmlxmlhttprequest_open, 2));
- prototype.setProperty(QLatin1String("setRequestHeader"), engine->newFunction(qmlxmlhttprequest_setRequestHeader, 2));
- prototype.setProperty(QLatin1String("send"), engine->newFunction(qmlxmlhttprequest_send));
- prototype.setProperty(QLatin1String("abort"), engine->newFunction(qmlxmlhttprequest_abort));
- prototype.setProperty(QLatin1String("getResponseHeader"), engine->newFunction(qmlxmlhttprequest_getResponseHeader, 1));
- prototype.setProperty(QLatin1String("getAllResponseHeaders"), engine->newFunction(qmlxmlhttprequest_getAllResponseHeaders));
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("open"), NEWFUNCTION(qmlxmlhttprequest_open), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("setRequestHeader"), NEWFUNCTION(qmlxmlhttprequest_setRequestHeader), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("send"), NEWFUNCTION(qmlxmlhttprequest_send), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("abort"), NEWFUNCTION(qmlxmlhttprequest_abort), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("getResponseHeader"), NEWFUNCTION(qmlxmlhttprequest_getResponseHeader), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("getAllResponseHeaders"), NEWFUNCTION(qmlxmlhttprequest_getAllResponseHeaders), attributes);
// Read-only properties
- prototype.setProperty(QLatin1String("readyState"), engine->newFunction(qmlxmlhttprequest_readyState), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("status"), engine->newFunction(qmlxmlhttprequest_status), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("statusText"), engine->newFunction(qmlxmlhttprequest_statusText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("responseText"), engine->newFunction(qmlxmlhttprequest_responseText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("responseXML"), engine->newFunction(qmlxmlhttprequest_responseXML), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("onreadystatechange"), engine->newFunction(qmlxmlhttprequest_onreadystatechange), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("readyState"), qmlxmlhttprequest_readyState, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("status"),qmlxmlhttprequest_status, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("statusText"),qmlxmlhttprequest_statusText, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("responseText"),qmlxmlhttprequest_responseText, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("responseXML"),qmlxmlhttprequest_responseXML, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
// State values
- prototype.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("UNSENT"), v8::Integer::New(0), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("OPENED"), v8::Integer::New(1), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("HEADERS_RECEIVED"), v8::Integer::New(2), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("LOADING"), v8::Integer::New(3), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("DONE"), v8::Integer::New(4), attributes);
// Constructor
- QScriptValue constructor = engine->newFunction(qmlxmlhttprequest_new, prototype);
- constructor.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- engine->globalObject().setProperty(QLatin1String("XMLHttpRequest"), constructor);
+ xmlhttprequest->Set(v8::String::New("UNSENT"), v8::Integer::New(0), attributes);
+ xmlhttprequest->Set(v8::String::New("OPENED"), v8::Integer::New(1), attributes);
+ xmlhttprequest->Set(v8::String::New("HEADERS_RECEIVED"), v8::Integer::New(2), attributes);
+ xmlhttprequest->Set(v8::String::New("LOADING"), v8::Integer::New(3), attributes);
+ xmlhttprequest->Set(v8::String::New("DONE"), v8::Integer::New(4), attributes);
+ engine->global()->Set(v8::String::New("XMLHttpRequest"), xmlhttprequest->GetFunction());
// DOM Exception
- QScriptValue domExceptionPrototype = engine->newObject();
- domExceptionPrototype.setProperty(QLatin1String("INDEX_SIZE_ERR"), INDEX_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("DOMSTRING_SIZE_ERR"), DOMSTRING_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("HIERARCHY_REQUEST_ERR"), HIERARCHY_REQUEST_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("WRONG_DOCUMENT_ERR"), WRONG_DOCUMENT_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_CHARACTER_ERR"), INVALID_CHARACTER_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NO_DATA_ALLOWED_ERR"), NO_DATA_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NO_MODIFICATION_ALLOWED_ERR"), NO_MODIFICATION_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NOT_FOUND_ERR"), NOT_FOUND_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NOT_SUPPORTED_ERR"), NOT_SUPPORTED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INUSE_ATTRIBUTE_ERR"), INUSE_ATTRIBUTE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_STATE_ERR"), INVALID_STATE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("SYNTAX_ERR"), SYNTAX_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_MODIFICATION_ERR"), INVALID_MODIFICATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NAMESPACE_ERR"), NAMESPACE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_ACCESS_ERR"), INVALID_ACCESS_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("VALIDATION_ERR"), VALIDATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("TYPE_MISMATCH_ERR"), TYPE_MISMATCH_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
-
- engine->globalObject().setProperty(QLatin1String("DOMException"), domExceptionPrototype);
+ v8::Local<v8::Object> domexception = v8::Object::New();
+ domexception->Set(v8::String::New("INDEX_SIZE_ERR"), v8::Integer::New(INDEX_SIZE_ERR), attributes);
+ domexception->Set(v8::String::New("DOMSTRING_SIZE_ERR"), v8::Integer::New(DOMSTRING_SIZE_ERR), attributes);
+ domexception->Set(v8::String::New("HIERARCHY_REQUEST_ERR"), v8::Integer::New(HIERARCHY_REQUEST_ERR), attributes);
+ domexception->Set(v8::String::New("WRONG_DOCUMENT_ERR"), v8::Integer::New(WRONG_DOCUMENT_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_CHARACTER_ERR"), v8::Integer::New(INVALID_CHARACTER_ERR), attributes);
+ domexception->Set(v8::String::New("NO_DATA_ALLOWED_ERR"), v8::Integer::New(NO_DATA_ALLOWED_ERR), attributes);
+ domexception->Set(v8::String::New("NO_MODIFICATION_ALLOWED_ERR"), v8::Integer::New(NO_MODIFICATION_ALLOWED_ERR), attributes);
+ domexception->Set(v8::String::New("NOT_FOUND_ERR"), v8::Integer::New(NOT_FOUND_ERR), attributes);
+ domexception->Set(v8::String::New("NOT_SUPPORTED_ERR"), v8::Integer::New(NOT_SUPPORTED_ERR), attributes);
+ domexception->Set(v8::String::New("INUSE_ATTRIBUTE_ERR"), v8::Integer::New(INUSE_ATTRIBUTE_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_STATE_ERR"), v8::Integer::New(INVALID_STATE_ERR), attributes);
+ domexception->Set(v8::String::New("SYNTAX_ERR"), v8::Integer::New(SYNTAX_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_MODIFICATION_ERR"), v8::Integer::New(INVALID_MODIFICATION_ERR), attributes);
+ domexception->Set(v8::String::New("NAMESPACE_ERR"), v8::Integer::New(NAMESPACE_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_ACCESS_ERR"), v8::Integer::New(INVALID_ACCESS_ERR), attributes);
+ domexception->Set(v8::String::New("VALIDATION_ERR"), v8::Integer::New(VALIDATION_ERR), attributes);
+ domexception->Set(v8::String::New("TYPE_MISMATCH_ERR"), v8::Integer::New(TYPE_MISMATCH_ERR), attributes);
+ engine->global()->Set(v8::String::New("DOMException"), domexception);
+
+ QDeclarativeXMLHttpRequestData *data = new QDeclarativeXMLHttpRequestData;
+ return data;
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest_p.h b/src/declarative/qml/qdeclarativexmlhttprequest_p.h
index 7863035842..ab2d9207e6 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest_p.h
+++ b/src/declarative/qml/qdeclarativexmlhttprequest_p.h
@@ -60,8 +60,10 @@
QT_BEGIN_NAMESPACE
-class QScriptEngine;
-void qt_add_qmlxmlhttprequest(QScriptEngine *engine);
+class QV8Engine;
+
+void *qt_add_qmlxmlhttprequest(QV8Engine *engine);
+void qt_rem_qmlxmlhttprequest(QV8Engine *engine, void *);
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qintrusivelist_p.h b/src/declarative/qml/qintrusivelist_p.h
index 459d051d07..b2a15a0a52 100644
--- a/src/declarative/qml/qintrusivelist_p.h
+++ b/src/declarative/qml/qintrusivelist_p.h
@@ -65,6 +65,7 @@ public:
inline QIntrusiveList();
inline ~QIntrusiveList();
+ inline bool isEmpty() const;
inline void insert(N *n);
inline void remove(N *n);
@@ -176,6 +177,12 @@ QIntrusiveList<N, member>::~QIntrusiveList()
}
template<class N, QIntrusiveListNode N::*member>
+bool QIntrusiveList<N, member>::isEmpty() const
+{
+ return __first == 0;
+}
+
+template<class N, QIntrusiveListNode N::*member>
void QIntrusiveList<N, member>::insert(N *n)
{
QIntrusiveListNode *nnode = &(n->*member);
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 62c1f97d60..1baa21f3ae 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -9,7 +9,6 @@ SOURCES += \
$$PWD/qdeclarativeproperty.cpp \
$$PWD/qdeclarativecomponent.cpp \
$$PWD/qdeclarativecontext.cpp \
- $$PWD/qdeclarativeinclude.cpp \
$$PWD/qdeclarativecustomparser.cpp \
$$PWD/qdeclarativepropertyvaluesource.cpp \
$$PWD/qdeclarativepropertyvalueinterceptor.cpp \
@@ -41,13 +40,6 @@ SOURCES += \
$$PWD/qdeclarativetypenotavailable.cpp \
$$PWD/qdeclarativetypenamecache.cpp \
$$PWD/qdeclarativescriptstring.cpp \
- $$PWD/qdeclarativeobjectscriptclass.cpp \
- $$PWD/qdeclarativescarceresourcescriptclass.cpp \
- $$PWD/qdeclarativecontextscriptclass.cpp \
- $$PWD/qdeclarativeglobalscriptclass.cpp \
- $$PWD/qdeclarativevaluetypescriptclass.cpp \
- $$PWD/qdeclarativetypenamescriptclass.cpp \
- $$PWD/qdeclarativelistscriptclass.cpp \
$$PWD/qdeclarativeworkerscript.cpp \
$$PWD/qdeclarativeimageprovider.cpp \
$$PWD/qdeclarativenetworkaccessmanagerfactory.cpp \
@@ -90,7 +82,6 @@ HEADERS += \
$$PWD/qdeclarativeinfo.h \
$$PWD/qdeclarativeproperty_p.h \
$$PWD/qdeclarativecontext_p.h \
- $$PWD/qdeclarativeinclude_p.h \
$$PWD/qdeclarativetypeloader_p.h \
$$PWD/qdeclarativelist.h \
$$PWD/qdeclarativelist_p.h \
@@ -114,13 +105,6 @@ HEADERS += \
$$PWD/qdeclarativetypenotavailable_p.h \
$$PWD/qdeclarativetypenamecache_p.h \
$$PWD/qdeclarativescriptstring.h \
- $$PWD/qdeclarativeobjectscriptclass_p.h \
- $$PWD/qdeclarativescarceresourcescriptclass_p.h \
- $$PWD/qdeclarativecontextscriptclass_p.h \
- $$PWD/qdeclarativeglobalscriptclass_p.h \
- $$PWD/qdeclarativevaluetypescriptclass_p.h \
- $$PWD/qdeclarativetypenamescriptclass_p.h \
- $$PWD/qdeclarativelistscriptclass_p.h \
$$PWD/qdeclarativeworkerscript_p.h \
$$PWD/qdeclarativeguard_p.h \
$$PWD/qdeclarativeimageprovider.h \
@@ -136,6 +120,7 @@ QT += sql
include(parser/parser.pri)
include(rewriter/rewriter.pri)
include(v4/v4.pri)
+include(v8/v8.pri)
# mirrors logic in corelib/kernel/kernel.pri
unix:!symbian: contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
index 5ef293de89..0ee7d4dc7d 100644
--- a/src/declarative/qml/v4/qdeclarativev4bindings.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
@@ -1492,7 +1492,8 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
QString str = QString::fromRawData(strdata, len);
- identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
+ // XXX not applicable in v8
+ // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
}
QML_V4_END_INSTR(InitString, initstring)
diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
index 103d5ba0df..928fea4487 100644
--- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
@@ -41,7 +41,6 @@
#include "qdeclarativev4irbuilder_p.h"
-#include <private/qdeclarativeglobalscriptclass_p.h> // For illegalNames
#include <private/qdeclarativeanchors_p_p.h> // For AnchorLine
#include <private/qsganchors_p_p.h> // For AnchorLine
#include <private/qdeclarativetypenamecache_p.h>
@@ -437,7 +436,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast)
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->globalClass->illegalNames().contains(name) ) {
+ } 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)) {
diff --git a/src/declarative/qml/v8/notes.txt b/src/declarative/qml/v8/notes.txt
new file mode 100644
index 0000000000..ff5a289b7c
--- /dev/null
+++ b/src/declarative/qml/v8/notes.txt
@@ -0,0 +1,4 @@
+Removed backwards compatible imports - QTBUG-17518
+
+autotest print() taking objects that don't ToString()
+autotest QDeclarativeV8Function
diff --git a/src/declarative/qml/v8/qhashedstring.cpp b/src/declarative/qml/v8/qhashedstring.cpp
new file mode 100644
index 0000000000..4a23e3b7dd
--- /dev/null
+++ b/src/declarative/qml/v8/qhashedstring.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** 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 "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
new file mode 100644
index 0000000000..acee03a9b5
--- /dev/null
+++ b/src/declarative/qml/v8/qhashedstring_p.h
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** 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 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 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) {}
+
+ QStringHashNode *nlist;
+ QStringHashNode *next;
+ QHashedString key;
+};
+
+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(v8::Handle<v8::String> &, quint32) 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(v8::Handle<v8::String> &) const;
+ inline T *value(v8::Handle<v8::String> &, quint32 hash) 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(v8::Handle<v8::String> &string, quint32 hash) const
+{
+ QStringHashNode *node = 0;
+ if (data.numBuckets) {
+ node = data.buckets[hash % data.numBuckets];
+ int length = string->Length();
+ while (node && (length != node->key.length() || !string->Equals((uint16_t*)node->key.constData(), length)))
+ node = node->next;
+ }
+
+ 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(v8::Handle<v8::String> &key) const
+{
+ return value(key, (quint32)key->Hash());
+}
+
+template<class T>
+T *QStringHash<T>::value(v8::Handle<v8::String> &key, quint32 hash) const
+{
+ Node *n = findNode(key, hash);
+ 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)->value;
+}
+
+template<class T>
+T &QStringHash<T>::operator[](const QHashedStringRef &key)
+{
+ Node *n = findNode(key);
+ if (n) return n->value;
+ else return createNode(key)->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));
+}
+
+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
new file mode 100644
index 0000000000..6aeb6f6458
--- /dev/null
+++ b/src/declarative/qml/v8/qv8_p.h
@@ -0,0 +1 @@
+#include "../../../3rdparty/v8/include/v8.h"
diff --git a/src/declarative/qml/v8/qv8contextwrapper.cpp b/src/declarative/qml/v8/qv8contextwrapper.cpp
new file mode 100644
index 0000000000..1af4b4c883
--- /dev/null
+++ b/src/declarative/qml/v8/qv8contextwrapper.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** 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 "qv8contextwrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativecontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QString internal(QLatin1String("You've stumbled onto an internal implementation detail "
+ "that should never have been exposed."));
+
+class QV8ContextResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(ContextType);
+
+public:
+ QV8ContextResource(QV8Engine *engine, QDeclarativeContextData *context, QObject *scopeObject);
+ ~QV8ContextResource();
+
+ inline QDeclarativeContextData *getContext() const;
+
+ QDeclarativeGuard<QObject> scopeObject;
+
+ quint32 hasSubContexts:1;
+ quint32 ownsContext:1;
+ quint32 readOnly:1;
+ quint32 dummy:29;
+
+ QObject *secondaryScope;
+
+ // XXX aakenned - this is somewhat of a horrible abuse of external strings :)
+ struct SubContext : public v8::String::ExternalStringResource {
+ SubContext(QDeclarativeContextData *context) : context(context) {}
+ QDeclarativeGuardedContextData context;
+
+ virtual const uint16_t* data() const { return (const uint16_t *)internal.constData(); }
+ virtual size_t length() const { return internal.length(); }
+ };
+
+private:
+ QDeclarativeGuardedContextData context;
+};
+
+QV8ContextResource::QV8ContextResource(QV8Engine *engine, QDeclarativeContextData *context, QObject *scopeObject)
+: QV8ObjectResource(engine), scopeObject(scopeObject), hasSubContexts(false), ownsContext(false),
+ readOnly(true), secondaryScope(0), context(context)
+{
+}
+
+QV8ContextResource::~QV8ContextResource()
+{
+ if (ownsContext && context)
+ context->destroy();
+}
+
+// Returns the context, including resolving a subcontext
+QDeclarativeContextData *QV8ContextResource::getContext() const
+{
+ if (!hasSubContexts)
+ return context;
+
+ v8::Local<v8::Value> callingdata = v8::Context::GetCallingScriptData();
+ if (callingdata.IsEmpty() || !callingdata->IsString())
+ return context;
+
+ v8::Local<v8::String> callingstring = callingdata->ToString();
+ Q_ASSERT(callingstring->IsExternal());
+ Q_ASSERT(callingstring->GetExternalStringResource());
+
+ SubContext *sc = static_cast<SubContext *>(callingstring->GetExternalStringResource());
+ return sc->context;
+}
+
+QV8ContextWrapper::QV8ContextWrapper()
+: m_engine(0)
+{
+}
+
+QV8ContextWrapper::~QV8ContextWrapper()
+{
+}
+
+void QV8ContextWrapper::destroy()
+{
+ m_urlConstructor.Dispose(); m_urlConstructor.Clear();
+ m_constructor.Dispose(); m_constructor.Clear();
+}
+
+void QV8ContextWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(NullGetter, NullSetter);
+ m_urlConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+}
+
+v8::Local<v8::Object> QV8ContextWrapper::qmlScope(QDeclarativeContextData *ctxt, QObject *scope)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ContextResource *r = new QV8ContextResource(m_engine, ctxt, scope);
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Local<v8::Object> QV8ContextWrapper::urlScope(const QUrl &url)
+{
+ QDeclarativeContextData *context = new QDeclarativeContextData;
+ context->url = url;
+ context->isInternal = true;
+ context->isJSContext = true;
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_urlConstructor->NewInstance();
+ QV8ContextResource *r = new QV8ContextResource(m_engine, context, 0);
+ r->ownsContext = true;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+void QV8ContextWrapper::setReadOnly(v8::Handle<v8::Object> qmlglobal, bool readOnly)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ Q_ASSERT(resource);
+ resource->readOnly = readOnly;
+}
+
+void QV8ContextWrapper::addSubContext(v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Script> script,
+ QDeclarativeContextData *ctxt)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ Q_ASSERT(resource);
+ resource->hasSubContexts = true;
+ script->SetData(v8::String::NewExternal(new QV8ContextResource::SubContext(ctxt)));
+}
+
+QObject *QV8ContextWrapper::setSecondaryScope(v8::Handle<v8::Object> ctxt, QObject *scope)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(ctxt);
+ if (!resource) return 0;
+
+ QObject *rv = resource->secondaryScope;
+ resource->secondaryScope = scope;
+ return rv;
+}
+
+QDeclarativeContextData *QV8ContextWrapper::callingContext()
+{
+ v8::Local<v8::Object> qmlglobal = v8::Context::GetCallingQmlGlobal();
+ if (qmlglobal.IsEmpty()) return 0;
+
+ QV8ContextResource *r = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ return r?r->getContext():0;
+}
+
+QDeclarativeContextData *QV8ContextWrapper::context(v8::Handle<v8::Value> value)
+{
+ if (!value->IsObject())
+ return 0;
+
+ v8::Handle<v8::Object> qmlglobal = v8::Handle<v8::Object>::Cast(value);
+ QV8ContextResource *r = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ return r?r->getContext():0;
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::NullGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ QV8Engine *engine = resource->engine;
+
+ QString error = QLatin1String("Can't find variable: ") + engine->toString(property);
+ v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error)));
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // XXX aakenned too agressive
+ QDeclarativeContextData *context = resource->getContext();
+
+ if (!context)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // Search type (attached property/enum/imported scripts) names
+ // Secondary scope object
+ // while (context) {
+ // Search context properties
+ // Search scope object
+ // Search context object
+ // context = context->parent
+ // }
+
+ QV8Engine *engine = resource->engine;
+ QObject *scopeObject = resource->scopeObject;
+
+ if (context->imports && QV8Engine::startsWithUpper(property)) {
+ // Search for attached properties, enums and imported scripts
+ QDeclarativeTypeNameCache::Data *data = context->imports->data(property);
+
+ if (data) {
+ if (data->importedScriptIndex != -1) {
+ int index = data->importedScriptIndex;
+ 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);
+ }
+ Q_ASSERT(!"Unreachable");
+ }
+
+ // Fall through
+ }
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+
+ if (resource->secondaryScope) {
+ v8::Handle<v8::Value> result = qobjectWrapper->getProperty(resource->secondaryScope, property,
+ QV8QObjectWrapper::IgnoreRevision);
+ if (!result.IsEmpty()) return result;
+ }
+
+ while (context) {
+ // Search context properties
+ if (context->propertyNames) {
+ int propertyIdx = context->propertyNames->value(property);
+
+ if (propertyIdx != -1) {
+ typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty;
+
+ if (propertyIdx < context->idValueCount) {
+
+ if (ep->captureProperties)
+ ep->capturedProperties << CapturedProperty(&context->idValues[propertyIdx].bindings);
+
+ return engine->newQObject(context->idValues[propertyIdx]);
+ } else {
+
+ QDeclarativeContextPrivate *cp = context->asQDeclarativeContextPrivate();
+
+ if (ep->captureProperties)
+ ep->capturedProperties << CapturedProperty(context->asQDeclarativeContext(), -1,
+ propertyIdx + cp->notifyIndex);
+
+ const QVariant &value = cp->propertyValues.at(propertyIdx);
+ if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
+ QDeclarativeListProperty<QObject> prop(context->asQDeclarativeContext(), (void*)propertyIdx,
+ 0,
+ QDeclarativeContextPrivate::context_count,
+ QDeclarativeContextPrivate::context_at);
+ return engine->listWrapper()->newList(prop, qMetaTypeId<QDeclarativeListProperty<QObject> >());
+ } else {
+ return engine->fromVariant(cp->propertyValues.at(propertyIdx));
+ }
+ }
+ }
+ }
+
+ // Search scope object
+ if (scopeObject) {
+ v8::Handle<v8::Value> result = qobjectWrapper->getProperty(scopeObject, property,
+ QV8QObjectWrapper::CheckRevision);
+ if (!result.IsEmpty()) return result;
+ }
+ scopeObject = 0;
+
+
+ // Search context object
+ if (context->contextObject) {
+ v8::Handle<v8::Value> result = qobjectWrapper->getProperty(context->contextObject, property,
+ QV8QObjectWrapper::CheckRevision);
+ if (!result.IsEmpty()) return result;
+ }
+
+ context = context->parent;
+ }
+
+ QString error = QLatin1String("Can't find variable: ") + engine->toString(property);
+ v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error)));
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::NullSetter(v8::Local<v8::String> property,
+ v8::Local<v8::Value>,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ QV8Engine *engine = resource->engine;
+
+ if (!resource->readOnly) {
+ return v8::Handle<v8::Value>();
+ } else {
+ QString error = QLatin1String("Invalid write to global property \"") + engine->toString(property) +
+ QLatin1String("\"");
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Undefined();
+ }
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // XXX aakenned too agressive
+ QDeclarativeContextData *context = resource->getContext();
+
+ if (!context)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // See QV8ContextWrapper::Getter for resolution order
+
+ QV8Engine *engine = resource->engine;
+ QObject *scopeObject = resource->scopeObject;
+
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+
+ // Search scope object
+ if (resource->secondaryScope && qobjectWrapper->setProperty(resource->secondaryScope, property, value,
+ QV8QObjectWrapper::IgnoreRevision))
+ return value;
+
+ while (context) {
+ // Search context properties
+ if (context->propertyNames && -1 != context->propertyNames->value(property))
+ return value;
+
+ // Search scope object
+ if (scopeObject &&
+ qobjectWrapper->setProperty(scopeObject, property, value, QV8QObjectWrapper::CheckRevision))
+ return value;
+ scopeObject = 0;
+
+ // Search context object
+ if (context->contextObject &&
+ qobjectWrapper->setProperty(context->contextObject, property, value, QV8QObjectWrapper::CheckRevision))
+ return value;
+
+ context = context->parent;
+ }
+
+ if (!resource->readOnly) {
+ return v8::Handle<v8::Value>();
+ } else {
+ QString error = QLatin1String("Invalid write to global property \"") + engine->toString(property) +
+ QLatin1String("\"");
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Undefined();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass_p.h b/src/declarative/qml/v8/qv8contextwrapper_p.h
index 26d82724f3..cc0705995b 100644
--- a/src/declarative/qml/qdeclarativecontextscriptclass_p.h
+++ b/src/declarative/qml/v8/qv8contextwrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVECONTEXTSCRIPTCLASS_P_H
-#define QDECLARATIVECONTEXTSCRIPTCLASS_P_H
+#ifndef QV8CONTEXTWRAPPER_P_H
+#define QV8CONTEXTWRAPPER_P_H
//
// W A R N I N G
@@ -53,54 +53,55 @@
// We mean it.
//
-#include "private/qdeclarativetypenamecache_p.h"
-#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qglobal.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
-class QDeclarativeContext;
+class QUrl;
+class QObject;
+class QV8Engine;
class QDeclarativeContextData;
-class QDeclarativeContextScriptClass : public QScriptDeclarativeClass
+class QV8ContextWrapper
{
public:
- QDeclarativeContextScriptClass(QDeclarativeEngine *);
- ~QDeclarativeContextScriptClass();
+ QV8ContextWrapper();
+ ~QV8ContextWrapper();
- QScriptValue newContext(QDeclarativeContextData *, QObject * = 0);
- QScriptValue newUrlContext(QDeclarativeContextData *, QObject *, const QString &);
- QScriptValue newUrlContext(const QString &);
- QScriptValue newSharedContext();
+ void init(QV8Engine *);
+ void destroy();
- QDeclarativeContextData *contextFromValue(const QScriptValue &);
- QUrl urlFromValue(const QScriptValue &);
+ v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
+ v8::Local<v8::Object> urlScope(const QUrl &);
- QObject *setOverrideObject(QScriptValue &, QObject *);
+ void setReadOnly(v8::Handle<v8::Object>, bool);
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ void addSubContext(v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Script>,
+ QDeclarativeContextData *ctxt);
-private:
- QScriptClass::QueryFlags queryProperty(QDeclarativeContextData *, QObject *scopeObject,
- const Identifier &,
- QScriptClass::QueryFlags flags,
- bool includeTypes);
-
- QDeclarativeEngine *engine;
+ // XXX aakenned - remove this abomination
+ QObject *setSecondaryScope(v8::Handle<v8::Object>, QObject *);
- QObject *lastScopeObject;
- QDeclarativeContextData *lastContext;
- QDeclarativeTypeNameCache::Data *lastData;
- int lastPropertyIndex;
- QScriptValue lastFunction;
-
- uint m_id;
+ QDeclarativeContextData *callingContext();
+ QDeclarativeContextData *context(v8::Handle<v8::Value>);
+private:
+ static v8::Handle<v8::Value> NullGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> NullSetter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+ v8::Persistent<v8::Function> m_urlConstructor;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVECONTEXTSCRIPTCLASS_P_H
+#endif // QV8CONTEXTWRAPPER_P_H
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp
new file mode 100644
index 0000000000..ced07e142f
--- /dev/null
+++ b/src/declarative/qml/v8/qv8engine.cpp
@@ -0,0 +1,1423 @@
+/****************************************************************************
+**
+** 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 "qv8engine_p.h"
+
+#include "qv8contextwrapper_p.h"
+#include "qv8include_p.h"
+#include "../../../3rdparty/javascriptcore/DateMath.h"
+
+#include <private/qdeclarativelist_p.h>
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativecomponent_p.h>
+#include <private/qdeclarativestringconverters_p.h>
+
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qnumeric.h>
+#include <QtGui/qdesktopservices.h>
+#include <QtGui/qfontdatabase.h>
+#include <private/qdeclarativeapplication_p.h>
+#include <private/qdeclarativexmlhttprequest_p.h>
+#include <private/qdeclarativesqldatabase_p.h>
+
+// XXX Need to check all the global functions will also work in a worker script where the QDeclarativeEngine
+// is not available
+QT_BEGIN_NAMESPACE
+
+QV8Engine::QV8Engine()
+: m_xmlHttpRequestData(0), m_sqlDatabaseData(0)
+{
+}
+
+QV8Engine::~QV8Engine()
+{
+ qt_rem_qmlsqldatabase(this, m_sqlDatabaseData);
+ m_sqlDatabaseData = 0;
+ qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
+ m_xmlHttpRequestData = 0;
+
+ m_getOwnPropertyNames.Dispose(); m_getOwnPropertyNames.Clear();
+
+ m_valueTypeWrapper.destroy();
+ m_variantWrapper.destroy();
+ m_listWrapper.destroy();
+ m_typeWrapper.destroy();
+ m_qobjectWrapper.destroy();
+ m_contextWrapper.destroy();
+ m_stringWrapper.destroy();
+ m_context.Dispose();
+}
+
+void QV8Engine::init(QDeclarativeEngine *engine)
+{
+ m_engine = engine;
+
+ QByteArray v8args = qgetenv("V8ARGS");
+ if (!v8args.isEmpty())
+ v8::V8::SetFlagsFromString(v8args.constData(), v8args.length());
+
+ v8::HandleScope handle_scope;
+ m_context = v8::Context::New();
+ v8::Context::Scope context_scope(m_context);
+
+ m_stringWrapper.init();
+ m_contextWrapper.init(this);
+ m_qobjectWrapper.init(this);
+ m_typeWrapper.init(this);
+ m_listWrapper.init(this);
+ m_variantWrapper.init(this);
+ m_valueTypeWrapper.init(this);
+
+ {
+ v8::Handle<v8::Value> v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames"));
+ m_getOwnPropertyNames = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(v));
+ }
+
+ initializeGlobal(m_context->Global());
+ freezeGlobal();
+}
+
+QString QV8Engine::toStringStatic(v8::Handle<v8::Value> jsstr)
+{
+ return toStringStatic(jsstr->ToString());
+}
+
+QString QV8Engine::toStringStatic(v8::Handle<v8::String> jsstr)
+{
+ QString qstr;
+ qstr.resize(jsstr->Length());
+ jsstr->Write((uint16_t*)qstr.data());
+ return qstr;
+}
+
+QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint)
+{
+ if (value.IsEmpty())
+ return QVariant();
+
+ if (value->IsObject()) {
+ QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource();
+ if (r) {
+ switch (r->resourceType()) {
+ case QV8ObjectResource::ContextType:
+ case QV8ObjectResource::TypeType:
+ case QV8ObjectResource::XMLHttpRequestType:
+ case QV8ObjectResource::DOMNodeType:
+ case QV8ObjectResource::SQLDatabaseType:
+ return QVariant();
+ case QV8ObjectResource::QObjectType:
+ return qVariantFromValue<QObject *>(m_qobjectWrapper.toQObject(r));
+ case QV8ObjectResource::ListType:
+ return m_listWrapper.toVariant(r);
+ case QV8ObjectResource::VariantType:
+ return m_variantWrapper.toVariant(r);
+ case QV8ObjectResource::ValueTypeType:
+ return m_valueTypeWrapper.toVariant(r);
+ }
+ }
+ }
+
+ if (typeHint == qMetaTypeId<QList<QObject *> >() && value->IsArray()) {
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
+
+ QList<QObject *> list;
+ uint32_t length = array->Length();
+ for (uint32_t ii = 0; ii < length; ++ii) {
+ v8::Local<v8::Value> arrayItem = array->Get(ii);
+ if (arrayItem->IsObject()) {
+ list << toQObject(arrayItem->ToObject());
+ } else {
+ list << 0;
+ }
+ }
+
+ return qVariantFromValue<QList<QObject*> >(list);
+ }
+
+ return toBasicVariant(value);
+}
+
+static v8::Handle<v8::Array> arrayFromStringList(QV8Engine *engine, const QStringList &list)
+{
+ v8::Context::Scope scope(engine->context());
+ v8::Local<v8::Array> result = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ result->Set(ii, engine->toString(list.at(ii)));
+ return result;
+}
+
+static v8::Handle<v8::Array> arrayFromVariantList(QV8Engine *engine, const QVariantList &list)
+{
+ v8::Context::Scope scope(engine->context());
+ v8::Local<v8::Array> result = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ result->Set(ii, engine->fromVariant(list.at(ii)));
+ return result;
+}
+
+static v8::Handle<v8::Object> objectFromVariantMap(QV8Engine *engine, const QVariantMap &map)
+{
+ v8::Context::Scope scope(engine->context());
+ v8::Local<v8::Object> object = v8::Object::New();
+ for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter)
+ object->Set(engine->toString(iter.key()), engine->fromVariant(iter.value()));
+ return object;
+}
+
+Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
+
+// Converts a QRegExp to a JS RegExp.
+// The conversion is not 100% exact since ECMA regexp and QRegExp
+// have different semantics/flags, but we try to do our best.
+static v8::Handle<v8::RegExp> regexpFromQRegExp(QV8Engine *engine, const QRegExp &re)
+{
+ // Convert the pattern to a ECMAScript pattern.
+ QString pattern = qt_regexp_toCanonical(re.pattern(), re.patternSyntax());
+ if (re.isMinimal()) {
+ QString ecmaPattern;
+ int len = pattern.length();
+ ecmaPattern.reserve(len);
+ int i = 0;
+ const QChar *wc = pattern.unicode();
+ bool inBracket = false;
+ while (i < len) {
+ QChar c = wc[i++];
+ ecmaPattern += c;
+ switch (c.unicode()) {
+ case '?':
+ case '+':
+ case '*':
+ case '}':
+ if (!inBracket)
+ ecmaPattern += QLatin1Char('?');
+ break;
+ case '\\':
+ if (i < len)
+ ecmaPattern += wc[i++];
+ break;
+ case '[':
+ inBracket = true;
+ break;
+ case ']':
+ inBracket = false;
+ break;
+ default:
+ break;
+ }
+ }
+ pattern = ecmaPattern;
+ }
+
+ int flags = v8::RegExp::kNone;
+ if (re.caseSensitivity() == Qt::CaseInsensitive)
+ flags |= v8::RegExp::kIgnoreCase;
+
+ return v8::RegExp::New(engine->toString(pattern), static_cast<v8::RegExp::Flags>(flags));
+}
+
+v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
+{
+ int type = variant.userType();
+ const void *ptr = variant.constData();
+
+ if (type < QMetaType::User) {
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Void:
+ return v8::Undefined();
+ case QMetaType::Bool:
+ return v8::Boolean::New(*reinterpret_cast<const bool*>(ptr));
+ case QMetaType::Int:
+ return v8::Integer::New(*reinterpret_cast<const int*>(ptr));
+ case QMetaType::UInt:
+ return v8::Integer::NewFromUnsigned(*reinterpret_cast<const uint*>(ptr));
+ case QMetaType::LongLong:
+ return v8::Number::New(*reinterpret_cast<const qlonglong*>(ptr));
+ case QMetaType::ULongLong:
+ return v8::Number::New(*reinterpret_cast<const qulonglong*>(ptr));
+ case QMetaType::Double:
+ return v8::Number::New(*reinterpret_cast<const double*>(ptr));
+ case QMetaType::QString:
+ return m_stringWrapper.toString(*reinterpret_cast<const QString*>(ptr));
+ case QMetaType::Float:
+ return v8::Number::New(*reinterpret_cast<const float*>(ptr));
+ case QMetaType::Short:
+ return v8::Integer::New(*reinterpret_cast<const short*>(ptr));
+ case QMetaType::UShort:
+ return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned short*>(ptr));
+ case QMetaType::Char:
+ return v8::Integer::New(*reinterpret_cast<const char*>(ptr));
+ case QMetaType::UChar:
+ return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned char*>(ptr));
+ case QMetaType::QChar:
+ return v8::Integer::New((*reinterpret_cast<const QChar*>(ptr)).unicode());
+ case QMetaType::QDateTime:
+ return v8::Date::New(qtDateTimeToJsDate(*reinterpret_cast<const QDateTime *>(ptr)));
+ case QMetaType::QDate:
+ return v8::Date::New(qtDateTimeToJsDate(QDateTime(*reinterpret_cast<const QDate *>(ptr))));
+ case QMetaType::QTime:
+ return v8::Date::New(qtDateTimeToJsDate(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr))));
+ case QMetaType::QRegExp:
+ return regexpFromQRegExp(this, *reinterpret_cast<const QRegExp *>(ptr));
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return newQObject(*reinterpret_cast<QObject* const *>(ptr));
+ case QMetaType::QStringList:
+ return arrayFromStringList(this, *reinterpret_cast<const QStringList *>(ptr));
+ case QMetaType::QVariantList:
+ return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
+ case QMetaType::QVariantMap:
+ return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr));
+
+ default:
+ break;
+ }
+
+ if (QDeclarativeValueType *vt = QDeclarativeEnginePrivate::get(m_engine)->valueTypes[type])
+ return m_valueTypeWrapper.newValueType(variant, vt);
+
+ } else {
+ if (type == qMetaTypeId<QDeclarativeListReference>()) {
+ typedef QDeclarativeListReferencePrivate QDLRP;
+ QDLRP *p = QDLRP::get((QDeclarativeListReference*)ptr);
+ if (p->object) {
+ return m_listWrapper.newList(p->property, p->propertyType);
+ } else {
+ return v8::Null();
+ }
+ } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ // XXX aakenned Can this be more optimal? Just use Array as a prototype and
+ // implement directly against QList<QObject*>?
+ const QList<QObject *> &list = *(QList<QObject *>*)ptr;
+ v8::Local<v8::Array> array = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ array->Set(ii, newQObject(list.at(ii)));
+ return array;
+ }
+
+ bool objOk;
+ QObject *obj = QDeclarativeMetaType::toQObject(variant, &objOk);
+ if (objOk)
+ return newQObject(obj);
+ }
+
+ return m_variantWrapper.newVariant(variant);
+
+ // XXX aakenned
+#if 0
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ result = newRegExp(exec, *reinterpret_cast<const QRegExp *>(ptr));
+ break;
+#endif
+#ifndef QT_NO_QOBJECT
+#endif
+ case QMetaType::QVariant:
+ result = eng->newVariant(*reinterpret_cast<const QVariant*>(ptr));
+ break;
+ default:
+ if (type == qMetaTypeId<QScriptValue>()) {
+ result = eng->scriptValueToJSCValue(*reinterpret_cast<const QScriptValue*>(ptr));
+ if (!result)
+ return JSC::jsUndefined();
+ }
+
+#ifndef QT_NO_QOBJECT
+ // lazy registration of some common list types
+ else if (type == qMetaTypeId<QObjectList>()) {
+ qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
+ return create(exec, type, ptr);
+ }
+#endif
+ else if (type == qMetaTypeId<QList<int> >()) {
+ qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
+ return create(exec, type, ptr);
+ }
+
+ else {
+ QByteArray typeName = QMetaType::typeName(type);
+ if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
+ return JSC::jsNull();
+ else
+ result = eng->newVariant(QVariant(type, ptr));
+ }
+ }
+ }
+#endif
+}
+
+// A handle scope and context must be entered
+v8::Local<v8::Script> QV8Engine::qmlModeCompile(const QString &source, const QString &fileName, int lineNumber)
+{
+ v8::Local<v8::String> v8source = m_stringWrapper.toString(source);
+ v8::Local<v8::String> v8fileName = m_stringWrapper.toString(fileName);
+
+ v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1));
+
+ v8::Local<v8::Script> script = v8::Script::Compile(v8source, &origin, 0, v8::Handle<v8::String>(),
+ v8::Script::QmlMode);
+
+ return script;
+}
+
+QNetworkAccessManager *QV8Engine::networkAccessManager()
+{
+ return QDeclarativeEnginePrivate::get(m_engine)->getNetworkAccessManager();
+}
+
+const QSet<QString> &QV8Engine::illegalNames() const
+{
+ return m_illegalNames;
+}
+
+// Requires a handle scope
+v8::Local<v8::Array> QV8Engine::getOwnPropertyNames(v8::Handle<v8::Object> o)
+{
+ v8::TryCatch tc;
+ v8::Handle<v8::Value> args[] = { o };
+ v8::Local<v8::Value> r = m_getOwnPropertyNames->Call(global(), 1, args);
+ if (tc.HasCaught())
+ return v8::Array::New();
+ else
+ return v8::Local<v8::Array>::Cast(r);
+}
+
+QDeclarativeContextData *QV8Engine::callingContext()
+{
+ return m_contextWrapper.callingContext();
+}
+
+// Converts a JS value to a QVariant.
+// Null, Undefined -> QVariant() (invalid)
+// Boolean -> QVariant(bool)
+// Number -> QVariant(double)
+// String -> QVariant(QString)
+// Array -> QVariantList(...)
+// Date -> QVariant(QDateTime)
+// RegExp -> QVariant(QRegExp)
+// [Any other object] -> QVariantMap(...)
+QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
+{
+ if (value->IsNull() || value->IsUndefined())
+ return QVariant();
+ else if (value->IsBoolean())
+ return value->ToBoolean()->Value();
+ else if (value->IsInt32())
+ return value->ToInt32()->Value();
+ else if (value->IsNumber())
+ return value->ToNumber()->Value();
+ else if (value->IsString())
+ return m_stringWrapper.toString(value->ToString());
+ if (value->IsDate())
+ return qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(value)->NumberValue());
+ // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
+
+ Q_ASSERT(value->IsObject());
+
+ if (value->IsRegExp()) {
+ v8::Context::Scope scope(context());
+ v8::Handle<v8::RegExp> jsRegExp = v8::Handle<v8::RegExp>::Cast(value);
+ // Copied from QtScript
+ // Converts a JS RegExp to a QRegExp.
+ // The conversion is not 100% exact since ECMA regexp and QRegExp
+ // have different semantics/flags, but we try to do our best.
+ QString pattern = toString(jsRegExp->GetSource());
+ Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
+ if (jsRegExp->GetFlags() & v8::RegExp::kIgnoreCase)
+ caseSensitivity = Qt::CaseInsensitive;
+ return QRegExp(pattern, caseSensitivity, QRegExp::RegExp2);
+ } else if (value->IsArray()) {
+ v8::Context::Scope scope(context());
+ QVariantList rv;
+
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
+ int length = array->Length();
+ for (int ii = 0; ii < length; ++ii)
+ rv << toVariant(array->Get(ii), -1);
+
+ return rv;
+ } else if (!value->IsFunction()) {
+ v8::Context::Scope scope(context());
+ v8::Handle<v8::Object> object = value->ToObject();
+ v8::Local<v8::Array> properties = object->GetPropertyNames();
+ int length = properties->Length();
+ if (length == 0)
+ return QVariant();
+
+ QVariantMap map;
+ for (int ii = 0; ii < length; ++ii) {
+ v8::Handle<v8::Value> property = properties->Get(ii);
+ map.insert(toString(property), toVariant(object->Get(property), -1));
+ }
+ return map;
+ }
+
+ return QVariant();
+}
+
+
+
+#include <QtGui/qvector3d.h>
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
+{
+ v8::Local<v8::Function> printFn = V8FUNCTION(print, this);
+
+ v8::Local<v8::Object> console = v8::Object::New();
+ console->Set(v8::String::New("log"), printFn);
+ console->Set(v8::String::New("debug"), printFn);
+
+ // XXX - Qt global object properties
+
+ v8::Local<v8::Object> qt = v8::Object::New();
+
+ // Set all the enums from the "Qt" namespace
+ const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
+ for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
+ QMetaEnum enumerator = qtMetaObject->enumerator(ii);
+ for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
+ qt->Set(v8::String::New(enumerator.key(jj)), v8::Integer::New(enumerator.value(jj)));
+ }
+ }
+
+ if (m_engine)
+ qt->Set(v8::String::New("application"), newQObject(new QDeclarativeApplication(m_engine)));
+
+ qt->Set(v8::String::New("include"), V8FUNCTION(QV8Include::include, this));
+ qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this));
+ qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this));
+ qt->Set(v8::String::New("hsla"), V8FUNCTION(hsla, this));
+ qt->Set(v8::String::New("rect"), V8FUNCTION(rect, this));
+ qt->Set(v8::String::New("point"), V8FUNCTION(point, this));
+ qt->Set(v8::String::New("size"), V8FUNCTION(size, this));
+ qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this));
+
+ if (m_engine) {
+ qt->Set(v8::String::New("lighter"), V8FUNCTION(lighter, this));
+ qt->Set(v8::String::New("darker"), V8FUNCTION(darker, this));
+ qt->Set(v8::String::New("tint"), V8FUNCTION(tint, this));
+ }
+
+ qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this));
+ qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this));
+ qt->Set(v8::String::New("formatDateTime"), V8FUNCTION(formatDateTime, this));
+
+ qt->Set(v8::String::New("openUrlExternally"), V8FUNCTION(openUrlExternally, this));
+ qt->Set(v8::String::New("fontFamilies"), V8FUNCTION(fontFamilies, this));
+ qt->Set(v8::String::New("md5"), V8FUNCTION(md5, this));
+ qt->Set(v8::String::New("btoa"), V8FUNCTION(btoa, this));
+ qt->Set(v8::String::New("atob"), V8FUNCTION(atob, this));
+ qt->Set(v8::String::New("quit"), V8FUNCTION(quit, this));
+ qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this));
+
+ if (m_engine) {
+ qt->Set(v8::String::New("createQmlObject"), V8FUNCTION(createQmlObject, this));
+ qt->Set(v8::String::New("createComponent"), V8FUNCTION(createComponent, this));
+ }
+
+ // XXX translator functions
+
+ global->Set(v8::String::New("print"), printFn);
+ global->Set(v8::String::New("console"), console);
+ global->Set(v8::String::New("Qt"), qt);
+
+ // XXX mainthread only
+ m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
+ m_sqlDatabaseData = qt_add_qmlsqldatabase(this);
+
+ {
+ v8::Handle<v8::Value> args[] = { 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)));
+ }
+}
+
+void QV8Engine::freezeGlobal()
+{
+ // Freeze the global object
+ // XXX I don't think this is sufficient as it misses non-enumerable properties
+#define FREEZE "(function freeze_recur(obj) { "\
+ " if (Qt.isQtObject(obj)) return;"\
+ " for (var prop in obj) { " \
+ " if (prop == \"connect\" || prop == \"disconnect\") {" \
+ " Object.freeze(obj[prop]); "\
+ " continue;" \
+ " }" \
+ " freeze_recur(obj[prop]);" \
+ " }" \
+ " if (obj instanceof Object) {" \
+ " Object.freeze(obj);" \
+ " }"\
+ "})(this);"
+ v8::Local<v8::Script> test = v8::Script::New(v8::String::New(FREEZE));
+#undef FREEZE
+
+ test->Run();
+}
+
+v8::Handle<v8::Value> QV8Engine::print(const v8::Arguments &args)
+{
+ QString result;
+ for (int i = 0; i < args.Length(); ++i) {
+ if (i != 0)
+ result.append(QLatin1Char(' '));
+
+ v8::Local<v8::String> jsstr = args[i]->ToString();
+ if (!jsstr.IsEmpty()) {
+ QString qstr;
+ qstr.resize(jsstr->Length());
+ jsstr->Write((uint16_t*)qstr.data());
+ result.append(qstr);
+ }
+ }
+ qDebug("%s", qPrintable(result));
+ return v8::Undefined();
+}
+
+/*!
+\qmlmethod bool Qt::isQtObject(object)
+Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
+*/
+v8::Handle<v8::Value> QV8Engine::isQtObject(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ return v8::Boolean::New(false);
+
+ return v8::Boolean::New(0 != V8ENGINE()->toQObject(args[0]));
+}
+
+/*!
+\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
+
+Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
+All components should be in the range 0-1 inclusive.
+*/
+v8::Handle<v8::Value> QV8Engine::rgba(const v8::Arguments &args)
+{
+ int argCount = args.Length();
+ if (argCount < 3 || argCount > 4)
+ V8THROW_ERROR("Qt.rgba(): Invalid arguments");
+
+ double r = args[0]->NumberValue();
+ double g = args[1]->NumberValue();
+ double b = args[2]->NumberValue();
+ double a = (argCount == 4) ? args[3]->NumberValue() : 1;
+
+ if (r < 0.0) r=0.0;
+ if (r > 1.0) r=1.0;
+ if (g < 0.0) g=0.0;
+ if (g > 1.0) g=1.0;
+ if (b < 0.0) b=0.0;
+ if (b > 1.0) b=1.0;
+ if (a < 0.0) a=0.0;
+ if (a > 1.0) a=1.0;
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
+}
+
+/*!
+\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
+
+Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
+All components should be in the range 0-1 inclusive.
+*/
+v8::Handle<v8::Value> QV8Engine::hsla(const v8::Arguments &args)
+{
+ int argCount = args.Length();
+ if (argCount < 3 || argCount > 4)
+ V8THROW_ERROR("Qt.hsla(): Invalid arguments");
+
+ double h = args[0]->NumberValue();
+ double s = args[1]->NumberValue();
+ double l = args[2]->NumberValue();
+ double a = (argCount == 4) ? args[3]->NumberValue() : 1;
+
+ if (h < 0.0) h=0.0;
+ if (h > 1.0) h=1.0;
+ if (s < 0.0) s=0.0;
+ if (s > 1.0) s=1.0;
+ if (l < 0.0) l=0.0;
+ if (l > 1.0) l=1.0;
+ if (a < 0.0) a=0.0;
+ if (a > 1.0) a=1.0;
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
+}
+
+/*!
+\qmlmethod rect Qt::rect(int x, int y, int width, int height)
+
+Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
+
+The returned object has \c x, \c y, \c width and \c height attributes with the given values.
+*/
+v8::Handle<v8::Value> QV8Engine::rect(const v8::Arguments &args)
+{
+ if (args.Length() != 4)
+ V8THROW_ERROR("Qt.rect(): Invalid arguments");
+
+ double x = args[0]->NumberValue();
+ double y = args[1]->NumberValue();
+ double w = args[2]->NumberValue();
+ double h = args[3]->NumberValue();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
+}
+
+/*!
+\qmlmethod point Qt::point(int x, int y)
+Returns a Point with the specified \c x and \c y coordinates.
+*/
+v8::Handle<v8::Value> QV8Engine::point(const v8::Arguments &args)
+{
+ if (args.Length() != 2)
+ V8THROW_ERROR("Qt.point(): Invalid arguments");
+
+ double x = args[0]->ToNumber()->Value();
+ double y = args[1]->ToNumber()->Value();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QPointF(x, y)));
+}
+
+/*!
+\qmlmethod Qt::size(int width, int height)
+Returns a Size with the specified \c width and \c height.
+*/
+v8::Handle<v8::Value> QV8Engine::size(const v8::Arguments &args)
+{
+ if (args.Length() != 2)
+ V8THROW_ERROR("Qt.size(): Invalid arguments");
+
+ double w = args[0]->ToNumber()->Value();
+ double h = args[1]->ToNumber()->Value();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h)));
+}
+
+/*!
+\qmlmethod Qt::vector3d(real x, real y, real z)
+Returns a Vector3D with the specified \c x, \c y and \c z.
+*/
+v8::Handle<v8::Value> QV8Engine::vector3d(const v8::Arguments &args)
+{
+ if (args.Length() != 3)
+ V8THROW_ERROR("Qt.vector(): Invalid arguments");
+
+ double x = args[0]->ToNumber()->Value();
+ double y = args[1]->ToNumber()->Value();
+ double z = args[2]->ToNumber()->Value();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QVector3D(x, y, z)));
+}
+
+/*!
+\qmlmethod color Qt::lighter(color baseColor, real factor)
+Returns a color lighter than \c baseColor by the \c factor provided.
+
+If the factor is greater than 1.0, this functions returns a lighter color.
+Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
+the return color is darker, but we recommend using the Qt.darker() function for this purpose.
+If the factor is 0 or negative, the return value is unspecified.
+
+The function converts the current RGB color to HSV, multiplies the value (V) component
+by factor and converts the color back to RGB.
+
+If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
+*/
+v8::Handle<v8::Value> QV8Engine::lighter(const v8::Arguments &args)
+{
+ if (args.Length() != 1 && args.Length() != 2)
+ V8THROW_ERROR("Qt.lighter(): Invalid arguments");
+
+ QColor color;
+ QVariant v = V8ENGINE()->toVariant(args[0], -1);
+ if (v.userType() == QVariant::Color) {
+ color = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ qreal factor = 1.5;
+ if (args.Length() == 2)
+ factor = args[1]->ToNumber()->Value();
+
+ color = color.lighter(int(qRound(factor*100.)));
+ return V8ENGINE()->fromVariant(QVariant::fromValue(color));
+}
+
+/*!
+\qmlmethod color Qt::darker(color baseColor, real factor)
+Returns a color darker than \c baseColor by the \c factor provided.
+
+If the factor is greater than 1.0, this function returns a darker color.
+Setting factor to 3.0 returns a color that has one-third the brightness.
+If the factor is less than 1.0, the return color is lighter, but we recommend using
+the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
+value is unspecified.
+
+The function converts the current RGB color to HSV, divides the value (V) component
+by factor and converts the color back to RGB.
+
+If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
+*/
+v8::Handle<v8::Value> QV8Engine::darker(const v8::Arguments &args)
+{
+ if (args.Length() != 1 && args.Length() != 2)
+ V8THROW_ERROR("Qt.darker(): Invalid arguments");
+
+ QColor color;
+ QVariant v = V8ENGINE()->toVariant(args[0], -1);
+ if (v.userType() == QVariant::Color) {
+ color = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ qreal factor = 2.0;
+ if (args.Length() == 2)
+ factor = args[1]->ToNumber()->Value();
+
+ color = color.darker(int(qRound(factor*100.)));
+ return V8ENGINE()->fromVariant(QVariant::fromValue(color));
+}
+
+/*!
+ \qmlmethod color Qt::tint(color baseColor, color tintColor)
+ This function allows tinting one color with another.
+
+ The tint color should usually be mostly transparent, or you will not be
+ able to see the underlying color. The below example provides a slight red
+ tint by having the tint color be pure red which is only 1/16th opaque.
+
+ \qml
+ Item {
+ Rectangle {
+ x: 0; width: 80; height: 80
+ color: "lightsteelblue"
+ }
+ Rectangle {
+ x: 100; width: 80; height: 80
+ color: Qt.tint("lightsteelblue", "#10FF0000")
+ }
+ }
+ \endqml
+ \image declarative-rect_tint.png
+
+ Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
+*/
+v8::Handle<v8::Value> QV8Engine::tint(const v8::Arguments &args)
+{
+ if (args.Length() != 2)
+ V8THROW_ERROR("Qt.tint(): Invalid arguments");
+
+ // base color
+ QColor color;
+ QVariant v = V8ENGINE()->toVariant(args[0], -1);
+ if (v.userType() == QVariant::Color) {
+ color = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ // tint color
+ QColor tintColor;
+ v = V8ENGINE()->toVariant(args[1], -1);
+ if (v.userType() == QVariant::Color) {
+ tintColor = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ // tint the base color and return the final color
+ QColor finalColor;
+ int a = tintColor.alpha();
+ if (a == 0xFF)
+ finalColor = tintColor;
+ else if (a == 0x00)
+ finalColor = color;
+ else {
+ qreal a = tintColor.alphaF();
+ qreal inv_a = 1.0 - a;
+
+ finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
+ tintColor.greenF() * a + color.greenF() * inv_a,
+ tintColor.blueF() * a + color.blueF() * inv_a,
+ a + inv_a * color.alphaF());
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(finalColor));
+}
+
+/*!
+\qmlmethod string Qt::formatDate(datetime date, variant format)
+
+Returns a string representation of \c date, optionally formatted according
+to \c format.
+
+The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
+property, a QDate, or QDateTime value. The \a format parameter may be any of
+the possible format values as described for
+\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
+
+If \a format is not specified, \a date is formatted using
+\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+*/
+v8::Handle<v8::Value> QV8Engine::formatDate(const v8::Arguments &args)
+{
+ if (args.Length() < 1 || args.Length() > 2)
+ V8THROW_ERROR("Qt.formatDate(): Invalid arguments");
+
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ QDate date = V8ENGINE()->toVariant(args[0], -1).toDateTime().date();
+ QString formattedDate;
+ if (args.Length() == 2) {
+ if (args[1]->IsString()) {
+ QString format = V8ENGINE()->toVariant(args[1], -1).toString();
+ formattedDate = date.toString(format);
+ } else if (args[1]->IsNumber()) {
+ quint32 intFormat = args[1]->ToNumber()->Value();
+ Qt::DateFormat format = Qt::DateFormat(intFormat);
+ formattedDate = date.toString(format);
+ } else {
+ V8THROW_ERROR("Qt.formatDate(): Invalid date format");
+ }
+ } else {
+ formattedDate = date.toString(enumFormat);
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDate));
+}
+
+/*!
+\qmlmethod string Qt::formatTime(datetime time, variant format)
+
+Returns a string representation of \c time, optionally formatted according to
+\c format.
+
+The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
+value. The \a format parameter may be any of the possible format values as
+described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
+
+If \a format is not specified, \a time is formatted using
+\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+*/
+v8::Handle<v8::Value> QV8Engine::formatTime(const v8::Arguments &args)
+{
+ if (args.Length() < 1 || args.Length() > 2)
+ V8THROW_ERROR("Qt.formatTime(): Invalid arguments");
+
+ QVariant argVariant = V8ENGINE()->toVariant(args[0], -1);
+ QTime time;
+ if (args[0]->IsDate() || (argVariant.type() == QVariant::String))
+ time = argVariant.toDateTime().time();
+ else // if (argVariant.type() == QVariant::Time), or invalid.
+ time = argVariant.toTime();
+
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ QString formattedTime;
+ if (args.Length() == 2) {
+ if (args[1]->IsString()) {
+ QString format = V8ENGINE()->toVariant(args[1], -1).toString();
+ formattedTime = time.toString(format);
+ } else if (args[1]->IsNumber()) {
+ quint32 intFormat = args[1]->ToNumber()->Value();
+ Qt::DateFormat format = Qt::DateFormat(intFormat);
+ formattedTime = time.toString(format);
+ } else {
+ V8THROW_ERROR("Qt.formatTime(): Invalid time format");
+ }
+ } else {
+ formattedTime = time.toString(enumFormat);
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(formattedTime));
+}
+
+/*!
+\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
+
+Returns a string representation of \c datetime, optionally formatted according to
+\c format.
+
+The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
+property, a QDate, QTime, or QDateTime value.
+
+If \a format is not provided, \a dateTime is formatted using
+\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
+\a format should be either:
+
+\list
+\o One of the Qt::DateFormat enumeration values, such as
+ \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
+\o A string that specifies the format of the returned string, as detailed below.
+\endlist
+
+If \a format specifies a format string, it should use the following expressions
+to specify the date:
+
+ \table
+ \header \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1-12)
+ \row \i MM \i the month as number with a leading zero (01-12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00-99)
+ \row \i yyyy \i the year as four digit number
+ \endtable
+
+In addition the following expressions can be used to specify the time:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP
+ \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
+ \row \i ap
+ \i use am/pm display. \e ap will be replaced by either "am" or "pm".
+ \endtable
+
+ All other input characters will be ignored. Any sequence of characters that
+ are enclosed in single quotes will be treated as text and not be used as an
+ expression. Two consecutive single quotes ("''") are replaced by a single quote
+ in the output.
+
+For example, if the following date/time value was specified:
+
+ \code
+ // 21 May 2001 14:13:09
+ var dateTime = new Date(2001, 5, 21, 14, 13, 09)
+ \endcode
+
+This \a dateTime value could be passed to \c Qt.formatDateTime(),
+\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
+with the \a format values below to produce the following results:
+
+ \table
+ \header \i Format \i Result
+ \row \i "dd.MM.yyyy" \i 21.05.2001
+ \row \i "ddd MMMM d yy" \i Tue May 21 01
+ \row \i "hh:mm:ss.zzz" \i 14:13:09.042
+ \row \i "h:m:s ap" \i 2:13:9 pm
+ \endtable
+*/
+v8::Handle<v8::Value> QV8Engine::formatDateTime(const v8::Arguments &args)
+{
+ if (args.Length() < 1 || args.Length() > 2)
+ V8THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
+
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ QDateTime dt = V8ENGINE()->toVariant(args[0], -1).toDateTime();
+ QString formattedDt;
+ if (args.Length() == 2) {
+ if (args[1]->IsString()) {
+ QString format = V8ENGINE()->toVariant(args[1], -1).toString();
+ formattedDt = dt.toString(format);
+ } else if (args[1]->IsNumber()) {
+ quint32 intFormat = args[1]->ToNumber()->Value();
+ Qt::DateFormat format = Qt::DateFormat(intFormat);
+ formattedDt = dt.toString(format);
+ } else {
+ V8THROW_ERROR("Qt.formatDateTime(): Invalid datetime format");
+ }
+ } else {
+ formattedDt = dt.toString(enumFormat);
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDt));
+}
+
+double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt)
+{
+ // from QScriptEngine::DateTimeToMs()
+ if (!dt.isValid()) {
+ return qSNaN();
+ }
+ QDateTime utc = dt.toUTC();
+ QDate date = utc.date();
+ QTime time = utc.time();
+ QV8DateConverter::JSC::GregorianDateTime tm;
+ tm.year = date.year() - 1900;
+ tm.month = date.month() - 1;
+ tm.monthDay = date.day();
+ tm.weekDay = date.dayOfWeek();
+ tm.yearDay = date.dayOfYear();
+ tm.hour = time.hour();
+ tm.minute = time.minute();
+ tm.second = time.second();
+ return QV8DateConverter::JSC::gregorianDateTimeToMS(tm, time.msec());
+}
+
+QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate)
+{
+ // from QScriptEngine::MsToDateTime()
+ if (qIsNaN(jsDate))
+ return QDateTime();
+ QV8DateConverter::JSC::GregorianDateTime tm;
+ QV8DateConverter::JSC::msToGregorianDateTime(jsDate, tm);
+
+ // from QScriptEngine::MsFromTime()
+ int ms = int(::fmod(jsDate, 1000.0));
+ if (ms < 0)
+ ms += int(1000.0);
+
+ QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
+ QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
+ return convertedUTC.toLocalTime();
+}
+
+/*!
+\qmlmethod bool Qt::openUrlExternally(url target)
+Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
+*/
+v8::Handle<v8::Value> QV8Engine::openUrlExternally(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ return V8ENGINE()->fromVariant(false);
+
+ bool ret = false;
+#ifndef QT_NO_DESKTOPSERVICES
+ ret = QDesktopServices::openUrl(V8ENGINE()->toVariant(resolvedUrl(args), -1).toUrl());
+#endif
+ return V8ENGINE()->fromVariant(ret);
+}
+
+/*!
+ \qmlmethod url Qt::resolvedUrl(url url)
+ Returns \a url resolved relative to the URL of the caller.
+*/
+v8::Handle<v8::Value> QV8Engine::resolvedUrl(const v8::Arguments &args)
+{
+ QUrl url = V8ENGINE()->toVariant(args[0], -1).toUrl();
+ // XXX uses QDeclarativeEngine which means it wont work in worker script?
+ QDeclarativeEngine *e = V8ENGINE()->engine();
+ QDeclarativeEnginePrivate *p = 0;
+ if (e) p = QDeclarativeEnginePrivate::get(e);
+ if (p) {
+ QDeclarativeContextData *ctxt = V8ENGINE()->callingContext();
+ if (ctxt)
+ return V8ENGINE()->fromVariant(ctxt->resolvedUrl(url));
+ else
+ return V8ENGINE()->fromVariant(url);
+ }
+
+ return V8ENGINE()->fromVariant(e->baseUrl().resolved(url));
+}
+
+/*!
+\qmlmethod list<string> Qt::fontFamilies()
+Returns a list of the font families available to the application.
+*/
+v8::Handle<v8::Value> QV8Engine::fontFamilies(const v8::Arguments &args)
+{
+ if (args.Length() != 0)
+ V8THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
+
+ QFontDatabase database;
+ return V8ENGINE()->fromVariant(database.families());
+}
+
+/*!
+\qmlmethod string Qt::md5(data)
+Returns a hex string of the md5 hash of \c data.
+*/
+v8::Handle<v8::Value> QV8Engine::md5(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.md5(): Invalid arguments");
+
+ QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
+ QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
+ return V8ENGINE()->toString(QLatin1String(result.toHex()));
+}
+
+/*!
+\qmlmethod string Qt::btoa(data)
+Binary to ASCII - this function returns a base64 encoding of \c data.
+*/
+v8::Handle<v8::Value> QV8Engine::btoa(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.btoa(): Invalid arguments");
+
+ QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
+
+ return V8ENGINE()->toString(QLatin1String(data.toBase64()));
+}
+
+/*!
+\qmlmethod string Qt::atob(data)
+ASCII to binary - this function returns a base64 decoding of \c data.
+*/
+v8::Handle<v8::Value> QV8Engine::atob(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.atob(): Invalid arguments");
+
+ QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
+
+ return V8ENGINE()->toString(QLatin1String(QByteArray::fromBase64(data)));
+}
+
+/*!
+\qmlmethod Qt::quit()
+This function causes the QDeclarativeEngine::quit() signal to be emitted.
+Within the \l {QML Viewer}, this causes the launcher application to exit;
+to quit a C++ application when this method is called, connect the
+QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
+*/
+v8::Handle<v8::Value> QV8Engine::quit(const v8::Arguments &args)
+{
+ // XXX worker script?
+ QDeclarativeEnginePrivate::get(V8ENGINE()->engine())->sendQuit();
+ return v8::Undefined();
+}
+
+/*!
+\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
+
+Returns a new object created from the given \a string of QML which will have the specified \a parent,
+or \c null if there was an error in creating the object.
+
+If \a filepath is specified, it will be used for error reporting for the created object.
+
+Example (where \c parentItem is the id of an existing QML item):
+
+\snippet doc/src/snippets/declarative/createQmlObject.qml 0
+
+In the case of an error, a QtScript Error object is thrown. This object has an additional property,
+\c qmlErrors, which is an array of the errors encountered.
+Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
+For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
+{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
+
+Note that this function returns immediately, and therefore may not work if
+the \a qml string loads new components (that is, external QML files that have not yet been loaded).
+If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
+
+See \l {Dynamic Object Management in QML} for more information on using this function.
+*/
+v8::Handle<v8::Value> QV8Engine::createQmlObject(const v8::Arguments &args)
+{
+ if (args.Length() < 2 || args.Length() > 3)
+ V8THROW_ERROR("Qt.createQmlObject(): Invalid arguments");
+
+ struct Error {
+ static v8::Local<v8::Value> create(QV8Engine *engine, const QList<QDeclarativeError> &errors) {
+ QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
+
+ v8::Local<v8::Array> qmlerrors = v8::Array::New(errors.count());
+ for (int ii = 0; ii < errors.count(); ++ii) {
+ const QDeclarativeError &error = errors.at(ii);
+ errorstr += QLatin1String("\n ") + error.toString();
+ v8::Local<v8::Object> qmlerror = v8::Object::New();
+ qmlerror->Set(v8::String::New("lineNumber"), v8::Integer::New(error.line()));
+ qmlerror->Set(v8::String::New("columnNumber"), v8::Integer::New(error.line()));
+ qmlerror->Set(v8::String::New("fileName"), engine->toString(error.url().toString()));
+ qmlerror->Set(v8::String::New("message"), engine->toString(error.description()));
+ qmlerrors->Set(ii, qmlerror);
+ }
+
+ v8::Local<v8::Value> error = v8::Exception::Error(engine->toString(errorstr));
+ v8::Local<v8::Object> errorObject = error->ToObject();
+ errorObject->Set(v8::String::New("qmlErrors"), qmlerrors);
+ return error;
+ }
+ };
+
+ QV8Engine *v8engine = V8ENGINE();
+ QDeclarativeEngine *engine = v8engine->engine();
+
+ QDeclarativeContextData *context = v8engine->callingContext();
+ Q_ASSERT(context);
+
+ QString qml = v8engine->toString(args[0]->ToString());
+ if (qml.isEmpty())
+ return v8::Null();
+
+ QUrl url;
+ if(args.Length() > 2)
+ url = QUrl(v8engine->toString(args[2]->ToString()));
+ else
+ url = QUrl(QLatin1String("inline"));
+
+ if (url.isValid() && url.isRelative())
+ url = context->resolvedUrl(url);
+
+ QObject *parentArg = v8engine->toQObject(args[1]);
+ if(!parentArg)
+ V8THROW_ERROR("Qt.createQmlObject(): Missing parent object");
+
+ QDeclarativeComponent component(engine);
+ component.setData(qml.toUtf8(), url);
+
+ if(component.isError()) {
+ v8::ThrowException(Error::create(v8engine, component.errors()));
+ return v8::Undefined();
+ }
+
+ if (!component.isReady())
+ V8THROW_ERROR("Qt.createQmlObject(): Component is not ready");
+
+ QObject *obj = component.beginCreate(context->asQDeclarativeContext());
+ if(obj)
+ QDeclarativeData::get(obj, true)->setImplicitDestructible();
+ component.completeCreate();
+
+ if(component.isError()) {
+ v8::ThrowException(Error::create(v8engine, component.errors()));
+ return v8::Undefined();
+ }
+
+ Q_ASSERT(obj);
+
+ obj->setParent(parentArg);
+
+ QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
+ for (int ii = 0; ii < functions.count(); ++ii) {
+ if (QDeclarativePrivate::Parented == functions.at(ii)(obj, parentArg))
+ break;
+ }
+
+ return v8engine->newQObject(obj);
+}
+
+/*!
+\qmlmethod object Qt::createComponent(url)
+
+Returns a \l Component object created using the QML file at the specified \a url,
+or \c null if an empty string was given.
+
+The returned component's \l Component::status property indicates whether the
+component was successfully created. If the status is \c Component.Error,
+see \l Component::errorString() for an error description.
+
+Call \l {Component::createObject()}{Component.createObject()} on the returned
+component to create an object instance of the component.
+
+For example:
+
+\snippet doc/src/snippets/declarative/createComponent-simple.qml 0
+
+See \l {Dynamic Object Management in QML} for more information on using this function.
+
+To create a QML object from an arbitrary string of QML (instead of a file),
+use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
+*/
+v8::Handle<v8::Value> QV8Engine::createComponent(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.createComponent(): Invalid arguments");
+
+ QV8Engine *v8engine = V8ENGINE();
+ QDeclarativeEngine *engine = v8engine->engine();
+
+ QDeclarativeContextData *context = v8engine->callingContext();
+ Q_ASSERT(context);
+
+ QString arg = v8engine->toString(args[0]->ToString());
+ if (arg.isEmpty())
+ return v8::Null();
+
+ QUrl url = context->resolvedUrl(QUrl(arg));
+ QDeclarativeComponent *c = new QDeclarativeComponent(engine, url, engine);
+ QDeclarativeComponentPrivate::get(c)->creationContext = context;
+ QDeclarativeData::get(c, true)->setImplicitDestructible();
+ return v8engine->newQObject(c);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h
new file mode 100644
index 0000000000..d4b8730dc7
--- /dev/null
+++ b/src/declarative/qml/v8/qv8engine_p.h
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** 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 QDECLARATIVEV8ENGINE_P_H
+#define QDECLARATIVEV8ENGINE_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/qvariant.h>
+#include <QtCore/qset.h>
+#include <private/qv8_p.h>
+
+#include <private/qdeclarativepropertycache_p.h>
+
+#include "qv8contextwrapper_p.h"
+#include "qv8qobjectwrapper_p.h"
+#include "qv8stringwrapper_p.h"
+#include "qv8typewrapper_p.h"
+#include "qv8listwrapper_p.h"
+#include "qv8variantwrapper_p.h"
+#include "qv8valuetypewrapper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#define V8_RESOURCE_TYPE(resourcetype) \
+public: \
+ enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \
+ virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \
+private:
+
+#define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
+#define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
+// XXX Are we mean to return a value here, or is an empty handle ok?
+#define V8THROW_ERROR(string) { \
+ v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
+ return v8::Handle<v8::Value>(); \
+}
+
+class QV8Engine;
+class QV8ObjectResource : public v8::Object::ExternalResource
+{
+public:
+ QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
+ enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType,
+ ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType };
+ virtual ResourceType resourceType() const = 0;
+
+ QV8Engine *engine;
+};
+
+template<class T>
+T *v8_resource_cast(v8::Handle<v8::Object> object) {
+ QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource());
+ return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0;
+}
+
+// Used to allow a QObject method take and return raw V8 handles without having to expose
+// v8 in the public API.
+// Use like this:
+// class MyClass : public QObject {
+// Q_OBJECT
+// ...
+// Q_INVOKABLE void myMethod(QDeclarativeV8Function*);
+// };
+// The QDeclarativeV8Function - and consequently the arguments and return value - only remains
+// valid during the call. If the return value isn't set within myMethod(), the will return
+// undefined.
+class QV8Engine;
+class QDeclarativeV8Function
+{
+public:
+ int Length() const { return _ac; }
+ v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); }
+ QDeclarativeContextData *context() { return _c; }
+ v8::Handle<v8::Object> qmlGlobal() { return *_g; }
+ void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; }
+ QV8Engine *engine() const { return _e; }
+private:
+ friend class QV8QObjectWrapper;
+ QDeclarativeV8Function();
+ QDeclarativeV8Function(const QDeclarativeV8Function &);
+ QDeclarativeV8Function &operator=(const QDeclarativeV8Function &);
+
+ QDeclarativeV8Function(int length, v8::Handle<v8::Object> &args,
+ v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global,
+ QDeclarativeContextData *c, QV8Engine *e)
+ : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {}
+
+ int _ac;
+ v8::Handle<v8::Object> *_a;
+ v8::Handle<v8::Value> *_r;
+ v8::Handle<v8::Object> *_g;
+ QDeclarativeContextData *_c;
+ QV8Engine *_e;
+};
+
+class QDeclarativeV8Handle
+{
+public:
+ QDeclarativeV8Handle() : d(0) {}
+ QDeclarativeV8Handle(const QDeclarativeV8Handle &other) : d(other.d) {}
+ QDeclarativeV8Handle &operator=(const QDeclarativeV8Handle &other) { d = other.d; return *this; }
+
+ static QDeclarativeV8Handle fromHandle(v8::Handle<v8::Value> h) {
+ return reinterpret_cast<QDeclarativeV8Handle &>(h);
+ }
+ v8::Handle<v8::Value> toHandle() const {
+ return reinterpret_cast<const v8::Handle<v8::Value> &>(*this);
+ }
+private:
+ void *d;
+};
+
+class QObject;
+class QDeclarativeEngine;
+class QDeclarativeValueType;
+class QNetworkAccessManager;
+class QDeclarativeContextData;
+class Q_AUTOTEST_EXPORT QV8Engine
+{
+public:
+ QV8Engine();
+ ~QV8Engine();
+
+ void init(QDeclarativeEngine *);
+
+ QDeclarativeEngine *engine() { return m_engine; }
+ v8::Local<v8::Object> global() { return m_context->Global(); }
+ v8::Handle<v8::Context> context() { return m_context; }
+ QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
+ QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
+ QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
+ QV8ListWrapper *listWrapper() { return &m_listWrapper; }
+ QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
+
+ void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
+ void *sqlDatabaseData() { return m_sqlDatabaseData; }
+
+ QDeclarativeContextData *callingContext();
+
+ v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
+
+ inline QString toString(v8::Handle<v8::Value> string);
+ inline QString toString(v8::Handle<v8::String> string);
+ static QString toStringStatic(v8::Handle<v8::Value>);
+ static QString toStringStatic(v8::Handle<v8::String>);
+ static inline bool startsWithUpper(v8::Handle<v8::String>);
+
+ QVariant toVariant(v8::Handle<v8::Value>, int typeHint);
+ v8::Handle<v8::Value> fromVariant(const QVariant &);
+ inline bool isVariant(v8::Handle<v8::Value>);
+
+ // Compile \a source (from \a fileName at \a lineNumber) in QML mode
+ v8::Local<v8::Script> qmlModeCompile(const QString &source,
+ const QString &fileName = QString(),
+ int lineNumber = 1);
+
+ // Return the QML global "scope" object for the \a ctxt context and \a scope object.
+ inline v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
+
+ // Return a JS wrapper for the given QObject \a object
+ inline v8::Handle<v8::Value> newQObject(QObject *object);
+ inline bool isQObject(v8::Handle<v8::Value>);
+ inline QObject *toQObject(v8::Handle<v8::Value>);
+
+ // Return a JS string for the given QString \a string
+ inline v8::Local<v8::String> toString(const QString &string);
+
+ // Create a new value type object
+ inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QDeclarativeValueType *);
+ inline v8::Handle<v8::Value> newValueType(const QVariant &, QDeclarativeValueType *);
+
+ // Create a new QVariant object. This doesn't examine the type of the variant, but always returns
+ // a QVariant wrapper
+ inline v8::Handle<v8::Value> newQVariant(const QVariant &);
+
+ // Return the network access manager for this engine. By default this returns the network
+ // access manager of the QDeclarativeEngine. It is overridden in the case of a threaded v8
+ // instance (like in WorkerScript).
+ virtual QNetworkAccessManager *networkAccessManager();
+
+ // Return the list of illegal id names (the names of the properties on the global object)
+ const QSet<QString> &illegalNames() const;
+
+private:
+ QDeclarativeEngine *m_engine;
+ v8::Persistent<v8::Context> m_context;
+
+ QV8StringWrapper m_stringWrapper;
+ QV8ContextWrapper m_contextWrapper;
+ QV8QObjectWrapper m_qobjectWrapper;
+ QV8TypeWrapper m_typeWrapper;
+ QV8ListWrapper m_listWrapper;
+ QV8VariantWrapper m_variantWrapper;
+ QV8ValueTypeWrapper m_valueTypeWrapper;
+
+ v8::Persistent<v8::Function> m_getOwnPropertyNames;
+
+ void *m_xmlHttpRequestData;
+ void *m_sqlDatabaseData;
+
+ QSet<QString> m_illegalNames;
+
+ QVariant toBasicVariant(v8::Handle<v8::Value>);
+
+ void initializeGlobal(v8::Handle<v8::Object>);
+ void freezeGlobal();
+
+ static v8::Handle<v8::Value> print(const v8::Arguments &args);
+ static v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
+ static v8::Handle<v8::Value> rgba(const v8::Arguments &args);
+ static v8::Handle<v8::Value> hsla(const v8::Arguments &args);
+ static v8::Handle<v8::Value> rect(const v8::Arguments &args);
+ static v8::Handle<v8::Value> point(const v8::Arguments &args);
+ static v8::Handle<v8::Value> size(const v8::Arguments &args);
+ static v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
+ static v8::Handle<v8::Value> lighter(const v8::Arguments &args);
+ static v8::Handle<v8::Value> darker(const v8::Arguments &args);
+ static v8::Handle<v8::Value> tint(const v8::Arguments &args);
+ static v8::Handle<v8::Value> formatDate(const v8::Arguments &args);
+ static v8::Handle<v8::Value> formatTime(const v8::Arguments &args);
+ static v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args);
+ static v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args);
+ static v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args);
+ static v8::Handle<v8::Value> md5(const v8::Arguments &args);
+ static v8::Handle<v8::Value> btoa(const v8::Arguments &args);
+ static v8::Handle<v8::Value> atob(const v8::Arguments &args);
+ static v8::Handle<v8::Value> quit(const v8::Arguments &args);
+ static v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args);
+ static v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args);
+ static v8::Handle<v8::Value> createComponent(const v8::Arguments &args);
+
+ double qtDateTimeToJsDate(const QDateTime &dt);
+ QDateTime qtDateTimeFromJsDate(double jsDate);
+};
+
+QString QV8Engine::toString(v8::Handle<v8::Value> string)
+{
+ return m_stringWrapper.toString(string->ToString());
+}
+
+QString QV8Engine::toString(v8::Handle<v8::String> string)
+{
+ return m_stringWrapper.toString(string);
+}
+
+bool QV8Engine::isVariant(v8::Handle<v8::Value> value)
+{
+ return m_variantWrapper.isVariant(value);
+}
+
+v8::Local<v8::Object> QV8Engine::qmlScope(QDeclarativeContextData *ctxt, QObject *scope)
+{
+ return m_contextWrapper.qmlScope(ctxt, scope);
+}
+
+bool QV8Engine::isQObject(v8::Handle<v8::Value> obj)
+{
+ return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false;
+}
+
+QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj)
+{
+ return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0;
+}
+
+v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object)
+{
+ return m_qobjectWrapper.newQObject(object);
+}
+
+v8::Local<v8::String> QV8Engine::toString(const QString &string)
+{
+ return m_stringWrapper.toString(string);
+}
+
+v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QDeclarativeValueType *type)
+{
+ return m_valueTypeWrapper.newValueType(object, property, type);
+}
+
+v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QDeclarativeValueType *type)
+{
+ return m_valueTypeWrapper.newValueType(value, type);
+}
+
+// XXX perf?
+bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
+{
+ uint16_t buffer[2];
+ int written = string->Write(buffer, 0, 1);
+ if (written == 0) return false;
+ uint16_t c = buffer[0];
+ return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) &&
+ ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase));
+}
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEV8ENGINE_P_H
diff --git a/src/declarative/qml/v8/qv8include.cpp b/src/declarative/qml/v8/qv8include.cpp
new file mode 100644
index 0000000000..f2b25e0a92
--- /dev/null
+++ b/src/declarative/qml/v8/qv8include.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** 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 "qv8include_p.h"
+
+#include <QtScript/qscriptengine.h>
+#include <QtNetwork/qnetworkrequest.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtCore/qfile.h>
+
+#include <private/qdeclarativeengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QV8Include::QV8Include(const QUrl &url, QV8Engine *engine, QDeclarativeContextData *context,
+ v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Function> callback)
+: m_engine(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
+{
+ m_qmlglobal = v8::Persistent<v8::Object>::New(qmlglobal);
+ if (!callback.IsEmpty())
+ m_callbackFunction = v8::Persistent<v8::Function>::New(callback);
+
+ m_resultObject = v8::Persistent<v8::Object>::New(resultValue());
+
+ m_network = engine->networkAccessManager();
+
+ QNetworkRequest request;
+ request.setUrl(url);
+
+ m_reply = m_network->get(request);
+ QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+}
+
+QV8Include::~QV8Include()
+{
+ delete m_reply; m_reply = 0;
+ m_callbackFunction.Dispose();
+ m_resultObject.Dispose();
+}
+
+v8::Local<v8::Object> QV8Include::resultValue(Status status)
+{
+ // XXX aakenned inefficient
+ v8::Local<v8::Object> result = v8::Object::New();
+ result->Set(v8::String::New("OK"), v8::Integer::New(Ok));
+ result->Set(v8::String::New("LOADING"), v8::Integer::New(Loading));
+ result->Set(v8::String::New("NETWORK_ERROR"), v8::Integer::New(NetworkError));
+ result->Set(v8::String::New("EXCEPTION"), v8::Integer::New(Exception));
+
+ result->Set(v8::String::New("status"), v8::Integer::New(status));
+
+ return result;
+}
+
+void QV8Include::callback(QV8Engine *engine, v8::Handle<v8::Function> callback, v8::Handle<v8::Object> status)
+{
+ if (!callback.IsEmpty()) {
+ v8::Handle<v8::Value> args[] = { status };
+ // XXX TryCatch?
+ callback->Call(engine->global(), 1, args);
+ }
+}
+
+v8::Handle<v8::Object> QV8Include::result()
+{
+ return m_resultObject;
+}
+
+#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
+void QV8Include::finished()
+{
+ m_redirectCount++;
+
+ if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) {
+ QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ m_url = m_url.resolved(redirect.toUrl());
+ delete m_reply;
+
+ QNetworkRequest request;
+ request.setUrl(m_url);
+
+ m_reply = m_network->get(request);
+ QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ return;
+ }
+ }
+
+ v8::HandleScope handle_scope;
+
+ if (m_reply->error() == QNetworkReply::NoError) {
+ QByteArray data = m_reply->readAll();
+
+ QString code = QString::fromUtf8(data);
+ QDeclarativeScriptParser::extractPragmas(code);
+
+ QDeclarativeContextData *importContext = new QDeclarativeContextData;
+ importContext->isInternal = true;
+ importContext->isJSContext = true;
+ importContext->url = m_url;
+ importContext->setParent(m_context, true);
+
+ v8::Context::Scope ctxtscope(m_engine->context());
+ v8::TryCatch try_catch;
+
+ v8::Local<v8::Script> script = m_engine->qmlModeCompile(code, m_url.toString());
+
+ if (!try_catch.HasCaught()) {
+ m_engine->contextWrapper()->addSubContext(m_qmlglobal, script, importContext);
+ script->Run(m_qmlglobal);
+ }
+
+ if (try_catch.HasCaught()) {
+ m_resultObject->Set(v8::String::New("status"), v8::Integer::New(Exception));
+ m_resultObject->Set(v8::String::New("exception"), try_catch.Exception());
+ } else {
+ m_resultObject->Set(v8::String::New("status"), v8::Integer::New(Ok));
+ }
+ } else {
+ m_resultObject->Set(v8::String::New("status"), v8::Integer::New(NetworkError));
+ }
+
+ callback(m_engine, m_callbackFunction, m_resultObject);
+
+ disconnect();
+ deleteLater();
+}
+
+/*
+ Documented in qv8engine.cpp
+*/
+v8::Handle<v8::Value> QV8Include::include(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ return v8::Undefined();
+
+ QV8Engine *engine = V8ENGINE();
+ QDeclarativeContextData *context = engine->callingContext();
+
+ if (!context || !context->isJSContext)
+ V8THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
+
+ QUrl url(context->resolvedUrl(QUrl(engine->toString(args[0]->ToString()))));
+
+ v8::Local<v8::Function> callbackFunction;
+ if (args.Length() >= 2 && args[1]->IsFunction())
+ callbackFunction = v8::Local<v8::Function>::Cast(args[1]);
+
+ QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+
+ v8::Local<v8::Object> result;
+
+ if (localFile.isEmpty()) {
+
+ QV8Include *i = new QV8Include(url, engine, context,
+ v8::Context::GetCallingQmlGlobal(),
+ callbackFunction);
+ result = v8::Local<v8::Object>::New(i->result());
+
+ } else {
+
+ QFile f(localFile);
+
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QString code = QString::fromUtf8(data);
+ QDeclarativeScriptParser::extractPragmas(code);
+
+ QDeclarativeContextData *importContext = new QDeclarativeContextData;
+ importContext->isInternal = true;
+ importContext->isJSContext = true;
+ importContext->url = url;
+ importContext->setParent(context, true);
+
+ v8::TryCatch try_catch;
+
+ v8::Local<v8::Script> script = engine->qmlModeCompile(code, url.toString());
+
+ if (!try_catch.HasCaught()) {
+ v8::Local<v8::Object> qmlglobal = v8::Context::GetCallingQmlGlobal();
+ engine->contextWrapper()->addSubContext(qmlglobal, script, importContext);
+ script->Run(qmlglobal);
+ }
+
+ if (try_catch.HasCaught()) {
+ result = resultValue(Exception);
+ result->Set(v8::String::New("exception"), try_catch.Exception());
+ } else {
+ result = resultValue(Ok);
+ }
+
+ } else {
+ result = resultValue(NetworkError);
+ }
+
+ callback(engine, callbackFunction, result);
+ }
+
+ if (result.IsEmpty())
+ return v8::Undefined();
+ else
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeinclude_p.h b/src/declarative/qml/v8/qv8include_p.h
index e56de79058..76997ba649 100644
--- a/src/declarative/qml/qdeclarativeinclude_p.h
+++ b/src/declarative/qml/v8/qv8include_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEINCLUDE_P_H
-#define QDECLARATIVEINCLUDE_P_H
+#ifndef QV8INCLUDE_P_H
+#define QV8INCLUDE_P_H
//
// W A R N I N G
@@ -55,19 +55,19 @@
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
-#include <QtScript/qscriptvalue.h>
#include <private/qdeclarativecontext_p.h>
#include <private/qdeclarativeguard_p.h>
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeEngine;
-class QScriptContext;
-class QScriptEngine;
class QNetworkAccessManager;
class QNetworkReply;
-class QDeclarativeInclude : public QObject
+class QV8Engine;
+class QV8Include : public QObject
{
Q_OBJECT
public:
@@ -78,38 +78,36 @@ public:
Exception = 3
};
- QDeclarativeInclude(const QUrl &, QDeclarativeEngine *, QScriptContext *ctxt);
- ~QDeclarativeInclude();
-
- void setCallback(const QScriptValue &);
- QScriptValue callback() const;
+ static v8::Handle<v8::Value> include(const v8::Arguments &args);
- QScriptValue result() const;
+private slots:
+ void finished();
- static QScriptValue resultValue(QScriptEngine *, Status status = Loading);
- static void callback(QScriptEngine *, QScriptValue &callback, QScriptValue &status);
+private:
+ QV8Include(const QUrl &, QV8Engine *, QDeclarativeContextData *,
+ v8::Handle<v8::Object>, v8::Handle<v8::Function>);
+ ~QV8Include();
- static QScriptValue include(QScriptContext *ctxt, QScriptEngine *engine);
- static QScriptValue worker_include(QScriptContext *ctxt, QScriptEngine *engine);
+ v8::Handle<v8::Object> result();
-public slots:
- void finished();
+ static v8::Local<v8::Object> resultValue(Status status = Loading);
+ static void callback(QV8Engine *engine, v8::Handle<v8::Function> callback, v8::Handle<v8::Object> status);
-private:
- QDeclarativeEngine *m_engine;
- QScriptEngine *m_scriptEngine;
+ QV8Engine *m_engine;
QNetworkAccessManager *m_network;
QDeclarativeGuard<QNetworkReply> m_reply;
QUrl m_url;
int m_redirectCount;
- QScriptValue m_callback;
- QScriptValue m_result;
+
+ v8::Persistent<v8::Function> m_callbackFunction;
+ v8::Persistent<v8::Object> m_resultObject;
+
QDeclarativeGuardedContextData m_context;
- QScriptValue m_scope[2];
+ v8::Persistent<v8::Object> m_qmlglobal;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVEINCLUDE_P_H
+#endif // QV8INCLUDE_P_H
diff --git a/src/declarative/qml/v8/qv8listwrapper.cpp b/src/declarative/qml/v8/qv8listwrapper.cpp
new file mode 100644
index 0000000000..9e1110fd85
--- /dev/null
+++ b/src/declarative/qml/v8/qv8listwrapper.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** 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 "qv8listwrapper_p.h"
+#include "qv8engine_p.h"
+#include <private/qdeclarativelist_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8ListResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(ListType);
+public:
+ QV8ListResource(QV8Engine *engine) : QV8ObjectResource(engine) {}
+
+ QDeclarativeGuard<QObject> object;
+ QDeclarativeListProperty<QObject> property;
+ int propertyType;
+};
+
+QV8ListWrapper::QV8ListWrapper()
+: m_engine(0)
+{
+}
+
+QV8ListWrapper::~QV8ListWrapper()
+{
+}
+
+void QV8ListWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter);
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, 0,
+ v8::Handle<v8::Value>(), v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+}
+
+void QV8ListWrapper::destroy()
+{
+ m_constructor.Dispose();
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::newList(QObject *object, int propId, int propType)
+{
+ if (!object || propId == -1)
+ return v8::Null();
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ListResource *r = new QV8ListResource(m_engine);
+ r->object = object;
+ r->propertyType = propType;
+ void *args[] = { &r->property, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::newList(const QDeclarativeListProperty<QObject> &prop, int propType)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ListResource *r = new QV8ListResource(m_engine);
+ r->object = prop.object;
+ r->property = prop;
+ r->propertyType = propType;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+QVariant QV8ListWrapper::toVariant(v8::Handle<v8::Object> obj)
+{
+ QV8ListResource *resource = v8_resource_cast<QV8ListResource>(obj);
+ if (resource) return toVariant(resource);
+ else return QVariant();
+}
+
+QVariant QV8ListWrapper::toVariant(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::ListType);
+ QV8ListResource *resource = static_cast<QV8ListResource *>(r);
+
+ if (!resource->object)
+ return QVariant();
+
+ return QVariant::fromValue(QDeclarativeListReferencePrivate::init(resource->property, resource->propertyType,
+ m_engine->engine()));
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ Q_UNUSED(info);
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ Q_UNUSED(info);
+ return value;
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::IndexedGetter(uint32_t index, const v8::AccessorInfo &info)
+{
+ QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This());
+
+ if (!resource || resource->object.isNull()) return v8::Undefined();
+
+ quint32 count = resource->property.count?resource->property.count(&resource->property):0;
+ if (index < count && resource->property.at) {
+ return resource->engine->newQObject(resource->property.at(&resource->property, index));
+ } else {
+ return v8::Undefined();
+ }
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::LengthGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+
+ QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This());
+
+ if (!resource || resource->object.isNull()) return v8::Undefined();
+
+ quint32 count = resource->property.count?resource->property.count(&resource->property):0;
+
+ return v8::Integer::NewFromUnsigned(count);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8listwrapper_p.h b/src/declarative/qml/v8/qv8listwrapper_p.h
new file mode 100644
index 0000000000..82fdaa7271
--- /dev/null
+++ b/src/declarative/qml/v8/qv8listwrapper_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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 QV8LISTWRAPPER_P_H
+#define QV8LISTWRAPPER_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 <QtDeclarative/qdeclarativelist.h>
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8Engine;
+class QV8ObjectResource;
+class QV8ListWrapper
+{
+public:
+ QV8ListWrapper();
+ ~QV8ListWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
+
+ v8::Handle<v8::Value> newList(QObject *, int, int);
+ v8::Handle<v8::Value> newList(const QDeclarativeListProperty<QObject> &, int);
+ QVariant toVariant(v8::Handle<v8::Object>);
+ QVariant toVariant(QV8ObjectResource *);
+
+private:
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> IndexedGetter(uint32_t index,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> LengthGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV8LISTWRAPPER_P_H
+
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
new file mode 100644
index 0000000000..99cede2072
--- /dev/null
+++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
@@ -0,0 +1,1714 @@
+/****************************************************************************
+**
+** 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 "qv8qobjectwrapper_p.h"
+#include "qv8contextwrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativeguard_p.h>
+#include <private/qdeclarativepropertycache_p.h>
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativevmemetaobject_p.h>
+#include <private/qdeclarativebinding_p.h>
+
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QDeclarativeV8Handle);
+
+#if defined(__GNUC__)
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
+// The code in this file does not violate strict aliasing, but GCC thinks it does
+// so turn off the warnings for us to have a clean build
+# pragma GCC diagnostic ignored "-Wstrict-aliasing"
+# endif
+#endif
+
+#define QOBJECT_TOSTRING_INDEX -2
+#define QOBJECT_DESTROY_INDEX -3
+
+class QV8QObjectResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(QObjectType);
+
+public:
+ QV8QObjectResource(QV8Engine *engine, QObject *object);
+
+ QDeclarativeGuard<QObject> object;
+};
+
+namespace {
+struct MetaCallArgument {
+ inline MetaCallArgument();
+ inline ~MetaCallArgument();
+ inline void *dataPtr();
+
+ inline void initAsType(int type);
+ inline void fromValue(int type, QV8Engine *, v8::Handle<v8::Value>);
+ inline v8::Handle<v8::Value> toValue(QV8Engine *);
+
+private:
+ MetaCallArgument(const MetaCallArgument &);
+
+ inline void cleanup();
+
+ char data[4 * sizeof(void *)];
+ int type;
+ bool isObjectType;
+};
+}
+
+QV8QObjectResource::QV8QObjectResource(QV8Engine *engine, QObject *object)
+: QV8ObjectResource(engine), object(object)
+{
+}
+
+QV8QObjectWrapper::QV8QObjectWrapper()
+: m_engine(0)
+{
+}
+
+QV8QObjectWrapper::~QV8QObjectWrapper()
+{
+}
+
+void QV8QObjectWrapper::destroy()
+{
+ qDeleteAll(m_connections);
+ m_connections.clear();
+
+ m_hiddenObject.Dispose();
+ m_destroySymbol.Dispose();
+ m_toStringSymbol.Dispose();
+ m_methodConstructor.Dispose();
+ m_constructor.Dispose();
+}
+
+#define FAST_VALUE_GETTER(name, cpptype, defaultvalue, constructor) \
+static v8::Handle<v8::Value> name ## ValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info) \
+{ \
+ v8::Handle<v8::Object> This = info.This(); \
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(This); \
+ \
+ if (!resource || resource->object.isNull()) return v8::Undefined(); \
+ \
+ QObject *object = resource->object; \
+ \
+ uint32_t data = info.Data()->Uint32Value(); \
+ int index = data & 0x7FFF; \
+ int notify = (data & 0x7FFF0000) >> 16; \
+ if (notify == 0x7FFF) notify = -1; \
+ \
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(resource->engine->engine()); \
+ if (notify /* 0 means constant */ && ep->captureProperties) { \
+ typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty; \
+ ep->capturedProperties << CapturedProperty(object, index, notify); \
+ } \
+ \
+ cpptype value = defaultvalue; \
+ void *args[] = { &value, 0 }; \
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, index, args); \
+ \
+ return constructor(value); \
+}
+
+#define CREATE_FUNCTION \
+ "(function(method) { "\
+ "return (function(object, data, qmlglobal) { "\
+ "return (function() { "\
+ "return method(object, data, qmlglobal, arguments.length, arguments); "\
+ "});"\
+ "});"\
+ "})"
+
+void QV8QObjectWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+
+ m_toStringSymbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("toString"));
+ m_destroySymbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("destroy"));
+ m_hiddenObject = v8::Persistent<v8::Object>::New(v8::Object::New());
+
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ v8::ScriptOrigin origin(m_hiddenObject); // Hack to allow us to identify these functions
+ v8::Local<v8::Script> script = v8::Script::New(v8::String::New(CREATE_FUNCTION), &origin);
+ v8::Local<v8::Function> fn = v8::Local<v8::Function>::Cast(script->Run());
+ v8::Handle<v8::Value> invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction();
+ v8::Handle<v8::Value> args[] = { invokeFn };
+ v8::Local<v8::Function> createFn = v8::Local<v8::Function>::Cast(fn->Call(engine->global(), 1, args));
+ m_methodConstructor = v8::Persistent<v8::Function>::New(createFn);
+ }
+
+ {
+ 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));
+ }
+}
+
+bool QV8QObjectWrapper::isQObject(v8::Handle<v8::Object> obj)
+{
+ return v8_resource_cast<QV8QObjectResource>(obj) != 0;
+}
+
+QObject *QV8QObjectWrapper::toQObject(v8::Handle<v8::Object> obj)
+{
+ QV8QObjectResource *r = v8_resource_cast<QV8QObjectResource>(obj);
+ return r?r->object:0;
+}
+
+// r *MUST* be a QV8ObjectResource (r->type() == QV8ObjectResource::QObjectType)
+QObject *QV8QObjectWrapper::QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::QObjectType);
+ return static_cast<QV8QObjectResource *>(r)->object;
+}
+
+// Load value properties
+static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
+ const QDeclarativePropertyCache::Data &property)
+{
+ Q_ASSERT(!property.isFunction());
+
+#define PROPERTY_LOAD(metatype, cpptype, constructor) \
+ if (property.propType == QMetaType:: metatype) { \
+ cpptype type = cpptype(); \
+ void *args[] = { &type, 0 }; \
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args); \
+ return constructor(type); \
+ }
+
+ if (property.isQObject()) {
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+ return engine->newQObject(rv);
+ } else if (property.isQList()) {
+ return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
+ } else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
+ else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Number::New)
+ else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
+ else PROPERTY_LOAD(QString, QString, engine->toString)
+ else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
+ else PROPERTY_LOAD(Float, float, v8::Number::New)
+ else PROPERTY_LOAD(Double, double, v8::Number::New)
+ else if(property.isV8Handle()) {
+ QDeclarativeV8Handle handle;
+ void *args[] = { &handle, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+ return reinterpret_cast<v8::Handle<v8::Value> &>(handle);
+ } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
+ if (valueType)
+ return engine->newValueType(object, property.coreIndex, valueType);
+ }
+
+ QVariant var = object->metaObject()->property(property.coreIndex).read(object);
+ return engine->fromVariant(var);
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object,
+ v8::Handle<v8::Value> *objectHandle,
+ v8::Handle<v8::String> property,
+ QV8QObjectWrapper::RevisionMode revisionMode)
+{
+ // XXX aakenned This can't possibly be the best solution!!!
+ struct MethodClosure {
+ static v8::Handle<v8::Value> create(QV8Engine *engine, QObject *object,
+ v8::Handle<v8::Value> *objectHandle,
+ int index) {
+ v8::Handle<v8::Value> argv[] = {
+ objectHandle?*objectHandle:engine->newQObject(object),
+ v8::Integer::New(index)
+ };
+ return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 2, argv);
+ }
+ static v8::Handle<v8::Value> createWithGlobal(QV8Engine *engine, QObject *object,
+ v8::Handle<v8::Value> *objectHandle,
+ int index) {
+ v8::Handle<v8::Value> argv[] = {
+ objectHandle?*objectHandle:engine->newQObject(object),
+ v8::Integer::New(index),
+ v8::Context::GetCallingQmlGlobal()
+ };
+ return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 3, argv);
+ }
+ };
+
+ if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property)) {
+ return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
+ } else if (engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property)) {
+ return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX);
+ }
+
+ QDeclarativePropertyCache::Data local;
+ QDeclarativePropertyCache::Data *result = 0;
+ result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+
+ if (!result)
+ return v8::Handle<v8::Value>();
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+
+ if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
+ return v8::Handle<v8::Value>();
+ }
+
+ typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty;
+
+ if (result->isFunction()) {
+ if (result->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
+ return ((QDeclarativeVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
+ } else if (result->flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex);
+ } else {
+ return MethodClosure::create(engine, object, objectHandle, result->coreIndex);
+ }
+ }
+
+ if (ep->captureProperties && !result->isConstant()) {
+ if (result->coreIndex == 0)
+ ep->capturedProperties << CapturedProperty(QDeclarativeData::get(object, true)->objectNameNotifier());
+ else
+ ep->capturedProperties << CapturedProperty(object, result->coreIndex, result->notifyIndex);
+ }
+
+ return LoadProperty(engine, object, *result);
+}
+
+// Setter for writable properties. Shared between the interceptor and fast property accessor
+static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativePropertyCache::Data *property,
+ v8::Handle<v8::Value> value)
+{
+ QDeclarativeBinding *newBinding = 0;
+
+ if (value->IsFunction()) {
+ QDeclarativeContextData *context = engine->callingContext();
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
+
+ v8::Local<v8::StackTrace> trace =
+ v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
+ v8::StackTrace::kScriptName));
+ v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
+ int lineNumber = frame->GetLineNumber();
+ QString url = engine->toString(frame->GetScriptName());
+
+ QDeclarativePropertyCache::ValueTypeData valueTypeData;
+ newBinding = new QDeclarativeBinding(&function, object, context);
+ newBinding->setSourceLocation(url, lineNumber);
+ newBinding->setTarget(QDeclarativePropertyPrivate::restore(*property, valueTypeData, object, context));
+ newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
+ }
+
+ QDeclarativeAbstractBinding *oldBinding =
+ QDeclarativePropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
+ if (oldBinding)
+ oldBinding->destroy();
+
+#define PROPERTY_STORE(cpptype, value) \
+ cpptype o = value; \
+ int status = -1; \
+ int flags = 0; \
+ void *argv[] = { &o, 0, &status, &flags }; \
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv);
+
+
+ if (value->IsNull() && property->isQObject()) {
+ PROPERTY_STORE(QObject*, 0);
+ } else if (value->IsUndefined() && property->isResettable()) {
+ void *a[] = { 0 };
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a);
+ } else if (value->IsUndefined() && property->propType == qMetaTypeId<QVariant>()) {
+ PROPERTY_STORE(QVariant, QVariant());
+ } else if (value->IsUndefined()) {
+ QString error = QLatin1String("Cannot assign [undefined] to ") +
+ QLatin1String(QMetaType::typeName(property->propType));
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ } else if (value->IsFunction()) {
+ // this is handled by the binding creation above
+ } else if (property->propType == QMetaType::Int && value->IsNumber()) {
+ PROPERTY_STORE(int, qRound(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::QReal && value->IsNumber()) {
+ PROPERTY_STORE(qreal, qreal(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::Float && value->IsNumber()) {
+ PROPERTY_STORE(float, float(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::Double && value->IsNumber()) {
+ PROPERTY_STORE(double, double(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::QString && value->IsString()) {
+ PROPERTY_STORE(QString, engine->toString(value->ToString()));
+ } else {
+ QVariant v;
+ if (property->isQList())
+ v = engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ else
+ v = engine->toVariant(value, property->propType);
+
+ QDeclarativeContextData *context = engine->callingContext();
+
+ if (!QDeclarativePropertyPrivate::write(object, *property, v, context)) {
+ const char *valueType = 0;
+ if (v.userType() == QVariant::Invalid) valueType = "null";
+ else valueType = QMetaType::typeName(v.userType());
+
+ QString error = QLatin1String("Cannot assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(QMetaType::typeName(property->propType));
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ }
+ }
+}
+
+bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, v8::Handle<v8::String> property,
+ v8::Handle<v8::Value> value, QV8QObjectWrapper::RevisionMode revisionMode)
+{
+ if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property) ||
+ engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property))
+ return true;
+
+ QDeclarativePropertyCache::Data local;
+ QDeclarativePropertyCache::Data *result = 0;
+ result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+
+ if (!result)
+ return false;
+
+ if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
+ return false;
+ }
+
+ if (!result->isWritable() && !result->isQList()) {
+ QString error = QLatin1String("Cannot assign to read-only property \"") +
+ engine->toString(property) + QLatin1Char('\"');
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return true;
+ }
+
+ StoreProperty(engine, object, result, value);
+
+ return true;
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+ v8::Handle<v8::Value> This = info.This();
+
+ if (!resource || resource->object.isNull()) return v8::Undefined();
+
+ QObject *object = resource->object;
+
+ QV8Engine *v8engine = resource->engine;
+ v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, property, QV8QObjectWrapper::IgnoreRevision);
+ if (!result.IsEmpty())
+ return result;
+
+ if (QV8Engine::startsWithUpper(property)) {
+ // Check for attached properties
+ QDeclarativeContextData *context = v8engine->callingContext();
+ QDeclarativeTypeNameCache::Data *data = context && (context->imports)?context->imports->data(property):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);
+ }
+ }
+
+ return v8::Undefined();
+ } else {
+ // XXX throw?
+ return v8::Undefined();
+ }
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return value;
+
+ QObject *object = resource->object;
+
+ QV8Engine *v8engine = resource->engine;
+ bool result = SetProperty(v8engine, object, property, value, QV8QObjectWrapper::IgnoreRevision);
+
+ if (!result) {
+ QString error = QLatin1String("Cannot assign to non-existent property \"") +
+ v8engine->toString(property) + QLatin1Char('\"');
+ v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
+ return value;
+ }
+
+ return value;
+}
+
+v8::Handle<v8::Integer> QV8QObjectWrapper::Query(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return v8::Handle<v8::Integer>();
+
+ QV8Engine *engine = resource->engine;
+ QObject *object = resource->object;
+
+ QDeclarativePropertyCache::Data local;
+ QDeclarativePropertyCache::Data *result = 0;
+ result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+
+ if (!result)
+ return v8::Handle<v8::Integer>();
+ else if (!result->isWritable() && !result->isQList())
+ return v8::Integer::New(v8::ReadOnly | v8::DontDelete);
+ else
+ return v8::Integer::New(v8::DontDelete);
+}
+
+v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return v8::Array::New();
+
+ QObject *object = resource->object;
+
+ QStringList result;
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(resource->engine->engine());
+
+ QDeclarativePropertyCache *cache = 0;
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ if (ddata)
+ cache = ddata->propertyCache;
+
+ if (!cache) {
+ cache = ep->cache(object);
+ if (cache) {
+ if (ddata) { cache->addref(); ddata->propertyCache = cache; }
+ } else {
+ // Not cachable - fall back to QMetaObject (eg. dynamic meta object)
+ // XXX QDeclarativeOpenMetaObject has a cache, so this is suboptimal.
+ // XXX This is a workaround for QTBUG-9420.
+ const QMetaObject *mo = object->metaObject();
+ int pc = mo->propertyCount();
+ int po = mo->propertyOffset();
+ for (int i=po; i<pc; ++i)
+ result << QString::fromUtf8(mo->property(i).name());
+ }
+ } else {
+ result = cache->propertyNames();
+ }
+
+ v8::Local<v8::Array> rv = v8::Array::New(result.count());
+
+ for (int ii = 0; ii < result.count(); ++ii)
+ rv->Set(ii, resource->engine->toString(result.at(ii)));
+
+ return rv;
+}
+
+FAST_VALUE_GETTER(QObject, QObject*, 0, resource->engine->newQObject);
+FAST_VALUE_GETTER(Int, int, 0, v8::Integer::New);
+FAST_VALUE_GETTER(Bool, bool, false, v8::Boolean::New);
+FAST_VALUE_GETTER(QString, QString, QString(), resource->engine->toString);
+FAST_VALUE_GETTER(UInt, uint, 0, v8::Integer::NewFromUnsigned);
+FAST_VALUE_GETTER(Float, float, 0, v8::Number::New);
+FAST_VALUE_GETTER(Double, double, 0, v8::Number::New);
+
+static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return;
+
+ QObject *object = resource->object;
+
+ uint32_t data = info.Data()->Uint32Value();
+ int index = data & 0x7FFF; // So that we can use the same data for Setter and Getter
+
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+ Q_ASSERT(ddata);
+ Q_ASSERT(ddata->propertyCache);
+
+ QDeclarativePropertyCache::Data *pdata = ddata->propertyCache->property(index);
+ Q_ASSERT(pdata);
+
+ Q_ASSERT(pdata->isWritable() || pdata->isQList());
+
+ StoreProperty(resource->engine, object, pdata, value);
+}
+
+static void WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *)
+{
+ Q_ASSERT(handle->IsObject());
+
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(handle->ToObject());
+
+ Q_ASSERT(resource);
+
+ QObject *object = resource->object;
+ if (object) {
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+ if (ddata) {
+ ddata->v8object.Clear();
+ if (!object->parent() && !ddata->indestructible)
+ object->deleteLater();
+ }
+ }
+
+ // XXX do we want to use the objectDataRefCount to support multiple concurrent engines?
+
+ handle.Dispose();
+}
+
+v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8Engine *engine)
+{
+ Q_ASSERT(object);
+
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+
+ Q_ASSERT(ddata && ddata->propertyCache && ddata->propertyCache == this);
+ Q_ASSERT(ddata->v8object.IsEmpty());
+
+ // Setup constructor
+ if (constructor.IsEmpty()) {
+ v8::Local<v8::FunctionTemplate> ft;
+
+ QString toString = QLatin1String("toString");
+ QString destroy = QLatin1String("destroy");
+
+ // XXX Enables fast property accessors. These more than double the property access
+ // performance, but the cost of setting up this structure hasn't been measured so
+ // its not guarenteed that this is a win overall
+ for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) {
+ Data *property = *iter;
+ if (property->isFunction() || !property->isWritable() ||
+ property->coreIndex >= 0x7FFF || property->notifyIndex >= 0x7FFF ||
+ property->coreIndex == 0)
+ continue;
+
+ v8::AccessorGetter fastgetter = 0;
+
+
+ if (property->isQObject())
+ fastgetter = QObjectValueGetter;
+ else if (property->propType == QMetaType::Int || property->isEnum())
+ fastgetter = IntValueGetter;
+ else if (property->propType == QMetaType::Bool)
+ fastgetter = BoolValueGetter;
+ else if (property->propType == QMetaType::QString)
+ fastgetter = QStringValueGetter;
+ else if (property->propType == QMetaType::UInt)
+ fastgetter = UIntValueGetter;
+ else if (property->propType == QMetaType::Float)
+ fastgetter = FloatValueGetter;
+ else if (property->propType == QMetaType::Double)
+ fastgetter = DoubleValueGetter;
+
+ if (fastgetter) {
+ int notifyIndex = property->notifyIndex;
+ if (property->isConstant()) notifyIndex = 0;
+ else if (notifyIndex == -1) notifyIndex = 0x7FFF;
+ uint32_t data = (property->notifyIndex & 0x7FFF) << 16 | property->coreIndex;
+
+ QString name = iter.key();
+ if (name == toString || name == destroy)
+ continue;
+
+ if (ft.IsEmpty()) {
+ ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter,
+ QV8QObjectWrapper::Setter,
+ QV8QObjectWrapper::Query,
+ 0,
+ QV8QObjectWrapper::Enumerator);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ }
+
+ ft->InstanceTemplate()->SetAccessor(engine->toString(name), fastgetter, FastValueSetter,
+ v8::Integer::NewFromUnsigned(data));
+ }
+ }
+
+ if (ft.IsEmpty()) {
+ constructor = v8::Persistent<v8::Function>::New(engine->qobjectWrapper()->m_constructor);
+ } else {
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter,
+ QV8QObjectWrapper::Setter,
+ QV8QObjectWrapper::Query,
+ 0,
+ QV8QObjectWrapper::Enumerator);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ }
+
+ v8::Local<v8::Object> result = constructor->NewInstance();
+ QV8QObjectResource *r = new QV8QObjectResource(engine, object);
+ result->SetExternalResource(r);
+
+ ddata->v8object = v8::Persistent<v8::Object>::New(result);
+ ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
+ return result;
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
+{
+ // XXX aakenned QDeclarativeObjectScriptClass::newQObject() does a lot more
+
+ if (!object)
+ return v8::Null();
+
+ if (QObjectPrivate::get(object)->wasDeleted)
+ return v8::Undefined();
+
+ QDeclarativeData *ddata = QDeclarativeData::get(object, true);
+
+ if (!ddata)
+ return v8::Undefined();
+
+ if (ddata->v8object.IsEmpty()) {
+
+ if (ddata->propertyCache) {
+ return ddata->propertyCache->newQObject(object, m_engine);
+ }
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8QObjectResource *r = new QV8QObjectResource(m_engine, object);
+ rv->SetExternalResource(r);
+ ddata->v8object = v8::Persistent<v8::Object>::New(rv);
+ }
+
+ // XXX do we have to check that the v8object isn't "owned" by another engine?
+
+ ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
+ return v8::Local<v8::Object>::New(ddata->v8object);
+}
+
+QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function)
+{
+ v8::ScriptOrigin origin = function->GetScriptOrigin();
+ if (origin.ResourceName()->StrictEquals(engine->qobjectWrapper()->m_hiddenObject)) {
+
+ // This is one of our special QObject method wrappers
+ v8::Handle<v8::Value> args[] = { engine->qobjectWrapper()->m_hiddenObject };
+ v8::Local<v8::Value> data = function->Call(engine->global(), 1, args);
+
+ if (data->IsArray()) {
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(data);
+ return qMakePair(engine->toQObject(array->Get(0)), array->Get(1)->Int32Value());
+ }
+
+ // In theory this can't fall through, but I suppose V8 might run out of memory or something
+ }
+
+ return qMakePair((QObject *)0, -1);
+}
+
+struct QV8QObjectConnectionList : public QObject, public QDeclarativeGuard<QObject>
+{
+ QV8QObjectConnectionList(QObject *object, QV8Engine *engine);
+ ~QV8QObjectConnectionList();
+
+ struct Connection {
+ v8::Persistent<v8::Object> thisObject;
+ v8::Persistent<v8::Function> function;
+ };
+
+ QV8Engine *engine;
+
+ typedef QHash<int, QList<Connection> > SlotHash;
+ SlotHash slotHash;
+
+ virtual void objectDestroyed(QObject *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **);
+};
+
+QV8QObjectConnectionList::QV8QObjectConnectionList(QObject *object, QV8Engine *engine)
+: QDeclarativeGuard<QObject>(object), engine(engine)
+{
+}
+
+QV8QObjectConnectionList::~QV8QObjectConnectionList()
+{
+ for (SlotHash::Iterator iter = slotHash.begin(); iter != slotHash.end(); ++iter) {
+ QList<Connection> &connections = *iter;
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ connections[ii].thisObject.Dispose();
+ connections[ii].function.Dispose();
+ }
+ }
+ slotHash.clear();
+}
+
+void QV8QObjectConnectionList::objectDestroyed(QObject *object)
+{
+ engine->qobjectWrapper()->m_connections.remove(object);
+ delete this;
+}
+
+int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, void **metaArgs)
+{
+ if (method == QMetaObject::InvokeMetaMethod) {
+ SlotHash::Iterator iter = slotHash.find(index);
+ if (iter == slotHash.end())
+ return -1;
+ QList<Connection> &connections = *iter;
+ if (connections.isEmpty())
+ return -1;
+
+ // XXX optimize
+ QMetaMethod method = data()->metaObject()->method(index);
+ Q_ASSERT(method.methodType() == QMetaMethod::Signal);
+ QList<QByteArray> params = method.parameterTypes();
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(engine->context());
+
+ QVarLengthArray<v8::Handle<v8::Value> > args(params.count());
+ int argCount = params.count();
+
+ for (int ii = 0; ii < argCount; ++ii) {
+ int type = QMetaType::type(params.at(ii).constData());
+ if (type == qMetaTypeId<QVariant>()) {
+ args[ii] = engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
+ } else {
+ args[ii] = engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
+ }
+ }
+
+ // XXX what if this list changes or this object is deleted during the calls?
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ Connection &connection = connections[ii];
+ if (connection.thisObject.IsEmpty()) {
+ connection.function->Call(engine->global(), argCount, args.data());
+ } else {
+ connection.function->Call(connection.thisObject, argCount, args.data());
+ }
+ }
+ }
+
+ return -1;
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Connect(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ V8THROW_ERROR("Function.prototype.connect: no arguments given");
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (!args.This()->IsFunction())
+ V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
+
+ QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QObject *signalObject = signalInfo.first;
+ int signalIndex = signalInfo.second;
+
+ if (signalIndex == -1)
+ V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
+
+ if (!signalObject)
+ V8THROW_ERROR("Function.prototype.connect: cannot connect to deleted QObject");
+
+ if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
+ V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
+
+ v8::Local<v8::Value> functionValue;
+ v8::Local<v8::Value> functionThisValue;
+
+ if (args.Length() == 1) {
+ functionValue = args[0];
+ } else {
+ functionThisValue = args[0];
+ functionValue = args[1];
+ }
+
+ if (!functionValue->IsFunction())
+ V8THROW_ERROR("Function.prototype.connect: target is not a function");
+
+ if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
+ V8THROW_ERROR("Function.prototype.connect: target this is not an object");
+
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+ QHash<QObject *, QV8QObjectConnectionList *> &connections = qobjectWrapper->m_connections;
+ QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connections.find(signalObject);
+ if (iter == connections.end())
+ iter = connections.insert(signalObject, new QV8QObjectConnectionList(signalObject, engine));
+
+ QV8QObjectConnectionList *connectionList = *iter;
+ QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex);
+ if (slotIter == connectionList->slotHash.end()) {
+ slotIter = connectionList->slotHash.insert(signalIndex, QList<QV8QObjectConnectionList::Connection>());
+ QMetaObject::connect(signalObject, signalIndex, connectionList, signalIndex);
+ }
+
+ QV8QObjectConnectionList::Connection connection;
+ if (!functionThisValue.IsEmpty())
+ connection.thisObject = v8::Persistent<v8::Object>::New(functionThisValue->ToObject());
+ connection.function = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(functionValue));
+
+ slotIter->append(connection);
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ V8THROW_ERROR("Function.prototype.disconnect: no arguments given");
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (!args.This()->IsFunction())
+ V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+
+ QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QObject *signalObject = signalInfo.first;
+ int signalIndex = signalInfo.second;
+
+ if (signalIndex == -1)
+ V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+
+ if (!signalObject)
+ V8THROW_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject");
+
+ if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
+ V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+
+ v8::Local<v8::Value> functionValue;
+ v8::Local<v8::Value> functionThisValue;
+
+ if (args.Length() == 1) {
+ functionValue = args[0];
+ } else {
+ functionThisValue = args[0];
+ functionValue = args[1];
+ }
+
+ if (!functionValue->IsFunction())
+ V8THROW_ERROR("Function.prototype.disconnect: target is not a function");
+
+ if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
+ V8THROW_ERROR("Function.prototype.disconnect: target this is not an object");
+
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+ QHash<QObject *, QV8QObjectConnectionList *> &connectionsList = qobjectWrapper->m_connections;
+ QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connectionsList.find(signalObject);
+ if (iter == connectionsList.end())
+ return v8::Undefined(); // Nothing to disconnect from
+
+ QV8QObjectConnectionList *connectionList = *iter;
+ QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex);
+ if (slotIter == connectionList->slotHash.end())
+ return v8::Undefined(); // Nothing to disconnect from
+
+ QList<QV8QObjectConnectionList::Connection> &connections = *slotIter;
+
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(functionValue);
+ QPair<QObject *, int> functionData = ExtractQtMethod(engine, function);
+
+ if (functionData.second != -1) {
+ // This is a QObject function wrapper
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ QV8QObjectConnectionList::Connection &connection = connections[ii];
+
+ if (connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() &&
+ (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) {
+
+ QPair<QObject *, int> connectedFunctionData = ExtractQtMethod(engine, connection.function);
+ if (connectedFunctionData == functionData) {
+ // Match!
+ connection.thisObject.Dispose();
+ connection.function.Dispose();
+ connections.removeAt(ii);
+ return v8::Undefined();
+ }
+ }
+ }
+
+ } else {
+ // This is a normal JS function
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ QV8QObjectConnectionList::Connection &connection = connections[ii];
+ if (connection.function->StrictEquals(function) &&
+ connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() &&
+ (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) {
+ // Match!
+ connection.thisObject.Dispose();
+ connection.function.Dispose();
+ connections.removeAt(ii);
+ return v8::Undefined();
+ }
+ }
+ }
+
+ return v8::Undefined();
+}
+
+/*!
+ Get the \a property of \a object. Returns an empty handle if the property doesn't exist.
+
+ Only searches for real properties of \a object (including methods), not attached properties etc.
+*/
+v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, v8::Handle<v8::String> property,
+ QV8QObjectWrapper::RevisionMode revisionMode)
+{
+ return GetProperty(m_engine, object, 0, property, revisionMode);
+}
+
+/*
+ Set the \a property of \a object to \a value.
+
+ Returns true if the property was "set" - even if this results in an exception being thrown -
+ and false if the object has no such property.
+
+ Only searches for real properties of \a object (including methods), not attached properties etc.
+*/
+bool QV8QObjectWrapper::setProperty(QObject *object, v8::Handle<v8::String> property,
+ v8::Handle<v8::Value> value, RevisionMode revisionMode)
+{
+ return SetProperty(m_engine, object, property, value, revisionMode);
+}
+
+namespace {
+struct CallArgs
+{
+ CallArgs(int length, v8::Handle<v8::Object> *args) : _length(length), _args(args) {}
+ int Length() const { return _length; }
+ v8::Local<v8::Value> operator[](int idx) { return (*_args)->Get(idx); }
+
+private:
+ int _length;
+ v8::Handle<v8::Object> *_args;
+};
+}
+
+static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnType, int argCount,
+ int *argTypes, QV8Engine *engine, CallArgs &callArgs)
+{
+ if (argCount > 0) {
+
+ QVarLengthArray<MetaCallArgument, 9> args(argCount + 1);
+ args[0].initAsType(returnType);
+
+ for (int ii = 0; ii < argCount; ++ii)
+ args[ii + 1].fromValue(argTypes[ii], engine, callArgs[ii]);
+
+ QVarLengthArray<void *, 9> argData(args.count());
+ for (int ii = 0; ii < args.count(); ++ii)
+ argData[ii] = args[ii].dataPtr();
+
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
+
+ return args[0].toValue(engine);
+
+ } else if (returnType != 0) {
+
+ MetaCallArgument arg;
+ arg.initAsType(returnType);
+
+ void *args[] = { arg.dataPtr() };
+
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
+
+ return arg.toValue(engine);
+
+ } else {
+
+ void *args[] = { 0 };
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
+ return v8::Undefined();
+
+ }
+}
+
+static int EnumType(const QMetaObject *meta, const QString &strname)
+{
+ QByteArray str = strname.toUtf8();
+ QByteArray scope;
+ QByteArray name;
+ int scopeIdx = str.lastIndexOf("::");
+ if (scopeIdx != -1) {
+ scope = str.left(scopeIdx);
+ name = str.mid(scopeIdx + 2);
+ } else {
+ name = str;
+ }
+ for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
+ QMetaEnum m = meta->enumerator(i);
+ if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
+ return QVariant::Int;
+ }
+ return QVariant::Invalid;
+}
+
+/*!
+ Returns the match score for converting \a actual to be of type \a conversionType. A
+ zero score means "perfect match" whereas a higher score is worse.
+
+ The conversion table is copied out of the QtScript callQtMethod() function.
+*/
+static int MatchScore(v8::Handle<v8::Value> actual, int conversionType,
+ const QByteArray &conversionTypeName)
+{
+ if (actual->IsNumber()) {
+ switch (conversionType) {
+ case QMetaType::Double:
+ return 0;
+ case QMetaType::Float:
+ return 1;
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ return 2;
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ return 3;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ return 4;
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ return 5;
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ return 6;
+ default:
+ return 10;
+ }
+ } else if (actual->IsString()) {
+ switch (conversionType) {
+ case QMetaType::QString:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual->IsBoolean()) {
+ switch (conversionType) {
+ case QMetaType::Bool:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual->IsDate()) {
+ switch (conversionType) {
+ case QMetaType::QDateTime:
+ return 0;
+ case QMetaType::QDate:
+ return 1;
+ case QMetaType::QTime:
+ return 2;
+ default:
+ return 10;
+ }
+ } else if (actual->IsRegExp()) {
+ switch (conversionType) {
+ case QMetaType::QRegExp:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual->IsArray()) {
+ switch (conversionType) {
+ case QMetaType::QStringList:
+ case QMetaType::QVariantList:
+ return 5;
+ default:
+ return 10;
+ }
+ } else if (actual->IsNull()) {
+ switch (conversionType) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ return 0;
+ default:
+ if (!conversionTypeName.endsWith('*'))
+ return 10;
+ else
+ return 0;
+ }
+ } else if (actual->IsObject()) {
+ v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(actual);
+
+ QV8ObjectResource *r = static_cast<QV8ObjectResource *>(obj->GetExternalResource());
+ if (r && r->resourceType() == QV8ObjectResource::QObjectType) {
+ switch (conversionType) {
+ case QMetaType::QObjectStar:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (r && r->resourceType() == QV8ObjectResource::VariantType) {
+ if (conversionType == qMetaTypeId<QVariant>())
+ return 0;
+ else if (r->engine->toVariant(actual, -1).userType() == conversionType)
+ return 0;
+ else
+ return 10;
+ } else {
+ return 10;
+ }
+
+ } else {
+ return 10;
+ }
+}
+
+static inline int QMetaObject_methods(const QMetaObject *metaObject)
+{
+ struct Private
+ {
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ };
+
+ return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
+}
+
+static QByteArray QMetaMethod_name(const QMetaMethod &m)
+{
+ QByteArray sig = m.signature();
+ int paren = sig.indexOf('(');
+ if (paren == -1)
+ return sig;
+ else
+ return sig.left(paren);
+}
+
+/*!
+Returns the next related method, if one, or 0.
+*/
+static const QDeclarativePropertyCache::Data * RelatedMethod(QObject *object,
+ const QDeclarativePropertyCache::Data *current,
+ QDeclarativePropertyCache::Data &dummy)
+{
+ QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
+ if (current->relatedIndex == -1)
+ return 0;
+
+ if (cache) {
+ return cache->method(current->relatedIndex);
+ } else {
+ const QMetaObject *mo = object->metaObject();
+ int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
+
+ while (methodOffset > current->relatedIndex) {
+ mo = mo->superClass();
+ methodOffset -= QMetaObject_methods(mo);
+ }
+
+ QMetaMethod method = mo->method(current->relatedIndex);
+ dummy.load(method);
+
+ // Look for overloaded methods
+ QByteArray methodName = QMetaMethod_name(method);
+ for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
+ if (methodName == QMetaMethod_name(mo->method(ii))) {
+ dummy.relatedIndex = ii;
+ return &dummy;
+ }
+ }
+
+ return &dummy;
+ }
+}
+
+static v8::Handle<v8::Value> CallPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
+ QV8Engine *engine, CallArgs &callArgs)
+{
+ if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
+
+ QMetaMethod m = object->metaObject()->method(data.coreIndex);
+ QList<QByteArray> argTypeNames = m.parameterTypes();
+ QVarLengthArray<int, 9> argTypes(argTypeNames.count());
+
+ // ### Cache
+ for (int ii = 0; ii < argTypeNames.count(); ++ii) {
+ argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
+ if (argTypes[ii] == QVariant::Invalid)
+ argTypes[ii] = EnumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
+ if (argTypes[ii] == QVariant::Invalid) {
+ QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)));
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Handle<v8::Value>();
+ }
+ }
+
+ if (argTypes.count() > callArgs.Length()) {
+ QString error = QLatin1String("Insufficient arguments");
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Handle<v8::Value>();
+ }
+
+ return CallMethod(object, data.coreIndex, data.propType, argTypes.count(),
+ argTypes.data(), engine, callArgs);
+
+ } else {
+
+ return CallMethod(object, data.coreIndex, data.propType, 0, 0, engine, callArgs);
+
+ }
+}
+
+/*!
+Resolve the overloaded method to call. The algorithm works conceptually like this:
+ 1. Resolve the set of overloads it is *possible* to call.
+ Impossible overloads include those that have too many parameters or have parameters
+ of unknown type.
+ 2. Filter the set of overloads to only contain those with the closest number of
+ parameters.
+ For example, if we are called with 3 parameters and there are 2 overloads that
+ take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
+ 3. Find the best remaining overload based on its match score.
+ If two or more overloads have the same match score, call the last one. The match
+ score is constructed by adding the matchScore() result for each of the parameters.
+*/
+static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativePropertyCache::Data &data,
+ QV8Engine *engine, CallArgs &callArgs)
+{
+ int argumentCount = callArgs.Length();
+
+ const QDeclarativePropertyCache::Data *best = 0;
+ int bestParameterScore = INT_MAX;
+ int bestMatchScore = INT_MAX;
+
+ QDeclarativePropertyCache::Data dummy;
+ const QDeclarativePropertyCache::Data *attempt = &data;
+
+ do {
+ QList<QByteArray> methodArgTypeNames;
+
+ if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
+ methodArgTypeNames = object->metaObject()->method(attempt->coreIndex).parameterTypes();
+
+ int methodArgumentCount = methodArgTypeNames.count();
+
+ if (methodArgumentCount > argumentCount)
+ continue; // We don't have sufficient arguments to call this method
+
+ int methodParameterScore = argumentCount - methodArgumentCount;
+ if (methodParameterScore > bestParameterScore)
+ continue; // We already have a better option
+
+ int methodMatchScore = 0;
+ QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
+
+ bool unknownArgument = false;
+ for (int ii = 0; ii < methodArgumentCount; ++ii) {
+ methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
+ if (methodArgTypes[ii] == QVariant::Invalid)
+ methodArgTypes[ii] = EnumType(object->metaObject(),
+ QString::fromLatin1(methodArgTypeNames.at(ii)));
+ if (methodArgTypes[ii] == QVariant::Invalid) {
+ unknownArgument = true;
+ break;
+ }
+ methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii], methodArgTypeNames.at(ii));
+ }
+ if (unknownArgument)
+ continue; // We don't understand all the parameters
+
+ if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
+ best = attempt;
+ bestParameterScore = methodParameterScore;
+ bestMatchScore = methodMatchScore;
+ }
+
+ if (bestParameterScore == 0 && bestMatchScore == 0)
+ break; // We can't get better than that
+
+ } while((attempt = RelatedMethod(object, attempt, dummy)) != 0);
+
+ if (best) {
+ return CallPrecise(object, *best, engine, callArgs);
+ } else {
+ QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
+ const QDeclarativePropertyCache::Data *candidate = &data;
+ while (candidate) {
+ error += QLatin1String("\n ") +
+ QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).signature());
+ candidate = RelatedMethod(object, candidate, dummy);
+ }
+
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Handle<v8::Value>();
+ }
+}
+
+static v8::Handle<v8::Value> ToString(QV8Engine *engine, QObject *object, int, v8::Handle<v8::Object>)
+{
+ QString result;
+ if (object) {
+ QString objectName = object->objectName();
+
+ result += QString::fromUtf8(object->metaObject()->className());
+ result += QLatin1String("(0x");
+ result += QString::number((quintptr)object,16);
+
+ if (!objectName.isEmpty()) {
+ result += QLatin1String(", \"");
+ result += objectName;
+ result += QLatin1Char('\"');
+ }
+
+ result += QLatin1Char(')');
+ } else {
+ result = QLatin1String("null");
+ }
+
+ return engine->toString(result);
+}
+
+static v8::Handle<v8::Value> Destroy(QV8Engine *, QObject *object, int argCount, v8::Handle<v8::Object> args)
+{
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+ if (!ddata || ddata->indestructible) {
+ const char *error = "Invalid attempt to destroy() an indestructible object";
+ v8::ThrowException(v8::Exception::Error(v8::String::New(error)));
+ return v8::Undefined();
+ }
+
+ int delay = 0;
+ if (argCount > 0)
+ delay = args->Get(0)->Uint32Value();
+
+ if (delay > 0)
+ QTimer::singleShot(delay, object, SLOT(deleteLater()));
+ else
+ object->deleteLater();
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
+{
+ // object, index, qmlglobal, argCount, args
+ Q_ASSERT(args.Length() == 5);
+ Q_ASSERT(args[0]->IsObject());
+
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(args[0]->ToObject());
+
+ if (!resource)
+ return v8::Undefined();
+
+ int argCount = args[3]->Int32Value();
+ v8::Handle<v8::Object> arguments = v8::Handle<v8::Object>::Cast(args[4]);
+
+ // Special hack to return info about this closure.
+ if (argCount == 1 && arguments->Get(0)->StrictEquals(resource->engine->qobjectWrapper()->m_hiddenObject)) {
+ v8::Local<v8::Array> data = v8::Array::New(2);
+ data->Set(0, args[0]);
+ data->Set(1, args[1]);
+ return data;
+ }
+
+ QObject *object = resource->object;
+ int index = args[1]->Int32Value();
+
+ if (!object)
+ return v8::Undefined();
+
+ if (index < 0) {
+ // Builtin functions
+ if (index == QOBJECT_TOSTRING_INDEX) {
+ return ToString(resource->engine, object, argCount, arguments);
+ } else if (index == QOBJECT_DESTROY_INDEX) {
+ return Destroy(resource->engine, object, argCount, arguments);
+ } else {
+ return v8::Undefined();
+ }
+ }
+
+ QDeclarativePropertyCache::Data method;
+
+ if (QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(object)->declarativeData)) {
+ if (ddata->propertyCache) {
+ QDeclarativePropertyCache::Data *d = ddata->propertyCache->method(index);
+ if (!d)
+ return v8::Undefined();
+ method = *d;
+ }
+ }
+
+ if (method.coreIndex == -1) {
+ QMetaMethod mm = object->metaObject()->method(index);
+ method.load(object->metaObject()->method(index));
+
+ if (method.coreIndex == -1)
+ return v8::Undefined();
+ }
+
+ if (method.flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ v8::Handle<v8::Value> rv;
+ v8::Handle<v8::Object> qmlglobal = args[2]->ToObject();
+
+ QDeclarativeV8Function func(argCount, arguments, rv, qmlglobal,
+ resource->engine->contextWrapper()->context(qmlglobal),
+ resource->engine);
+ QDeclarativeV8Function *funcptr = &func;
+
+ void *args[] = { 0, &funcptr };
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method.coreIndex, args);
+
+ if (rv.IsEmpty()) return v8::Undefined();
+ return rv;
+ }
+
+ CallArgs callArgs(argCount, &arguments);
+ if (method.relatedIndex == -1) {
+ return CallPrecise(object, method, resource->engine, callArgs);
+ } else {
+ return CallOverloaded(object, method, resource->engine, callArgs);
+ }
+}
+
+MetaCallArgument::MetaCallArgument()
+: type(QVariant::Invalid), isObjectType(false)
+{
+}
+
+MetaCallArgument::~MetaCallArgument()
+{
+ cleanup();
+}
+
+void MetaCallArgument::cleanup()
+{
+ if (type == QMetaType::QString) {
+ ((QString *)&data)->~QString();
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ ((QVariant *)&data)->~QVariant();
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ ((QScriptValue *)&data)->~QScriptValue();
+ } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ ((QList<QObject *> *)&data)->~QList<QObject *>();
+ }
+}
+
+void *MetaCallArgument::dataPtr()
+{
+ if (type == -1)
+ return ((QVariant *)data)->data();
+ else
+ return (void *)&data;
+}
+
+void MetaCallArgument::initAsType(int callType)
+{
+ if (type != 0) { cleanup(); type = 0; }
+ if (callType == 0) return;
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (&data) QScriptValue();
+ type = callType;
+ } else if (callType == QMetaType::Int ||
+ callType == QMetaType::UInt ||
+ callType == QMetaType::Bool ||
+ callType == QMetaType::Double ||
+ callType == QMetaType::Float) {
+ type = callType;
+ } else if (callType == QMetaType::QObjectStar) {
+ *((QObject **)&data) = 0;
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ new (&data) QString();
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ type = callType;
+ new (&data) QVariant();
+ } else if (callType == qMetaTypeId<QList<QObject *> >()) {
+ type = callType;
+ new (&data) QList<QObject *>();
+ } else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
+ type = callType;
+ new (&data) v8::Handle<v8::Value>();
+ } else {
+ type = -1;
+ new (&data) QVariant(callType, (void *)0);
+ }
+}
+
+void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Value> value)
+{
+ if (type != 0) { cleanup(); type = 0; }
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (&data) QScriptValue();
+ type = qMetaTypeId<QScriptValue>();
+ } else if (callType == QMetaType::Int) {
+ *((int *)&data) = int(value->Int32Value());
+ type = callType;
+ } else if (callType == QMetaType::UInt) {
+ *((uint *)&data) = uint(value->Uint32Value());
+ type = callType;
+ } else if (callType == QMetaType::Bool) {
+ *((bool *)&data) = value->BooleanValue();
+ type = callType;
+ } else if (callType == QMetaType::Double) {
+ *((double *)&data) = double(value->NumberValue());
+ type = callType;
+ } else if (callType == QMetaType::Float) {
+ *((float *)&data) = float(value->NumberValue());
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ if (value->IsNull() || value->IsUndefined())
+ new (&data) QString();
+ else
+ new (&data) QString(engine->toString(value->ToString()));
+ type = callType;
+ } else if (callType == QMetaType::QObjectStar) {
+ *((QObject **)&data) = engine->toQObject(value);
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ new (&data) QVariant(engine->toVariant(value, -1));
+ type = callType;
+ } else if (callType == qMetaTypeId<QList<QObject*> >()) {
+ QList<QObject *> *list = new (&data) QList<QObject *>();
+ if (value->IsArray()) {
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
+ uint32_t length = array->Length();
+ for (uint32_t ii = 0; ii < length; ++ii)
+ list->append(engine->toQObject(array->Get(ii)));
+ } else {
+ list->append(engine->toQObject(value));
+ }
+ type = callType;
+ } else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
+ new (&data) v8::Handle<v8::Value>(value);
+ type = callType;
+ } else {
+ new (&data) QVariant();
+ type = -1;
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QVariant v = engine->toVariant(value, -1);
+
+ if (v.userType() == callType) {
+ *((QVariant *)&data) = v;
+ } else if (v.canConvert((QVariant::Type)callType)) {
+ *((QVariant *)&data) = v;
+ ((QVariant *)&data)->convert((QVariant::Type)callType);
+ } else if (const QMetaObject *mo = ep->rawMetaObjectForType(callType)) {
+ QObject *obj = ep->toQObject(v);
+
+ if (obj) {
+ const QMetaObject *objMo = obj->metaObject();
+ while (objMo && objMo != mo) objMo = objMo->superClass();
+ if (!objMo) obj = 0;
+ }
+
+ *((QVariant *)&data) = QVariant(callType, &obj);
+ } else {
+ *((QVariant *)&data) = QVariant(callType, (void *)0);
+ }
+ }
+}
+
+v8::Handle<v8::Value> MetaCallArgument::toValue(QV8Engine *engine)
+{
+ if (type == qMetaTypeId<QScriptValue>()) {
+ return v8::Undefined();
+ } else if (type == QMetaType::Int) {
+ return v8::Integer::New(*((int *)&data));
+ } else if (type == QMetaType::UInt) {
+ return v8::Integer::NewFromUnsigned(*((uint *)&data));
+ } else if (type == QMetaType::Bool) {
+ return v8::Boolean::New(*((bool *)&data));
+ } else if (type == QMetaType::Double) {
+ return v8::Number::New(*((double *)&data));
+ } else if (type == QMetaType::Float) {
+ return v8::Number::New(*((float *)&data));
+ } else if (type == QMetaType::QString) {
+ return engine->toString(*((QString *)&data));
+ } else if (type == QMetaType::QObjectStar) {
+ QObject *object = *((QObject **)&data);
+ if (object)
+ QDeclarativeData::get(object, true)->setImplicitDestructible();
+ return engine->newQObject(object);
+ } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ // XXX aakenned Can this be more optimal? Just use Array as a prototype and
+ // implement directly against QList<QObject*>?
+ QList<QObject *> &list = *(QList<QObject *>*)&data;
+ v8::Local<v8::Array> array = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ array->Set(ii, engine->newQObject(list.at(ii)));
+ return array;
+ } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
+ return *(v8::Handle<v8::Value>*)&data;
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ QVariant value = *((QVariant *)&data);
+ v8::Handle<v8::Value> rv = engine->fromVariant(value);
+ if (QObject *object = engine->toQObject(rv))
+ QDeclarativeData::get(object, true)->setImplicitDestructible();
+ return rv;
+ } else {
+ return v8::Undefined();
+ }
+}
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper_p.h b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
new file mode 100644
index 0000000000..f63396945e
--- /dev/null
+++ b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 QV8QOBJECTWRAPPER_P_H
+#define QV8QOBJECTWRAPPER_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/qmetatype.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qhash.h>
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QV8Engine;
+class QV8ObjectResource;
+class QDeclarativePropertyCache;
+class QV8QObjectConnectionList;
+class Q_AUTOTEST_EXPORT QV8QObjectWrapper
+{
+public:
+ QV8QObjectWrapper();
+ ~QV8QObjectWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
+
+ v8::Handle<v8::Value> newQObject(QObject *object);
+ bool isQObject(v8::Handle<v8::Object>);
+ QObject *toQObject(v8::Handle<v8::Object>);
+ QObject *toQObject(QV8ObjectResource *);
+
+ enum RevisionMode { IgnoreRevision, CheckRevision };
+ v8::Handle<v8::Value> getProperty(QObject *, v8::Handle<v8::String>, RevisionMode);
+ bool setProperty(QObject *, v8::Handle<v8::String>, v8::Handle<v8::Value>, RevisionMode);
+
+private:
+ friend class QDeclarativePropertyCache;
+ friend class QV8QObjectConnectionList;
+
+ static v8::Handle<v8::Value> GetProperty(QV8Engine *, QObject *, v8::Handle<v8::Value> *,
+ v8::Handle<v8::String>, QV8QObjectWrapper::RevisionMode);
+ static bool SetProperty(QV8Engine *, QObject *, v8::Handle<v8::String>,
+ v8::Handle<v8::Value>, QV8QObjectWrapper::RevisionMode);
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Integer> Query(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Connect(const v8::Arguments &args);
+ static v8::Handle<v8::Value> Disconnect(const v8::Arguments &args);
+ static v8::Handle<v8::Value> Invoke(const v8::Arguments &args);
+ static QPair<QObject *, int> ExtractQtMethod(QV8Engine *, v8::Handle<v8::Function>);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+ v8::Persistent<v8::Function> m_methodConstructor;
+ v8::Persistent<v8::String> m_toStringSymbol;
+ v8::Persistent<v8::String> m_destroySymbol;
+ v8::Persistent<v8::Object> m_hiddenObject;
+ QHash<QObject *, QV8QObjectConnectionList *> m_connections;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV8QOBJECTWRAPPER_P_H
+
+
diff --git a/src/declarative/qml/v8/qv8stringwrapper.cpp b/src/declarative/qml/v8/qv8stringwrapper.cpp
new file mode 100644
index 0000000000..883c4826c5
--- /dev/null
+++ b/src/declarative/qml/v8/qv8stringwrapper.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 "qv8stringwrapper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QV8StringResource : public v8::String::ExternalStringResource
+{
+public:
+ QV8StringResource(const QString &str) : str(str) {}
+ virtual const uint16_t* data() const { return (uint16_t*)str.constData(); }
+ virtual size_t length() const { return str.length(); }
+ virtual void Dispose() { delete this; }
+
+ QString str;
+};
+
+QV8StringWrapper::QV8StringWrapper()
+{
+}
+
+QV8StringWrapper::~QV8StringWrapper()
+{
+}
+
+void QV8StringWrapper::init()
+{
+}
+
+void QV8StringWrapper::destroy()
+{
+}
+
+v8::Local<v8::String> QV8StringWrapper::toString(const QString &qstr)
+{
+// return v8::String::NewExternal(new QV8StringResource(qstr));
+ return v8::String::New((uint16_t*)qstr.constData(), qstr.length());
+}
+
+QString QV8StringWrapper::toString(v8::Handle<v8::String> jsstr)
+{
+ if (jsstr.IsEmpty()) {
+ return QString();
+ } else if (jsstr->IsExternal()) {
+ QV8StringResource *r = (QV8StringResource *)jsstr->GetExternalStringResource();
+ return r->str;
+ } else {
+ QString qstr;
+ qstr.resize(jsstr->Length());
+ jsstr->Write((uint16_t*)qstr.data());
+ return qstr;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h b/src/declarative/qml/v8/qv8stringwrapper_p.h
index 01cfb6ecac..8dde5c8c44 100644
--- a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h
+++ b/src/declarative/qml/v8/qv8stringwrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEGLOBALSCRIPTCLASS_P_H
-#define QDECLARATIVEGLOBALSCRIPTCLASS_P_H
+#ifndef QDECLARATIVEV8STRINGWRAPPER_P_H
+#define QDECLARATIVEV8STRINGWRAPPER_P_H
//
// W A R N I N G
@@ -53,34 +53,24 @@
// We mean it.
//
-#include <QtScript/qscriptclass.h>
-#include <QtCore/qset.h>
+#include <QtCore/qstring.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QDeclarativeGlobalScriptClass : public QScriptClass
+class Q_AUTOTEST_EXPORT QV8StringWrapper
{
public:
- QDeclarativeGlobalScriptClass(QScriptEngine *);
+ QV8StringWrapper();
+ ~QV8StringWrapper();
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
+ void init();
+ void destroy();
- virtual void setProperty(QScriptValue &object, const QScriptString &name,
- uint id, const QScriptValue &value);
-
- void explicitSetProperty(const QStringList &, const QList<QScriptValue> &);
-
- const QScriptValue &staticGlobalObject() const { return m_staticGlobalObject; }
-
- const QSet<QString> &illegalNames() const { return m_illegalNames; }
-
-private:
- QSet<QString> m_illegalNames;
- QScriptValue m_staticGlobalObject;
+ v8::Local<v8::String> toString(const QString &);
+ QString toString(v8::Handle<v8::String>);
};
QT_END_NAMESPACE
-#endif // QDECLARATIVEGLOBALSCRIPTCLASS_P_H
+#endif // QDECLARATIVEV8STRINGWRAPPER_P_H
diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp
new file mode 100644
index 0000000000..2067f73fae
--- /dev/null
+++ b/src/declarative/qml/v8/qv8typewrapper.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** 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 "qv8contextwrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativecontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8TypeResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(TypeType);
+
+public:
+ QV8TypeResource(QV8Engine *engine);
+ virtual ~QV8TypeResource();
+
+ QV8TypeWrapper::TypeNameMode mode;
+
+ QDeclarativeGuard<QObject> object;
+ QDeclarativeType *type;
+ QDeclarativeTypeNameCache *typeNamespace;
+};
+
+QV8TypeResource::QV8TypeResource(QV8Engine *engine)
+: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0)
+{
+}
+
+QV8TypeResource::~QV8TypeResource()
+{
+ if (typeNamespace) typeNamespace->release();
+}
+
+QV8TypeWrapper::QV8TypeWrapper()
+: m_engine(0)
+{
+}
+
+QV8TypeWrapper::~QV8TypeWrapper()
+{
+}
+
+void QV8TypeWrapper::destroy()
+{
+ m_constructor.Dispose();
+}
+
+void QV8TypeWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+}
+
+v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode)
+{
+ Q_ASSERT(t);
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8TypeResource *r = new QV8TypeResource(m_engine);
+ r->mode = mode; r->object = o; r->type = t;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, TypeNameMode mode)
+{
+ Q_ASSERT(t);
+ // XXX aakenned - NewInstance() is slow for our case
+ 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;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ v8::Object::ExternalResource *r = info.This()->GetExternalResource();
+ QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined();
+
+ QV8Engine *v8engine = resource->engine;
+ QObject *object = resource->object;
+
+ if (resource->type) {
+ 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);
+ }
+ }
+
+ // Fall through to undefined
+
+ } else if (resource->object) {
+ QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
+ if (ao)
+ return v8engine->qobjectWrapper()->getProperty(ao, property, QV8QObjectWrapper::IgnoreRevision);
+
+ // Fall through to undefined
+ }
+
+ // Fall through to undefined
+
+ } else if (resource->typeNamespace) {
+
+ QDeclarativeTypeNameCache *typeNamespace = resource->typeNamespace;
+ QDeclarativeTypeNameCache::Data *d = typeNamespace->data(property);
+ Q_ASSERT(!d || !d->typeNamespace); // Nested namespaces not supported
+
+ if (d && d->type) {
+ return v8engine->typeWrapper()->newObject(object, d->type, resource->mode);
+ } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) {
+
+ // XXX QtScript/JSC required
+ return v8::Undefined();
+
+ }
+
+ // Fall through to undefined
+
+ } else {
+ Q_ASSERT(!"Unreachable");
+ }
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ v8::Object::ExternalResource *r = info.This()->GetExternalResource();
+ QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
+
+ if (!resource)
+ return value;
+
+ QV8Engine *v8engine = resource->engine;
+
+ // XXX module api
+
+ if (resource->type && resource->object) {
+ QDeclarativeType *type = resource->type;
+ QObject *object = resource->object;
+ QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
+ if (ao)
+ v8engine->qobjectWrapper()->setProperty(ao, property, value, QV8QObjectWrapper::IgnoreRevision);
+ }
+
+ return value;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h b/src/declarative/qml/v8/qv8typewrapper_p.h
index 49e1ae809e..166bf3b7fa 100644
--- a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h
+++ b/src/declarative/qml/v8/qv8typewrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVETYPENAMESCRIPTCLASS_P_H
-#define QDECLARATIVETYPENAMESCRIPTCLASS_P_H
+#ifndef QV8TYPEWRAPPER_P_H
+#define QV8TYPEWRAPPER_P_H
//
// W A R N I N G
@@ -52,42 +52,41 @@
//
// We mean it.
//
-#include "private/qdeclarativeengine_p.h"
-#include <private/qscriptdeclarativeclass_p.h>
-#include <QtScript/qscriptclass.h>
+#include <QtCore/qglobal.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
+class QObject;
+class QV8Engine;
class QDeclarativeType;
class QDeclarativeTypeNameCache;
-class QDeclarativeTypeNameScriptClass : public QScriptDeclarativeClass
+class QV8TypeWrapper
{
public:
- QDeclarativeTypeNameScriptClass(QDeclarativeEngine *);
- ~QDeclarativeTypeNameScriptClass();
+ QV8TypeWrapper();
+ ~QV8TypeWrapper();
- enum TypeNameMode { IncludeEnums, ExcludeEnums };
- QScriptValue newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums);
- QScriptValue newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums);
-
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
+ void init(QV8Engine *);
+ void destroy();
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ enum TypeNameMode { IncludeEnums, ExcludeEnums };
+ v8::Local<v8::Object> newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums);
+ v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums);
private:
- QDeclarativeEngine *engine;
- QObject *object;
- QDeclarativeType *type;
- QDeclarativeMetaType::ModuleApiInstance *api;
- quint32 enumValue;
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVETYPENAMESCRIPTCLASS_P_H
+#endif // QV8TYPEWRAPPER_P_H
diff --git a/src/declarative/qml/v8/qv8valuetypewrapper.cpp b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
new file mode 100644
index 0000000000..6dfb4312bc
--- /dev/null
+++ b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** 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 "qv8valuetypewrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativevaluetype_p.h>
+#include <private/qdeclarativebinding_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8ValueTypeResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(ValueTypeType);
+
+public:
+ enum ObjectType { Reference, Copy };
+
+ QV8ValueTypeResource(QV8Engine *engine, ObjectType objectType);
+
+ ObjectType objectType;
+ QDeclarativeValueType *type;
+};
+
+class QV8ValueTypeReferenceResource : public QV8ValueTypeResource
+{
+public:
+ QV8ValueTypeReferenceResource(QV8Engine *engine);
+
+ QDeclarativeGuard<QObject> object;
+ int property;
+};
+
+class QV8ValueTypeCopyResource : public QV8ValueTypeResource
+{
+public:
+ QV8ValueTypeCopyResource(QV8Engine *engine);
+
+ QVariant value;
+};
+
+QV8ValueTypeResource::QV8ValueTypeResource(QV8Engine *engine, ObjectType objectType)
+: QV8ObjectResource(engine), objectType(objectType)
+{
+}
+
+QV8ValueTypeReferenceResource::QV8ValueTypeReferenceResource(QV8Engine *engine)
+: QV8ValueTypeResource(engine, Reference)
+{
+}
+
+QV8ValueTypeCopyResource::QV8ValueTypeCopyResource(QV8Engine *engine)
+: QV8ValueTypeResource(engine, Copy)
+{
+}
+
+QV8ValueTypeWrapper::QV8ValueTypeWrapper()
+: m_engine(0)
+{
+}
+
+QV8ValueTypeWrapper::~QV8ValueTypeWrapper()
+{
+}
+
+void QV8ValueTypeWrapper::destroy()
+{
+ m_constructor.Dispose();
+}
+
+void QV8ValueTypeWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+}
+
+v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(QObject *object, int property, QDeclarativeValueType *type)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ValueTypeReferenceResource *r = new QV8ValueTypeReferenceResource(m_engine);
+ r->type = type; r->object = object; r->property = property;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(const QVariant &value, QDeclarativeValueType *type)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ValueTypeCopyResource *r = new QV8ValueTypeCopyResource(m_engine);
+ r->type = type; r->value = value;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+QVariant QV8ValueTypeWrapper::toVariant(v8::Handle<v8::Object> obj)
+{
+ QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(obj);
+ if (r) return toVariant(r);
+ else return QVariant();
+}
+
+QVariant QV8ValueTypeWrapper::toVariant(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::ValueTypeType);
+ QV8ValueTypeResource *resource = static_cast<QV8ValueTypeResource *>(r);
+
+ if (resource->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(resource);
+
+ if (reference->object) {
+ reference->type->read(reference->object, reference->property);
+ return reference->type->value();
+ } else {
+ return QVariant();
+ }
+
+ } else {
+ Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy);
+
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource);
+
+ return copy->value;
+ }
+}
+
+v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This());
+ if (!r) return v8::Undefined();
+
+ // XXX aakenned - this is horribly inefficient. People seem to have taken a
+ // liking to value type properties, so we should probably try and optimize it
+ // a little.
+
+ QByteArray propName = r->engine->toString(property).toUtf8();
+ int index = r->type->metaObject()->indexOfProperty(propName.constData());
+ if (index == -1)
+ return v8::Undefined();
+
+ if (r->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r);
+
+ if (!reference->object)
+ return v8::Undefined();
+
+ r->type->read(reference->object, reference->property);
+ } else {
+ Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy);
+
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(r);
+
+ r->type->setValue(copy->value);
+ }
+
+ QMetaProperty prop = r->type->metaObject()->property(index);
+ QVariant result = prop.read(r->type);
+
+ return r->engine->fromVariant(result);
+}
+
+v8::Handle<v8::Value> QV8ValueTypeWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This());
+ if (!r) return value;
+
+ QByteArray propName = r->engine->toString(property).toUtf8();
+ int index = r->type->metaObject()->indexOfProperty(propName.constData());
+ if (index == -1)
+ return value;
+
+ if (r->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r);
+
+ if (!reference->object ||
+ !reference->object->metaObject()->property(reference->property).isWritable())
+ return value;
+
+ r->type->read(reference->object, reference->property);
+ QMetaProperty p = r->type->metaObject()->property(index);
+
+ QDeclarativeBinding *newBinding = 0;
+
+ if (value->IsFunction()) {
+ QDeclarativeContextData *context = r->engine->callingContext();
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
+
+ QDeclarativePropertyCache::Data cacheData;
+ cacheData.flags = QDeclarativePropertyCache::Data::IsWritable;
+ cacheData.propType = reference->object->metaObject()->property(reference->property).userType();
+ cacheData.coreIndex = reference->property;
+
+ QDeclarativePropertyCache::ValueTypeData valueTypeData;
+ valueTypeData.valueTypeCoreIdx = index;
+ valueTypeData.valueTypePropType = p.userType();
+
+ v8::Local<v8::StackTrace> trace =
+ v8::StackTrace::CurrentStackTrace(1,
+ (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
+ v8::StackTrace::kScriptName));
+ v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
+ int lineNumber = frame->GetLineNumber();
+ QString url = r->engine->toString(frame->GetScriptName());
+
+ newBinding = new QDeclarativeBinding(&function, reference->object, context);
+ newBinding->setSourceLocation(url, lineNumber);
+ newBinding->setTarget(QDeclarativePropertyPrivate::restore(cacheData, valueTypeData,
+ reference->object, context));
+ newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
+ }
+
+ QDeclarativeAbstractBinding *oldBinding =
+ QDeclarativePropertyPrivate::setBinding(reference->object, reference->property, index, newBinding);
+ if (oldBinding)
+ oldBinding->destroy();
+
+ if (!value->IsFunction()) {
+ QVariant v = r->engine->toVariant(value, -1);
+
+ if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
+ v = v.toInt();
+
+ p.write(reference->type, v);
+
+ reference->type->write(reference->object, reference->property, 0);
+ }
+
+ } else {
+ Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy);
+
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(r);
+
+ QVariant v = r->engine->toVariant(value, -1);
+
+ r->type->setValue(copy->value);
+ QMetaProperty p = r->type->metaObject()->property(index);
+ p.write(r->type, v);
+ copy->value = r->type->value();
+ }
+
+ return value;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h b/src/declarative/qml/v8/qv8valuetypewrapper_p.h
index 8988c0be6a..b4bc90cfec 100644
--- a/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h
+++ b/src/declarative/qml/v8/qv8valuetypewrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEVALUETYPESCRIPTCLASS_P_H
-#define QDECLARATIVEVALUETYPESCRIPTCLASS_P_H
+#ifndef QV8VALUETYPEWRAPPER_P_H
+#define QV8VALUETYPEWRAPPER_P_H
//
// W A R N I N G
@@ -53,35 +53,43 @@
// We mean it.
//
-
-#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qglobal.h>
+#include <QtDeclarative/qdeclarativelist.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
+class QV8Engine;
+class QV8ObjectResource;
class QDeclarativeValueType;
-class QDeclarativeValueTypeScriptClass : public QScriptDeclarativeClass
+class QV8ValueTypeWrapper
{
public:
- QDeclarativeValueTypeScriptClass(QDeclarativeEngine *);
- ~QDeclarativeValueTypeScriptClass();
+ QV8ValueTypeWrapper();
+ ~QV8ValueTypeWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
- QScriptValue newObject(QObject *object, int coreIndex, QDeclarativeValueType *);
- QScriptValue newObject(const QVariant &, QDeclarativeValueType *);
+ v8::Local<v8::Object> newValueType(QObject *, int, QDeclarativeValueType *);
+ v8::Local<v8::Object> newValueType(const QVariant &, QDeclarativeValueType *);
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ QVariant toVariant(v8::Handle<v8::Object>);
+ QVariant toVariant(QV8ObjectResource *);
- virtual QVariant toVariant(Object *, bool *ok = 0);
- QVariant toVariant(const QScriptValue &);
private:
- QDeclarativeEngine *engine;
- int m_lastIndex;
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVEVALUETYPESCRIPTCLASS_P_H
+#endif // QV8VALUETYPEWRAPPER_P_H
+
diff --git a/src/declarative/qml/v8/qv8variantwrapper.cpp b/src/declarative/qml/v8/qv8variantwrapper.cpp
new file mode 100644
index 0000000000..2d91a335b2
--- /dev/null
+++ b/src/declarative/qml/v8/qv8variantwrapper.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** 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 "qv8variantwrapper_p.h"
+#include "qv8engine_p.h"
+#include "qdeclarativeengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QV8VariantResource : public QV8ObjectResource,
+ public QDeclarativeEnginePrivate::ScarceResourceData
+{
+ V8_RESOURCE_TYPE(VariantType);
+public:
+ QV8VariantResource(QV8Engine *engine, const QVariant &data);
+};
+
+QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data)
+: QV8ObjectResource(engine), QDeclarativeEnginePrivate::ScarceResourceData(data)
+{
+}
+
+QV8VariantWrapper::QV8VariantWrapper()
+: m_engine(0)
+{
+}
+
+QV8VariantWrapper::~QV8VariantWrapper()
+{
+}
+
+void QV8VariantWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ m_preserve = v8::Persistent<v8::Function>::New(v8::FunctionTemplate::New(Preserve)->GetFunction());
+ m_destroy = v8::Persistent<v8::Function>::New(v8::FunctionTemplate::New(Destroy)->GetFunction());
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("preserve"), PreserveGetter, 0,
+ m_preserve, v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("destroy"), DestroyGetter, 0,
+ m_destroy, v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ m_scarceConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+
+}
+
+void QV8VariantWrapper::destroy()
+{
+ m_destroy.Dispose();
+ m_preserve.Dispose();
+ m_scarceConstructor.Dispose();
+ m_constructor.Dispose();
+}
+
+v8::Local<v8::Object> QV8VariantWrapper::newVariant(const QVariant &value)
+{
+ bool scarceResource = value.type() == QVariant::Pixmap ||
+ value.type() == QVariant::Image;
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine->engine());
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv;
+ QV8VariantResource *r = new QV8VariantResource(m_engine, value);
+
+ if (scarceResource) {
+ Q_ASSERT(ep->scarceResourcesRefCount);
+ rv = m_scarceConstructor->NewInstance();
+ ep->scarceResources.insert(r);
+ } else {
+ rv = m_constructor->NewInstance();
+ }
+
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+bool QV8VariantWrapper::isVariant(v8::Handle<v8::Value> value)
+{
+ return value->IsObject() && v8_resource_cast<QV8VariantResource>(value->ToObject());
+}
+
+QVariant QV8VariantWrapper::toVariant(v8::Handle<v8::Object> obj)
+{
+ QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(obj);
+ return r?r->data:QVariant();
+}
+
+QVariant QV8VariantWrapper::toVariant(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::VariantType);
+ return static_cast<QV8VariantResource *>(r)->data;
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::PreserveGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ return info.Data();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::DestroyGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ return info.Data();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Preserve(const v8::Arguments &args)
+{
+ QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
+ if (resource) {
+ resource->node.remove();
+ }
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Destroy(const v8::Arguments &args)
+{
+ QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
+ if (resource) {
+ resource->data = QVariant();
+ resource->node.remove();
+ }
+ return v8::Undefined();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8variantwrapper_p.h b/src/declarative/qml/v8/qv8variantwrapper_p.h
new file mode 100644
index 0000000000..391ec4c21a
--- /dev/null
+++ b/src/declarative/qml/v8/qv8variantwrapper_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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 QV8VARIANTWRAPPER_P_H
+#define QV8VARIANTWRAPPER_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 <QtDeclarative/qdeclarativelist.h>
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8Engine;
+class QV8ObjectResource;
+class QV8VariantWrapper
+{
+public:
+ QV8VariantWrapper();
+ ~QV8VariantWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
+
+ v8::Local<v8::Object> newVariant(const QVariant &);
+ bool isVariant(v8::Handle<v8::Value>);
+ QVariant toVariant(v8::Handle<v8::Object>);
+ QVariant toVariant(QV8ObjectResource *);
+
+private:
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> PreserveGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> DestroyGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Preserve(const v8::Arguments &args);
+ static v8::Handle<v8::Value> Destroy(const v8::Arguments &args);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+ v8::Persistent<v8::Function> m_scarceConstructor;
+ v8::Persistent<v8::Function> m_preserve;
+ v8::Persistent<v8::Function> m_destroy;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV8VARIANTWRAPPER_P_H
+
diff --git a/src/declarative/qml/v8/qv8worker.cpp b/src/declarative/qml/v8/qv8worker.cpp
new file mode 100644
index 0000000000..6b6ecd8c2a
--- /dev/null
+++ b/src/declarative/qml/v8/qv8worker.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** 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 "qv8worker_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// We allow the following JavaScript types to be passed between the main and
+// the secondary thread:
+// + undefined
+// + null
+// + Boolean
+// + String
+// + Function
+// + Array
+// + "Simple" Objects
+// + Number
+// + Date
+// + RegExp
+// <quint8 type><quint24 size><data>
+
+enum Type {
+ WorkerUndefined,
+ WorkerNull,
+ WorkerTrue,
+ WorkerFalse,
+ WorkerString,
+ WorkerFunction,
+ WorkerArray,
+ WorkerObject,
+ WorkerInt32,
+ WorkerUint32,
+ WorkerNumber,
+ WorkerDate,
+ WorkerRegexp
+};
+
+static inline quint32 valueheader(Type type, quint32 size = 0)
+{
+ return quint8(type) << 24 | (size & 0xFFFFFF);
+}
+
+static inline Type headertype(quint32 header)
+{
+ return (Type)(header >> 24);
+}
+
+static inline quint32 headersize(quint32 header)
+{
+ return header & 0xFFFFFF;
+}
+
+static inline void push(QByteArray &data, quint32 value)
+{
+ data.append((const char *)&value, sizeof(quint32));
+}
+
+static inline void push(QByteArray &data, double value)
+{
+ data.append((const char *)&value, sizeof(double));
+}
+
+static inline void reserve(QByteArray &data, int extra)
+{
+ data.reserve(data.size() + extra);
+}
+
+static inline quint32 popUint32(const char *&data)
+{
+ quint32 rv = *((quint32 *)data);
+ data += sizeof(quint32);
+ return rv;
+}
+
+static inline double popDouble(const char *&data)
+{
+ double rv = *((double *)data);
+ data += sizeof(double);
+ return rv;
+}
+
+// XXX double check exception safety
+
+#include <QDebug>
+#define ALIGN(size) (((size) + 3) & ~3)
+void QV8Worker::serialize(QByteArray &data, v8::Handle<v8::Value> v, QV8Engine *engine)
+{
+ if (v.IsEmpty()) {
+ } else if (v->IsUndefined()) {
+ push(data, valueheader(WorkerUndefined));
+ } else if (v->IsNull()) {
+ push(data, valueheader(WorkerNull));
+ } else if (v->IsTrue()) {
+ push(data, valueheader(WorkerTrue));
+ } else if (v->IsFalse()) {
+ push(data, valueheader(WorkerFalse));
+ } else if (v->IsString()) {
+ v8::Handle<v8::String> string = v->ToString();
+ int length = string->Length() + 1;
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ int utf16size = ALIGN(length * sizeof(uint16_t));
+
+ reserve(data, utf16size + sizeof(quint32));
+ push(data, valueheader(WorkerString, length));
+
+ int offset = data.size();
+ data.resize(data.size() + utf16size);
+ char *buffer = data.data() + offset;
+
+ string->Write((uint16_t*)buffer);
+ } else if (v->IsFunction()) {
+ // XXX
+ push(data, valueheader(WorkerUndefined));
+ } else if (v->IsArray()) {
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(v);
+ uint32_t length = array->Length();
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ reserve(data, sizeof(quint32) + length * sizeof(quint32));
+ push(data, valueheader(WorkerArray, length));
+ for (uint32_t ii = 0; ii < length; ++ii)
+ serialize(data, array->Get(ii), engine);
+ } else if (v->IsInt32()) {
+ reserve(data, 2 * sizeof(quint32));
+ push(data, valueheader(WorkerInt32));
+ push(data, (quint32)v->Int32Value());
+ } else if (v->IsUint32()) {
+ reserve(data, 2 * sizeof(quint32));
+ push(data, valueheader(WorkerUint32));
+ push(data, v->Uint32Value());
+ } else if (v->IsNumber()) {
+ reserve(data, sizeof(quint32) + sizeof(double));
+ push(data, valueheader(WorkerNumber));
+ push(data, v->NumberValue());
+ } else if (v->IsDate()) {
+ reserve(data, sizeof(quint32) + sizeof(double));
+ push(data, valueheader(WorkerDate));
+ push(data, v8::Handle<v8::Date>::Cast(v)->NumberValue());
+ } else if (v->IsRegExp()) {
+ v8::Handle<v8::RegExp> regexp = v8::Handle<v8::RegExp>::Cast(v);
+ quint32 flags = regexp->GetFlags();
+ v8::Local<v8::String> source = regexp->GetSource();
+
+ int length = source->Length() + 1;
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ int utf16size = ALIGN(length * sizeof(uint16_t));
+
+ reserve(data, sizeof(quint32) + utf16size);
+ push(data, valueheader(WorkerRegexp, flags));
+ push(data, (quint32)length);
+ int offset = data.size();
+ data.resize(data.size() + utf16size);
+ char *buffer = data.data() + offset;
+
+ source->Write((uint16_t*)buffer);
+ } else if (v->IsObject() && !v->ToObject()->GetExternalResource()) {
+ v8::Handle<v8::Object> object = v->ToObject();
+ v8::Local<v8::Array> properties = engine->getOwnPropertyNames(object);
+ quint32 length = properties->Length();
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ push(data, valueheader(WorkerObject, length));
+ v8::TryCatch tc;
+ for (quint32 ii = 0; ii < length; ++ii) {
+ v8::Local<v8::String> str = properties->Get(ii)->ToString();
+ serialize(data, str, engine);
+
+ v8::Local<v8::Value> val = object->Get(str);
+ if (tc.HasCaught()) {
+ serialize(data, v8::Undefined(), engine);
+ tc.Reset();
+ } else {
+ serialize(data, val, engine);
+ }
+ }
+ } else {
+ push(data, valueheader(WorkerUndefined));
+ }
+
+ // XXX Need to serialize QDeclarativeListModel
+ /*
+ QDeclarativeListModel *lm = qobject_cast<QDeclarativeListModel *>(value.toQObject());
+ if (lm) {
+ QDeclarativeListModelWorkerAgent *agent = lm->agent();
+ if (agent) {
+ QDeclarativeListModelWorkerAgent::VariantRef v(agent);
+ return QVariant::fromValue(v);
+ } else {
+ return QVariant();
+ }
+ }
+ */
+}
+
+v8::Handle<v8::Value> QV8Worker::deserialize(const char *&data, QV8Engine *engine)
+{
+ quint32 header = popUint32(data);
+ Type type = headertype(header);
+
+ switch (type) {
+ case WorkerUndefined:
+ return v8::Undefined();
+ case WorkerNull:
+ return v8::Null();
+ case WorkerTrue:
+ return v8::True();
+ case WorkerFalse:
+ return v8::False();
+ case WorkerString:
+ {
+ quint32 size = headersize(header);
+ v8::Local<v8::String> string = v8::String::New((uint16_t*)data, size - 1);
+ data += ALIGN(size * sizeof(uint16_t));
+ return string;
+ }
+ case WorkerFunction:
+ Q_ASSERT(!"Unreachable");
+ break;
+ case WorkerArray:
+ {
+ quint32 size = headersize(header);
+ v8::Local<v8::Array> array = v8::Array::New(size);
+ for (quint32 ii = 0; ii < size; ++ii) {
+ array->Set(ii, deserialize(data, engine));
+ }
+ return array;
+ }
+ case WorkerObject:
+ {
+ quint32 size = headersize(header);
+ v8::Local<v8::Object> o = v8::Object::New();
+ for (quint32 ii = 0; ii < size; ++ii) {
+ v8::Handle<v8::Value> name = deserialize(data, engine);
+ v8::Handle<v8::Value> value = deserialize(data, engine);
+ o->Set(name, value);
+ }
+ return o;
+ }
+ case WorkerInt32:
+ return v8::Integer::New((qint32)popUint32(data));
+ case WorkerUint32:
+ return v8::Integer::NewFromUnsigned(popUint32(data));
+ case WorkerNumber:
+ return v8::Number::New(popDouble(data));
+ case WorkerDate:
+ return v8::Date::New(popDouble(data));
+ case WorkerRegexp:
+ {
+ quint32 flags = headersize(header);
+ quint32 length = popUint32(data);
+ v8::Local<v8::String> source = v8::String::New((uint16_t*)data, length - 1);
+ data += ALIGN(length * sizeof(uint16_t));
+ return v8::RegExp::New(source, (v8::RegExp::Flags)flags);
+ }
+ }
+ Q_ASSERT(!"Unreachable");
+ return v8::Undefined();
+}
+
+QByteArray QV8Worker::serialize(v8::Handle<v8::Value> value, QV8Engine *engine)
+{
+ QByteArray rv;
+ serialize(rv, value, engine);
+ return rv;
+}
+
+v8::Handle<v8::Value> QV8Worker::deserialize(const QByteArray &data, QV8Engine *engine)
+{
+ const char *stream = data.constData();
+ return deserialize(stream, engine);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qdeclarativelistscriptclass_p.h b/src/declarative/qml/v8/qv8worker_p.h
index 005380b92c..086e18e7e0 100644
--- a/src/declarative/qml/qdeclarativelistscriptclass_p.h
+++ b/src/declarative/qml/v8/qv8worker_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVELISTSCRIPTCLASS_P_H
-#define QDECLARATIVELISTSCRIPTCLASS_P_H
+#ifndef QV8WORKER_P_H
+#define QV8WORKER_P_H
//
// W A R N I N G
@@ -53,35 +53,23 @@
// We mean it.
//
-#include <private/qscriptdeclarativeclass_p.h>
-#include "qdeclarativelist.h"
+#include "qv8engine_p.h"
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
-class QDeclarativeListScriptClass : public QScriptDeclarativeClass
-{
+class QV8Worker {
public:
- QDeclarativeListScriptClass(QDeclarativeEngine *);
- ~QDeclarativeListScriptClass();
+ struct SavedData {
+ };
- QScriptValue newList(QObject *, int, int);
- QScriptValue newList(const QDeclarativeListProperty<QObject> &, int);
-
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual QVariant toVariant(Object *, bool *ok);
+ static QByteArray serialize(v8::Handle<v8::Value>, QV8Engine *);
+ static v8::Handle<v8::Value> deserialize(const QByteArray &, QV8Engine *);
private:
- PersistentIdentifier m_lengthId;
- QDeclarativeEngine *engine;
-
- quint32 lastIndex;
+ static void serialize(QByteArray &, v8::Handle<v8::Value>, QV8Engine *);
+ static v8::Handle<v8::Value> deserialize(const char *&, QV8Engine *);
};
QT_END_NAMESPACE
-#endif // QDECLARATIVELISTSCRIPTCLASS_P_H
-
+#endif // QV8WORKER_P_H
diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri
new file mode 100644
index 0000000000..d91acd7759
--- /dev/null
+++ b/src/declarative/qml/v8/v8.pri
@@ -0,0 +1,32 @@
+INCLUDEPATH += $$PWD/../../../3rdparty/javascriptcore
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qv8_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 \
+ $$PWD/qv8listwrapper_p.h \
+ $$PWD/qv8variantwrapper_p.h \
+ $$PWD/qv8valuetypewrapper_p.h \
+ $$PWD/qv8include_p.h \
+ $$PWD/qv8worker_p.h \
+ $$PWD/../../../3rdparty/javascriptcore/DateMath.h \
+
+SOURCES += \
+ $$PWD/qv8stringwrapper.cpp \
+ $$PWD/qv8engine.cpp \
+ $$PWD/qhashedstring.cpp \
+ $$PWD/qv8contextwrapper.cpp \
+ $$PWD/qv8qobjectwrapper.cpp \
+ $$PWD/qv8typewrapper.cpp \
+ $$PWD/qv8listwrapper.cpp \
+ $$PWD/qv8variantwrapper.cpp \
+ $$PWD/qv8valuetypewrapper.cpp \
+ $$PWD/qv8include.cpp \
+ $$PWD/qv8worker.cpp \
+ $$PWD/../../../3rdparty/javascriptcore/DateMath.cpp \
+
diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp
index 61b2d3463a..372b318e7e 100644
--- a/src/declarative/util/qdeclarativelistmodel.cpp
+++ b/src/declarative/util/qdeclarativelistmodel.cpp
@@ -1353,7 +1353,9 @@ QScriptValue NestedListModel::get(int index) const
if (!node)
return 0;
+#if 0
return QDeclarativeEnginePrivate::qmlScriptObject(node->object(this), eng);
+#endif
}
void NestedListModel::set(int index, const QScriptValue& valuemap, QList<int> *roles)
diff --git a/src/src.pro b/src/src.pro
index 1f47672180..e825502451 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS += declarative plugins
+SUBDIRS += v8 declarative plugins
contains(QT_CONFIG, qmltest): SUBDIRS += qmltest
SUBDIRS += imports
diff --git a/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
new file mode 100644
index 0000000000..9f4abbc5e5
--- /dev/null
+++ b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
@@ -0,0 +1,124 @@
+From be15626304572957f432160bb0fa35af5e6663b2 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 1/7] 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 | 17 +++++++++++++++++
+ src/api.cc | 15 +++++++++++++++
+ src/objects.cc | 29 +++++++++++++++++++++++++++++
+ src/objects.h | 2 ++
+ 4 files changed, 63 insertions(+), 0 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index d15d024..ac3c062 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -994,6 +994,23 @@ class String : public Primitive {
+ V8EXPORT int Utf8Length() const;
+
+ /**
++ * Returns the hash of this string.
++ */
++ V8EXPORT uint32_t Hash() const;
++
++ /**
++ * Compute a hash value for the passed UTF16 string
++ * data.
++ */
++ V8EXPORT static uint32_t ComputeHash(uint16_t *string, int length);
++
++ /**
++ * Returns true if this string is equal to the external
++ * string data provided.
++ */
++ V8EXPORT bool Equals(uint16_t *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
+diff --git a/src/api.cc b/src/api.cc
+index a2373cd..09b6b93 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -3284,6 +3284,21 @@ 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();
++}
++
++uint32_t String::ComputeHash(uint16_t *string, int length) {
++ return i::HashSequentialString<i::uc16>(string, length) >> i::String::kHashShift;
++}
++
++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);
++}
+
+ int String::WriteUtf8(char* buffer,
+ int capacity,
+diff --git a/src/objects.cc b/src/objects.cc
+index df61956..bbdb37b 100644
+--- a/src/objects.cc
++++ b/src/objects.cc
+@@ -5346,6 +5346,35 @@ 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();
++
++ Isolate* isolate = GetIsolate();
++ 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->objects_string_compare_buffer_a()->Reset(0, lhs);
++ VectorIterator<uc16> ib(string, length);
++ return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib);
++ }
++}
+
+ bool String::SlowEquals(String* other) {
+ // Fast check: negative check with lengths.
+diff --git a/src/objects.h b/src/objects.h
+index e966b3d..cd11c88 100644
+--- a/src/objects.h
++++ b/src/objects.h
+@@ -5359,6 +5359,8 @@ class String: public HeapObject {
+ bool IsAsciiEqualTo(Vector<const char> str);
+ bool IsTwoByteEqualTo(Vector<const uc16> str);
+
++ bool SlowEqualsExternal(uc16 *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
+--
+1.7.2.3
+
diff --git a/src/v8/0002-Add-a-bit-field-3-to-Map.patch b/src/v8/0002-Add-a-bit-field-3-to-Map.patch
new file mode 100644
index 0000000000..537c3aaafb
--- /dev/null
+++ b/src/v8/0002-Add-a-bit-field-3-to-Map.patch
@@ -0,0 +1,118 @@
+From edf12cdcd4ec04bc6de8c031c0b9c13a664ba7a9 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 2/7] 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 2b6c11f..4a58bf6 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 65aec5d..bbe05f6 100644
+--- a/src/objects-inl.h
++++ b/src/objects-inl.h
+@@ -2429,6 +2429,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 bbdb37b..fcde7eb 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 cd11c88..124c353 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/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
new file mode 100644
index 0000000000..2792df32b7
--- /dev/null
+++ b/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
@@ -0,0 +1,364 @@
+From 001373a7856d8a6f4620552c62ae87866c4194c0 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 3/7] 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 ac3c062..beaaca4 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -2142,6 +2142,7 @@ class V8EXPORT FunctionTemplate : public Template {
+ NamedPropertyQuery query,
+ NamedPropertyDeleter remover,
+ NamedPropertyEnumerator enumerator,
++ bool is_fallback,
+ Handle<Value> data);
+ void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,
+ IndexedPropertySetter setter,
+@@ -2226,6 +2227,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 09b6b93..ebca4f9 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 bbe05f6..0c09e84 100644
+--- a/src/objects-inl.h
++++ b/src/objects-inl.h
+@@ -2520,6 +2520,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));
+ }
+@@ -2969,6 +2984,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 fcde7eb..d72e30b 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 124c353..4389456 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;
+@@ -6267,6 +6275,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);
+
+@@ -6286,7 +6295,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/v8/0004-Generalize-external-object-resources.patch b/src/v8/0004-Generalize-external-object-resources.patch
new file mode 100644
index 0000000000..56b1a46342
--- /dev/null
+++ b/src/v8/0004-Generalize-external-object-resources.patch
@@ -0,0 +1,894 @@
+From d5dbc0acceb9cc848dfd994b2f54bc37c624fe98 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 4/7] 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 beaaca4..eaa0ec4 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -1603,6 +1603,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);
+@@ -2304,6 +2323,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 ebca4f9..f62c5a0 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 ---
+
+
+@@ -3624,6 +3652,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 ---
+
+
+@@ -4116,7 +4172,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);
+ }
+
+@@ -4134,7 +4190,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;
+ }
+@@ -4147,7 +4203,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);
+ }
+
+@@ -4166,7 +4222,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 99737ed..84f8b39 100644
+--- a/src/heap-inl.h
++++ b/src/heap-inl.h
+@@ -203,21 +203,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();
++ }
++ }
+ }
+
+
+@@ -554,53 +569,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 4a58bf6..46df787 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));
+ }
+
+
+@@ -4465,7 +4465,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");
+ }
+@@ -4967,7 +4967,7 @@ void Heap::TearDown() {
+
+ isolate_->global_handles()->TearDown();
+
+- external_string_table_.TearDown();
++ external_resource_table_.TearDown();
+
+ new_space_.TearDown();
+
+@@ -5832,31 +5832,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 0c09e84..a205f02 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.
+@@ -2520,6 +2537,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) {
+@@ -3016,6 +3047,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 4389456..61685cc 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;
+@@ -6417,6 +6427,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);
+
+@@ -6433,7 +6444,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/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/v8/0005-Introduce-a-QML-compilation-mode.patch
new file mode 100644
index 0000000000..2b49648337
--- /dev/null
+++ b/src/v8/0005-Introduce-a-QML-compilation-mode.patch
@@ -0,0 +1,1369 @@
+From 6311077b6acd840a5b877e293fdc8eda3f83701e 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 5/7] 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 | 46 +++++++++++++++++++++-----
+ src/ast-inl.h | 5 +++
+ src/ast.h | 1 +
+ src/compiler.cc | 15 +++++++-
+ src/compiler.h | 24 +++++++++++---
+ 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/ia32/code-stubs-ia32.cc | 7 ++++
+ src/ia32/full-codegen-ia32.cc | 21 +++++++-----
+ 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 | 16 +++++++++
+ 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 | 21 +++++++-----
+ src/x64/macro-assembler-x64.h | 5 +++
+ 30 files changed, 320 insertions(+), 77 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index eaa0ec4..62715ec 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.
+@@ -3299,6 +3308,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 f62c5a0..e2efcaa 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;
+ }
+@@ -3915,6 +3925,24 @@ 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::JavaScriptFrameIterator it;
++ if (it.done()) return Local<Object>();
++ i::Context *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/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/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..ca4b62d 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,7 +145,8 @@ class CompilationInfo BASE_EMBEDDED {
+
+ // Determine whether or not we can adaptively optimize.
+ bool AllowOptimize() {
+- return V8::UseCrankshaft() && !closure_.is_null();
++ // XXX - fix qml mode optimizations
++ return V8::UseCrankshaft() && !closure_.is_null() && !is_qml_mode();
+ }
+
+ private:
+@@ -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 46df787..6e02262 100644
+--- a/src/heap.cc
++++ b/src/heap.cc
+@@ -3792,6 +3792,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());
+@@ -3814,6 +3815,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/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..28b78ba 100644
+--- a/src/ia32/full-codegen-ia32.cc
++++ b/src/ia32/full-codegen-ia32.cc
+@@ -1107,10 +1107,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 +1214,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 +1837,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 +2113,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 +2191,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/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 a205f02..8c0c2d0 100644
+--- a/src/objects-inl.h
++++ b/src/objects-inl.h
+@@ -3241,6 +3241,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 61685cc..f6549be 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..e34e762 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;
+@@ -516,6 +517,7 @@ bool Scope::HasTrivialContext() const {
+ if (scope->is_eval_scope()) return false;
+ if (scope->scope_inside_with_) return false;
+ if (scope->num_heap_slots_ > 0) return false;
++ if (scope->qml_mode_ && is_global_scope() && inner_scopes_.length()) return false;
+ }
+ return true;
+ }
+@@ -796,6 +798,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 +822,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 +835,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);
+ }
+ }
+ }
+@@ -1112,6 +1123,11 @@ void Scope::AllocateVariablesRecursively() {
+ must_have_local_context = is_function_scope();
+ }
+
++ if (qml_mode_ && is_global_scope() && inner_scopes_.length()) {
++ must_have_local_context = true;
++ num_heap_slots_++; // This is a hack to force a context to be allocated to save the QML global
++ }
++
+ // If we didn't allocate any locals in the local context, then we only
+ // need the minimal number of slots if we must have a local context.
+ if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
+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..342fe9b 100644
+--- a/src/x64/full-codegen-x64.cc
++++ b/src/x64/full-codegen-x64.cc
+@@ -1119,10 +1119,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 +1227,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 +1806,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 +2085,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 +2163,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/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/v8/0006-Allow-access-to-the-calling-script-data.patch b/src/v8/0006-Allow-access-to-the-calling-script-data.patch
new file mode 100644
index 0000000000..5ce64b779e
--- /dev/null
+++ b/src/v8/0006-Allow-access-to-the-calling-script-data.patch
@@ -0,0 +1,48 @@
+From b14d06d5999113a9a546bf045878d6f1a24b9c69 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 6/7] 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 62715ec..42ddbd9 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -3309,6 +3309,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 e2efcaa..4c3c013 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -3942,6 +3942,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/v8/0007-Fix-warnings.patch b/src/v8/0007-Fix-warnings.patch
new file mode 100644
index 0000000000..b337e7f727
--- /dev/null
+++ b/src/v8/0007-Fix-warnings.patch
@@ -0,0 +1,46 @@
+From 15eb9c6a9444307a867a854c742505c15bd8b867 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 7/7] Fix warnings
+
+---
+ include/v8.h | 16 ++++++++--------
+ 1 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 42ddbd9..bc229f9 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -2388,7 +2388,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>();
+ }
+
+@@ -3694,13 +3694,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/v8/README b/src/v8/README
new file mode 100644
index 0000000000..2dc39705aa
--- /dev/null
+++ b/src/v8/README
@@ -0,0 +1 @@
+These patches apply cleanly against v8 at 2eaa4b29586fdbd5d41f7b7d9e72ecca6d53dbd2
diff --git a/src/v8/v8.pro b/src/v8/v8.pro
new file mode 100644
index 0000000000..c3d2e634c1
--- /dev/null
+++ b/src/v8/v8.pro
@@ -0,0 +1,263 @@
+TEMPLATE = lib
+CONFIG += staticlib
+
+CONFIG += building-libs
+
+QT =
+
+win32|mac:!macx-xcode:CONFIG += debug_and_release
+macx:CONFIG(debug, debug|release) {
+ TARGET = v8_debug
+}
+
+equals(QT_ARCH, "x64")|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
+
+# 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/v8/v8base.pri b/src/v8/v8base.pri
new file mode 100644
index 0000000000..f57663ed3e
--- /dev/null
+++ b/src/v8/v8base.pri
@@ -0,0 +1,18 @@
+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
+ # FIXME how to find 4.5 series?
+ 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/v8/wrapcc.pl b/src/v8/wrapcc.pl
new file mode 100755
index 0000000000..463ab059ba
--- /dev/null
+++ b/src/v8/wrapcc.pl
@@ -0,0 +1,48 @@
+#!/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$
+## 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$
+##
+#############################################################################
+
+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/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
index 20fa8548fd..bc694669b6 100644
--- a/tests/auto/declarative/declarative.pro
+++ b/tests/auto/declarative/declarative.pro
@@ -94,7 +94,8 @@ contains(QT_CONFIG, private_tests) {
qsgtext \
qsgtextedit \
qsgtextinput \
- qsgvisualdatamodel
+ qsgvisualdatamodel \
+ v8
}
diff --git a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp
index 1762ff7874..973d3a8d22 100644
--- a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp
+++ b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp
@@ -342,7 +342,7 @@ void tst_qdeclarativecontext::setContextProperty()
QDeclarativeContext ctxt(engine.rootContext());
ctxt.setContextProperty("ctxtProp", QVariant());
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Result of expression 'ctxtProp' [undefined] is not an object.");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Cannot read property 'a' of undefined");
QObject *obj = component.create(&ctxt);
QVariant v = obj->property("obj");
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml
index a778dcc8b6..0455271dac 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/propertyAssignmentErrors.qml
@@ -6,17 +6,24 @@ QtObject {
property int a
property variant b
+ property bool test1: false;
+ property bool test2: false;
+
Component.onCompleted: {
try {
root.a = undefined;
} catch(e) {
- console.log (e.fileName + ":" + e.lineNumber + ":" + e);
+ if (e.message == "Cannot assign [undefined] to int" &&
+ e.stack.indexOf("propertyAssignmentErrors.qml:14") != -1)
+ root.test1 = true;
}
try {
root.a = "Hello";
} catch(e) {
- console.log (e.fileName + ":" + e.lineNumber + ":" + e);
+ if (e.message == "Cannot assign QString to int" &&
+ e.stack.indexOf("propertyAssignmentErrors.qml:22") != -1)
+ root.test2 = true;
}
}
}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_11600.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_11600.qml
index b7bb366698..7fcf2bebd7 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_11600.qml
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtbug_11600.qml
@@ -4,5 +4,5 @@ import "qtbug_11600.js" as Test
QtObject {
id: goo
- property bool test: undefined == goo.Test.foo
+ property bool test: undefined == goo.Test
}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml
index b1342fea90..9b07080054 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/scarceresources/scarceResourceFunctionFail.qml
@@ -11,6 +11,7 @@ QtObject {
id: root
property MyScarceResourceObject a: MyScarceResourceObject { id: scarceResourceProvider }
property variant scarceResourceCopy;
+ property string srp_name: a.toString();
function retrieveScarceResource() {
root.scarceResourceCopy = scarceResourceProvider.scarceResource(); // common syntax error, should throw exception
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index b2859b5b5b..4142c88ea5 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -49,7 +49,6 @@
#include <QtCore/qdir.h>
#include <QtCore/qnumeric.h>
#include <private/qdeclarativeengine_p.h>
-#include <private/qdeclarativeglobalscriptclass_p.h>
#include <private/qscriptdeclarativeclass_p.h>
#include "testtypes.h"
#include "testhttpserver.h"
@@ -1199,7 +1198,11 @@ void tst_qdeclarativeecmascript::functionErrors()
url = componentTwo.url().toString();
object = componentTwo.create();
QVERIFY(object != 0);
- warning = url + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
+
+ QString srpname = object->property("srp_name").toString();
+
+ warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
+ QLatin1String(" is not a function");
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
delete object;
@@ -1214,15 +1217,12 @@ void tst_qdeclarativeecmascript::propertyAssignmentErrors()
QString url = component.url().toString();
- QString warning1 = url + ":11:Error: Cannot assign [undefined] to int";
- QString warning2 = url + ":17:Error: Cannot assign QString to int";
-
- QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData());
- QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData());
-
QObject *object = component.create();
QVERIFY(object != 0);
+ QCOMPARE(object->property("test1").toBool(), true);
+ QCOMPARE(object->property("test2").toBool(), true);
+
delete object;
}
@@ -1277,7 +1277,7 @@ void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
QString url = component.url().toString();
- QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object.";
+ QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
@@ -1490,56 +1490,119 @@ void tst_qdeclarativeecmascript::regExpBug()
delete object;
}
+static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
+{
+ QString functionSource = QLatin1String("(function(object) { return ") +
+ QLatin1String(source) + QLatin1String(" })");
+ v8::TryCatch tc;
+ v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
+ if (tc.HasCaught())
+ return false;
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
+ if (function.IsEmpty())
+ return false;
+ v8::Handle<v8::Value> args[] = { o };
+ function->Call(engine->global(), 1, args);
+ return tc.HasCaught();
+}
+
+static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
+ const char *source, v8::Handle<v8::Value> result)
+{
+ QString functionSource = QLatin1String("(function(object) { return ") +
+ QLatin1String(source) + QLatin1String(" })");
+ v8::TryCatch tc;
+ v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
+ if (tc.HasCaught())
+ return false;
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
+ if (function.IsEmpty())
+ return false;
+ v8::Handle<v8::Value> args[] = { o };
+
+ v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
+
+ if (tc.HasCaught())
+ return false;
+
+ return value->StrictEquals(result);
+}
+
+static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
+ const char *source)
+{
+ QString functionSource = QLatin1String("(function(object) { return ") +
+ QLatin1String(source) + QLatin1String(" })");
+ v8::TryCatch tc;
+ v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
+ if (tc.HasCaught())
+ return v8::Handle<v8::Value>();
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
+ if (function.IsEmpty())
+ return v8::Handle<v8::Value>();
+ v8::Handle<v8::Value> args[] = { o };
+
+ v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
+
+ if (tc.HasCaught())
+ return v8::Handle<v8::Value>();
+ return value;
+}
+
+#define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
+#define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
+#define EVALUATE(source) evaluate(engine, object, source)
+
void tst_qdeclarativeecmascript::callQtInvokables()
{
MyInvokableObject o;
QDeclarativeEngine qmlengine;
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
- QScriptEngine *engine = &ep->scriptEngine;
+
+ QV8Engine *engine = &ep->v8engine;
- QStringList names; QList<QScriptValue> values;
- names << QLatin1String("object"); values << ep->objectClass->newQObject(&o);
- names << QLatin1String("undefined"); values << engine->undefinedValue();
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(engine->context());
- ep->globalClass->explicitSetProperty(names, values);
+ v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
// Non-existent methods
o.reset();
- QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true);
+ QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), -1);
QCOMPARE(o.actuals().count(), 0);
o.reset();
- QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true);
+ QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), -1);
QCOMPARE(o.actuals().count(), 0);
// Insufficient arguments
o.reset();
- QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
+ QVERIFY(EVALUATE_ERROR("object.method_int()"));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), -1);
QCOMPARE(o.actuals().count(), 0);
o.reset();
- QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
+ QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), -1);
QCOMPARE(o.actuals().count(), 0);
// Excessive arguments
o.reset();
- QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 8);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(10));
o.reset();
- QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 9);
QCOMPARE(o.actuals().count(), 2);
@@ -1548,27 +1611,28 @@ void tst_qdeclarativeecmascript::callQtInvokables()
// Test return types
o.reset();
- QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 0);
QCOMPARE(o.actuals().count(), 0);
o.reset();
- QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
+ QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 1);
QCOMPARE(o.actuals().count(), 0);
o.reset();
- QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.75)));
+ QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 2);
QCOMPARE(o.actuals().count(), 0);
o.reset();
{
- QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
- QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
+ v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
+ QVERIFY(!ret.IsEmpty());
+ QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 3);
QCOMPARE(o.actuals().count(), 0);
@@ -1576,81 +1640,83 @@ void tst_qdeclarativeecmascript::callQtInvokables()
o.reset();
{
- QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
- QVERIFY(ret.isQObject());
- QCOMPARE(ret.toQObject(), (QObject *)&o);
+ v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
+ QCOMPARE(engine->toQObject(ret), (QObject *)&o);
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 4);
QCOMPARE(o.actuals().count(), 0);
}
o.reset();
- QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 5);
QCOMPARE(o.actuals().count(), 0);
+ // XXX enable once qml/qtscript integration is implemented
+#if 0
o.reset();
{
- QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
- QVERIFY(ret.isString());
- QCOMPARE(ret.toString(), QString("Hello world"));
+ v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
+ QVERIFY(ret->IsString());
+ QCOMPARE(engine->toString(ret), QString("Hello world"));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 6);
QCOMPARE(o.actuals().count(), 0);
}
+#endif
o.reset();
- QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
+ QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 7);
QCOMPARE(o.actuals().count(), 0);
// Test arg types
o.reset();
- QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 8);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(94));
o.reset();
- QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 8);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(94));
o.reset();
- QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 8);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 8);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 8);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 8);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 9);
QCOMPARE(o.actuals().count(), 2);
@@ -1658,56 +1724,56 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().at(1), QVariant(9));
o.reset();
- QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 10);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(94.3));
o.reset();
- QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 10);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(94.3));
o.reset();
- QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 10);
QCOMPARE(o.actuals().count(), 1);
QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 10);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 10);
QCOMPARE(o.actuals().count(), 1);
QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 10);
QCOMPARE(o.actuals().count(), 1);
QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 11);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 11);
QCOMPARE(o.actuals().count(), 1);
@@ -1716,7 +1782,7 @@ void tst_qdeclarativeecmascript::callQtInvokables()
o.reset();
{
QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
- QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 11);
QCOMPARE(o.actuals().count(), 1);
@@ -1724,126 +1790,128 @@ void tst_qdeclarativeecmascript::callQtInvokables()
}
o.reset();
- QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 11);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QString()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 11);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QString()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 12);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 12);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 12);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 12);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 12);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 12);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 13);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 13);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 13);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 13);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 13);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
+ // XXX enable once qml/qtscript integration is implemented
+#if 0
o.reset();
- QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 14);
QCOMPARE(o.actuals().count(), 1);
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
o.reset();
- QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 14);
QCOMPARE(o.actuals().count(), 1);
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
o.reset();
- QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 14);
QCOMPARE(o.actuals().count(), 1);
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 14);
QCOMPARE(o.actuals().count(), 1);
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
o.reset();
- QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 15);
QCOMPARE(o.actuals().count(), 2);
@@ -1851,7 +1919,7 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
o.reset();
- QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 15);
QCOMPARE(o.actuals().count(), 2);
@@ -1859,7 +1927,7 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
o.reset();
- QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 15);
QCOMPARE(o.actuals().count(), 2);
@@ -1867,28 +1935,29 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
o.reset();
- QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 15);
QCOMPARE(o.actuals().count(), 2);
QCOMPARE(o.actuals().at(0), QVariant(44));
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
+#endif
o.reset();
- QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
+ QVERIFY(EVALUATE_ERROR("object.method_overload()"));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), -1);
QCOMPARE(o.actuals().count(), 0);
o.reset();
- QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 16);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(10));
o.reset();
- QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 17);
QCOMPARE(o.actuals().count(), 2);
@@ -1896,21 +1965,21 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().at(1), QVariant(11));
o.reset();
- QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 18);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
o.reset();
- QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 19);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(9));
o.reset();
- QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
+ QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 20);
QCOMPARE(o.actuals().count(), 2);
@@ -1918,7 +1987,7 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().at(1), QVariant(19));
o.reset();
- QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
+ QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 20);
QCOMPARE(o.actuals().count(), 2);
@@ -1926,14 +1995,14 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().at(1), QVariant(13));
o.reset();
- QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), -3);
QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(9));
o.reset();
- QCOMPARE(engine->evaluate("object.method_QVariant(9)").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 21);
QCOMPARE(o.actuals().count(), 2);
@@ -1941,7 +2010,7 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().at(1), QVariant());
o.reset();
- QCOMPARE(engine->evaluate("object.method_QVariant(\"Hello\", \"World\")").isUndefined(), true);
+ QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 21);
QCOMPARE(o.actuals().count(), 2);
@@ -2236,7 +2305,8 @@ void tst_qdeclarativeecmascript::ownership()
QVERIFY(own.object != 0);
QObject *object = component.create(context);
- QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
+
+ engine.collectGarbage();
QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
@@ -2253,7 +2323,8 @@ void tst_qdeclarativeecmascript::ownership()
QVERIFY(own.object != 0);
QObject *object = component.create(context);
- QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
+
+ engine.collectGarbage();
QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
@@ -2337,6 +2408,7 @@ void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
delete object;
}
+ engine.collectGarbage();
QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
QVERIFY(source.value == 0);
@@ -2638,7 +2710,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(object != 0);
QVERIFY(object->property("scarceResourceCopy").isValid());
QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
delete object;
@@ -2648,7 +2720,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(object != 0);
QVERIFY(object->property("scarceResourceCopy").isValid());
QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
delete object;
@@ -2657,7 +2729,7 @@ void tst_qdeclarativeecmascript::scarceResources()
object = componentThree.create();
QVERIFY(object != 0);
QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
delete object;
@@ -2669,7 +2741,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(object != 0);
QVERIFY(object->property("scarceResourceTest").isValid());
QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
delete object;
@@ -2679,7 +2751,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(object != 0);
QVERIFY(object->property("scarceResourceTest").isValid());
QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
delete object;
@@ -2689,7 +2761,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(object != 0);
QVERIFY(object->property("scarceResourceTest").isValid());
QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
delete object;
@@ -2698,14 +2770,14 @@ void tst_qdeclarativeecmascript::scarceResources()
QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
object = componentSeven.create();
QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
- QVERIFY(ep->scarceResources == 0); // but they should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
delete object;
QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
object = componentEight.create();
QVERIFY(object != 0);
QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
delete object;
QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
@@ -2716,7 +2788,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
- QVERIFY(ep->scarceResources == 0); // this will still be zero, because "preserve()" REMOVES it from this list.
+ QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
delete object;
// test that scarce resources are handled properly in signal invocation
@@ -2739,7 +2811,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
delete object;
// test that scarce resources are handled properly from js functions in qml files
@@ -2758,7 +2830,7 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
delete object;
// test that if an exception occurs while invoking js function from cpp, that the resources are released.
@@ -2768,13 +2840,14 @@ void tst_qdeclarativeecmascript::scarceResources()
QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
- QString expectedWarning = QLatin1String("file://") + TEST_FILE("scarceresources/scarceResourceFunctionFail.qml").toLocalFile() + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
- QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData()); // we expect a meaningful warning to be printed.
+ QString srp_name = object->property("srp_name").toString();
+ QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
- QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
delete object;
}
@@ -3060,11 +3133,11 @@ void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
QVERIFY(!o->property("a").isValid());
QString url = component.url().toString();
- QString warning = url + ":63: Unable to assign QString to int";
+ QString warning = url + ":67: Unable to assign QString to int";
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
o->setProperty("assignWrongType", true);
- warning = url + ":70: Unable to assign QString to int";
+ warning = url + ":71: Unable to assign QString to int";
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
o->setProperty("assignWrongTypeToValueType", true);
diff --git a/tests/auto/declarative/qdeclarativeitem/data/mapCoordinates.qml b/tests/auto/declarative/qdeclarativeitem/data/mapCoordinates.qml
index bb20ecc8f6..48fb38da2b 100644
--- a/tests/auto/declarative/qdeclarativeitem/data/mapCoordinates.qml
+++ b/tests/auto/declarative/qdeclarativeitem/data/mapCoordinates.qml
@@ -33,11 +33,11 @@ Item {
function checkMapAToInvalid(x, y) {
var pos = itemA.mapToItem(1122, x, y)
- return pos.x == undefined && pos.y == undefined
+ return pos == undefined;
}
function checkMapAFromInvalid(x, y) {
var pos = itemA.mapFromItem(1122, x, y)
- return pos.x == undefined && pos.y == undefined
+ return pos == undefined;
}
}
diff --git a/tests/auto/declarative/qdeclarativeqt/data/dateTimeConversion.qml b/tests/auto/declarative/qdeclarativeqt/data/dateTimeConversion.qml
new file mode 100644
index 0000000000..06203285a9
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeqt/data/dateTimeConversion.qml
@@ -0,0 +1,14 @@
+import QtQuick 1.0
+
+QtObject {
+ // months are 0-based - so January = 0, December = 11.
+ property variant qtime: new Date(0,0,0,14,15,38,200) // yyyy/MM/dd 14:15:38.200
+ property variant qdate: new Date(2008,11,24) // 2008/12/24 hh:mm:ss.zzz
+ property variant qdatetime: new Date(2008,11,24,14,15,38,200) // 2008/12/24 14:15:38.200
+
+ property variant qdatetime2: new Date(2852,11,31,23,59,59,500) // 2852/12/31 23:59:59.500
+ property variant qdatetime3: new Date(1970,0,1,0,0,0,0) // 1970/01/01 00:00:00.000
+ property variant qdatetime4: new Date(1586,1,2) // 1586/02/02 hh:mm:ss.zzz
+ property variant qdatetime5: new Date(955,0,1,0,0,0,0) // 955/01/01 00:00:00.000
+ property variant qdatetime6: new Date(113,1,24,14,15,38,200) // 113/02/24 14:15:38.200
+}
diff --git a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp
index fc8939f297..c15c079f37 100644
--- a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp
+++ b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp
@@ -82,8 +82,11 @@ private slots:
void createComponent_pragmaLibrary();
void createQmlObject();
void consoleLog();
+ void dateTimeConversion();
void dateTimeFormatting();
void dateTimeFormatting_data();
+ void dateTimeFormattingVariants();
+ void dateTimeFormattingVariants_data();
void isQtObject();
void btoa();
void atob();
@@ -412,11 +415,11 @@ void tst_qdeclarativeqt::createQmlObject()
QDeclarativeComponent component(&engine, TEST_FILE("createQmlObject.qml"));
QString warning1 = component.url().toString() + ":7: Error: Qt.createQmlObject(): Invalid arguments";
- QString warning2 = component.url().toString()+ ":10: Error: Qt.createQmlObject() failed to create object: \n " + TEST_FILE("inline").toString() + ":2:10: Blah is not a type";
- QString warning3 = component.url().toString()+ ":11: Error: Qt.createQmlObject() failed to create object: \n " + TEST_FILE("main.qml").toString() + ":4:1: Duplicate property name";
+ QString warning2 = component.url().toString()+ ":10: Error: Qt.createQmlObject(): failed to create object: \n " + TEST_FILE("inline").toString() + ":2:10: Blah is not a type";
+ QString warning3 = component.url().toString()+ ":11: Error: Qt.createQmlObject(): failed to create object: \n " + TEST_FILE("main.qml").toString() + ":4:1: Duplicate property name";
QString warning4 = component.url().toString()+ ":9: Error: Qt.createQmlObject(): Missing parent object";
QString warning5 = component.url().toString()+ ":8: Error: Qt.createQmlObject(): Invalid arguments";
- QString warning6 = "RunTimeError: Qt.createQmlObject() failed to create object: \n " + TEST_FILE("inline").toString() + ":3: Cannot assign object type QObject with no default method";
+ QString warning6 = "RunTimeError: Qt.createQmlObject(): failed to create object: \n " + TEST_FILE("inline").toString() + ":3: Cannot assign object type QObject with no default method";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
@@ -448,6 +451,31 @@ void tst_qdeclarativeqt::consoleLog()
delete object;
}
+void tst_qdeclarativeqt::dateTimeConversion()
+{
+ QDate date(2008,12,24);
+ QTime time(14,15,38,200);
+ QDateTime dateTime(date, time);
+ QDateTime dateTime2(QDate(2852,12,31), QTime(23,59,59,500));
+ QDateTime dateTime3(QDate(1970,1,1), QTime(0,0,0,0));
+ QDateTime dateTime4(QDate(1586,2,2), QTime(0,0,0,0));
+ QDateTime dateTime5(QDate(955,1,1), QTime(0,0,0,0));
+ QDateTime dateTime6(QDate(113,2,24), QTime(14,15,38,200));
+
+ QDeclarativeEngine eng;
+ QDeclarativeComponent component(&eng, TEST_FILE("dateTimeConversion.qml"));
+ QObject *obj = component.create();
+
+ QCOMPARE(obj->property("qdate").toDate(), date);
+ QCOMPARE(obj->property("qtime").toTime(), time);
+ QCOMPARE(obj->property("qdatetime").toDateTime(), dateTime);
+ QCOMPARE(obj->property("qdatetime2").toDateTime(), dateTime2);
+ QCOMPARE(obj->property("qdatetime3").toDateTime(), dateTime3);
+ QCOMPARE(obj->property("qdatetime4").toDateTime(), dateTime4);
+ QCOMPARE(obj->property("qdatetime5").toDateTime(), dateTime5);
+ QCOMPARE(obj->property("qdatetime6").toDateTime(), dateTime6);
+}
+
void tst_qdeclarativeqt::dateTimeFormatting()
{
QFETCH(QString, method);
@@ -482,14 +510,13 @@ void tst_qdeclarativeqt::dateTimeFormatting()
QVERIFY(object != 0);
QVERIFY(inputProperties.count() > 0);
-
QVariant result;
foreach(const QString &prop, inputProperties) {
QVERIFY(QMetaObject::invokeMethod(object, method.toUtf8().constData(),
Q_RETURN_ARG(QVariant, result),
Q_ARG(QVariant, prop)));
-
QStringList output = result.toStringList();
+ QCOMPARE(output.size(), expectedResults.size());
for (int i=0; i<output.count(); i++)
QCOMPARE(output[i], expectedResults[i]);
}
@@ -530,6 +557,86 @@ void tst_qdeclarativeqt::dateTimeFormatting_data()
<< dateTime.toString("M/d/yy H:m:s a"));
}
+void tst_qdeclarativeqt::dateTimeFormattingVariants()
+{
+ QFETCH(QString, method);
+ QFETCH(QVariant, variant);
+ QFETCH(QStringList, expectedResults);
+
+ QDeclarativeEngine eng;
+ eng.rootContext()->setContextProperty("qvariant", variant);
+ QDeclarativeComponent component(&eng, TEST_FILE("formatting.qml"));
+
+ QStringList warnings;
+ warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Invalid date format"
+ << component.url().toString() + ":36: Error: Qt.formatDate(): Invalid arguments"
+ << component.url().toString() + ":40: Error: Qt.formatTime(): Invalid time format"
+ << component.url().toString() + ":39: Error: Qt.formatTime(): Invalid arguments"
+ << component.url().toString() + ":43: Error: Qt.formatDateTime(): Invalid datetime format"
+ << component.url().toString() + ":42: Error: Qt.formatDateTime(): Invalid arguments";
+
+ foreach (const QString &warning, warnings)
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+
+ QObject *object = component.create();
+ QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
+ QVERIFY(object != 0);
+
+ QVariant result;
+ QVERIFY(QMetaObject::invokeMethod(object, method.toUtf8().constData(),
+ Q_RETURN_ARG(QVariant, result),
+ Q_ARG(QVariant, QString(QLatin1String("qvariant")))));
+ QStringList output = result.toStringList();
+ QCOMPARE(output, expectedResults);
+
+ delete object;
+}
+
+void tst_qdeclarativeqt::dateTimeFormattingVariants_data()
+{
+ QTest::addColumn<QString>("method");
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QStringList>("expectedResults");
+
+ QDateTime temporary;
+
+ QTime time(11, 16, 39, 755);
+ temporary = QDateTime(QDate(1970,1,1), time);
+ QTest::newRow("formatDate, qtime") << "formatDate" << QVariant::fromValue(time) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
+ QTest::newRow("formatDateTime, qtime") << "formatDateTime" << QVariant::fromValue(time) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
+ QTest::newRow("formatTime, qtime") << "formatTime" << QVariant::fromValue(time) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
+
+ QDate date(2011,5,31);
+ temporary = QDateTime(date);
+ QTest::newRow("formatDate, qdate") << "formatDate" << QVariant::fromValue(date) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
+ QTest::newRow("formatDateTime, qdate") << "formatDateTime" << QVariant::fromValue(date) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
+ QTest::newRow("formatTime, qdate") << "formatTime" << QVariant::fromValue(date) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
+
+ QDateTime dateTime(date, time);
+ temporary = dateTime;
+ QTest::newRow("formatDate, qdatetime") << "formatDate" << QVariant::fromValue(dateTime) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
+ QTest::newRow("formatDateTime, qdatetime") << "formatDateTime" << QVariant::fromValue(dateTime) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
+ QTest::newRow("formatTime, qdatetime") << "formatTime" << QVariant::fromValue(dateTime) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
+
+ QString string(QLatin1String("2011/05/31 11:16:39.755"));
+ temporary = QDateTime::fromString(string, "yyyy/MM/dd HH:mm:ss.zzz");
+ QTest::newRow("formatDate, qstring") << "formatDate" << QVariant::fromValue(string) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
+ QTest::newRow("formatDateTime, qstring") << "formatDateTime" << QVariant::fromValue(string) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
+ QTest::newRow("formatTime, qstring") << "formatTime" << QVariant::fromValue(string) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
+
+ QColor color(Qt::red);
+ temporary = QVariant::fromValue(color).toDateTime();
+ QTest::newRow("formatDate, qcolor") << "formatDate" << QVariant::fromValue(color) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
+ QTest::newRow("formatDateTime, qcolor") << "formatDateTime" << QVariant::fromValue(color) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
+ QTest::newRow("formatTime, qcolor") << "formatTime" << QVariant::fromValue(color) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
+
+ int integer(4);
+ temporary = QVariant::fromValue(integer).toDateTime();
+ QTest::newRow("formatDate, int") << "formatDate" << QVariant::fromValue(integer) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
+ QTest::newRow("formatDateTime, int") << "formatDateTime" << QVariant::fromValue(integer) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
+ QTest::newRow("formatTime, int") << "formatTime" << QVariant::fromValue(integer) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
+}
+
void tst_qdeclarativeqt::isQtObject()
{
QDeclarativeComponent component(&engine, TEST_FILE("isQtObject.qml"));
diff --git a/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp b/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp
index 330bd4fdf2..874c3229f9 100644
--- a/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp
+++ b/tests/auto/declarative/qdeclarativesqldatabase/tst_qdeclarativesqldatabase.cpp
@@ -230,7 +230,8 @@ void tst_qdeclarativesqldatabase::testQml_cleanopen()
// making it more like the tests are running in new processes.
testQml();
- QDeclarativeEnginePrivate::getScriptEngine(engine)->collectGarbage(); // close databases
+ engine->collectGarbage();
+
foreach (QString dbname, QSqlDatabase::connectionNames()) {
QSqlDatabase::removeDatabase(dbname);
}
diff --git a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp
index b64e10c50d..e76ba9596f 100644
--- a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp
+++ b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp
@@ -53,8 +53,6 @@
#include <private/qdeclarativeengine_p.h>
#include "../../../shared/util.h"
-Q_DECLARE_METATYPE(QScriptValue)
-
#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
#define SRCDIR "."
@@ -191,13 +189,12 @@ void tst_QDeclarativeWorkerScript::messaging_sendJsObject()
// QVariant roundtrip, since the properties will be stored in a QVariantMap.
QString jsObject = "{'haste': 1125, 'name': 'zyz', 'spell power': 3101}";
- QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(worker));
- QScriptValue sv = engine->newObject();
- sv.setProperty("haste", 1125);
- sv.setProperty("name", "zyz");
- sv.setProperty("spell power", 3101);
+ QVariantMap map;
+ map.insert("haste", 1125);
+ map.insert("name", "zyz");
+ map.insert("spell power", 3101);
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, qVariantFromValue(sv))));
+ QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, qVariantFromValue(map))));
waitForEchoMessage(worker);
QVariant result = qVariantFromValue(false);
@@ -261,7 +258,7 @@ void tst_QDeclarativeWorkerScript::scriptError_onLoad()
QVERIFY(worker != 0);
QTRY_COMPARE(qdeclarativeworkerscript_lastWarning,
- TEST_FILE("data/script_error_onLoad.js").toString() + QLatin1String(":3: SyntaxError: Parse error"));
+ TEST_FILE("data/script_error_onLoad.js").toString() + QLatin1String(":3: SyntaxError: Unexpected identifier"));
qInstallMsgHandler(previousMsgHandler);
qApp->processEvents();
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/data/invalidMethodUsage.qml b/tests/auto/declarative/qdeclarativexmlhttprequest/data/invalidMethodUsage.qml
index 68f22f5f33..312292deaf 100644
--- a/tests/auto/declarative/qdeclarativexmlhttprequest/data/invalidMethodUsage.qml
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/data/invalidMethodUsage.qml
@@ -1,7 +1,6 @@
import QtQuick 1.0
QtObject {
- property bool onreadystatechange: false
property bool readyState: false
property bool status: false
property bool statusText: false
@@ -19,17 +18,6 @@ QtObject {
var o = 10;
try {
- XMLHttpRequest.prototype.onreadystatechange
- } catch (e) {
- if (!(e instanceof ReferenceError))
- return;
-
- if (e.message != "Not an XMLHttpRequest object")
- return;
-
- onreadystatechange = true;
- }
- try {
XMLHttpRequest.prototype.readyState
} catch (e) {
if (!(e instanceof ReferenceError))
diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp b/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
index 7f158fce67..9622b19004 100644
--- a/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
+++ b/tests/auto/declarative/qdeclarativexmlhttprequest/tst_qdeclarativexmlhttprequest.cpp
@@ -958,7 +958,6 @@ void tst_qdeclarativexmlhttprequest::invalidMethodUsage()
QObject *object = component.create();
QVERIFY(object != 0);
- QCOMPARE(object->property("onreadystatechange").toBool(), true);
QCOMPARE(object->property("readyState").toBool(), true);
QCOMPARE(object->property("status").toBool(), true);
QCOMPARE(object->property("statusText").toBool(), true);
diff --git a/tests/auto/declarative/v8/tst_v8.cpp b/tests/auto/declarative/v8/tst_v8.cpp
new file mode 100644
index 0000000000..a40638034c
--- /dev/null
+++ b/tests/auto/declarative/v8/tst_v8.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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$
+** 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 <qtest.h>
+#include "../../../../src/3rdparty/v8/include/v8.h"
+
+using namespace v8;
+
+class tst_v8 : public QObject
+{
+ Q_OBJECT
+public:
+ tst_v8() {}
+
+private slots:
+ void initTestCase() {}
+ void cleanupTestCase();
+
+ void eval();
+
+private:
+ Persistent<Context> context;
+};
+
+void tst_v8::eval()
+{
+ HandleScope handle_scope;
+ context = Context::New();
+ Context::Scope context_scope(context);
+
+ Local<Object> qmlglobal = Object::New();
+ qmlglobal->Set(String::New("a"), v8::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);
+
+ QVERIFY(!tc.HasCaught());
+ QCOMPARE(result->Int32Value(), 1922);
+}
+
+void tst_v8::cleanupTestCase()
+{
+ context.Dispose();
+ context = Persistent<Context>();
+}
+
+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
new file mode 100644
index 0000000000..0fc27d80b4
--- /dev/null
+++ b/tests/auto/declarative/v8/v8.pro
@@ -0,0 +1,14 @@
+load(qttest_p4)
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_v8.cpp
+
+CONFIG += parallel_test
+
+LIBS += -L../../../../src/v8/
+macx:CONFIG(debug, debug|release) {
+ LIBS += -lv8_debug
+} else {
+ LIBS += -lv8
+}
+