Add built chrome extension
diff --git a/chrome-extension/COPYING b/chrome-extension/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/chrome-extension/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state 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 program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/chrome-extension/checked.png b/chrome-extension/checked.png
new file mode 100644
index 0000000..cbd9330
--- /dev/null
+++ b/chrome-extension/checked.png
Binary files differ
diff --git a/chrome-extension/espeak_tts_engine.js b/chrome-extension/espeak_tts_engine.js
new file mode 100644
index 0000000..2992188
--- /dev/null
+++ b/chrome-extension/espeak_tts_engine.js
@@ -0,0 +1,332 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a the GPL license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview eSpeak text-to-speech extension.
+ */
+
+'use strict';
+
+/**
+ * @constructor
+ */
+var EspeakTtsEngine = function() {
+ this.callback_ = null;
+ this.utterance_ = null;
+ this.tts_ = null;
+ this.bufferLen_ = 256;
+ this.buffers_ = [];
+ this.currentBuffer_ = null;
+ this.currentBufferIndex_ = 0;
+ this.context_ = new AudioContext();
+ this.scriptNode_ = this.context_.createScriptProcessor(
+ this.bufferLen_, 1, 1);
+ this.gainNode_ = this.context_.createGain();
+ this.scriptNode_.onaudioprocess = this.onAudioProcess.bind(this);
+ this.gainNode_.connect(this.context_.destination);
+ this.playing_ = false;
+ this.ttsEngineApiVoices_ = [];
+ this.internalVoiceInfos_ = [];
+ this.defaultEspeakVoiceName_ = null;
+ this.volume_ = 1.0;
+ this.startTime_ = null;
+ this.eventQueue_ = [];
+ this.timeoutIds_ = [];
+};
+
+/**
+ *
+ */
+EspeakTtsEngine.prototype.getLangInfoArray = function() {
+ return this.langInfoArray_;
+};
+
+/**
+ * Function called on startup.
+ */
+EspeakTtsEngine.prototype.init = function() {
+ this.tts_ = new eSpeakNG('js/espeakng.worker.js', (function() {
+ this.updateVoices();
+ }).bind(this));
+
+ chrome.ttsEngine.onSpeak.addListener(this.onSpeak.bind(this));
+ chrome.ttsEngine.onStop.addListener(this.onStop.bind(this));
+};
+
+/**
+ * Function called when the set of enabled voices has changed.
+ */
+EspeakTtsEngine.prototype.updateVoices = function() {
+ console.log('updateVoices');
+ this.tts_.list_voices((function (langInfoArray) {
+ this.langInfoArray_ = langInfoArray;
+ this.ttsEngineApiVoices_ = [];
+ this.internalVoiceInfos_ = [];
+ this.langsRemaining_ = this.langInfoArray_.length;
+ this.langInfoArray_.forEach((function(langInfo) {
+ isEspeakLanguageEnabled(langInfo, (function(enabled) {
+ if (enabled) {
+ var voiceName = 'eSpeak ' + langInfo.name;
+ var ttsEngineApiVoice = {
+ voiceName: voiceName,
+ lang: langInfo.languages[0].name,
+ remote: false,
+ eventTypes: [
+ 'start', 'end', 'word', 'sentence', 'error'
+ ]};
+ this.ttsEngineApiVoices_.push(ttsEngineApiVoice);
+
+ var internalVoiceInfo = {
+ voiceName: voiceName,
+ espeakVoiceName: langInfo.name,
+ languages: langInfo.languages
+ };
+ this.internalVoiceInfos_.push(internalVoiceInfo);
+ }
+
+ this.langsRemaining_--;
+ if (this.langsRemaining_ == 0) {
+ this.finishUpdatingVoices_();
+ }
+ }).bind(this));
+ }).bind(this));
+ }).bind(this));
+};
+
+/**
+ *
+ */
+EspeakTtsEngine.prototype.finishUpdatingVoices_ = function() {
+ console.log('finishUpdatingVoices_');
+ chrome.ttsEngine.updateVoices(this.ttsEngineApiVoices_);
+ console.log('Loaded ' + this.ttsEngineApiVoices_.length +
+ ' voices');
+
+ this.defaultEspeakVoiceName_ = null;var defaultValue = isEspeakLanguageEnabledByDefault(langInfo);
+
+ var key = langInfo.identifier;
+ chrome.storage.local.get(key, (function(result) {
+ var value = (result[key] !== undefined ? result[key] :
+ defaultValue);
+ console.log(key, value);
+ $(key).checked = value;
+ }).bind(this));
+ this.defaultEspeakVoiceName_ = this.getBestEspeakVoice(
+ '', navigator.language);
+ console.log('Default voice: ' + this.defaultEspeakVoiceName_);
+};
+
+/**
+ * Called by the client to stop speech.
+ */
+EspeakTtsEngine.prototype.onStop = function() {
+ this.playing_ = false;
+ this.scriptNode_.disconnect();
+ this.callback_ = null;
+ this.eventQueue_ = [];
+ this.timeoutIds_.forEach(function(timeoutId) {
+ window.clearTimeout(timeoutId);
+ });
+};
+
+/**
+ * Called by the client to start speech synthesis.
+ *
+ * @param {string} utterance The utterance to say.
+ * @param {object} options The options affecting the speech, like language,
+ * pitch, rate, etc.
+ * @param {function(object)} callback The function to receive messages from the
+ * engine.
+ */
+EspeakTtsEngine.prototype.onSpeak = function(utterance, options, callback) {
+ console.log('Will speak: "' + utterance + '" lang="' + options.lang + '"');
+
+ this.onStop();
+
+ this.callback_ = callback;
+ this.buffers_.length = 0;
+ this.utterance_ = utterance;
+
+ var espeakVoiceName = this.getBestEspeakVoice(
+ options.voiceName, options.lang);
+ this.tts_.set_voice(espeakVoiceName);
+
+ // Chrome TTS rates range from 0.1 to 10.0, with 1.0 as the default.
+ // eSpeak rates range from 80 to 450, with 175 as the default.
+ var rate = Math.min(Math.max(Math.floor(options.rate * 175), 80), 450);
+ this.tts_.set_rate(rate);
+
+ // Chrome TTS pitches range from 0.0 to 2.0, with 1.0 as the default.
+ // eSpeak pitches range from 0 to 99, with 50 as the default.
+ var pitch = Math.min(Math.max(Math.floor(options.pitch * 50), 0), 99);
+ this.tts_.set_pitch(pitch);
+
+ var volume = Math.min(Math.max(options.volume, 0.0), 1.0);
+ this.gainNode_.gain.value = volume;
+
+ this.tts_.synthesize(
+ utterance,
+ (function(samples, events) {
+ var isEnd = false;
+ if (events) {
+ events.forEach((function(event) {
+ switch (event.type) {
+ case 'samplerate':
+ // Incomplete?
+ break;
+ case 'sentence':
+ case 'word':
+ this.scheduleTimepointEvent(
+ event.audio_position,
+ event.text_position,
+ event.type);
+ break;
+ case 'end':
+ isEnd = true;
+ break;
+ }
+ // event.text_position;
+ // event.word_length;
+ // event.audio_position;
+ }).bind(this));
+ }
+ var sampleArray = new Float32Array(samples);
+ this.processSamples(sampleArray, isEnd);
+ }).bind(this));
+};
+
+EspeakTtsEngine.prototype.getBestEspeakVoice = function(
+ desiredVoiceName, desiredLang) {
+ var exactMatchEspeakVoiceName = null;
+ var langMatchEspeakVoiceName = null;
+ var langMatch = '';
+ this.internalVoiceInfos_.forEach((function(voice) {
+ if (desiredVoiceName == voice.voiceName)
+ exactMatchEspeakVoiceName = voice.espeakVoiceName;
+ voice.languages.forEach((function(lang) {
+ if (desiredLang.toLowerCase() == lang.name.toLowerCase() &&
+ lang.name.length > langMatch.length) {
+ langMatch = lang.name;
+ langMatchEspeakVoiceName = voice.voiceName;
+ }
+ }).bind(this));
+ }).bind(this));
+
+ if (exactMatchEspeakVoiceName)
+ return exactMatchEspeakVoiceName;
+
+ if (langMatchEspeakVoiceName)
+ return langMatchEspeakVoiceName;
+
+ return this.defaultEspeakVoiceName_;
+};
+
+EspeakTtsEngine.prototype.processSamples = function(samples, isEnd) {
+ if (!this.callback_) {
+ console.error('Ignoring call to processSamples with no callback');
+ return;
+ }
+
+ var i = 0;
+ var len = samples.length;
+ while (i < len) {
+ var chunkLen = Math.min(this.bufferLen_ - this.currentBufferIndex_,
+ len - i);
+ if (!this.currentBuffer_)
+ this.currentBuffer_ = new Float32Array(this.bufferLen_);
+ this.currentBuffer_.set(samples.subarray(i, i + chunkLen));
+ i += chunkLen;
+ this.currentBufferIndex_ += chunkLen;
+ if (this.currentBufferIndex_ == this.bufferLen_) {
+ this.buffers_.push(this.currentBuffer_);
+ this.currentBufferIndex_ = 0;
+ this.currentBuffer_ = null;
+ }
+ }
+
+ // Push final buffer, not complete.
+ if (isEnd && this.currentBufferIndex_ > 0) {
+ this.buffers_.push(this.currentBuffer_);
+ this.currentBufferIndex_ = 0;
+ this.currentBuffer_ = null;
+ }
+
+ if (this.buffers_.length && !this.playing_) {
+ this.scriptNode_.connect(this.gainNode_);
+ this.playing_ = true;
+ this.callback_({
+ 'type': 'start',
+ 'charIndex': 0
+ });
+ this.startTime_ = new Date();
+ this.scheduleQueuedTimepointEvents();
+ }
+};
+
+EspeakTtsEngine.prototype.onAudioProcess = function(audioProcessingEvent) {
+ if (!this.buffers_.length) {
+ this.callback_({
+ 'type': 'end',
+ 'charIndex': this.utterance_.length
+ });
+ this.onStop();
+ return;
+ }
+
+ var outputBuffer = audioProcessingEvent.outputBuffer;
+ var outputData = outputBuffer.getChannelData(0);
+ var buffer = this.buffers_.shift();
+ outputData.set(buffer);
+};
+
+EspeakTtsEngine.prototype.scheduleTimepointEvent = function(
+ audioPositionMillis,
+ textPosition,
+ eventType) {
+ if (!this.playing_) {
+ this.eventQueue_.push({'audioPositionMillis': audioPositionMillis,
+ 'textPosition': textPosition,
+ 'eventType': eventType});
+ return;
+ }
+
+ var currentTimeMillis = (new Date()) - this.startTime_;
+ var deltaTimeMillis = audioPositionMillis - currentTimeMillis;
+ if (deltaTimeMillis < -100) {
+ console.log('Skipping event ' + eventType + ' in the past');
+ // Skip it if it's too much in the past.
+ return;
+ } else if (deltaTimeMillis < 2) {
+ // It's basically now, fire it.
+ this.callback_({
+ 'type': eventType,
+ 'charIndex': textPosition
+ });
+ return;
+ }
+
+ var timeoutId = window.setTimeout((function() {
+ this.callback_({
+ 'type': eventType,
+ 'charIndex': textPosition
+ });
+ }).bind(this), deltaTimeMillis);
+ this.timeoutIds_.push(timeoutId);
+}
+
+EspeakTtsEngine.prototype.scheduleQueuedTimepointEvents = function() {
+ console.assert(this.playing_);
+ var events = this.eventQueue_;
+ this.eventQueue_ = [];
+ events.forEach((function(event) {
+ this.scheduleTimepointEvent(
+ event.audioPositionMillis,
+ event.textPosition,
+ event.eventType);
+ }).bind(this));
+}
+
+
+window.engine = new EspeakTtsEngine();
+engine.init();
diff --git a/chrome-extension/js/espeakng.js b/chrome-extension/js/espeakng.js
new file mode 100644
index 0000000..a225835
--- /dev/null
+++ b/chrome-extension/js/espeakng.js
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014-2017 Eitan Isaacson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see: <http://www.gnu.org/licenses/>.
+ */
+
+function eSpeakNG(worker_path, ready_cb) {
+ this.worker = new Worker(worker_path);
+ this.ready = false;
+ this.worker.onmessage = function(e) {
+ if (e.data !== 'ready') {
+ return;
+ }
+ this.worker.onmessage = null;
+ this.worker.addEventListener('message', this);
+ this.ready = true;
+ if (ready_cb) {
+ ready_cb();
+ }
+ }.bind(this);
+}
+
+eSpeakNG.prototype.handleEvent = function (evt) {
+ var callback = evt.data.callback;
+ if (callback && this[callback]) {
+ this[callback].apply(this, evt.data.result);
+ if (evt.data.done) {
+ delete this[callback];
+ }
+ return;
+ }
+};
+
+function _createAsyncMethod(method) {
+ return function() {
+ var lastArg = arguments[arguments.length - 1];
+ var message = { method: method, args: Array.prototype.slice.call(arguments, 0) };
+ if (typeof lastArg == 'function') {
+ var callback = '_' + method + '_' + Math.random().toString().substring(2) +'_cb';
+ this[callback] = lastArg;
+ message.args.pop();
+ message.callback = callback;
+ }
+ this.worker.postMessage(message);
+ };
+}
+
+for (var method of [
+ 'list_voices',
+ 'get_rate',
+ 'get_pitch',
+ 'set_rate',
+ 'set_pitch',
+ 'set_voice',
+ 'synthesize',
+ 'synthesize_ipa'
+ ]) {
+ eSpeakNG.prototype[method] = _createAsyncMethod(method);
+}
diff --git a/chrome-extension/js/espeakng.worker.data b/chrome-extension/js/espeakng.worker.data
new file mode 100644
index 0000000..f145e1a
--- /dev/null
+++ b/chrome-extension/js/espeakng.worker.data
Binary files differ
diff --git a/chrome-extension/js/espeakng.worker.js b/chrome-extension/js/espeakng.worker.js
new file mode 100644
index 0000000..58c2de8
--- /dev/null
+++ b/chrome-extension/js/espeakng.worker.js
@@ -0,0 +1,7211 @@
+// The Module object: Our interface to the outside world. We import
+// and export values on it. There are various ways Module can be used:
+// 1. Not defined. We create it here
+// 2. A function parameter, function(Module) { ..generated code.. }
+// 3. pre-run appended it, var Module = {}; ..generated code..
+// 4. External script tag defines var Module.
+// We need to check if Module already exists (e.g. case 3 above).
+// Substitution will be replaced with actual code on later stage of the build,
+// this way Closure Compiler will not mangle it (e.g. case 4. above).
+// Note that if you want to run closure, and also to use Module
+// after the generated code, you will need to define var Module = {};
+// before the code. Then that object will be used in the code, and you
+// can continue to use Module afterwards as well.
+var Module = typeof Module !== 'undefined' ? Module : {};
+
+// --pre-jses are emitted after the Module integration code, so that they can
+// refer to Module (if they choose; they can also define Module)
+
+
+var Module = typeof Module !== 'undefined' ? Module : {};
+
+if (!Module.expectedDataFileDownloads) {
+ Module.expectedDataFileDownloads = 0;
+ Module.finishedDataFileDownloads = 0;
+}
+Module.expectedDataFileDownloads++;
+(function() {
+ var loadPackage = function(metadata) {
+
+ var PACKAGE_PATH;
+ if (typeof window === 'object') {
+ PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
+ } else if (typeof location !== 'undefined') {
+ // worker
+ PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
+ } else {
+ throw 'using preloaded data can only be done on a web page or in a web worker';
+ }
+ var PACKAGE_NAME = 'js/espeakng.worker.data';
+ var REMOTE_PACKAGE_BASE = 'espeakng.worker.data';
+ if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
+ Module['locateFile'] = Module['locateFilePackage'];
+ Module.printErr('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
+ }
+ var REMOTE_PACKAGE_NAME = typeof Module['locateFile'] === 'function' ?
+ Module['locateFile'](REMOTE_PACKAGE_BASE) :
+ ((Module['filePackagePrefixURL'] || '') + REMOTE_PACKAGE_BASE);
+
+ var REMOTE_PACKAGE_SIZE = metadata.remote_package_size;
+ var PACKAGE_UUID = metadata.package_uuid;
+
+ function fetchRemotePackage(packageName, packageSize, callback, errback) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', packageName, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onprogress = function(event) {
+ var url = packageName;
+ var size = packageSize;
+ if (event.total) size = event.total;
+ if (event.loaded) {
+ if (!xhr.addedTotal) {
+ xhr.addedTotal = true;
+ if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
+ Module.dataFileDownloads[url] = {
+ loaded: event.loaded,
+ total: size
+ };
+ } else {
+ Module.dataFileDownloads[url].loaded = event.loaded;
+ }
+ var total = 0;
+ var loaded = 0;
+ var num = 0;
+ for (var download in Module.dataFileDownloads) {
+ var data = Module.dataFileDownloads[download];
+ total += data.total;
+ loaded += data.loaded;
+ num++;
+ }
+ total = Math.ceil(total * Module.expectedDataFileDownloads/num);
+ if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
+ } else if (!Module.dataFileDownloads) {
+ if (Module['setStatus']) Module['setStatus']('Downloading data...');
+ }
+ };
+ xhr.onerror = function(event) {
+ throw new Error("NetworkError for: " + packageName);
+ }
+ xhr.onload = function(event) {
+ if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
+ var packageData = xhr.response;
+ callback(packageData);
+ } else {
+ throw new Error(xhr.statusText + " : " + xhr.responseURL);
+ }
+ };
+ xhr.send(null);
+ };
+
+ function handleError(error) {
+ console.error('package error:', error);
+ };
+
+ var fetchedCallback = null;
+ var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
+
+ if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
+ if (fetchedCallback) {
+ fetchedCallback(data);
+ fetchedCallback = null;
+ } else {
+ fetched = data;
+ }
+ }, handleError);
+
+ function runWithFS() {
+
+ function assert(check, msg) {
+ if (!check) throw msg + new Error().stack;
+ }
+Module['FS_createPath']('/', 'usr', true, true);
+Module['FS_createPath']('/usr', 'share', true, true);
+Module['FS_createPath']('/usr/share', 'espeak-ng-data', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data', 'lang', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'aav', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'art', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'sai', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'dra', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'zls', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'jpx', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'roa', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'azc', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'cel', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'ira', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'bnt', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'grk', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'sit', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'sem', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'ine', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'zlw', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'ccs', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'cus', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'urj', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'zle', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'poz', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'esx', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'bat', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'trk', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'inc', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'gmq', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'gmw', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/lang', 'itc', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data', 'voices', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/voices', '!v', true, true);
+Module['FS_createPath']('/usr/share/espeak-ng-data/voices', 'mb', true, true);
+
+ function DataRequest(start, end, crunched, audio) {
+ this.start = start;
+ this.end = end;
+ this.crunched = crunched;
+ this.audio = audio;
+ }
+ DataRequest.prototype = {
+ requests: {},
+ open: function(mode, name) {
+ this.name = name;
+ this.requests[name] = this;
+ Module['addRunDependency']('fp ' + this.name);
+ },
+ send: function() {},
+ onload: function() {
+ var byteArray = this.byteArray.subarray(this.start, this.end);
+
+ this.finish(byteArray);
+
+ },
+ finish: function(byteArray) {
+ var that = this;
+
+ Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
+ Module['removeRunDependency']('fp ' + that.name);
+
+ this.requests[this.name] = null;
+ }
+ };
+
+ var files = metadata.files;
+ for (var i = 0; i < files.length; ++i) {
+ new DataRequest(files[i].start, files[i].end, files[i].crunched, files[i].audio).open('GET', files[i].filename);
+ }
+
+
+ function processPackageData(arrayBuffer) {
+ Module.finishedDataFileDownloads++;
+ assert(arrayBuffer, 'Loading data file failed.');
+ assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData');
+ var byteArray = new Uint8Array(arrayBuffer);
+ var curr;
+
+ // copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though
+ // (we may be allocating before malloc is ready, during startup).
+ if (Module['SPLIT_MEMORY']) Module.printErr('warning: you should run the file packager with --no-heap-copy when SPLIT_MEMORY is used, otherwise copying into the heap may fail due to the splitting');
+ var ptr = Module['getMemory'](byteArray.length);
+ Module['HEAPU8'].set(byteArray, ptr);
+ DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
+
+ var files = metadata.files;
+ for (var i = 0; i < files.length; ++i) {
+ DataRequest.prototype.requests[files[i].filename].onload();
+ }
+ Module['removeRunDependency']('datafile_js/espeakng.worker.data');
+
+ };
+ Module['addRunDependency']('datafile_js/espeakng.worker.data');
+
+ if (!Module.preloadResults) Module.preloadResults = {};
+
+ Module.preloadResults[PACKAGE_NAME] = {fromCache: false};
+ if (fetched) {
+ processPackageData(fetched);
+ fetched = null;
+ } else {
+ fetchedCallback = processPackageData;
+ }
+
+ }
+ if (Module['calledRun']) {
+ runWithFS();
+ } else {
+ if (!Module['preRun']) Module['preRun'] = [];
+ Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
+ }
+
+ }
+ loadPackage({"files": [{"audio": 0, "start": 0, "crunched": 0, "end": 42392, "filename": "/usr/share/espeak-ng-data/tr_dict"}, {"audio": 0, "start": 42392, "crunched": 0, "end": 44694, "filename": "/usr/share/espeak-ng-data/om_dict"}, {"audio": 0, "start": 44694, "crunched": 0, "end": 111914, "filename": "/usr/share/espeak-ng-data/el_dict"}, {"audio": 0, "start": 111914, "crunched": 0, "end": 116092, "filename": "/usr/share/espeak-ng-data/no_dict"}, {"audio": 0, "start": 116092, "crunched": 0, "end": 119879, "filename": "/usr/share/espeak-ng-data/gd_dict"}, {"audio": 0, "start": 119879, "crunched": 0, "end": 206774, "filename": "/usr/share/espeak-ng-data/ml_dict"}, {"audio": 0, "start": 206774, "crunched": 0, "end": 254254, "filename": "/usr/share/espeak-ng-data/ga_dict"}, {"audio": 0, "start": 254254, "crunched": 0, "end": 496795, "filename": "/usr/share/espeak-ng-data/da_dict"}, {"audio": 0, "start": 496795, "crunched": 0, "end": 586498, "filename": "/usr/share/espeak-ng-data/my_dict"}, {"audio": 0, "start": 586498, "crunched": 0, "end": 668549, "filename": "/usr/share/espeak-ng-data/or_dict"}, {"audio": 0, "start": 668549, "crunched": 0, "end": 673794, "filename": "/usr/share/espeak-ng-data/bpy_dict"}, {"audio": 0, "start": 673794, "crunched": 0, "end": 961962, "filename": "/usr/share/espeak-ng-data/fa_dict"}, {"audio": 0, "start": 961962, "crunched": 0, "end": 1008003, "filename": "/usr/share/espeak-ng-data/sk_dict"}, {"audio": 0, "start": 1008003, "crunched": 0, "end": 1065757, "filename": "/usr/share/espeak-ng-data/ru_dict"}, {"audio": 0, "start": 1065757, "crunched": 0, "end": 1125390, "filename": "/usr/share/espeak-ng-data/mk_dict"}, {"audio": 0, "start": 1125390, "crunched": 0, "end": 1201193, "filename": "/usr/share/espeak-ng-data/zh_dict"}, {"audio": 0, "start": 1201193, "crunched": 0, "end": 1244925, "filename": "/usr/share/espeak-ng-data/bs_dict"}, {"audio": 0, "start": 1244925, "crunched": 0, "end": 1389014, "filename": "/usr/share/espeak-ng-data/it_dict"}, {"audio": 0, "start": 1389014, "crunched": 0, "end": 1465568, "filename": "/usr/share/espeak-ng-data/ur_dict"}, {"audio": 0, "start": 1465568, "crunched": 0, "end": 1529077, "filename": "/usr/share/espeak-ng-data/pt_dict"}, {"audio": 0, "start": 1529077, "crunched": 0, "end": 1578327, "filename": "/usr/share/espeak-ng-data/vi_dict"}, {"audio": 0, "start": 1578327, "crunched": 0, "end": 1659950, "filename": "/usr/share/espeak-ng-data/kn_dict"}, {"audio": 0, "start": 1659950, "crunched": 0, "end": 1666343, "filename": "/usr/share/espeak-ng-data/kok_dict"}, {"audio": 0, "start": 1666343, "crunched": 0, "end": 1749003, "filename": "/usr/share/espeak-ng-data/bg_dict"}, {"audio": 0, "start": 1749003, "crunched": 0, "end": 1823017, "filename": "/usr/share/espeak-ng-data/pa_dict"}, {"audio": 0, "start": 1823017, "crunched": 0, "end": 1864855, "filename": "/usr/share/espeak-ng-data/sq_dict"}, {"audio": 0, "start": 1864855, "crunched": 0, "end": 1907741, "filename": "/usr/share/espeak-ng-data/ja_dict"}, {"audio": 0, "start": 1907741, "crunched": 0, "end": 1909869, "filename": "/usr/share/espeak-ng-data/pap_dict"}, {"audio": 0, "start": 1909869, "crunched": 0, "end": 2028569, "filename": "/usr/share/espeak-ng-data/af_dict"}, {"audio": 0, "start": 2028569, "crunched": 0, "end": 2030125, "filename": "/usr/share/espeak-ng-data/zhy_dict"}, {"audio": 0, "start": 2030125, "crunched": 0, "end": 2035149, "filename": "/usr/share/espeak-ng-data/as_dict"}, {"audio": 0, "start": 2035149, "crunched": 0, "end": 2085214, "filename": "/usr/share/espeak-ng-data/ms_dict"}, {"audio": 0, "start": 2085214, "crunched": 0, "end": 2126570, "filename": "/usr/share/espeak-ng-data/is_dict"}, {"audio": 0, "start": 2126570, "crunched": 0, "end": 2166736, "filename": "/usr/share/espeak-ng-data/cy_dict"}, {"audio": 0, "start": 2166736, "crunched": 0, "end": 2210729, "filename": "/usr/share/espeak-ng-data/sv_dict"}, {"audio": 0, "start": 2210729, "crunched": 0, "end": 2252246, "filename": "/usr/share/espeak-ng-data/sl_dict"}, {"audio": 0, "start": 2252246, "crunched": 0, "end": 2312054, "filename": "/usr/share/espeak-ng-data/ky_dict"}, {"audio": 0, "start": 2312054, "crunched": 0, "end": 2371564, "filename": "/usr/share/espeak-ng-data/de_dict"}, {"audio": 0, "start": 2371564, "crunched": 0, "end": 2458106, "filename": "/usr/share/espeak-ng-data/hi_dict"}, {"audio": 0, "start": 2458106, "crunched": 0, "end": 2502439, "filename": "/usr/share/espeak-ng-data/sr_dict"}, {"audio": 0, "start": 2502439, "crunched": 0, "end": 2561209, "filename": "/usr/share/espeak-ng-data/lv_dict"}, {"audio": 0, "start": 2561209, "crunched": 0, "end": 2562743, "filename": "/usr/share/espeak-ng-data/nci_dict"}, {"audio": 0, "start": 2562743, "crunched": 0, "end": 2565011, "filename": "/usr/share/espeak-ng-data/ku_dict"}, {"audio": 0, "start": 2565011, "crunched": 0, "end": 2609085, "filename": "/usr/share/espeak-ng-data/ko_dict"}, {"audio": 0, "start": 2609085, "crunched": 0, "end": 2613469, "filename": "/usr/share/espeak-ng-data/mt_dict"}, {"audio": 0, "start": 2613469, "crunched": 0, "end": 2678598, "filename": "/usr/share/espeak-ng-data/ro_dict"}, {"audio": 0, "start": 2678598, "crunched": 0, "end": 2681670, "filename": "/usr/share/espeak-ng-data/tn_dict"}, {"audio": 0, "start": 2681670, "crunched": 0, "end": 2722504, "filename": "/usr/share/espeak-ng-data/fi_dict"}, {"audio": 0, "start": 2722504, "crunched": 0, "end": 2810276, "filename": "/usr/share/espeak-ng-data/te_dict"}, {"audio": 0, "start": 2810276, "crunched": 0, "end": 2842984, "filename": "/usr/share/espeak-ng-data/phonindex"}, {"audio": 0, "start": 2842984, "crunched": 0, "end": 2891512, "filename": "/usr/share/espeak-ng-data/phontab"}, {"audio": 0, "start": 2891512, "crunched": 0, "end": 2970128, "filename": "/usr/share/espeak-ng-data/si_dict"}, {"audio": 0, "start": 2970128, "crunched": 0, "end": 3029719, "filename": "/usr/share/espeak-ng-data/fr_dict"}, {"audio": 0, "start": 3029719, "crunched": 0, "end": 3087039, "filename": "/usr/share/espeak-ng-data/hy_dict"}, {"audio": 0, "start": 3087039, "crunched": 0, "end": 3127410, "filename": "/usr/share/espeak-ng-data/az_dict"}, {"audio": 0, "start": 3127410, "crunched": 0, "end": 3185739, "filename": "/usr/share/espeak-ng-data/am_dict"}, {"audio": 0, "start": 3185739, "crunched": 0, "end": 3187860, "filename": "/usr/share/espeak-ng-data/tt_dict"}, {"audio": 0, "start": 3187860, "crunched": 0, "end": 3192537, "filename": "/usr/share/espeak-ng-data/eo_dict"}, {"audio": 0, "start": 3192537, "crunched": 0, "end": 3357730, "filename": "/usr/share/espeak-ng-data/en_dict"}, {"audio": 0, "start": 3357730, "crunched": 0, "end": 3438164, "filename": "/usr/share/espeak-ng-data/ka_dict"}, {"audio": 0, "start": 3438164, "crunched": 0, "end": 3444860, "filename": "/usr/share/espeak-ng-data/an_dict"}, {"audio": 0, "start": 3444860, "crunched": 0, "end": 3486252, "filename": "/usr/share/espeak-ng-data/et_dict"}, {"audio": 0, "start": 3486252, "crunched": 0, "end": 3489681, "filename": "/usr/share/espeak-ng-data/grc_dict"}, {"audio": 0, "start": 3489681, "crunched": 0, "end": 3492838, "filename": "/usr/share/espeak-ng-data/gn_dict"}, {"audio": 0, "start": 3492838, "crunched": 0, "end": 3556031, "filename": "/usr/share/espeak-ng-data/nl_dict"}, {"audio": 0, "start": 3556031, "crunched": 0, "end": 3629572, "filename": "/usr/share/espeak-ng-data/pl_dict"}, {"audio": 0, "start": 3629572, "crunched": 0, "end": 4105840, "filename": "/usr/share/espeak-ng-data/ar_dict"}, {"audio": 0, "start": 4105840, "crunched": 0, "end": 4151496, "filename": "/usr/share/espeak-ng-data/lt_dict"}, {"audio": 0, "start": 4151496, "crunched": 0, "end": 4682284, "filename": "/usr/share/espeak-ng-data/phondata"}, {"audio": 0, "start": 4682284, "crunched": 0, "end": 4684365, "filename": "/usr/share/espeak-ng-data/ia_dict"}, {"audio": 0, "start": 4684365, "crunched": 0, "end": 4760857, "filename": "/usr/share/espeak-ng-data/gu_dict"}, {"audio": 0, "start": 4760857, "crunched": 0, "end": 4767925, "filename": "/usr/share/espeak-ng-data/sd_dict"}, {"audio": 0, "start": 4767925, "crunched": 0, "end": 4769693, "filename": "/usr/share/espeak-ng-data/intonations"}, {"audio": 0, "start": 4769693, "crunched": 0, "end": 4851195, "filename": "/usr/share/espeak-ng-data/mr_dict"}, {"audio": 0, "start": 4851195, "crunched": 0, "end": 4934289, "filename": "/usr/share/espeak-ng-data/bn_dict"}, {"audio": 0, "start": 4934289, "crunched": 0, "end": 4979948, "filename": "/usr/share/espeak-ng-data/hr_dict"}, {"audio": 0, "start": 4979948, "crunched": 0, "end": 5066909, "filename": "/usr/share/espeak-ng-data/ne_dict"}, {"audio": 0, "start": 5066909, "crunched": 0, "end": 5070300, "filename": "/usr/share/espeak-ng-data/hak_dict"}, {"audio": 0, "start": 5070300, "crunched": 0, "end": 5072357, "filename": "/usr/share/espeak-ng-data/jbo_dict"}, {"audio": 0, "start": 5072357, "crunched": 0, "end": 5114276, "filename": "/usr/share/espeak-ng-data/ca_dict"}, {"audio": 0, "start": 5114276, "crunched": 0, "end": 5116921, "filename": "/usr/share/espeak-ng-data/kl_dict"}, {"audio": 0, "start": 5116921, "crunched": 0, "end": 5267297, "filename": "/usr/share/espeak-ng-data/hu_dict"}, {"audio": 0, "start": 5267297, "crunched": 0, "end": 5313515, "filename": "/usr/share/espeak-ng-data/cs_dict"}, {"audio": 0, "start": 5313515, "crunched": 0, "end": 5317332, "filename": "/usr/share/espeak-ng-data/la_dict"}, {"audio": 0, "start": 5317332, "crunched": 0, "end": 5362384, "filename": "/usr/share/espeak-ng-data/eu_dict"}, {"audio": 0, "start": 5362384, "crunched": 0, "end": 5363700, "filename": "/usr/share/espeak-ng-data/mi_dict"}, {"audio": 0, "start": 5363700, "crunched": 0, "end": 5403431, "filename": "/usr/share/espeak-ng-data/id_dict"}, {"audio": 0, "start": 5403431, "crunched": 0, "end": 5448632, "filename": "/usr/share/espeak-ng-data/es_dict"}, {"audio": 0, "start": 5448632, "crunched": 0, "end": 5451502, "filename": "/usr/share/espeak-ng-data/lfn_dict"}, {"audio": 0, "start": 5451502, "crunched": 0, "end": 5495757, "filename": "/usr/share/espeak-ng-data/sw_dict"}, {"audio": 0, "start": 5495757, "crunched": 0, "end": 5699028, "filename": "/usr/share/espeak-ng-data/ta_dict"}, {"audio": 0, "start": 5699028, "crunched": 0, "end": 5699068, "filename": "/usr/share/espeak-ng-data/lang/eu"}, {"audio": 0, "start": 5699068, "crunched": 0, "end": 5699119, "filename": "/usr/share/espeak-ng-data/lang/ko"}, {"audio": 0, "start": 5699119, "crunched": 0, "end": 5699327, "filename": "/usr/share/espeak-ng-data/lang/aav/vi-VN-x-central"}, {"audio": 0, "start": 5699327, "crunched": 0, "end": 5699388, "filename": "/usr/share/espeak-ng-data/lang/aav/vi"}, {"audio": 0, "start": 5699388, "crunched": 0, "end": 5699595, "filename": "/usr/share/espeak-ng-data/lang/aav/vi-VN-x-south"}, {"audio": 0, "start": 5699595, "crunched": 0, "end": 5699678, "filename": "/usr/share/espeak-ng-data/lang/art/jbo"}, {"audio": 0, "start": 5699678, "crunched": 0, "end": 5699813, "filename": "/usr/share/espeak-ng-data/lang/art/lfn"}, {"audio": 0, "start": 5699813, "crunched": 0, "end": 5699854, "filename": "/usr/share/espeak-ng-data/lang/art/eo"}, {"audio": 0, "start": 5699854, "crunched": 0, "end": 5699883, "filename": "/usr/share/espeak-ng-data/lang/art/ia"}, {"audio": 0, "start": 5699883, "crunched": 0, "end": 5699930, "filename": "/usr/share/espeak-ng-data/lang/sai/gn"}, {"audio": 0, "start": 5699930, "crunched": 0, "end": 5699985, "filename": "/usr/share/espeak-ng-data/lang/dra/kn"}, {"audio": 0, "start": 5699985, "crunched": 0, "end": 5700036, "filename": "/usr/share/espeak-ng-data/lang/dra/ta"}, {"audio": 0, "start": 5700036, "crunched": 0, "end": 5700106, "filename": "/usr/share/espeak-ng-data/lang/dra/te"}, {"audio": 0, "start": 5700106, "crunched": 0, "end": 5700163, "filename": "/usr/share/espeak-ng-data/lang/dra/ml"}, {"audio": 0, "start": 5700163, "crunched": 0, "end": 5700442, "filename": "/usr/share/espeak-ng-data/lang/zls/sr"}, {"audio": 0, "start": 5700442, "crunched": 0, "end": 5700571, "filename": "/usr/share/espeak-ng-data/lang/zls/bg"}, {"audio": 0, "start": 5700571, "crunched": 0, "end": 5700829, "filename": "/usr/share/espeak-ng-data/lang/zls/bs"}, {"audio": 0, "start": 5700829, "crunched": 0, "end": 5700872, "filename": "/usr/share/espeak-ng-data/lang/zls/sl"}, {"audio": 0, "start": 5700872, "crunched": 0, "end": 5700900, "filename": "/usr/share/espeak-ng-data/lang/zls/mk"}, {"audio": 0, "start": 5700900, "crunched": 0, "end": 5701190, "filename": "/usr/share/espeak-ng-data/lang/zls/hr"}, {"audio": 0, "start": 5701190, "crunched": 0, "end": 5701242, "filename": "/usr/share/espeak-ng-data/lang/jpx/ja"}, {"audio": 0, "start": 5701242, "crunched": 0, "end": 5701305, "filename": "/usr/share/espeak-ng-data/lang/roa/es"}, {"audio": 0, "start": 5701305, "crunched": 0, "end": 5701405, "filename": "/usr/share/espeak-ng-data/lang/roa/fr-CH"}, {"audio": 0, "start": 5701405, "crunched": 0, "end": 5701582, "filename": "/usr/share/espeak-ng-data/lang/roa/es-419"}, {"audio": 0, "start": 5701582, "crunched": 0, "end": 5701675, "filename": "/usr/share/espeak-ng-data/lang/roa/fr"}, {"audio": 0, "start": 5701675, "crunched": 0, "end": 5701737, "filename": "/usr/share/espeak-ng-data/lang/roa/pap"}, {"audio": 0, "start": 5701737, "crunched": 0, "end": 5701763, "filename": "/usr/share/espeak-ng-data/lang/roa/ro"}, {"audio": 0, "start": 5701763, "crunched": 0, "end": 5701886, "filename": "/usr/share/espeak-ng-data/lang/roa/it"}, {"audio": 0, "start": 5701886, "crunched": 0, "end": 5701995, "filename": "/usr/share/espeak-ng-data/lang/roa/pt"}, {"audio": 0, "start": 5701995, "crunched": 0, "end": 5702022, "filename": "/usr/share/espeak-ng-data/lang/roa/an"}, {"audio": 0, "start": 5702022, "crunched": 0, "end": 5702131, "filename": "/usr/share/espeak-ng-data/lang/roa/pt-BR"}, {"audio": 0, "start": 5702131, "crunched": 0, "end": 5702228, "filename": "/usr/share/espeak-ng-data/lang/roa/fr-BE"}, {"audio": 0, "start": 5702228, "crunched": 0, "end": 5702253, "filename": "/usr/share/espeak-ng-data/lang/roa/ca"}, {"audio": 0, "start": 5702253, "crunched": 0, "end": 5702367, "filename": "/usr/share/espeak-ng-data/lang/azc/nci"}, {"audio": 0, "start": 5702367, "crunched": 0, "end": 5702432, "filename": "/usr/share/espeak-ng-data/lang/cel/cy"}, {"audio": 0, "start": 5702432, "crunched": 0, "end": 5702483, "filename": "/usr/share/espeak-ng-data/lang/cel/gd"}, {"audio": 0, "start": 5702483, "crunched": 0, "end": 5702549, "filename": "/usr/share/espeak-ng-data/lang/cel/ga"}, {"audio": 0, "start": 5702549, "crunched": 0, "end": 5702818, "filename": "/usr/share/espeak-ng-data/lang/ira/fa-Latn"}, {"audio": 0, "start": 5702818, "crunched": 0, "end": 5702908, "filename": "/usr/share/espeak-ng-data/lang/ira/fa"}, {"audio": 0, "start": 5702908, "crunched": 0, "end": 5702948, "filename": "/usr/share/espeak-ng-data/lang/ira/ku"}, {"audio": 0, "start": 5702948, "crunched": 0, "end": 5702989, "filename": "/usr/share/espeak-ng-data/lang/bnt/sw"}, {"audio": 0, "start": 5702989, "crunched": 0, "end": 5703031, "filename": "/usr/share/espeak-ng-data/lang/bnt/tn"}, {"audio": 0, "start": 5703031, "crunched": 0, "end": 5703130, "filename": "/usr/share/espeak-ng-data/lang/grk/grc"}, {"audio": 0, "start": 5703130, "crunched": 0, "end": 5703153, "filename": "/usr/share/espeak-ng-data/lang/grk/el"}, {"audio": 0, "start": 5703153, "crunched": 0, "end": 5703833, "filename": "/usr/share/espeak-ng-data/lang/sit/cmn"}, {"audio": 0, "start": 5703833, "crunched": 0, "end": 5704042, "filename": "/usr/share/espeak-ng-data/lang/sit/yue"}, {"audio": 0, "start": 5704042, "crunched": 0, "end": 5704185, "filename": "/usr/share/espeak-ng-data/lang/sit/hak"}, {"audio": 0, "start": 5704185, "crunched": 0, "end": 5704241, "filename": "/usr/share/espeak-ng-data/lang/sit/my"}, {"audio": 0, "start": 5704241, "crunched": 0, "end": 5704282, "filename": "/usr/share/espeak-ng-data/lang/sem/am"}, {"audio": 0, "start": 5704282, "crunched": 0, "end": 5704629, "filename": "/usr/share/espeak-ng-data/lang/sem/ar"}, {"audio": 0, "start": 5704629, "crunched": 0, "end": 5704670, "filename": "/usr/share/espeak-ng-data/lang/sem/mt"}, {"audio": 0, "start": 5704670, "crunched": 0, "end": 5705035, "filename": "/usr/share/espeak-ng-data/lang/ine/hyw"}, {"audio": 0, "start": 5705035, "crunched": 0, "end": 5705096, "filename": "/usr/share/espeak-ng-data/lang/ine/hy"}, {"audio": 0, "start": 5705096, "crunched": 0, "end": 5705213, "filename": "/usr/share/espeak-ng-data/lang/ine/sq"}, {"audio": 0, "start": 5705213, "crunched": 0, "end": 5705265, "filename": "/usr/share/espeak-ng-data/lang/zlw/sk"}, {"audio": 0, "start": 5705265, "crunched": 0, "end": 5705316, "filename": "/usr/share/espeak-ng-data/lang/zlw/cs"}, {"audio": 0, "start": 5705316, "crunched": 0, "end": 5705368, "filename": "/usr/share/espeak-ng-data/lang/zlw/pl"}, {"audio": 0, "start": 5705368, "crunched": 0, "end": 5705394, "filename": "/usr/share/espeak-ng-data/lang/ccs/ka"}, {"audio": 0, "start": 5705394, "crunched": 0, "end": 5705433, "filename": "/usr/share/espeak-ng-data/lang/cus/om"}, {"audio": 0, "start": 5705433, "crunched": 0, "end": 5705472, "filename": "/usr/share/espeak-ng-data/lang/urj/fi"}, {"audio": 0, "start": 5705472, "crunched": 0, "end": 5705546, "filename": "/usr/share/espeak-ng-data/lang/urj/hu"}, {"audio": 0, "start": 5705546, "crunched": 0, "end": 5705573, "filename": "/usr/share/espeak-ng-data/lang/urj/et"}, {"audio": 0, "start": 5705573, "crunched": 0, "end": 5705639, "filename": "/usr/share/espeak-ng-data/lang/zle/ru"}, {"audio": 0, "start": 5705639, "crunched": 0, "end": 5706006, "filename": "/usr/share/espeak-ng-data/lang/poz/mi"}, {"audio": 0, "start": 5706006, "crunched": 0, "end": 5706451, "filename": "/usr/share/espeak-ng-data/lang/poz/ms"}, {"audio": 0, "start": 5706451, "crunched": 0, "end": 5706585, "filename": "/usr/share/espeak-ng-data/lang/poz/id"}, {"audio": 0, "start": 5706585, "crunched": 0, "end": 5706615, "filename": "/usr/share/espeak-ng-data/lang/esx/kl"}, {"audio": 0, "start": 5706615, "crunched": 0, "end": 5706643, "filename": "/usr/share/espeak-ng-data/lang/bat/lt"}, {"audio": 0, "start": 5706643, "crunched": 0, "end": 5706962, "filename": "/usr/share/espeak-ng-data/lang/bat/lv"}, {"audio": 0, "start": 5706962, "crunched": 0, "end": 5706987, "filename": "/usr/share/espeak-ng-data/lang/trk/tr"}, {"audio": 0, "start": 5706987, "crunched": 0, "end": 5707032, "filename": "/usr/share/espeak-ng-data/lang/trk/az"}, {"audio": 0, "start": 5707032, "crunched": 0, "end": 5707055, "filename": "/usr/share/espeak-ng-data/lang/trk/tt"}, {"audio": 0, "start": 5707055, "crunched": 0, "end": 5707098, "filename": "/usr/share/espeak-ng-data/lang/trk/ky"}, {"audio": 0, "start": 5707098, "crunched": 0, "end": 5707137, "filename": "/usr/share/espeak-ng-data/lang/inc/bpy"}, {"audio": 0, "start": 5707137, "crunched": 0, "end": 5707176, "filename": "/usr/share/espeak-ng-data/lang/inc/or"}, {"audio": 0, "start": 5707176, "crunched": 0, "end": 5707201, "filename": "/usr/share/espeak-ng-data/lang/inc/bn"}, {"audio": 0, "start": 5707201, "crunched": 0, "end": 5707243, "filename": "/usr/share/espeak-ng-data/lang/inc/as"}, {"audio": 0, "start": 5707243, "crunched": 0, "end": 5707266, "filename": "/usr/share/espeak-ng-data/lang/inc/hi"}, {"audio": 0, "start": 5707266, "crunched": 0, "end": 5707291, "filename": "/usr/share/espeak-ng-data/lang/inc/pa"}, {"audio": 0, "start": 5707291, "crunched": 0, "end": 5707346, "filename": "/usr/share/espeak-ng-data/lang/inc/si"}, {"audio": 0, "start": 5707346, "crunched": 0, "end": 5707372, "filename": "/usr/share/espeak-ng-data/lang/inc/kok"}, {"audio": 0, "start": 5707372, "crunched": 0, "end": 5707438, "filename": "/usr/share/espeak-ng-data/lang/inc/sd"}, {"audio": 0, "start": 5707438, "crunched": 0, "end": 5707475, "filename": "/usr/share/espeak-ng-data/lang/inc/ne"}, {"audio": 0, "start": 5707475, "crunched": 0, "end": 5707517, "filename": "/usr/share/espeak-ng-data/lang/inc/gu"}, {"audio": 0, "start": 5707517, "crunched": 0, "end": 5707558, "filename": "/usr/share/espeak-ng-data/lang/inc/mr"}, {"audio": 0, "start": 5707558, "crunched": 0, "end": 5707652, "filename": "/usr/share/espeak-ng-data/lang/inc/ur"}, {"audio": 0, "start": 5707652, "crunched": 0, "end": 5707709, "filename": "/usr/share/espeak-ng-data/lang/gmq/da"}, {"audio": 0, "start": 5707709, "crunched": 0, "end": 5707750, "filename": "/usr/share/espeak-ng-data/lang/gmq/is"}, {"audio": 0, "start": 5707750, "crunched": 0, "end": 5707789, "filename": "/usr/share/espeak-ng-data/lang/gmq/sv"}, {"audio": 0, "start": 5707789, "crunched": 0, "end": 5707890, "filename": "/usr/share/espeak-ng-data/lang/gmq/nb"}, {"audio": 0, "start": 5707890, "crunched": 0, "end": 5707927, "filename": "/usr/share/espeak-ng-data/lang/gmw/nl"}, {"audio": 0, "start": 5707927, "crunched": 0, "end": 5708115, "filename": "/usr/share/espeak-ng-data/lang/gmw/en-GB-x-gbcwmd"}, {"audio": 0, "start": 5708115, "crunched": 0, "end": 5708364, "filename": "/usr/share/espeak-ng-data/lang/gmw/en-GB-x-rp"}, {"audio": 0, "start": 5708364, "crunched": 0, "end": 5708504, "filename": "/usr/share/espeak-ng-data/lang/gmw/en"}, {"audio": 0, "start": 5708504, "crunched": 0, "end": 5708543, "filename": "/usr/share/espeak-ng-data/lang/gmw/de"}, {"audio": 0, "start": 5708543, "crunched": 0, "end": 5708818, "filename": "/usr/share/espeak-ng-data/lang/gmw/en-US"}, {"audio": 0, "start": 5708818, "crunched": 0, "end": 5709113, "filename": "/usr/share/espeak-ng-data/lang/gmw/en-GB-scotland"}, {"audio": 0, "start": 5709113, "crunched": 0, "end": 5709250, "filename": "/usr/share/espeak-ng-data/lang/gmw/af"}, {"audio": 0, "start": 5709250, "crunched": 0, "end": 5709488, "filename": "/usr/share/espeak-ng-data/lang/gmw/en-GB-x-gbclan"}, {"audio": 0, "start": 5709488, "crunched": 0, "end": 5709823, "filename": "/usr/share/espeak-ng-data/lang/gmw/en-029"}, {"audio": 0, "start": 5709823, "crunched": 0, "end": 5710109, "filename": "/usr/share/espeak-ng-data/lang/itc/la"}, {"audio": 0, "start": 5710109, "crunched": 0, "end": 5710373, "filename": "/usr/share/espeak-ng-data/voices/!v/m2"}, {"audio": 0, "start": 5710373, "crunched": 0, "end": 5710656, "filename": "/usr/share/espeak-ng-data/voices/!v/Gene2"}, {"audio": 0, "start": 5710656, "crunched": 0, "end": 5710971, "filename": "/usr/share/espeak-ng-data/voices/!v/Annie"}, {"audio": 0, "start": 5710971, "crunched": 0, "end": 5711196, "filename": "/usr/share/espeak-ng-data/voices/!v/max"}, {"audio": 0, "start": 5711196, "crunched": 0, "end": 5711561, "filename": "/usr/share/espeak-ng-data/voices/!v/Lee"}, {"audio": 0, "start": 5711561, "crunched": 0, "end": 5711948, "filename": "/usr/share/espeak-ng-data/voices/!v/aunty"}, {"audio": 0, "start": 5711948, "crunched": 0, "end": 5712298, "filename": "/usr/share/espeak-ng-data/voices/!v/f4"}, {"audio": 0, "start": 5712298, "crunched": 0, "end": 5712573, "filename": "/usr/share/espeak-ng-data/voices/!v/zac"}, {"audio": 0, "start": 5712573, "crunched": 0, "end": 5712908, "filename": "/usr/share/espeak-ng-data/voices/!v/m1"}, {"audio": 0, "start": 5712908, "crunched": 0, "end": 5713178, "filename": "/usr/share/espeak-ng-data/voices/!v/Michael"}, {"audio": 0, "start": 5713178, "crunched": 0, "end": 5713545, "filename": "/usr/share/espeak-ng-data/voices/!v/steph2"}, {"audio": 0, "start": 5713545, "crunched": 0, "end": 5713922, "filename": "/usr/share/espeak-ng-data/voices/!v/steph3"}, {"audio": 0, "start": 5713922, "crunched": 0, "end": 5714314, "filename": "/usr/share/espeak-ng-data/voices/!v/whisperf"}, {"audio": 0, "start": 5714314, "crunched": 0, "end": 5714675, "filename": "/usr/share/espeak-ng-data/voices/!v/kaukovalta"}, {"audio": 0, "start": 5714675, "crunched": 0, "end": 5714713, "filename": "/usr/share/espeak-ng-data/voices/!v/klatt2"}, {"audio": 0, "start": 5714713, "crunched": 0, "end": 5714996, "filename": "/usr/share/espeak-ng-data/voices/!v/m8"}, {"audio": 0, "start": 5714996, "crunched": 0, "end": 5715266, "filename": "/usr/share/espeak-ng-data/voices/!v/Mario"}, {"audio": 0, "start": 5715266, "crunched": 0, "end": 5715670, "filename": "/usr/share/espeak-ng-data/voices/!v/michel"}, {"audio": 0, "start": 5715670, "crunched": 0, "end": 5715960, "filename": "/usr/share/espeak-ng-data/voices/!v/m4"}, {"audio": 0, "start": 5715960, "crunched": 0, "end": 5716335, "filename": "/usr/share/espeak-ng-data/voices/!v/f3"}, {"audio": 0, "start": 5716335, "crunched": 0, "end": 5719529, "filename": "/usr/share/espeak-ng-data/voices/!v/Mr serious"}, {"audio": 0, "start": 5719529, "crunched": 0, "end": 5719853, "filename": "/usr/share/espeak-ng-data/voices/!v/f1"}, {"audio": 0, "start": 5719853, "crunched": 0, "end": 5720116, "filename": "/usr/share/espeak-ng-data/voices/!v/iven3"}, {"audio": 0, "start": 5720116, "crunched": 0, "end": 5720381, "filename": "/usr/share/espeak-ng-data/voices/!v/rob"}, {"audio": 0, "start": 5720381, "crunched": 0, "end": 5723571, "filename": "/usr/share/espeak-ng-data/voices/!v/norbert"}, {"audio": 0, "start": 5723571, "crunched": 0, "end": 5723757, "filename": "/usr/share/espeak-ng-data/voices/!v/whisper"}, {"audio": 0, "start": 5723757, "crunched": 0, "end": 5724037, "filename": "/usr/share/espeak-ng-data/voices/!v/iven2"}, {"audio": 0, "start": 5724037, "crunched": 0, "end": 5724420, "filename": "/usr/share/espeak-ng-data/voices/!v/travis"}, {"audio": 0, "start": 5724420, "crunched": 0, "end": 5724725, "filename": "/usr/share/espeak-ng-data/voices/!v/Denis"}, {"audio": 0, "start": 5724725, "crunched": 0, "end": 5724763, "filename": "/usr/share/espeak-ng-data/voices/!v/klatt"}, {"audio": 0, "start": 5724763, "crunched": 0, "end": 5725044, "filename": "/usr/share/espeak-ng-data/voices/!v/Gene"}, {"audio": 0, "start": 5725044, "crunched": 0, "end": 5725268, "filename": "/usr/share/espeak-ng-data/voices/!v/boris"}, {"audio": 0, "start": 5725268, "crunched": 0, "end": 5725535, "filename": "/usr/share/espeak-ng-data/voices/!v/Jacky"}, {"audio": 0, "start": 5725535, "crunched": 0, "end": 5725955, "filename": "/usr/share/espeak-ng-data/voices/!v/Storm"}, {"audio": 0, "start": 5725955, "crunched": 0, "end": 5726320, "filename": "/usr/share/espeak-ng-data/voices/!v/Andy"}, {"audio": 0, "start": 5726320, "crunched": 0, "end": 5726582, "filename": "/usr/share/espeak-ng-data/voices/!v/iven"}, {"audio": 0, "start": 5726582, "crunched": 0, "end": 5726844, "filename": "/usr/share/espeak-ng-data/voices/!v/m5"}, {"audio": 0, "start": 5726844, "crunched": 0, "end": 5727098, "filename": "/usr/share/espeak-ng-data/voices/!v/m7"}, {"audio": 0, "start": 5727098, "crunched": 0, "end": 5727286, "filename": "/usr/share/espeak-ng-data/voices/!v/m6"}, {"audio": 0, "start": 5727286, "crunched": 0, "end": 5730473, "filename": "/usr/share/espeak-ng-data/voices/!v/john"}, {"audio": 0, "start": 5730473, "crunched": 0, "end": 5730877, "filename": "/usr/share/espeak-ng-data/voices/!v/AnxiousAndy"}, {"audio": 0, "start": 5730877, "crunched": 0, "end": 5730916, "filename": "/usr/share/espeak-ng-data/voices/!v/klatt4"}, {"audio": 0, "start": 5730916, "crunched": 0, "end": 5731280, "filename": "/usr/share/espeak-ng-data/voices/!v/steph"}, {"audio": 0, "start": 5731280, "crunched": 0, "end": 5731668, "filename": "/usr/share/espeak-ng-data/voices/!v/linda"}, {"audio": 0, "start": 5731668, "crunched": 0, "end": 5732025, "filename": "/usr/share/espeak-ng-data/voices/!v/f2"}, {"audio": 0, "start": 5732025, "crunched": 0, "end": 5732118, "filename": "/usr/share/espeak-ng-data/voices/!v/croak"}, {"audio": 0, "start": 5732118, "crunched": 0, "end": 5732392, "filename": "/usr/share/espeak-ng-data/voices/!v/robert"}, {"audio": 0, "start": 5732392, "crunched": 0, "end": 5732431, "filename": "/usr/share/espeak-ng-data/voices/!v/klatt3"}, {"audio": 0, "start": 5732431, "crunched": 0, "end": 5732785, "filename": "/usr/share/espeak-ng-data/voices/!v/quincy"}, {"audio": 0, "start": 5732785, "crunched": 0, "end": 5733085, "filename": "/usr/share/espeak-ng-data/voices/!v/m3"}, {"audio": 0, "start": 5733085, "crunched": 0, "end": 5736275, "filename": "/usr/share/espeak-ng-data/voices/!v/Tweaky"}, {"audio": 0, "start": 5736275, "crunched": 0, "end": 5736700, "filename": "/usr/share/espeak-ng-data/voices/!v/f5"}, {"audio": 0, "start": 5736700, "crunched": 0, "end": 5736811, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-cr1"}, {"audio": 0, "start": 5736811, "crunched": 0, "end": 5736893, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-cz2"}, {"audio": 0, "start": 5736893, "crunched": 0, "end": 5736981, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ca1"}, {"audio": 0, "start": 5736981, "crunched": 0, "end": 5737076, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ee1"}, {"audio": 0, "start": 5737076, "crunched": 0, "end": 5737205, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de4"}, {"audio": 0, "start": 5737205, "crunched": 0, "end": 5737286, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ro1-en"}, {"audio": 0, "start": 5737286, "crunched": 0, "end": 5737391, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr4-en"}, {"audio": 0, "start": 5737391, "crunched": 0, "end": 5737561, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-us1"}, {"audio": 0, "start": 5737561, "crunched": 0, "end": 5737635, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de6-en"}, {"audio": 0, "start": 5737635, "crunched": 0, "end": 5737763, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de2"}, {"audio": 0, "start": 5737763, "crunched": 0, "end": 5737999, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de5"}, {"audio": 0, "start": 5737999, "crunched": 0, "end": 5738086, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-it2"}, {"audio": 0, "start": 5738086, "crunched": 0, "end": 5738183, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-es1"}, {"audio": 0, "start": 5738183, "crunched": 0, "end": 5738271, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-af1"}, {"audio": 0, "start": 5738271, "crunched": 0, "end": 5738358, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ro1"}, {"audio": 0, "start": 5738358, "crunched": 0, "end": 5738443, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-tr1"}, {"audio": 0, "start": 5738443, "crunched": 0, "end": 5738621, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-us2"}, {"audio": 0, "start": 5738621, "crunched": 0, "end": 5738704, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de6-grc"}, {"audio": 0, "start": 5738704, "crunched": 0, "end": 5738854, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de7"}, {"audio": 0, "start": 5738854, "crunched": 0, "end": 5738938, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ar2"}, {"audio": 0, "start": 5738938, "crunched": 0, "end": 5739118, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-us3"}, {"audio": 0, "start": 5739118, "crunched": 0, "end": 5739220, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-sw2"}, {"audio": 0, "start": 5739220, "crunched": 0, "end": 5739311, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-es2"}, {"audio": 0, "start": 5739311, "crunched": 0, "end": 5739398, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-lt2"}, {"audio": 0, "start": 5739398, "crunched": 0, "end": 5739499, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-id1"}, {"audio": 0, "start": 5739499, "crunched": 0, "end": 5739601, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-hu1"}, {"audio": 0, "start": 5739601, "crunched": 0, "end": 5739697, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-nl2"}, {"audio": 0, "start": 5739697, "crunched": 0, "end": 5739780, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr3"}, {"audio": 0, "start": 5739780, "crunched": 0, "end": 5739850, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-cz1"}, {"audio": 0, "start": 5739850, "crunched": 0, "end": 5739931, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de4-en"}, {"audio": 0, "start": 5739931, "crunched": 0, "end": 5740013, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-pl1-en"}, {"audio": 0, "start": 5740013, "crunched": 0, "end": 5740112, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-pl1"}, {"audio": 0, "start": 5740112, "crunched": 0, "end": 5740231, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-br2"}, {"audio": 0, "start": 5740231, "crunched": 0, "end": 5740322, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-nl2-en"}, {"audio": 0, "start": 5740322, "crunched": 0, "end": 5740420, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-sw1"}, {"audio": 0, "start": 5740420, "crunched": 0, "end": 5740564, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de1"}, {"audio": 0, "start": 5740564, "crunched": 0, "end": 5740647, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr7"}, {"audio": 0, "start": 5740647, "crunched": 0, "end": 5740743, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de1-en"}, {"audio": 0, "start": 5740743, "crunched": 0, "end": 5740853, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr4"}, {"audio": 0, "start": 5740853, "crunched": 0, "end": 5740952, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-sw2-en"}, {"audio": 0, "start": 5740952, "crunched": 0, "end": 5741040, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ca2"}, {"audio": 0, "start": 5741040, "crunched": 0, "end": 5741139, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de3"}, {"audio": 0, "start": 5741139, "crunched": 0, "end": 5741233, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-gr2"}, {"audio": 0, "start": 5741233, "crunched": 0, "end": 5741323, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de5-en"}, {"audio": 0, "start": 5741323, "crunched": 0, "end": 5741468, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-it4"}, {"audio": 0, "start": 5741468, "crunched": 0, "end": 5741583, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-br1"}, {"audio": 0, "start": 5741583, "crunched": 0, "end": 5741680, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-hu1-en"}, {"audio": 0, "start": 5741680, "crunched": 0, "end": 5741766, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ic1"}, {"audio": 0, "start": 5741766, "crunched": 0, "end": 5741880, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-tr2"}, {"audio": 0, "start": 5741880, "crunched": 0, "end": 5742024, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-vz1"}, {"audio": 0, "start": 5742024, "crunched": 0, "end": 5742173, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr1"}, {"audio": 0, "start": 5742173, "crunched": 0, "end": 5742260, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-lt1"}, {"audio": 0, "start": 5742260, "crunched": 0, "end": 5742380, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-mx1"}, {"audio": 0, "start": 5742380, "crunched": 0, "end": 5743133, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ir1"}, {"audio": 0, "start": 5743133, "crunched": 0, "end": 5743252, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-br4"}, {"audio": 0, "start": 5743252, "crunched": 0, "end": 5743336, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-it1"}, {"audio": 0, "start": 5743336, "crunched": 0, "end": 5743419, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr5"}, {"audio": 0, "start": 5743419, "crunched": 0, "end": 5743534, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-br3"}, {"audio": 0, "start": 5743534, "crunched": 0, "end": 5743654, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-mx2"}, {"audio": 0, "start": 5743654, "crunched": 0, "end": 5743737, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-af1-en"}, {"audio": 0, "start": 5743737, "crunched": 0, "end": 5743820, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-la1"}, {"audio": 0, "start": 5743820, "crunched": 0, "end": 5743934, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-pt1"}, {"audio": 0, "start": 5743934, "crunched": 0, "end": 5744022, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-gr2-en"}, {"audio": 0, "start": 5744022, "crunched": 0, "end": 5744105, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr6"}, {"audio": 0, "start": 5744105, "crunched": 0, "end": 5744227, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de6"}, {"audio": 0, "start": 5744227, "crunched": 0, "end": 5744311, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-ar1"}, {"audio": 0, "start": 5744311, "crunched": 0, "end": 5744404, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-sw1-en"}, {"audio": 0, "start": 5744404, "crunched": 0, "end": 5744517, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-en1"}, {"audio": 0, "start": 5744517, "crunched": 0, "end": 5744659, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-it3"}, {"audio": 0, "start": 5744659, "crunched": 0, "end": 5744745, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr2"}, {"audio": 0, "start": 5744745, "crunched": 0, "end": 5744841, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de3-en"}, {"audio": 0, "start": 5744841, "crunched": 0, "end": 5744933, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-cn1"}, {"audio": 0, "start": 5744933, "crunched": 0, "end": 5745035, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-fr1-en"}, {"audio": 0, "start": 5745035, "crunched": 0, "end": 5745115, "filename": "/usr/share/espeak-ng-data/voices/mb/mb-de2-en"}], "remote_package_size": 5745115, "package_uuid": "189117b1-7497-461c-a28c-a448c48a1955"});
+
+})();
+
+
+
+// Sometimes an existing Module object exists with properties
+// meant to overwrite the default module functionality. Here
+// we collect those properties and reapply _after_ we configure
+// the current environment's defaults to avoid having to be so
+// defensive during initialization.
+var moduleOverrides = {};
+var key;
+for (key in Module) {
+ if (Module.hasOwnProperty(key)) {
+ moduleOverrides[key] = Module[key];
+ }
+}
+
+Module['arguments'] = [];
+Module['thisProgram'] = './this.program';
+Module['quit'] = function(status, toThrow) {
+ throw toThrow;
+};
+Module['preRun'] = [];
+Module['postRun'] = [];
+
+// The environment setup code below is customized to use Module.
+// *** Environment setup code ***
+var ENVIRONMENT_IS_WEB = false;
+var ENVIRONMENT_IS_WORKER = false;
+var ENVIRONMENT_IS_NODE = false;
+var ENVIRONMENT_IS_SHELL = false;
+
+// Three configurations we can be running in:
+// 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false)
+// 2) We could be the application main() thread proxied to worker. (with Emscripten -s PROXY_TO_WORKER=1) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false)
+// 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true)
+
+if (Module['ENVIRONMENT']) {
+ if (Module['ENVIRONMENT'] === 'WEB') {
+ ENVIRONMENT_IS_WEB = true;
+ } else if (Module['ENVIRONMENT'] === 'WORKER') {
+ ENVIRONMENT_IS_WORKER = true;
+ } else if (Module['ENVIRONMENT'] === 'NODE') {
+ ENVIRONMENT_IS_NODE = true;
+ } else if (Module['ENVIRONMENT'] === 'SHELL') {
+ ENVIRONMENT_IS_SHELL = true;
+ } else {
+ throw new Error('Module[\'ENVIRONMENT\'] value is not valid. must be one of: WEB|WORKER|NODE|SHELL.');
+ }
+} else {
+ ENVIRONMENT_IS_WEB = typeof window === 'object';
+ ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
+ ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function' && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
+ ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+}
+
+
+if (ENVIRONMENT_IS_NODE) {
+ // Expose functionality in the same simple way that the shells work
+ // Note that we pollute the global namespace here, otherwise we break in node
+ var nodeFS;
+ var nodePath;
+
+ Module['read'] = function shell_read(filename, binary) {
+ var ret;
+ if (!nodeFS) nodeFS = require('fs');
+ if (!nodePath) nodePath = require('path');
+ filename = nodePath['normalize'](filename);
+ ret = nodeFS['readFileSync'](filename);
+ return binary ? ret : ret.toString();
+ };
+
+ Module['readBinary'] = function readBinary(filename) {
+ var ret = Module['read'](filename, true);
+ if (!ret.buffer) {
+ ret = new Uint8Array(ret);
+ }
+ assert(ret.buffer);
+ return ret;
+ };
+
+ if (process['argv'].length > 1) {
+ Module['thisProgram'] = process['argv'][1].replace(/\\/g, '/');
+ }
+
+ Module['arguments'] = process['argv'].slice(2);
+
+ if (typeof module !== 'undefined') {
+ module['exports'] = Module;
+ }
+
+ process['on']('uncaughtException', function(ex) {
+ // suppress ExitStatus exceptions from showing an error
+ if (!(ex instanceof ExitStatus)) {
+ throw ex;
+ }
+ });
+ // Currently node will swallow unhandled rejections, but this behavior is
+ // deprecated, and in the future it will exit with error status.
+ process['on']('unhandledRejection', function(reason, p) {
+ Module['printErr']('node.js exiting due to unhandled promise rejection');
+ process['exit'](1);
+ });
+
+ Module['inspect'] = function () { return '[Emscripten Module object]'; };
+}
+else if (ENVIRONMENT_IS_SHELL) {
+ if (typeof read != 'undefined') {
+ Module['read'] = function shell_read(f) {
+ return read(f);
+ };
+ }
+
+ Module['readBinary'] = function readBinary(f) {
+ var data;
+ if (typeof readbuffer === 'function') {
+ return new Uint8Array(readbuffer(f));
+ }
+ data = read(f, 'binary');
+ assert(typeof data === 'object');
+ return data;
+ };
+
+ if (typeof scriptArgs != 'undefined') {
+ Module['arguments'] = scriptArgs;
+ } else if (typeof arguments != 'undefined') {
+ Module['arguments'] = arguments;
+ }
+
+ if (typeof quit === 'function') {
+ Module['quit'] = function(status, toThrow) {
+ quit(status);
+ }
+ }
+}
+else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ Module['read'] = function shell_read(url) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.send(null);
+ return xhr.responseText;
+ };
+
+ if (ENVIRONMENT_IS_WORKER) {
+ Module['readBinary'] = function readBinary(url) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.responseType = 'arraybuffer';
+ xhr.send(null);
+ return new Uint8Array(xhr.response);
+ };
+ }
+
+ Module['readAsync'] = function readAsync(url, onload, onerror) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onload = function xhr_onload() {
+ if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
+ onload(xhr.response);
+ return;
+ }
+ onerror();
+ };
+ xhr.onerror = onerror;
+ xhr.send(null);
+ };
+
+ Module['setWindowTitle'] = function(title) { document.title = title };
+}
+else {
+ // Unreachable because SHELL is dependent on the others
+ throw new Error('unknown runtime environment');
+}
+
+// console.log is checked first, as 'print' on the web will open a print dialogue
+// printErr is preferable to console.warn (works better in shells)
+// bind(console) is necessary to fix IE/Edge closed dev tools panel behavior.
+Module['print'] = typeof console !== 'undefined' ? console.log.bind(console) : (typeof print !== 'undefined' ? print : null);
+Module['printErr'] = typeof printErr !== 'undefined' ? printErr : ((typeof console !== 'undefined' && console.warn.bind(console)) || Module['print']);
+
+// *** Environment setup code ***
+
+// Closure helpers
+Module.print = Module['print'];
+Module.printErr = Module['printErr'];
+
+// Merge back in the overrides
+for (key in moduleOverrides) {
+ if (moduleOverrides.hasOwnProperty(key)) {
+ Module[key] = moduleOverrides[key];
+ }
+}
+// Free the object hierarchy contained in the overrides, this lets the GC
+// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
+moduleOverrides = undefined;
+
+
+
+// {{PREAMBLE_ADDITIONS}}
+
+var STACK_ALIGN = 16;
+
+// stack management, and other functionality that is provided by the compiled code,
+// should not be used before it is ready
+stackSave = stackRestore = stackAlloc = setTempRet0 = getTempRet0 = function() {
+ abort('cannot use the stack before compiled code is ready to run, and has provided stack access');
+};
+
+function staticAlloc(size) {
+ assert(!staticSealed);
+ var ret = STATICTOP;
+ STATICTOP = (STATICTOP + size + 15) & -16;
+ return ret;
+}
+
+function dynamicAlloc(size) {
+ assert(DYNAMICTOP_PTR);
+ var ret = HEAP32[DYNAMICTOP_PTR>>2];
+ var end = (ret + size + 15) & -16;
+ HEAP32[DYNAMICTOP_PTR>>2] = end;
+ if (end >= TOTAL_MEMORY) {
+ var success = enlargeMemory();
+ if (!success) {
+ HEAP32[DYNAMICTOP_PTR>>2] = ret;
+ return 0;
+ }
+ }
+ return ret;
+}
+
+function alignMemory(size, factor) {
+ if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default
+ var ret = size = Math.ceil(size / factor) * factor;
+ return ret;
+}
+
+function getNativeTypeSize(type) {
+ switch (type) {
+ case 'i1': case 'i8': return 1;
+ case 'i16': return 2;
+ case 'i32': return 4;
+ case 'i64': return 8;
+ case 'float': return 4;
+ case 'double': return 8;
+ default: {
+ if (type[type.length-1] === '*') {
+ return 4; // A pointer
+ } else if (type[0] === 'i') {
+ var bits = parseInt(type.substr(1));
+ assert(bits % 8 === 0);
+ return bits / 8;
+ } else {
+ return 0;
+ }
+ }
+ }
+}
+
+function warnOnce(text) {
+ if (!warnOnce.shown) warnOnce.shown = {};
+ if (!warnOnce.shown[text]) {
+ warnOnce.shown[text] = 1;
+ Module.printErr(text);
+ }
+}
+
+
+
+var jsCallStartIndex = 1;
+var functionPointers = new Array(2);
+
+// 'sig' parameter is only used on LLVM wasm backend
+function addFunction(func, sig) {
+ if (typeof sig === 'undefined') {
+ Module.printErr('Warning: addFunction: Provide a wasm function signature ' +
+ 'string as a second argument');
+ }
+ var base = 0;
+ for (var i = base; i < base + 2; i++) {
+ if (!functionPointers[i]) {
+ functionPointers[i] = func;
+ return jsCallStartIndex + i;
+ }
+ }
+ throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.';
+}
+
+function removeFunction(index) {
+ functionPointers[index-jsCallStartIndex] = null;
+}
+
+var funcWrappers = {};
+
+function getFuncWrapper(func, sig) {
+ if (!func) return; // on null pointer, return undefined
+ assert(sig);
+ if (!funcWrappers[sig]) {
+ funcWrappers[sig] = {};
+ }
+ var sigCache = funcWrappers[sig];
+ if (!sigCache[func]) {
+ // optimize away arguments usage in common cases
+ if (sig.length === 1) {
+ sigCache[func] = function dynCall_wrapper() {
+ return dynCall(sig, func);
+ };
+ } else if (sig.length === 2) {
+ sigCache[func] = function dynCall_wrapper(arg) {
+ return dynCall(sig, func, [arg]);
+ };
+ } else {
+ // general case
+ sigCache[func] = function dynCall_wrapper() {
+ return dynCall(sig, func, Array.prototype.slice.call(arguments));
+ };
+ }
+ }
+ return sigCache[func];
+}
+
+
+function makeBigInt(low, high, unsigned) {
+ return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0));
+}
+
+function dynCall(sig, ptr, args) {
+ if (args && args.length) {
+ assert(args.length == sig.length-1);
+ assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
+ return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
+ } else {
+ assert(sig.length == 1);
+ assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
+ return Module['dynCall_' + sig].call(null, ptr);
+ }
+}
+
+
+function getCompilerSetting(name) {
+ throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for getCompilerSetting or emscripten_get_compiler_setting to work';
+}
+
+var Runtime = {
+ // FIXME backwards compatibility layer for ports. Support some Runtime.*
+ // for now, fix it there, then remove it from here. That way we
+ // can minimize any period of breakage.
+ dynCall: dynCall, // for SDL2 port
+ // helpful errors
+ getTempRet0: function() { abort('getTempRet0() is now a top-level function, after removing the Runtime object. Remove "Runtime."') },
+ staticAlloc: function() { abort('staticAlloc() is now a top-level function, after removing the Runtime object. Remove "Runtime."') },
+ stackAlloc: function() { abort('stackAlloc() is now a top-level function, after removing the Runtime object. Remove "Runtime."') },
+};
+
+// The address globals begin at. Very low in memory, for code size and optimization opportunities.
+// Above 0 is static memory, starting with globals.
+// Then the stack.
+// Then 'dynamic' memory for sbrk.
+var GLOBAL_BASE = 1024;
+
+
+
+// === Preamble library stuff ===
+
+// Documentation for the public APIs defined in this file must be updated in:
+// site/source/docs/api_reference/preamble.js.rst
+// A prebuilt local version of the documentation is available at:
+// site/build/text/docs/api_reference/preamble.js.txt
+// You can also build docs locally as HTML or other formats in site/
+// An online HTML version (which may be of a different version of Emscripten)
+// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
+
+
+
+//========================================
+// Runtime essentials
+//========================================
+
+var ABORT = 0; // whether we are quitting the application. no code should run after this. set in exit() and abort()
+var EXITSTATUS = 0;
+
+/** @type {function(*, string=)} */
+function assert(condition, text) {
+ if (!condition) {
+ abort('Assertion failed: ' + text);
+ }
+}
+
+var globalScope = this;
+
+// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
+function getCFunc(ident) {
+ var func = Module['_' + ident]; // closure exported function
+ assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
+ return func;
+}
+
+var JSfuncs = {
+ // Helpers for cwrap -- it can't refer to Runtime directly because it might
+ // be renamed by closure, instead it calls JSfuncs['stackSave'].body to find
+ // out what the minified function name is.
+ 'stackSave': function() {
+ stackSave()
+ },
+ 'stackRestore': function() {
+ stackRestore()
+ },
+ // type conversion from js to c
+ 'arrayToC' : function(arr) {
+ var ret = stackAlloc(arr.length);
+ writeArrayToMemory(arr, ret);
+ return ret;
+ },
+ 'stringToC' : function(str) {
+ var ret = 0;
+ if (str !== null && str !== undefined && str !== 0) { // null string
+ // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
+ var len = (str.length << 2) + 1;
+ ret = stackAlloc(len);
+ stringToUTF8(str, ret, len);
+ }
+ return ret;
+ }
+};
+
+// For fast lookup of conversion functions
+var toC = {
+ 'string': JSfuncs['stringToC'], 'array': JSfuncs['arrayToC']
+};
+
+// C calling interface.
+function ccall (ident, returnType, argTypes, args, opts) {
+ var func = getCFunc(ident);
+ var cArgs = [];
+ var stack = 0;
+ assert(returnType !== 'array', 'Return type should not be "array".');
+ if (args) {
+ for (var i = 0; i < args.length; i++) {
+ var converter = toC[argTypes[i]];
+ if (converter) {
+ if (stack === 0) stack = stackSave();
+ cArgs[i] = converter(args[i]);
+ } else {
+ cArgs[i] = args[i];
+ }
+ }
+ }
+ var ret = func.apply(null, cArgs);
+ if (returnType === 'string') ret = Pointer_stringify(ret);
+ else if (returnType === 'boolean') ret = Boolean(ret);
+ if (stack !== 0) {
+ stackRestore(stack);
+ }
+ return ret;
+}
+
+function cwrap (ident, returnType, argTypes) {
+ argTypes = argTypes || [];
+ var cfunc = getCFunc(ident);
+ // When the function takes numbers and returns a number, we can just return
+ // the original function
+ var numericArgs = argTypes.every(function(type){ return type === 'number'});
+ var numericRet = returnType !== 'string';
+ if (numericRet && numericArgs) {
+ return cfunc;
+ }
+ return function() {
+ return ccall(ident, returnType, argTypes, arguments);
+ }
+}
+
+/** @type {function(number, number, string, boolean=)} */
+function setValue(ptr, value, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': HEAP8[((ptr)>>0)]=value; break;
+ case 'i8': HEAP8[((ptr)>>0)]=value; break;
+ case 'i16': HEAP16[((ptr)>>1)]=value; break;
+ case 'i32': HEAP32[((ptr)>>2)]=value; break;
+ case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break;
+ case 'float': HEAPF32[((ptr)>>2)]=value; break;
+ case 'double': HEAPF64[((ptr)>>3)]=value; break;
+ default: abort('invalid type for setValue: ' + type);
+ }
+}
+
+/** @type {function(number, string, boolean=)} */
+function getValue(ptr, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': return HEAP8[((ptr)>>0)];
+ case 'i8': return HEAP8[((ptr)>>0)];
+ case 'i16': return HEAP16[((ptr)>>1)];
+ case 'i32': return HEAP32[((ptr)>>2)];
+ case 'i64': return HEAP32[((ptr)>>2)];
+ case 'float': return HEAPF32[((ptr)>>2)];
+ case 'double': return HEAPF64[((ptr)>>3)];
+ default: abort('invalid type for getValue: ' + type);
+ }
+ return null;
+}
+
+var ALLOC_NORMAL = 0; // Tries to use _malloc()
+var ALLOC_STACK = 1; // Lives for the duration of the current function call
+var ALLOC_STATIC = 2; // Cannot be freed
+var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk
+var ALLOC_NONE = 4; // Do not allocate
+
+// allocate(): This is for internal use. You can use it yourself as well, but the interface
+// is a little tricky (see docs right below). The reason is that it is optimized
+// for multiple syntaxes to save space in generated code. So you should
+// normally not use allocate(), and instead allocate memory using _malloc(),
+// initialize it with setValue(), and so forth.
+// @slab: An array of data, or a number. If a number, then the size of the block to allocate,
+// in *bytes* (note that this is sometimes confusing: the next parameter does not
+// affect this!)
+// @types: Either an array of types, one for each byte (or 0 if no type at that position),
+// or a single type which is used for the entire block. This only matters if there
+// is initial data - if @slab is a number, then this does not matter at all and is
+// ignored.
+// @allocator: How to allocate memory, see ALLOC_*
+/** @type {function((TypedArray|Array<number>|number), string, number, number=)} */
+function allocate(slab, types, allocator, ptr) {
+ var zeroinit, size;
+ if (typeof slab === 'number') {
+ zeroinit = true;
+ size = slab;
+ } else {
+ zeroinit = false;
+ size = slab.length;
+ }
+
+ var singleType = typeof types === 'string' ? types : null;
+
+ var ret;
+ if (allocator == ALLOC_NONE) {
+ ret = ptr;
+ } else {
+ ret = [typeof _malloc === 'function' ? _malloc : staticAlloc, stackAlloc, staticAlloc, dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
+ }
+
+ if (zeroinit) {
+ var stop;
+ ptr = ret;
+ assert((ret & 3) == 0);
+ stop = ret + (size & ~3);
+ for (; ptr < stop; ptr += 4) {
+ HEAP32[((ptr)>>2)]=0;
+ }
+ stop = ret + size;
+ while (ptr < stop) {
+ HEAP8[((ptr++)>>0)]=0;
+ }
+ return ret;
+ }
+
+ if (singleType === 'i8') {
+ if (slab.subarray || slab.slice) {
+ HEAPU8.set(/** @type {!Uint8Array} */ (slab), ret);
+ } else {
+ HEAPU8.set(new Uint8Array(slab), ret);
+ }
+ return ret;
+ }
+
+ var i = 0, type, typeSize, previousType;
+ while (i < size) {
+ var curr = slab[i];
+
+ type = singleType || types[i];
+ if (type === 0) {
+ i++;
+ continue;
+ }
+ assert(type, 'Must know what type to store in allocate!');
+
+ if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
+
+ setValue(ret+i, curr, type);
+
+ // no need to look up size unless type changes, so cache it
+ if (previousType !== type) {
+ typeSize = getNativeTypeSize(type);
+ previousType = type;
+ }
+ i += typeSize;
+ }
+
+ return ret;
+}
+
+// Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready
+function getMemory(size) {
+ if (!staticSealed) return staticAlloc(size);
+ if (!runtimeInitialized) return dynamicAlloc(size);
+ return _malloc(size);
+}
+
+/** @type {function(number, number=)} */
+function Pointer_stringify(ptr, length) {
+ if (length === 0 || !ptr) return '';
+ // TODO: use TextDecoder
+ // Find the length, and check for UTF while doing so
+ var hasUtf = 0;
+ var t;
+ var i = 0;
+ while (1) {
+ assert(ptr + i < TOTAL_MEMORY);
+ t = HEAPU8[(((ptr)+(i))>>0)];
+ hasUtf |= t;
+ if (t == 0 && !length) break;
+ i++;
+ if (length && i == length) break;
+ }
+ if (!length) length = i;
+
+ var ret = '';
+
+ if (hasUtf < 128) {
+ var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack
+ var curr;
+ while (length > 0) {
+ curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
+ ret = ret ? ret + curr : curr;
+ ptr += MAX_CHUNK;
+ length -= MAX_CHUNK;
+ }
+ return ret;
+ }
+ return UTF8ToString(ptr);
+}
+
+// Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+
+function AsciiToString(ptr) {
+ var str = '';
+ while (1) {
+ var ch = HEAP8[((ptr++)>>0)];
+ if (!ch) return str;
+ str += String.fromCharCode(ch);
+ }
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP.
+
+function stringToAscii(str, outPtr) {
+ return writeAsciiToMemory(str, outPtr, false);
+}
+
+// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
+// a copy of that string as a Javascript String object.
+
+var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined;
+function UTF8ArrayToString(u8Array, idx) {
+ var endPtr = idx;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
+ // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
+ while (u8Array[endPtr]) ++endPtr;
+
+ if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) {
+ return UTF8Decoder.decode(u8Array.subarray(idx, endPtr));
+ } else {
+ var u0, u1, u2, u3, u4, u5;
+
+ var str = '';
+ while (1) {
+ // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
+ u0 = u8Array[idx++];
+ if (!u0) return str;
+ if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
+ u1 = u8Array[idx++] & 63;
+ if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
+ u2 = u8Array[idx++] & 63;
+ if ((u0 & 0xF0) == 0xE0) {
+ u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
+ } else {
+ u3 = u8Array[idx++] & 63;
+ if ((u0 & 0xF8) == 0xF0) {
+ u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3;
+ } else {
+ u4 = u8Array[idx++] & 63;
+ if ((u0 & 0xFC) == 0xF8) {
+ u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4;
+ } else {
+ u5 = u8Array[idx++] & 63;
+ u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5;
+ }
+ }
+ }
+ if (u0 < 0x10000) {
+ str += String.fromCharCode(u0);
+ } else {
+ var ch = u0 - 0x10000;
+ str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
+ }
+ }
+ }
+}
+
+// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+
+function UTF8ToString(ptr) {
+ return UTF8ArrayToString(HEAPU8,ptr);
+}
+
+// Copies the given Javascript String object 'str' to the given byte array at address 'outIdx',
+// encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP.
+// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Parameters:
+// str: the Javascript string to copy.
+// outU8Array: the array to copy to. Each index in this array is assumed to be one 8-byte element.
+// outIdx: The starting offset in the array to begin the copying.
+// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
+// terminator, i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else.
+// maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
+ if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes.
+ return 0;
+
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
+ var u = str.charCodeAt(i); // possibly a lead surrogate
+ if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
+ if (u <= 0x7F) {
+ if (outIdx >= endIdx) break;
+ outU8Array[outIdx++] = u;
+ } else if (u <= 0x7FF) {
+ if (outIdx + 1 >= endIdx) break;
+ outU8Array[outIdx++] = 0xC0 | (u >> 6);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else if (u <= 0xFFFF) {
+ if (outIdx + 2 >= endIdx) break;
+ outU8Array[outIdx++] = 0xE0 | (u >> 12);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else if (u <= 0x1FFFFF) {
+ if (outIdx + 3 >= endIdx) break;
+ outU8Array[outIdx++] = 0xF0 | (u >> 18);
+ outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else if (u <= 0x3FFFFFF) {
+ if (outIdx + 4 >= endIdx) break;
+ outU8Array[outIdx++] = 0xF8 | (u >> 24);
+ outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else {
+ if (outIdx + 5 >= endIdx) break;
+ outU8Array[outIdx++] = 0xFC | (u >> 30);
+ outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ }
+ }
+ // Null-terminate the pointer to the buffer.
+ outU8Array[outIdx] = 0;
+ return outIdx - startIdx;
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP.
+// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF8(str, outPtr, maxBytesToWrite) {
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
+ return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
+}
+
+// Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
+
+function lengthBytesUTF8(str) {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var u = str.charCodeAt(i); // possibly a lead surrogate
+ if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
+ if (u <= 0x7F) {
+ ++len;
+ } else if (u <= 0x7FF) {
+ len += 2;
+ } else if (u <= 0xFFFF) {
+ len += 3;
+ } else if (u <= 0x1FFFFF) {
+ len += 4;
+ } else if (u <= 0x3FFFFFF) {
+ len += 5;
+ } else {
+ len += 6;
+ }
+ }
+ return len;
+}
+
+// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+
+var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined;
+function UTF16ToString(ptr) {
+ assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!');
+ var endPtr = ptr;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
+ // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
+ var idx = endPtr >> 1;
+ while (HEAP16[idx]) ++idx;
+ endPtr = idx << 1;
+
+ if (endPtr - ptr > 32 && UTF16Decoder) {
+ return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
+ } else {
+ var i = 0;
+
+ var str = '';
+ while (1) {
+ var codeUnit = HEAP16[(((ptr)+(i*2))>>1)];
+ if (codeUnit == 0) return str;
+ ++i;
+ // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
+ str += String.fromCharCode(codeUnit);
+ }
+ }
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP.
+// Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Parameters:
+// str: the Javascript string to copy.
+// outPtr: Byte address in Emscripten HEAP where to write the string to.
+// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
+// terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else.
+// maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF16(str, outPtr, maxBytesToWrite) {
+ assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!');
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ if (maxBytesToWrite === undefined) {
+ maxBytesToWrite = 0x7FFFFFFF;
+ }
+ if (maxBytesToWrite < 2) return 0;
+ maxBytesToWrite -= 2; // Null terminator.
+ var startPtr = outPtr;
+ var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length;
+ for (var i = 0; i < numCharsToWrite; ++i) {
+ // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
+ var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
+ HEAP16[((outPtr)>>1)]=codeUnit;
+ outPtr += 2;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP16[((outPtr)>>1)]=0;
+ return outPtr - startPtr;
+}
+
+// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
+
+function lengthBytesUTF16(str) {
+ return str.length*2;
+}
+
+function UTF32ToString(ptr) {
+ assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!');
+ var i = 0;
+
+ var str = '';
+ while (1) {
+ var utf32 = HEAP32[(((ptr)+(i*4))>>2)];
+ if (utf32 == 0)
+ return str;
+ ++i;
+ // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ if (utf32 >= 0x10000) {
+ var ch = utf32 - 0x10000;
+ str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
+ } else {
+ str += String.fromCharCode(utf32);
+ }
+ }
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP.
+// Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Parameters:
+// str: the Javascript string to copy.
+// outPtr: Byte address in Emscripten HEAP where to write the string to.
+// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
+// terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else.
+// maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF32(str, outPtr, maxBytesToWrite) {
+ assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!');
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ if (maxBytesToWrite === undefined) {
+ maxBytesToWrite = 0x7FFFFFFF;
+ }
+ if (maxBytesToWrite < 4) return 0;
+ var startPtr = outPtr;
+ var endPtr = startPtr + maxBytesToWrite - 4;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
+ if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
+ var trailSurrogate = str.charCodeAt(++i);
+ codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
+ }
+ HEAP32[((outPtr)>>2)]=codeUnit;
+ outPtr += 4;
+ if (outPtr + 4 > endPtr) break;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP32[((outPtr)>>2)]=0;
+ return outPtr - startPtr;
+}
+
+// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
+
+function lengthBytesUTF32(str) {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var codeUnit = str.charCodeAt(i);
+ if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
+ len += 4;
+ }
+
+ return len;
+}
+
+// Allocate heap space for a JS string, and write it there.
+// It is the responsibility of the caller to free() that memory.
+function allocateUTF8(str) {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = _malloc(size);
+ if (ret) stringToUTF8Array(str, HEAP8, ret, size);
+ return ret;
+}
+
+// Allocate stack space for a JS string, and write it there.
+function allocateUTF8OnStack(str) {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = stackAlloc(size);
+ stringToUTF8Array(str, HEAP8, ret, size);
+ return ret;
+}
+
+function demangle(func) {
+ warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling');
+ return func;
+}
+
+function demangleAll(text) {
+ var regex =
+ /__Z[\w\d_]+/g;
+ return text.replace(regex,
+ function(x) {
+ var y = demangle(x);
+ return x === y ? x : (x + ' [' + y + ']');
+ });
+}
+
+function jsStackTrace() {
+ var err = new Error();
+ if (!err.stack) {
+ // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown,
+ // so try that as a special-case.
+ try {
+ throw new Error(0);
+ } catch(e) {
+ err = e;
+ }
+ if (!err.stack) {
+ return '(no stack trace available)';
+ }
+ }
+ return err.stack.toString();
+}
+
+function stackTrace() {
+ var js = jsStackTrace();
+ if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
+ return demangleAll(js);
+}
+
+// Memory management
+
+var PAGE_SIZE = 16384;
+var WASM_PAGE_SIZE = 65536;
+var ASMJS_PAGE_SIZE = 16777216;
+var MIN_TOTAL_MEMORY = 16777216;
+
+function alignUp(x, multiple) {
+ if (x % multiple > 0) {
+ x += multiple - (x % multiple);
+ }
+ return x;
+}
+
+var HEAP,
+/** @type {ArrayBuffer} */
+ buffer,
+/** @type {Int8Array} */
+ HEAP8,
+/** @type {Uint8Array} */
+ HEAPU8,
+/** @type {Int16Array} */
+ HEAP16,
+/** @type {Uint16Array} */
+ HEAPU16,
+/** @type {Int32Array} */
+ HEAP32,
+/** @type {Uint32Array} */
+ HEAPU32,
+/** @type {Float32Array} */
+ HEAPF32,
+/** @type {Float64Array} */
+ HEAPF64;
+
+function updateGlobalBuffer(buf) {
+ Module['buffer'] = buffer = buf;
+}
+
+function updateGlobalBufferViews() {
+ Module['HEAP8'] = HEAP8 = new Int8Array(buffer);
+ Module['HEAP16'] = HEAP16 = new Int16Array(buffer);
+ Module['HEAP32'] = HEAP32 = new Int32Array(buffer);
+ Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer);
+ Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer);
+ Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer);
+ Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer);
+ Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer);
+}
+
+var STATIC_BASE, STATICTOP, staticSealed; // static area
+var STACK_BASE, STACKTOP, STACK_MAX; // stack area
+var DYNAMIC_BASE, DYNAMICTOP_PTR; // dynamic area handled by sbrk
+
+ STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0;
+ staticSealed = false;
+
+
+// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
+function writeStackCookie() {
+ assert((STACK_MAX & 3) == 0);
+ HEAPU32[(STACK_MAX >> 2)-1] = 0x02135467;
+ HEAPU32[(STACK_MAX >> 2)-2] = 0x89BACDFE;
+}
+
+function checkStackCookie() {
+ if (HEAPU32[(STACK_MAX >> 2)-1] != 0x02135467 || HEAPU32[(STACK_MAX >> 2)-2] != 0x89BACDFE) {
+ abort('Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x02135467, but received 0x' + HEAPU32[(STACK_MAX >> 2)-2].toString(16) + ' ' + HEAPU32[(STACK_MAX >> 2)-1].toString(16));
+ }
+ // Also test the global address 0 for integrity. This check is not compatible with SAFE_SPLIT_MEMORY though, since that mode already tests all address 0 accesses on its own.
+ if (HEAP32[0] !== 0x63736d65 /* 'emsc' */) throw 'Runtime error: The application has corrupted its heap memory area (address zero)!';
+}
+
+function abortStackOverflow(allocSize) {
+ abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (STACK_MAX - stackSave() + allocSize) + ' bytes available!');
+}
+
+function abortOnCannotGrowMemory() {
+ abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
+}
+
+
+function enlargeMemory() {
+ abortOnCannotGrowMemory();
+}
+
+
+var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880;
+var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216;
+if (TOTAL_MEMORY < TOTAL_STACK) Module.printErr('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')');
+
+// Initialize the runtime's memory
+// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
+assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined,
+ 'JS engine does not provide full typed array support');
+
+
+
+// Use a provided buffer, if there is one, or else allocate a new one
+if (Module['buffer']) {
+ buffer = Module['buffer'];
+ assert(buffer.byteLength === TOTAL_MEMORY, 'provided buffer should be ' + TOTAL_MEMORY + ' bytes, but it is ' + buffer.byteLength);
+} else {
+ // Use a WebAssembly memory where available
+ if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') {
+ assert(TOTAL_MEMORY % WASM_PAGE_SIZE === 0);
+ Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE });
+ buffer = Module['wasmMemory'].buffer;
+ } else
+ {
+ buffer = new ArrayBuffer(TOTAL_MEMORY);
+ }
+ assert(buffer.byteLength === TOTAL_MEMORY);
+ Module['buffer'] = buffer;
+}
+updateGlobalBufferViews();
+
+
+function getTotalMemory() {
+ return TOTAL_MEMORY;
+}
+
+// Endianness check (note: assumes compiler arch was little-endian)
+ HEAP32[0] = 0x63736d65; /* 'emsc' */
+HEAP16[1] = 0x6373;
+if (HEAPU8[2] !== 0x73 || HEAPU8[3] !== 0x63) throw 'Runtime error: expected the system to be little-endian!';
+
+function callRuntimeCallbacks(callbacks) {
+ while(callbacks.length > 0) {
+ var callback = callbacks.shift();
+ if (typeof callback == 'function') {
+ callback();
+ continue;
+ }
+ var func = callback.func;
+ if (typeof func === 'number') {
+ if (callback.arg === undefined) {
+ Module['dynCall_v'](func);
+ } else {
+ Module['dynCall_vi'](func, callback.arg);
+ }
+ } else {
+ func(callback.arg === undefined ? null : callback.arg);
+ }
+ }
+}
+
+var __ATPRERUN__ = []; // functions called before the runtime is initialized
+var __ATINIT__ = []; // functions called during startup
+var __ATMAIN__ = []; // functions called when main() is to be run
+var __ATEXIT__ = []; // functions called during shutdown
+var __ATPOSTRUN__ = []; // functions called after the runtime has exited
+
+var runtimeInitialized = false;
+var runtimeExited = false;
+
+
+function preRun() {
+ // compatibility - merge in anything from Module['preRun'] at this time
+ if (Module['preRun']) {
+ if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
+ while (Module['preRun'].length) {
+ addOnPreRun(Module['preRun'].shift());
+ }
+ }
+ callRuntimeCallbacks(__ATPRERUN__);
+}
+
+function ensureInitRuntime() {
+ checkStackCookie();
+ if (runtimeInitialized) return;
+ runtimeInitialized = true;
+ callRuntimeCallbacks(__ATINIT__);
+}
+
+function preMain() {
+ checkStackCookie();
+ callRuntimeCallbacks(__ATMAIN__);
+}
+
+function exitRuntime() {
+ checkStackCookie();
+ callRuntimeCallbacks(__ATEXIT__);
+ runtimeExited = true;
+}
+
+function postRun() {
+ checkStackCookie();
+ // compatibility - merge in anything from Module['postRun'] at this time
+ if (Module['postRun']) {
+ if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
+ while (Module['postRun'].length) {
+ addOnPostRun(Module['postRun'].shift());
+ }
+ }
+ callRuntimeCallbacks(__ATPOSTRUN__);
+}
+
+function addOnPreRun(cb) {
+ __ATPRERUN__.unshift(cb);
+}
+
+function addOnInit(cb) {
+ __ATINIT__.unshift(cb);
+}
+
+function addOnPreMain(cb) {
+ __ATMAIN__.unshift(cb);
+}
+
+function addOnExit(cb) {
+ __ATEXIT__.unshift(cb);
+}
+
+function addOnPostRun(cb) {
+ __ATPOSTRUN__.unshift(cb);
+}
+
+// Deprecated: This function should not be called because it is unsafe and does not provide
+// a maximum length limit of how many bytes it is allowed to write. Prefer calling the
+// function stringToUTF8Array() instead, which takes in a maximum length that can be used
+// to be secure from out of bounds writes.
+/** @deprecated */
+function writeStringToMemory(string, buffer, dontAddNull) {
+ warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
+
+ var /** @type {number} */ lastChar, /** @type {number} */ end;
+ if (dontAddNull) {
+ // stringToUTF8Array always appends null. If we don't want to do that, remember the
+ // character that existed at the location where the null will be placed, and restore
+ // that after the write (below).
+ end = buffer + lengthBytesUTF8(string);
+ lastChar = HEAP8[end];
+ }
+ stringToUTF8(string, buffer, Infinity);
+ if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character.
+}
+
+function writeArrayToMemory(array, buffer) {
+ assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)')
+ HEAP8.set(array, buffer);
+}
+
+function writeAsciiToMemory(str, buffer, dontAddNull) {
+ for (var i = 0; i < str.length; ++i) {
+ assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff);
+ HEAP8[((buffer++)>>0)]=str.charCodeAt(i);
+ }
+ // Null-terminate the pointer to the HEAP.
+ if (!dontAddNull) HEAP8[((buffer)>>0)]=0;
+}
+
+function unSign(value, bits, ignore) {
+ if (value >= 0) {
+ return value;
+ }
+ return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
+ : Math.pow(2, bits) + value;
+}
+function reSign(value, bits, ignore) {
+ if (value <= 0) {
+ return value;
+ }
+ var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
+ : Math.pow(2, bits-1);
+ if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that
+ // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
+ // TODO: In i64 mode 1, resign the two parts separately and safely
+ value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
+ }
+ return value;
+}
+
+assert(Math['imul'] && Math['fround'] && Math['clz32'] && Math['trunc'], 'this is a legacy browser, build with LEGACY_VM_SUPPORT');
+
+var Math_abs = Math.abs;
+var Math_cos = Math.cos;
+var Math_sin = Math.sin;
+var Math_tan = Math.tan;
+var Math_acos = Math.acos;
+var Math_asin = Math.asin;
+var Math_atan = Math.atan;
+var Math_atan2 = Math.atan2;
+var Math_exp = Math.exp;
+var Math_log = Math.log;
+var Math_sqrt = Math.sqrt;
+var Math_ceil = Math.ceil;
+var Math_floor = Math.floor;
+var Math_pow = Math.pow;
+var Math_imul = Math.imul;
+var Math_fround = Math.fround;
+var Math_round = Math.round;
+var Math_min = Math.min;
+var Math_max = Math.max;
+var Math_clz32 = Math.clz32;
+var Math_trunc = Math.trunc;
+
+// A counter of dependencies for calling run(). If we need to
+// do asynchronous work before running, increment this and
+// decrement it. Incrementing must happen in a place like
+// PRE_RUN_ADDITIONS (used by emcc to add file preloading).
+// Note that you can add dependencies in preRun, even though
+// it happens right before run - run will be postponed until
+// the dependencies are met.
+var runDependencies = 0;
+var runDependencyWatcher = null;
+var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
+var runDependencyTracking = {};
+
+function getUniqueRunDependency(id) {
+ var orig = id;
+ while (1) {
+ if (!runDependencyTracking[id]) return id;
+ id = orig + Math.random();
+ }
+ return id;
+}
+
+function addRunDependency(id) {
+ runDependencies++;
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+ if (id) {
+ assert(!runDependencyTracking[id]);
+ runDependencyTracking[id] = 1;
+ if (runDependencyWatcher === null && typeof setInterval !== 'undefined') {
+ // Check for missing dependencies every few seconds
+ runDependencyWatcher = setInterval(function() {
+ if (ABORT) {
+ clearInterval(runDependencyWatcher);
+ runDependencyWatcher = null;
+ return;
+ }
+ var shown = false;
+ for (var dep in runDependencyTracking) {
+ if (!shown) {
+ shown = true;
+ Module.printErr('still waiting on run dependencies:');
+ }
+ Module.printErr('dependency: ' + dep);
+ }
+ if (shown) {
+ Module.printErr('(end of list)');
+ }
+ }, 10000);
+ }
+ } else {
+ Module.printErr('warning: run dependency added without ID');
+ }
+}
+
+function removeRunDependency(id) {
+ runDependencies--;
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+ if (id) {
+ assert(runDependencyTracking[id]);
+ delete runDependencyTracking[id];
+ } else {
+ Module.printErr('warning: run dependency removed without ID');
+ }
+ if (runDependencies == 0) {
+ if (runDependencyWatcher !== null) {
+ clearInterval(runDependencyWatcher);
+ runDependencyWatcher = null;
+ }
+ if (dependenciesFulfilled) {
+ var callback = dependenciesFulfilled;
+ dependenciesFulfilled = null;
+ callback(); // can add another dependenciesFulfilled
+ }
+ }
+}
+
+Module["preloadedImages"] = {}; // maps url to image data
+Module["preloadedAudios"] = {}; // maps url to audio data
+
+
+
+var memoryInitializer = null;
+
+
+
+
+
+
+// Prefix of data URIs emitted by SINGLE_FILE and related options.
+var dataURIPrefix = 'data:application/octet-stream;base64,';
+
+// Indicates whether filename is a base64 data URI.
+function isDataURI(filename) {
+ return String.prototype.startsWith ?
+ filename.startsWith(dataURIPrefix) :
+ filename.indexOf(dataURIPrefix) === 0;
+}
+
+
+
+
+function integrateWasmJS() {
+ // wasm.js has several methods for creating the compiled code module here:
+ // * 'native-wasm' : use native WebAssembly support in the browser
+ // * 'interpret-s-expr': load s-expression code from a .wast and interpret
+ // * 'interpret-binary': load binary wasm and interpret
+ // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret
+ // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing)
+ // The method is set at compile time (BINARYEN_METHOD)
+ // The method can be a comma-separated list, in which case, we will try the
+ // options one by one. Some of them can fail gracefully, and then we can try
+ // the next.
+
+ // inputs
+
+ var method = 'native-wasm';
+
+ var wasmTextFile = 'espeakng.worker.wast';
+ var wasmBinaryFile = 'espeakng.worker.wasm';
+ var asmjsCodeFile = 'espeakng.worker.temp.asm.js';
+
+ if (typeof Module['locateFile'] === 'function') {
+ if (!isDataURI(wasmTextFile)) {
+ wasmTextFile = Module['locateFile'](wasmTextFile);
+ }
+ if (!isDataURI(wasmBinaryFile)) {
+ wasmBinaryFile = Module['locateFile'](wasmBinaryFile);
+ }
+ if (!isDataURI(asmjsCodeFile)) {
+ asmjsCodeFile = Module['locateFile'](asmjsCodeFile);
+ }
+ }
+
+ // utilities
+
+ var wasmPageSize = 64*1024;
+
+ var info = {
+ 'global': null,
+ 'env': null,
+ 'asm2wasm': { // special asm2wasm imports
+ "f64-rem": function(x, y) {
+ return x % y;
+ },
+ "debugger": function() {
+ debugger;
+ }
+ },
+ 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program.
+ };
+
+ var exports = null;
+
+
+ function mergeMemory(newBuffer) {
+ // The wasm instance creates its memory. But static init code might have written to
+ // buffer already, including the mem init file, and we must copy it over in a proper merge.
+ // TODO: avoid this copy, by avoiding such static init writes
+ // TODO: in shorter term, just copy up to the last static init write
+ var oldBuffer = Module['buffer'];
+ if (newBuffer.byteLength < oldBuffer.byteLength) {
+ Module['printErr']('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here');
+ }
+ var oldView = new Int8Array(oldBuffer);
+ var newView = new Int8Array(newBuffer);
+
+
+ newView.set(oldView);
+ updateGlobalBuffer(newBuffer);
+ updateGlobalBufferViews();
+ }
+
+ function fixImports(imports) {
+ return imports;
+ }
+
+ function getBinary() {
+ try {
+ if (Module['wasmBinary']) {
+ return new Uint8Array(Module['wasmBinary']);
+ }
+ if (Module['readBinary']) {
+ return Module['readBinary'](wasmBinaryFile);
+ } else {
+ throw "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)";
+ }
+ }
+ catch (err) {
+ abort(err);
+ }
+ }
+
+ function getBinaryPromise() {
+ // if we don't have the binary yet, and have the Fetch api, use that
+ // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web
+ if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') {
+ return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
+ if (!response['ok']) {
+ throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
+ }
+ return response['arrayBuffer']();
+ }).catch(function () {
+ return getBinary();
+ });
+ }
+ // Otherwise, getBinary should be able to get it synchronously
+ return new Promise(function(resolve, reject) {
+ resolve(getBinary());
+ });
+ }
+
+ // do-method functions
+
+
+ function doNativeWasm(global, env, providedBuffer) {
+ if (typeof WebAssembly !== 'object') {
+ Module['printErr']('no native wasm support detected');
+ return false;
+ }
+ // prepare memory import
+ if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) {
+ Module['printErr']('no native wasm Memory in use');
+ return false;
+ }
+ env['memory'] = Module['wasmMemory'];
+ // Load the wasm module and create an instance of using native support in the JS engine.
+ info['global'] = {
+ 'NaN': NaN,
+ 'Infinity': Infinity
+ };
+ info['global.Math'] = Math;
+ info['env'] = env;
+ // handle a generated wasm instance, receiving its exports and
+ // performing other necessary setup
+ function receiveInstance(instance, module) {
+ exports = instance.exports;
+ if (exports.memory) mergeMemory(exports.memory);
+ Module['asm'] = exports;
+ Module["usingWasm"] = true;
+ removeRunDependency('wasm-instantiate');
+ }
+ addRunDependency('wasm-instantiate');
+
+ // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
+ // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
+ // to any other async startup actions they are performing.
+ if (Module['instantiateWasm']) {
+ try {
+ return Module['instantiateWasm'](info, receiveInstance);
+ } catch(e) {
+ Module['printErr']('Module.instantiateWasm callback failed with error: ' + e);
+ return false;
+ }
+ }
+
+ // Async compilation can be confusing when an error on the page overwrites Module
+ // (for example, if the order of elements is wrong, and the one defining Module is
+ // later), so we save Module and check it later.
+ var trueModule = Module;
+ function receiveInstantiatedSource(output) {
+ // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance.
+ // receiveInstance() will swap in the exports (to Module.asm) so they can be called
+ assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
+ trueModule = null;
+ receiveInstance(output['instance'], output['module']);
+ }
+ function instantiateArrayBuffer(receiver) {
+ getBinaryPromise().then(function(binary) {
+ return WebAssembly.instantiate(binary, info);
+ }).then(receiver).catch(function(reason) {
+ Module['printErr']('failed to asynchronously prepare wasm: ' + reason);
+ abort(reason);
+ });
+ }
+ // Prefer streaming instantiation if available.
+ if (!Module['wasmBinary'] &&
+ typeof WebAssembly.instantiateStreaming === 'function' &&
+ !isDataURI(wasmBinaryFile) &&
+ typeof fetch === 'function') {
+ WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info)
+ .then(receiveInstantiatedSource)
+ .catch(function(reason) {
+ // We expect the most common failure cause to be a bad MIME type for the binary,
+ // in which case falling back to ArrayBuffer instantiation should work.
+ Module['printErr']('wasm streaming compile failed: ' + reason);
+ Module['printErr']('falling back to ArrayBuffer instantiation');
+ instantiateArrayBuffer(receiveInstantiatedSource);
+ });
+ } else {
+ instantiateArrayBuffer(receiveInstantiatedSource);
+ }
+ return {}; // no exports yet; we'll fill them in later
+ }
+
+
+ // We may have a preloaded value in Module.asm, save it
+ Module['asmPreload'] = Module['asm'];
+
+ // Memory growth integration code
+
+ var asmjsReallocBuffer = Module['reallocBuffer'];
+
+ var wasmReallocBuffer = function(size) {
+ var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB.
+ size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size
+ var old = Module['buffer'];
+ var oldSize = old.byteLength;
+ if (Module["usingWasm"]) {
+ // native wasm support
+ try {
+ var result = Module['wasmMemory'].grow((size - oldSize) / wasmPageSize); // .grow() takes a delta compared to the previous size
+ if (result !== (-1 | 0)) {
+ // success in native wasm memory growth, get the buffer from the memory
+ return Module['buffer'] = Module['wasmMemory'].buffer;
+ } else {
+ return null;
+ }
+ } catch(e) {
+ console.error('Module.reallocBuffer: Attempted to grow from ' + oldSize + ' bytes to ' + size + ' bytes, but got error: ' + e);
+ return null;
+ }
+ }
+ };
+
+ Module['reallocBuffer'] = function(size) {
+ if (finalMethod === 'asmjs') {
+ return asmjsReallocBuffer(size);
+ } else {
+ return wasmReallocBuffer(size);
+ }
+ };
+
+ // we may try more than one; this is the final one, that worked and we are using
+ var finalMethod = '';
+
+ // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate
+ // the wasm module at that time, and it receives imports and provides exports and so forth, the app
+ // doesn't need to care that it is wasm or olyfilled wasm or asm.js.
+
+ Module['asm'] = function(global, env, providedBuffer) {
+ env = fixImports(env);
+
+ // import table
+ if (!env['table']) {
+ var TABLE_SIZE = Module['wasmTableSize'];
+ if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least
+ var MAX_TABLE_SIZE = Module['wasmMaxTableSize'];
+ if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') {
+ if (MAX_TABLE_SIZE !== undefined) {
+ env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, 'maximum': MAX_TABLE_SIZE, 'element': 'anyfunc' });
+ } else {
+ env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, element: 'anyfunc' });
+ }
+ } else {
+ env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least
+ }
+ Module['wasmTable'] = env['table'];
+ }
+
+ if (!env['memoryBase']) {
+ env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves
+ }
+ if (!env['tableBase']) {
+ env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change
+ }
+
+ // try the methods. each should return the exports if it succeeded
+
+ var exports;
+ exports = doNativeWasm(global, env, providedBuffer);
+
+ if (!exports) abort('no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods');
+
+
+ return exports;
+ };
+
+ var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later
+}
+
+integrateWasmJS();
+
+// === Body ===
+
+var ASM_CONSTS = [];
+
+
+
+
+
+STATIC_BASE = GLOBAL_BASE;
+
+STATICTOP = STATIC_BASE + 214656;
+/* global initializers */ __ATINIT__.push();
+
+
+
+
+
+
+
+var STATIC_BUMP = 214656;
+Module["STATIC_BASE"] = STATIC_BASE;
+Module["STATIC_BUMP"] = STATIC_BUMP;
+
+/* no memory initializer */
+var tempDoublePtr = STATICTOP; STATICTOP += 16;
+
+assert(tempDoublePtr % 8 == 0);
+
+function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much
+
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+
+ HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
+
+ HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
+
+ HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
+
+}
+
+function copyTempDouble(ptr) {
+
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+
+ HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
+
+ HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
+
+ HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
+
+ HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];
+
+ HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];
+
+ HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];
+
+ HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];
+
+}
+
+// {{PRE_LIBRARY}}
+
+
+
+
+ function _emscripten_get_now() { abort() }
+
+ function _emscripten_get_now_is_monotonic() {
+ // return whether emscripten_get_now is guaranteed monotonic; the Date.now
+ // implementation is not :(
+ return ENVIRONMENT_IS_NODE || (typeof dateNow !== 'undefined') ||
+ ((ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && self['performance'] && self['performance']['now']);
+ }
+
+ var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};
+
+ function ___setErrNo(value) {
+ if (Module['___errno_location']) HEAP32[((Module['___errno_location']())>>2)]=value;
+ else Module.printErr('failed to set errno from JS');
+ return value;
+ }function _clock_gettime(clk_id, tp) {
+ // int clock_gettime(clockid_t clk_id, struct timespec *tp);
+ var now;
+ if (clk_id === 0) {
+ now = Date.now();
+ } else if (clk_id === 1 && _emscripten_get_now_is_monotonic()) {
+ now = _emscripten_get_now();
+ } else {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ }
+ HEAP32[((tp)>>2)]=(now/1000)|0; // seconds
+ HEAP32[(((tp)+(4))>>2)]=((now % 1000)*1000*1000)|0; // nanoseconds
+ return 0;
+ }function ___clock_gettime() {
+ return _clock_gettime.apply(null, arguments)
+ }
+
+
+ function __ZSt18uncaught_exceptionv() { // std::uncaught_exception()
+ return !!__ZSt18uncaught_exceptionv.uncaught_exception;
+ }
+
+
+
+ var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:function (adjusted) {
+ if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted;
+ for (var ptr in EXCEPTIONS.infos) {
+ var info = EXCEPTIONS.infos[ptr];
+ if (info.adjusted === adjusted) {
+ return ptr;
+ }
+ }
+ return adjusted;
+ },addRef:function (ptr) {
+ if (!ptr) return;
+ var info = EXCEPTIONS.infos[ptr];
+ info.refcount++;
+ },decRef:function (ptr) {
+ if (!ptr) return;
+ var info = EXCEPTIONS.infos[ptr];
+ assert(info.refcount > 0);
+ info.refcount--;
+ // A rethrown exception can reach refcount 0; it must not be discarded
+ // Its next handler will clear the rethrown flag and addRef it, prior to
+ // final decRef and destruction here
+ if (info.refcount === 0 && !info.rethrown) {
+ if (info.destructor) {
+ Module['dynCall_vi'](info.destructor, ptr);
+ }
+ delete EXCEPTIONS.infos[ptr];
+ ___cxa_free_exception(ptr);
+ }
+ },clearRef:function (ptr) {
+ if (!ptr) return;
+ var info = EXCEPTIONS.infos[ptr];
+ info.refcount = 0;
+ }};
+ function ___resumeException(ptr) {
+ if (!EXCEPTIONS.last) { EXCEPTIONS.last = ptr; }
+ throw ptr + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
+ }function ___cxa_find_matching_catch() {
+ var thrown = EXCEPTIONS.last;
+ if (!thrown) {
+ // just pass through the null ptr
+ return ((setTempRet0(0),0)|0);
+ }
+ var info = EXCEPTIONS.infos[thrown];
+ var throwntype = info.type;
+ if (!throwntype) {
+ // just pass through the thrown ptr
+ return ((setTempRet0(0),thrown)|0);
+ }
+ var typeArray = Array.prototype.slice.call(arguments);
+
+ var pointer = Module['___cxa_is_pointer_type'](throwntype);
+ // can_catch receives a **, add indirection
+ if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4);
+ HEAP32[((___cxa_find_matching_catch.buffer)>>2)]=thrown;
+ thrown = ___cxa_find_matching_catch.buffer;
+ // The different catch blocks are denoted by different types.
+ // Due to inheritance, those types may not precisely match the
+ // type of the thrown object. Find one which matches, and
+ // return the type of the catch block which should be called.
+ for (var i = 0; i < typeArray.length; i++) {
+ if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) {
+ thrown = HEAP32[((thrown)>>2)]; // undo indirection
+ info.adjusted = thrown;
+ return ((setTempRet0(typeArray[i]),thrown)|0);
+ }
+ }
+ // Shouldn't happen unless we have bogus data in typeArray
+ // or encounter a type for which emscripten doesn't have suitable
+ // typeinfo defined. Best-efforts match just in case.
+ thrown = HEAP32[((thrown)>>2)]; // undo indirection
+ return ((setTempRet0(throwntype),thrown)|0);
+ }function ___gxx_personality_v0() {
+ }
+
+ function ___lock() {}
+
+ function ___map_file(pathname, size) {
+ ___setErrNo(ERRNO_CODES.EPERM);
+ return -1;
+ }
+
+
+
+
+ var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"};
+
+ var PATH={splitPath:function (filename) {
+ var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+ return splitPathRe.exec(filename).slice(1);
+ },normalizeArray:function (parts, allowAboveRoot) {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === '.') {
+ parts.splice(i, 1);
+ } else if (last === '..') {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (; up; up--) {
+ parts.unshift('..');
+ }
+ }
+ return parts;
+ },normalize:function (path) {
+ var isAbsolute = path.charAt(0) === '/',
+ trailingSlash = path.substr(-1) === '/';
+ // Normalize the path
+ path = PATH.normalizeArray(path.split('/').filter(function(p) {
+ return !!p;
+ }), !isAbsolute).join('/');
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+ return (isAbsolute ? '/' : '') + path;
+ },dirname:function (path) {
+ var result = PATH.splitPath(path),
+ root = result[0],
+ dir = result[1];
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return '.';
+ }
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.substr(0, dir.length - 1);
+ }
+ return root + dir;
+ },basename:function (path) {
+ // EMSCRIPTEN return '/'' for '/', not an empty string
+ if (path === '/') return '/';
+ var lastSlash = path.lastIndexOf('/');
+ if (lastSlash === -1) return path;
+ return path.substr(lastSlash+1);
+ },extname:function (path) {
+ return PATH.splitPath(path)[3];
+ },join:function () {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return PATH.normalize(paths.join('/'));
+ },join2:function (l, r) {
+ return PATH.normalize(l + '/' + r);
+ },resolve:function () {
+ var resolvedPath = '',
+ resolvedAbsolute = false;
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? arguments[i] : FS.cwd();
+ // Skip empty and invalid entries
+ if (typeof path !== 'string') {
+ throw new TypeError('Arguments to path.resolve must be strings');
+ } else if (!path) {
+ return ''; // an invalid portion invalidates the whole thing
+ }
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charAt(0) === '/';
+ }
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+ resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) {
+ return !!p;
+ }), !resolvedAbsolute).join('/');
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+ },relative:function (from, to) {
+ from = PATH.resolve(from).substr(1);
+ to = PATH.resolve(to).substr(1);
+ function trim(arr) {
+ var start = 0;
+ for (; start < arr.length; start++) {
+ if (arr[start] !== '') break;
+ }
+ var end = arr.length - 1;
+ for (; end >= 0; end--) {
+ if (arr[end] !== '') break;
+ }
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+ var fromParts = trim(from.split('/'));
+ var toParts = trim(to.split('/'));
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push('..');
+ }
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+ return outputParts.join('/');
+ }};
+
+ var TTY={ttys:[],init:function () {
+ // https://github.com/kripken/emscripten/pull/1555
+ // if (ENVIRONMENT_IS_NODE) {
+ // // currently, FS.init does not distinguish if process.stdin is a file or TTY
+ // // device, it always assumes it's a TTY device. because of this, we're forcing
+ // // process.stdin to UTF8 encoding to at least make stdin reading compatible
+ // // with text files until FS.init can be refactored.
+ // process['stdin']['setEncoding']('utf8');
+ // }
+ },shutdown:function () {
+ // https://github.com/kripken/emscripten/pull/1555
+ // if (ENVIRONMENT_IS_NODE) {
+ // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
+ // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation
+ // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
+ // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
+ // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
+ // process['stdin']['pause']();
+ // }
+ },register:function (dev, ops) {
+ TTY.ttys[dev] = { input: [], output: [], ops: ops };
+ FS.registerDevice(dev, TTY.stream_ops);
+ },stream_ops:{open:function (stream) {
+ var tty = TTY.ttys[stream.node.rdev];
+ if (!tty) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
+ }
+ stream.tty = tty;
+ stream.seekable = false;
+ },close:function (stream) {
+ // flush any pending line data
+ stream.tty.ops.flush(stream.tty);
+ },flush:function (stream) {
+ stream.tty.ops.flush(stream.tty);
+ },read:function (stream, buffer, offset, length, pos /* ignored */) {
+ if (!stream.tty || !stream.tty.ops.get_char) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENXIO);
+ }
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = stream.tty.ops.get_char(stream.tty);
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset+i] = result;
+ }
+ if (bytesRead) {
+ stream.node.timestamp = Date.now();
+ }
+ return bytesRead;
+ },write:function (stream, buffer, offset, length, pos) {
+ if (!stream.tty || !stream.tty.ops.put_char) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENXIO);
+ }
+ for (var i = 0; i < length; i++) {
+ try {
+ stream.tty.ops.put_char(stream.tty, buffer[offset+i]);
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ }
+ if (length) {
+ stream.node.timestamp = Date.now();
+ }
+ return i;
+ }},default_tty_ops:{get_char:function (tty) {
+ if (!tty.input.length) {
+ var result = null;
+ if (ENVIRONMENT_IS_NODE) {
+ // we will read data by chunks of BUFSIZE
+ var BUFSIZE = 256;
+ var buf = new Buffer(BUFSIZE);
+ var bytesRead = 0;
+
+ var isPosixPlatform = (process.platform != 'win32'); // Node doesn't offer a direct check, so test by exclusion
+
+ var fd = process.stdin.fd;
+ if (isPosixPlatform) {
+ // Linux and Mac cannot use process.stdin.fd (which isn't set up as sync)
+ var usingDevice = false;
+ try {
+ fd = fs.openSync('/dev/stdin', 'r');
+ usingDevice = true;
+ } catch (e) {}
+ }
+
+ try {
+ bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, null);
+ } catch(e) {
+ // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes,
+ // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0.
+ if (e.toString().indexOf('EOF') != -1) bytesRead = 0;
+ else throw e;
+ }
+
+ if (usingDevice) { fs.closeSync(fd); }
+ if (bytesRead > 0) {
+ result = buf.slice(0, bytesRead).toString('utf-8');
+ } else {
+ result = null;
+ }
+
+ } else if (typeof window != 'undefined' &&
+ typeof window.prompt == 'function') {
+ // Browser.
+ result = window.prompt('Input: '); // returns null on cancel
+ if (result !== null) {
+ result += '\n';
+ }
+ } else if (typeof readline == 'function') {
+ // Command line.
+ result = readline();
+ if (result !== null) {
+ result += '\n';
+ }
+ }
+ if (!result) {
+ return null;
+ }
+ tty.input = intArrayFromString(result, true);
+ }
+ return tty.input.shift();
+ },put_char:function (tty, val) {
+ if (val === null || val === 10) {
+ Module['print'](UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle.
+ }
+ },flush:function (tty) {
+ if (tty.output && tty.output.length > 0) {
+ Module['print'](UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ }},default_tty1_ops:{put_char:function (tty, val) {
+ if (val === null || val === 10) {
+ Module['printErr'](UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val);
+ }
+ },flush:function (tty) {
+ if (tty.output && tty.output.length > 0) {
+ Module['printErr'](UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ }}};
+
+ var MEMFS={ops_table:null,mount:function (mount) {
+ return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },createNode:function (parent, name, mode, dev) {
+ if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
+ // no supported
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ if (!MEMFS.ops_table) {
+ MEMFS.ops_table = {
+ dir: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ lookup: MEMFS.node_ops.lookup,
+ mknod: MEMFS.node_ops.mknod,
+ rename: MEMFS.node_ops.rename,
+ unlink: MEMFS.node_ops.unlink,
+ rmdir: MEMFS.node_ops.rmdir,
+ readdir: MEMFS.node_ops.readdir,
+ symlink: MEMFS.node_ops.symlink
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek
+ }
+ },
+ file: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek,
+ read: MEMFS.stream_ops.read,
+ write: MEMFS.stream_ops.write,
+ allocate: MEMFS.stream_ops.allocate,
+ mmap: MEMFS.stream_ops.mmap,
+ msync: MEMFS.stream_ops.msync
+ }
+ },
+ link: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ readlink: MEMFS.node_ops.readlink
+ },
+ stream: {}
+ },
+ chrdev: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: FS.chrdev_stream_ops
+ }
+ };
+ }
+ var node = FS.createNode(parent, name, mode, dev);
+ if (FS.isDir(node.mode)) {
+ node.node_ops = MEMFS.ops_table.dir.node;
+ node.stream_ops = MEMFS.ops_table.dir.stream;
+ node.contents = {};
+ } else if (FS.isFile(node.mode)) {
+ node.node_ops = MEMFS.ops_table.file.node;
+ node.stream_ops = MEMFS.ops_table.file.stream;
+ node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
+ // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
+ // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
+ // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
+ node.contents = null;
+ } else if (FS.isLink(node.mode)) {
+ node.node_ops = MEMFS.ops_table.link.node;
+ node.stream_ops = MEMFS.ops_table.link.stream;
+ } else if (FS.isChrdev(node.mode)) {
+ node.node_ops = MEMFS.ops_table.chrdev.node;
+ node.stream_ops = MEMFS.ops_table.chrdev.stream;
+ }
+ node.timestamp = Date.now();
+ // add the new node to the parent
+ if (parent) {
+ parent.contents[name] = node;
+ }
+ return node;
+ },getFileDataAsRegularArray:function (node) {
+ if (node.contents && node.contents.subarray) {
+ var arr = [];
+ for (var i = 0; i < node.usedBytes; ++i) arr.push(node.contents[i]);
+ return arr; // Returns a copy of the original data.
+ }
+ return node.contents; // No-op, the file contents are already in a JS array. Return as-is.
+ },getFileDataAsTypedArray:function (node) {
+ if (!node.contents) return new Uint8Array;
+ if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
+ return new Uint8Array(node.contents);
+ },expandFileStorage:function (node, newCapacity) {
+ // If we are asked to expand the size of a file that already exists, revert to using a standard JS array to store the file
+ // instead of a typed array. This makes resizing the array more flexible because we can just .push() elements at the back to
+ // increase the size.
+ if (node.contents && node.contents.subarray && newCapacity > node.contents.length) {
+ node.contents = MEMFS.getFileDataAsRegularArray(node);
+ node.usedBytes = node.contents.length; // We might be writing to a lazy-loaded file which had overridden this property, so force-reset it.
+ }
+
+ if (!node.contents || node.contents.subarray) { // Keep using a typed array if creating a new storage, or if old one was a typed array as well.
+ var prevCapacity = node.contents ? node.contents.length : 0;
+ if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
+ // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
+ // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
+ // avoid overshooting the allocation cap by a very large margin.
+ var CAPACITY_DOUBLING_MAX = 1024 * 1024;
+ newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) | 0);
+ if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(newCapacity); // Allocate new storage.
+ if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
+ return;
+ }
+ // Not using a typed array to back the file storage. Use a standard JS array instead.
+ if (!node.contents && newCapacity > 0) node.contents = [];
+ while (node.contents.length < newCapacity) node.contents.push(0);
+ },resizeFileStorage:function (node, newSize) {
+ if (node.usedBytes == newSize) return;
+ if (newSize == 0) {
+ node.contents = null; // Fully decommit when requesting a resize to zero.
+ node.usedBytes = 0;
+ return;
+ }
+ if (!node.contents || node.contents.subarray) { // Resize a typed array if that is being used as the backing store.
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(new ArrayBuffer(newSize)); // Allocate new storage.
+ if (oldContents) {
+ node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
+ }
+ node.usedBytes = newSize;
+ return;
+ }
+ // Backing with a JS array.
+ if (!node.contents) node.contents = [];
+ if (node.contents.length > newSize) node.contents.length = newSize;
+ else while (node.contents.length < newSize) node.contents.push(0);
+ node.usedBytes = newSize;
+ },node_ops:{getattr:function (node) {
+ var attr = {};
+ // device numbers reuse inode numbers.
+ attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
+ attr.ino = node.id;
+ attr.mode = node.mode;
+ attr.nlink = 1;
+ attr.uid = 0;
+ attr.gid = 0;
+ attr.rdev = node.rdev;
+ if (FS.isDir(node.mode)) {
+ attr.size = 4096;
+ } else if (FS.isFile(node.mode)) {
+ attr.size = node.usedBytes;
+ } else if (FS.isLink(node.mode)) {
+ attr.size = node.link.length;
+ } else {
+ attr.size = 0;
+ }
+ attr.atime = new Date(node.timestamp);
+ attr.mtime = new Date(node.timestamp);
+ attr.ctime = new Date(node.timestamp);
+ // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
+ // but this is not required by the standard.
+ attr.blksize = 4096;
+ attr.blocks = Math.ceil(attr.size / attr.blksize);
+ return attr;
+ },setattr:function (node, attr) {
+ if (attr.mode !== undefined) {
+ node.mode = attr.mode;
+ }
+ if (attr.timestamp !== undefined) {
+ node.timestamp = attr.timestamp;
+ }
+ if (attr.size !== undefined) {
+ MEMFS.resizeFileStorage(node, attr.size);
+ }
+ },lookup:function (parent, name) {
+ throw FS.genericErrors[ERRNO_CODES.ENOENT];
+ },mknod:function (parent, name, mode, dev) {
+ return MEMFS.createNode(parent, name, mode, dev);
+ },rename:function (old_node, new_dir, new_name) {
+ // if we're overwriting a directory at new_name, make sure it's empty.
+ if (FS.isDir(old_node.mode)) {
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {
+ }
+ if (new_node) {
+ for (var i in new_node.contents) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
+ }
+ }
+ }
+ // do the internal rewiring
+ delete old_node.parent.contents[old_node.name];
+ old_node.name = new_name;
+ new_dir.contents[new_name] = old_node;
+ old_node.parent = new_dir;
+ },unlink:function (parent, name) {
+ delete parent.contents[name];
+ },rmdir:function (parent, name) {
+ var node = FS.lookupNode(parent, name);
+ for (var i in node.contents) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
+ }
+ delete parent.contents[name];
+ },readdir:function (node) {
+ var entries = ['.', '..']
+ for (var key in node.contents) {
+ if (!node.contents.hasOwnProperty(key)) {
+ continue;
+ }
+ entries.push(key);
+ }
+ return entries;
+ },symlink:function (parent, newname, oldpath) {
+ var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
+ node.link = oldpath;
+ return node;
+ },readlink:function (node) {
+ if (!FS.isLink(node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ return node.link;
+ }},stream_ops:{read:function (stream, buffer, offset, length, position) {
+ var contents = stream.node.contents;
+ if (position >= stream.node.usedBytes) return 0;
+ var size = Math.min(stream.node.usedBytes - position, length);
+ assert(size >= 0);
+ if (size > 8 && contents.subarray) { // non-trivial, and typed array
+ buffer.set(contents.subarray(position, position + size), offset);
+ } else {
+ for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
+ }
+ return size;
+ },write:function (stream, buffer, offset, length, position, canOwn) {
+ if (!length) return 0;
+ var node = stream.node;
+ node.timestamp = Date.now();
+
+ if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
+ if (canOwn) {
+ assert(position === 0, 'canOwn must imply no weird position inside the file');
+ node.contents = buffer.subarray(offset, offset + length);
+ node.usedBytes = length;
+ return length;
+ } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
+ node.contents = new Uint8Array(buffer.subarray(offset, offset + length));
+ node.usedBytes = length;
+ return length;
+ } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
+ node.contents.set(buffer.subarray(offset, offset + length), position);
+ return length;
+ }
+ }
+
+ // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
+ MEMFS.expandFileStorage(node, position+length);
+ if (node.contents.subarray && buffer.subarray) node.contents.set(buffer.subarray(offset, offset + length), position); // Use typed array write if available.
+ else {
+ for (var i = 0; i < length; i++) {
+ node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
+ }
+ }
+ node.usedBytes = Math.max(node.usedBytes, position+length);
+ return length;
+ },llseek:function (stream, offset, whence) {
+ var position = offset;
+ if (whence === 1) { // SEEK_CUR.
+ position += stream.position;
+ } else if (whence === 2) { // SEEK_END.
+ if (FS.isFile(stream.node.mode)) {
+ position += stream.node.usedBytes;
+ }
+ }
+ if (position < 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ return position;
+ },allocate:function (stream, offset, length) {
+ MEMFS.expandFileStorage(stream.node, offset + length);
+ stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
+ },mmap:function (stream, buffer, offset, length, position, prot, flags) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
+ }
+ var ptr;
+ var allocated;
+ var contents = stream.node.contents;
+ // Only make a new copy when MAP_PRIVATE is specified.
+ if ( !(flags & 2) &&
+ (contents.buffer === buffer || contents.buffer === buffer.buffer) ) {
+ // We can't emulate MAP_SHARED when the file is not backed by the buffer
+ // we're mapping to (e.g. the HEAP buffer).
+ allocated = false;
+ ptr = contents.byteOffset;
+ } else {
+ // Try to avoid unnecessary slices.
+ if (position > 0 || position + length < stream.node.usedBytes) {
+ if (contents.subarray) {
+ contents = contents.subarray(position, position + length);
+ } else {
+ contents = Array.prototype.slice.call(contents, position, position + length);
+ }
+ }
+ allocated = true;
+ ptr = _malloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOMEM);
+ }
+ buffer.set(contents, ptr);
+ }
+ return { ptr: ptr, allocated: allocated };
+ },msync:function (stream, buffer, offset, length, mmapFlags) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
+ }
+ if (mmapFlags & 2) {
+ // MAP_PRIVATE calls need not to be synced back to underlying fs
+ return 0;
+ }
+
+ var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
+ // should we check if bytesWritten and length are the same?
+ return 0;
+ }}};
+
+ var IDBFS={dbs:{},indexedDB:function () {
+ if (typeof indexedDB !== 'undefined') return indexedDB;
+ var ret = null;
+ if (typeof window === 'object') ret = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
+ assert(ret, 'IDBFS used, but indexedDB not supported');
+ return ret;
+ },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) {
+ // reuse all of the core MEMFS functionality
+ return MEMFS.mount.apply(null, arguments);
+ },syncfs:function (mount, populate, callback) {
+ IDBFS.getLocalSet(mount, function(err, local) {
+ if (err) return callback(err);
+
+ IDBFS.getRemoteSet(mount, function(err, remote) {
+ if (err) return callback(err);
+
+ var src = populate ? remote : local;
+ var dst = populate ? local : remote;
+
+ IDBFS.reconcile(src, dst, callback);
+ });
+ });
+ },getDB:function (name, callback) {
+ // check the cache first
+ var db = IDBFS.dbs[name];
+ if (db) {
+ return callback(null, db);
+ }
+
+ var req;
+ try {
+ req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION);
+ } catch (e) {
+ return callback(e);
+ }
+ if (!req) {
+ return callback("Unable to connect to IndexedDB");
+ }
+ req.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ var transaction = e.target.transaction;
+
+ var fileStore;
+
+ if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) {
+ fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME);
+ } else {
+ fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME);
+ }
+
+ if (!fileStore.indexNames.contains('timestamp')) {
+ fileStore.createIndex('timestamp', 'timestamp', { unique: false });
+ }
+ };
+ req.onsuccess = function() {
+ db = req.result;
+
+ // add to the cache
+ IDBFS.dbs[name] = db;
+ callback(null, db);
+ };
+ req.onerror = function(e) {
+ callback(this.error);
+ e.preventDefault();
+ };
+ },getLocalSet:function (mount, callback) {
+ var entries = {};
+
+ function isRealDir(p) {
+ return p !== '.' && p !== '..';
+ };
+ function toAbsolute(root) {
+ return function(p) {
+ return PATH.join2(root, p);
+ }
+ };
+
+ var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));
+
+ while (check.length) {
+ var path = check.pop();
+ var stat;
+
+ try {
+ stat = FS.stat(path);
+ } catch (e) {
+ return callback(e);
+ }
+
+ if (FS.isDir(stat.mode)) {
+ check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path)));
+ }
+
+ entries[path] = { timestamp: stat.mtime };
+ }
+
+ return callback(null, { type: 'local', entries: entries });
+ },getRemoteSet:function (mount, callback) {
+ var entries = {};
+
+ IDBFS.getDB(mount.mountpoint, function(err, db) {
+ if (err) return callback(err);
+
+ try {
+ var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly');
+ transaction.onerror = function(e) {
+ callback(this.error);
+ e.preventDefault();
+ };
+
+ var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
+ var index = store.index('timestamp');
+
+ index.openKeyCursor().onsuccess = function(event) {
+ var cursor = event.target.result;
+
+ if (!cursor) {
+ return callback(null, { type: 'remote', db: db, entries: entries });
+ }
+
+ entries[cursor.primaryKey] = { timestamp: cursor.key };
+
+ cursor.continue();
+ };
+ } catch (e) {
+ return callback(e);
+ }
+ });
+ },loadLocalEntry:function (path, callback) {
+ var stat, node;
+
+ try {
+ var lookup = FS.lookupPath(path);
+ node = lookup.node;
+ stat = FS.stat(path);
+ } catch (e) {
+ return callback(e);
+ }
+
+ if (FS.isDir(stat.mode)) {
+ return callback(null, { timestamp: stat.mtime, mode: stat.mode });
+ } else if (FS.isFile(stat.mode)) {
+ // Performance consideration: storing a normal JavaScript array to a IndexedDB is much slower than storing a typed array.
+ // Therefore always convert the file contents to a typed array first before writing the data to IndexedDB.
+ node.contents = MEMFS.getFileDataAsTypedArray(node);
+ return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents });
+ } else {
+ return callback(new Error('node type not supported'));
+ }
+ },storeLocalEntry:function (path, entry, callback) {
+ try {
+ if (FS.isDir(entry.mode)) {
+ FS.mkdir(path, entry.mode);
+ } else if (FS.isFile(entry.mode)) {
+ FS.writeFile(path, entry.contents, { canOwn: true });
+ } else {
+ return callback(new Error('node type not supported'));
+ }
+
+ FS.chmod(path, entry.mode);
+ FS.utime(path, entry.timestamp, entry.timestamp);
+ } catch (e) {
+ return callback(e);
+ }
+
+ callback(null);
+ },removeLocalEntry:function (path, callback) {
+ try {
+ var lookup = FS.lookupPath(path);
+ var stat = FS.stat(path);
+
+ if (FS.isDir(stat.mode)) {
+ FS.rmdir(path);
+ } else if (FS.isFile(stat.mode)) {
+ FS.unlink(path);
+ }
+ } catch (e) {
+ return callback(e);
+ }
+
+ callback(null);
+ },loadRemoteEntry:function (store, path, callback) {
+ var req = store.get(path);
+ req.onsuccess = function(event) { callback(null, event.target.result); };
+ req.onerror = function(e) {
+ callback(this.error);
+ e.preventDefault();
+ };
+ },storeRemoteEntry:function (store, path, entry, callback) {
+ var req = store.put(entry, path);
+ req.onsuccess = function() { callback(null); };
+ req.onerror = function(e) {
+ callback(this.error);
+ e.preventDefault();
+ };
+ },removeRemoteEntry:function (store, path, callback) {
+ var req = store.delete(path);
+ req.onsuccess = function() { callback(null); };
+ req.onerror = function(e) {
+ callback(this.error);
+ e.preventDefault();
+ };
+ },reconcile:function (src, dst, callback) {
+ var total = 0;
+
+ var create = [];
+ Object.keys(src.entries).forEach(function (key) {
+ var e = src.entries[key];
+ var e2 = dst.entries[key];
+ if (!e2 || e.timestamp > e2.timestamp) {
+ create.push(key);
+ total++;
+ }
+ });
+
+ var remove = [];
+ Object.keys(dst.entries).forEach(function (key) {
+ var e = dst.entries[key];
+ var e2 = src.entries[key];
+ if (!e2) {
+ remove.push(key);
+ total++;
+ }
+ });
+
+ if (!total) {
+ return callback(null);
+ }
+
+ var errored = false;
+ var completed = 0;
+ var db = src.type === 'remote' ? src.db : dst.db;
+ var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite');
+ var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
+
+ function done(err) {
+ if (err) {
+ if (!done.errored) {
+ done.errored = true;
+ return callback(err);
+ }
+ return;
+ }
+ if (++completed >= total) {
+ return callback(null);
+ }
+ };
+
+ transaction.onerror = function(e) {
+ done(this.error);
+ e.preventDefault();
+ };
+
+ // sort paths in ascending order so directory entries are created
+ // before the files inside them
+ create.sort().forEach(function (path) {
+ if (dst.type === 'local') {
+ IDBFS.loadRemoteEntry(store, path, function (err, entry) {
+ if (err) return done(err);
+ IDBFS.storeLocalEntry(path, entry, done);
+ });
+ } else {
+ IDBFS.loadLocalEntry(path, function (err, entry) {
+ if (err) return done(err);
+ IDBFS.storeRemoteEntry(store, path, entry, done);
+ });
+ }
+ });
+
+ // sort paths in descending order so files are deleted before their
+ // parent directories
+ remove.sort().reverse().forEach(function(path) {
+ if (dst.type === 'local') {
+ IDBFS.removeLocalEntry(path, done);
+ } else {
+ IDBFS.removeRemoteEntry(store, path, done);
+ }
+ });
+ }};
+
+ var NODEFS={isWindows:false,staticInit:function () {
+ NODEFS.isWindows = !!process.platform.match(/^win/);
+ var flags = process["binding"]("constants");
+ // Node.js 4 compatibility: it has no namespaces for constants
+ if (flags["fs"]) {
+ flags = flags["fs"];
+ }
+ NODEFS.flagsForNodeMap = {
+ "1024": flags["O_APPEND"],
+ "64": flags["O_CREAT"],
+ "128": flags["O_EXCL"],
+ "0": flags["O_RDONLY"],
+ "2": flags["O_RDWR"],
+ "4096": flags["O_SYNC"],
+ "512": flags["O_TRUNC"],
+ "1": flags["O_WRONLY"]
+ };
+ },bufferFrom:function (arrayBuffer) {
+ // Node.js < 4.5 compatibility: Buffer.from does not support ArrayBuffer
+ // Buffer.from before 4.5 was just a method inherited from Uint8Array
+ // Buffer.alloc has been added with Buffer.from together, so check it instead
+ return Buffer.alloc ? Buffer.from(arrayBuffer) : new Buffer(arrayBuffer);
+ },mount:function (mount) {
+ assert(ENVIRONMENT_IS_NODE);
+ return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0);
+ },createNode:function (parent, name, mode, dev) {
+ if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ var node = FS.createNode(parent, name, mode);
+ node.node_ops = NODEFS.node_ops;
+ node.stream_ops = NODEFS.stream_ops;
+ return node;
+ },getMode:function (path) {
+ var stat;
+ try {
+ stat = fs.lstatSync(path);
+ if (NODEFS.isWindows) {
+ // Node.js on Windows never represents permission bit 'x', so
+ // propagate read bits to execute bits
+ stat.mode = stat.mode | ((stat.mode & 292) >> 2);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ return stat.mode;
+ },realPath:function (node) {
+ var parts = [];
+ while (node.parent !== node) {
+ parts.push(node.name);
+ node = node.parent;
+ }
+ parts.push(node.mount.opts.root);
+ parts.reverse();
+ return PATH.join.apply(null, parts);
+ },flagsForNode:function (flags) {
+ flags &= ~0x200000 /*O_PATH*/; // Ignore this flag from musl, otherwise node.js fails to open the file.
+ flags &= ~0x800 /*O_NONBLOCK*/; // Ignore this flag from musl, otherwise node.js fails to open the file.
+ flags &= ~0x8000 /*O_LARGEFILE*/; // Ignore this flag from musl, otherwise node.js fails to open the file.
+ flags &= ~0x80000 /*O_CLOEXEC*/; // Some applications may pass it; it makes no sense for a single process.
+ var newFlags = 0;
+ for (var k in NODEFS.flagsForNodeMap) {
+ if (flags & k) {
+ newFlags |= NODEFS.flagsForNodeMap[k];
+ flags ^= k;
+ }
+ }
+
+ if (!flags) {
+ return newFlags;
+ } else {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ },node_ops:{getattr:function (node) {
+ var path = NODEFS.realPath(node);
+ var stat;
+ try {
+ stat = fs.lstatSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096.
+ // See http://support.microsoft.com/kb/140365
+ if (NODEFS.isWindows && !stat.blksize) {
+ stat.blksize = 4096;
+ }
+ if (NODEFS.isWindows && !stat.blocks) {
+ stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0;
+ }
+ return {
+ dev: stat.dev,
+ ino: stat.ino,
+ mode: stat.mode,
+ nlink: stat.nlink,
+ uid: stat.uid,
+ gid: stat.gid,
+ rdev: stat.rdev,
+ size: stat.size,
+ atime: stat.atime,
+ mtime: stat.mtime,
+ ctime: stat.ctime,
+ blksize: stat.blksize,
+ blocks: stat.blocks
+ };
+ },setattr:function (node, attr) {
+ var path = NODEFS.realPath(node);
+ try {
+ if (attr.mode !== undefined) {
+ fs.chmodSync(path, attr.mode);
+ // update the common node structure mode as well
+ node.mode = attr.mode;
+ }
+ if (attr.timestamp !== undefined) {
+ var date = new Date(attr.timestamp);
+ fs.utimesSync(path, date, date);
+ }
+ if (attr.size !== undefined) {
+ fs.truncateSync(path, attr.size);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },lookup:function (parent, name) {
+ var path = PATH.join2(NODEFS.realPath(parent), name);
+ var mode = NODEFS.getMode(path);
+ return NODEFS.createNode(parent, name, mode);
+ },mknod:function (parent, name, mode, dev) {
+ var node = NODEFS.createNode(parent, name, mode, dev);
+ // create the backing node for this in the fs root as well
+ var path = NODEFS.realPath(node);
+ try {
+ if (FS.isDir(node.mode)) {
+ fs.mkdirSync(path, node.mode);
+ } else {
+ fs.writeFileSync(path, '', { mode: node.mode });
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ return node;
+ },rename:function (oldNode, newDir, newName) {
+ var oldPath = NODEFS.realPath(oldNode);
+ var newPath = PATH.join2(NODEFS.realPath(newDir), newName);
+ try {
+ fs.renameSync(oldPath, newPath);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },unlink:function (parent, name) {
+ var path = PATH.join2(NODEFS.realPath(parent), name);
+ try {
+ fs.unlinkSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },rmdir:function (parent, name) {
+ var path = PATH.join2(NODEFS.realPath(parent), name);
+ try {
+ fs.rmdirSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },readdir:function (node) {
+ var path = NODEFS.realPath(node);
+ try {
+ return fs.readdirSync(path);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },symlink:function (parent, newName, oldPath) {
+ var newPath = PATH.join2(NODEFS.realPath(parent), newName);
+ try {
+ fs.symlinkSync(oldPath, newPath);
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },readlink:function (node) {
+ var path = NODEFS.realPath(node);
+ try {
+ path = fs.readlinkSync(path);
+ path = NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root), path);
+ return path;
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ }},stream_ops:{open:function (stream) {
+ var path = NODEFS.realPath(stream.node);
+ try {
+ if (FS.isFile(stream.node.mode)) {
+ stream.nfd = fs.openSync(path, NODEFS.flagsForNode(stream.flags));
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },close:function (stream) {
+ try {
+ if (FS.isFile(stream.node.mode) && stream.nfd) {
+ fs.closeSync(stream.nfd);
+ }
+ } catch (e) {
+ if (!e.code) throw e;
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },read:function (stream, buffer, offset, length, position) {
+ // Node.js < 6 compatibility: node errors on 0 length reads
+ if (length === 0) return 0;
+ try {
+ return fs.readSync(stream.nfd, NODEFS.bufferFrom(buffer.buffer), offset, length, position);
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },write:function (stream, buffer, offset, length, position) {
+ try {
+ return fs.writeSync(stream.nfd, NODEFS.bufferFrom(buffer.buffer), offset, length, position);
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ },llseek:function (stream, offset, whence) {
+ var position = offset;
+ if (whence === 1) { // SEEK_CUR.
+ position += stream.position;
+ } else if (whence === 2) { // SEEK_END.
+ if (FS.isFile(stream.node.mode)) {
+ try {
+ var stat = fs.fstatSync(stream.nfd);
+ position += stat.size;
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES[e.code]);
+ }
+ }
+ }
+
+ if (position < 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+
+ return position;
+ }}};
+
+ var WORKERFS={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:function (mount) {
+ assert(ENVIRONMENT_IS_WORKER);
+ if (!WORKERFS.reader) WORKERFS.reader = new FileReaderSync();
+ var root = WORKERFS.createNode(null, '/', WORKERFS.DIR_MODE, 0);
+ var createdParents = {};
+ function ensureParent(path) {
+ // return the parent node, creating subdirs as necessary
+ var parts = path.split('/');
+ var parent = root;
+ for (var i = 0; i < parts.length-1; i++) {
+ var curr = parts.slice(0, i+1).join('/');
+ // Issue 4254: Using curr as a node name will prevent the node
+ // from being found in FS.nameTable when FS.open is called on
+ // a path which holds a child of this node,
+ // given that all FS functions assume node names
+ // are just their corresponding parts within their given path,
+ // rather than incremental aggregates which include their parent's
+ // directories.
+ if (!createdParents[curr]) {
+ createdParents[curr] = WORKERFS.createNode(parent, parts[i], WORKERFS.DIR_MODE, 0);
+ }
+ parent = createdParents[curr];
+ }
+ return parent;
+ }
+ function base(path) {
+ var parts = path.split('/');
+ return parts[parts.length-1];
+ }
+ // We also accept FileList here, by using Array.prototype
+ Array.prototype.forEach.call(mount.opts["files"] || [], function(file) {
+ WORKERFS.createNode(ensureParent(file.name), base(file.name), WORKERFS.FILE_MODE, 0, file, file.lastModifiedDate);
+ });
+ (mount.opts["blobs"] || []).forEach(function(obj) {
+ WORKERFS.createNode(ensureParent(obj["name"]), base(obj["name"]), WORKERFS.FILE_MODE, 0, obj["data"]);
+ });
+ (mount.opts["packages"] || []).forEach(function(pack) {
+ pack['metadata'].files.forEach(function(file) {
+ var name = file.filename.substr(1); // remove initial slash
+ WORKERFS.createNode(ensureParent(name), base(name), WORKERFS.FILE_MODE, 0, pack['blob'].slice(file.start, file.end));
+ });
+ });
+ return root;
+ },createNode:function (parent, name, mode, dev, contents, mtime) {
+ var node = FS.createNode(parent, name, mode);
+ node.mode = mode;
+ node.node_ops = WORKERFS.node_ops;
+ node.stream_ops = WORKERFS.stream_ops;
+ node.timestamp = (mtime || new Date).getTime();
+ assert(WORKERFS.FILE_MODE !== WORKERFS.DIR_MODE);
+ if (mode === WORKERFS.FILE_MODE) {
+ node.size = contents.size;
+ node.contents = contents;
+ } else {
+ node.size = 4096;
+ node.contents = {};
+ }
+ if (parent) {
+ parent.contents[name] = node;
+ }
+ return node;
+ },node_ops:{getattr:function (node) {
+ return {
+ dev: 1,
+ ino: undefined,
+ mode: node.mode,
+ nlink: 1,
+ uid: 0,
+ gid: 0,
+ rdev: undefined,
+ size: node.size,
+ atime: new Date(node.timestamp),
+ mtime: new Date(node.timestamp),
+ ctime: new Date(node.timestamp),
+ blksize: 4096,
+ blocks: Math.ceil(node.size / 4096),
+ };
+ },setattr:function (node, attr) {
+ if (attr.mode !== undefined) {
+ node.mode = attr.mode;
+ }
+ if (attr.timestamp !== undefined) {
+ node.timestamp = attr.timestamp;
+ }
+ },lookup:function (parent, name) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ },mknod:function (parent, name, mode, dev) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ },rename:function (oldNode, newDir, newName) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ },unlink:function (parent, name) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ },rmdir:function (parent, name) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ },readdir:function (node) {
+ var entries = ['.', '..'];
+ for (var key in node.contents) {
+ if (!node.contents.hasOwnProperty(key)) {
+ continue;
+ }
+ entries.push(key);
+ }
+ return entries;
+ },symlink:function (parent, newName, oldPath) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ },readlink:function (node) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }},stream_ops:{read:function (stream, buffer, offset, length, position) {
+ if (position >= stream.node.size) return 0;
+ var chunk = stream.node.contents.slice(position, position + length);
+ var ab = WORKERFS.reader.readAsArrayBuffer(chunk);
+ buffer.set(new Uint8Array(ab), offset);
+ return chunk.size;
+ },write:function (stream, buffer, offset, length, position) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ },llseek:function (stream, offset, whence) {
+ var position = offset;
+ if (whence === 1) { // SEEK_CUR.
+ position += stream.position;
+ } else if (whence === 2) { // SEEK_END.
+ if (FS.isFile(stream.node.mode)) {
+ position += stream.node.size;
+ }
+ }
+ if (position < 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ return position;
+ }}};
+
+ var _stdin=STATICTOP; STATICTOP += 16;;
+
+ var _stdout=STATICTOP; STATICTOP += 16;;
+
+ var _stderr=STATICTOP; STATICTOP += 16;;var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function (e) {
+ if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
+ return ___setErrNo(e.errno);
+ },lookupPath:function (path, opts) {
+ path = PATH.resolve(FS.cwd(), path);
+ opts = opts || {};
+
+ if (!path) return { path: '', node: null };
+
+ var defaults = {
+ follow_mount: true,
+ recurse_count: 0
+ };
+ for (var key in defaults) {
+ if (opts[key] === undefined) {
+ opts[key] = defaults[key];
+ }
+ }
+
+ if (opts.recurse_count > 8) { // max recursive lookup of 8
+ throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
+ }
+
+ // split the path
+ var parts = PATH.normalizeArray(path.split('/').filter(function(p) {
+ return !!p;
+ }), false);
+
+ // start at the root
+ var current = FS.root;
+ var current_path = '/';
+
+ for (var i = 0; i < parts.length; i++) {
+ var islast = (i === parts.length-1);
+ if (islast && opts.parent) {
+ // stop resolving
+ break;
+ }
+
+ current = FS.lookupNode(current, parts[i]);
+ current_path = PATH.join2(current_path, parts[i]);
+
+ // jump to the mount's root node if this is a mountpoint
+ if (FS.isMountpoint(current)) {
+ if (!islast || (islast && opts.follow_mount)) {
+ current = current.mounted.root;
+ }
+ }
+
+ // by default, lookupPath will not follow a symlink if it is the final path component.
+ // setting opts.follow = true will override this behavior.
+ if (!islast || opts.follow) {
+ var count = 0;
+ while (FS.isLink(current.mode)) {
+ var link = FS.readlink(current_path);
+ current_path = PATH.resolve(PATH.dirname(current_path), link);
+
+ var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
+ current = lookup.node;
+
+ if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
+ throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
+ }
+ }
+ }
+ }
+
+ return { path: current_path, node: current };
+ },getPath:function (node) {
+ var path;
+ while (true) {
+ if (FS.isRoot(node)) {
+ var mount = node.mount.mountpoint;
+ if (!path) return mount;
+ return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
+ }
+ path = path ? node.name + '/' + path : node.name;
+ node = node.parent;
+ }
+ },hashName:function (parentid, name) {
+ var hash = 0;
+
+
+ for (var i = 0; i < name.length; i++) {
+ hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
+ }
+ return ((parentid + hash) >>> 0) % FS.nameTable.length;
+ },hashAddNode:function (node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ node.name_next = FS.nameTable[hash];
+ FS.nameTable[hash] = node;
+ },hashRemoveNode:function (node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ if (FS.nameTable[hash] === node) {
+ FS.nameTable[hash] = node.name_next;
+ } else {
+ var current = FS.nameTable[hash];
+ while (current) {
+ if (current.name_next === node) {
+ current.name_next = node.name_next;
+ break;
+ }
+ current = current.name_next;
+ }
+ }
+ },lookupNode:function (parent, name) {
+ var err = FS.mayLookup(parent);
+ if (err) {
+ throw new FS.ErrnoError(err, parent);
+ }
+ var hash = FS.hashName(parent.id, name);
+ for (var node = FS.nameTable[hash]; node; node = node.name_next) {
+ var nodeName = node.name;
+ if (node.parent.id === parent.id && nodeName === name) {
+ return node;
+ }
+ }
+ // if we failed to find it in the cache, call into the VFS
+ return FS.lookup(parent, name);
+ },createNode:function (parent, name, mode, rdev) {
+ if (!FS.FSNode) {
+ FS.FSNode = function(parent, name, mode, rdev) {
+ if (!parent) {
+ parent = this; // root node sets parent to itself
+ }
+ this.parent = parent;
+ this.mount = parent.mount;
+ this.mounted = null;
+ this.id = FS.nextInode++;
+ this.name = name;
+ this.mode = mode;
+ this.node_ops = {};
+ this.stream_ops = {};
+ this.rdev = rdev;
+ };
+
+ FS.FSNode.prototype = {};
+
+ // compatibility
+ var readMode = 292 | 73;
+ var writeMode = 146;
+
+ // NOTE we must use Object.defineProperties instead of individual calls to
+ // Object.defineProperty in order to make closure compiler happy
+ Object.defineProperties(FS.FSNode.prototype, {
+ read: {
+ get: function() { return (this.mode & readMode) === readMode; },
+ set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; }
+ },
+ write: {
+ get: function() { return (this.mode & writeMode) === writeMode; },
+ set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; }
+ },
+ isFolder: {
+ get: function() { return FS.isDir(this.mode); }
+ },
+ isDevice: {
+ get: function() { return FS.isChrdev(this.mode); }
+ }
+ });
+ }
+
+ var node = new FS.FSNode(parent, name, mode, rdev);
+
+ FS.hashAddNode(node);
+
+ return node;
+ },destroyNode:function (node) {
+ FS.hashRemoveNode(node);
+ },isRoot:function (node) {
+ return node === node.parent;
+ },isMountpoint:function (node) {
+ return !!node.mounted;
+ },isFile:function (mode) {
+ return (mode & 61440) === 32768;
+ },isDir:function (mode) {
+ return (mode & 61440) === 16384;
+ },isLink:function (mode) {
+ return (mode & 61440) === 40960;
+ },isChrdev:function (mode) {
+ return (mode & 61440) === 8192;
+ },isBlkdev:function (mode) {
+ return (mode & 61440) === 24576;
+ },isFIFO:function (mode) {
+ return (mode & 61440) === 4096;
+ },isSocket:function (mode) {
+ return (mode & 49152) === 49152;
+ },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function (str) {
+ var flags = FS.flagModes[str];
+ if (typeof flags === 'undefined') {
+ throw new Error('Unknown file open mode: ' + str);
+ }
+ return flags;
+ },flagsToPermissionString:function (flag) {
+ var perms = ['r', 'w', 'rw'][flag & 3];
+ if ((flag & 512)) {
+ perms += 'w';
+ }
+ return perms;
+ },nodePermissions:function (node, perms) {
+ if (FS.ignorePermissions) {
+ return 0;
+ }
+ // return 0 if any user, group or owner bits are set.
+ if (perms.indexOf('r') !== -1 && !(node.mode & 292)) {
+ return ERRNO_CODES.EACCES;
+ } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) {
+ return ERRNO_CODES.EACCES;
+ } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) {
+ return ERRNO_CODES.EACCES;
+ }
+ return 0;
+ },mayLookup:function (dir) {
+ var err = FS.nodePermissions(dir, 'x');
+ if (err) return err;
+ if (!dir.node_ops.lookup) return ERRNO_CODES.EACCES;
+ return 0;
+ },mayCreate:function (dir, name) {
+ try {
+ var node = FS.lookupNode(dir, name);
+ return ERRNO_CODES.EEXIST;
+ } catch (e) {
+ }
+ return FS.nodePermissions(dir, 'wx');
+ },mayDelete:function (dir, name, isdir) {
+ var node;
+ try {
+ node = FS.lookupNode(dir, name);
+ } catch (e) {
+ return e.errno;
+ }
+ var err = FS.nodePermissions(dir, 'wx');
+ if (err) {
+ return err;
+ }
+ if (isdir) {
+ if (!FS.isDir(node.mode)) {
+ return ERRNO_CODES.ENOTDIR;
+ }
+ if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
+ return ERRNO_CODES.EBUSY;
+ }
+ } else {
+ if (FS.isDir(node.mode)) {
+ return ERRNO_CODES.EISDIR;
+ }
+ }
+ return 0;
+ },mayOpen:function (node, flags) {
+ if (!node) {
+ return ERRNO_CODES.ENOENT;
+ }
+ if (FS.isLink(node.mode)) {
+ return ERRNO_CODES.ELOOP;
+ } else if (FS.isDir(node.mode)) {
+ if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write
+ (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only)
+ return ERRNO_CODES.EISDIR;
+ }
+ }
+ return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
+ },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) {
+ fd_start = fd_start || 0;
+ fd_end = fd_end || FS.MAX_OPEN_FDS;
+ for (var fd = fd_start; fd <= fd_end; fd++) {
+ if (!FS.streams[fd]) {
+ return fd;
+ }
+ }
+ throw new FS.ErrnoError(ERRNO_CODES.EMFILE);
+ },getStream:function (fd) {
+ return FS.streams[fd];
+ },createStream:function (stream, fd_start, fd_end) {
+ if (!FS.FSStream) {
+ FS.FSStream = function(){};
+ FS.FSStream.prototype = {};
+ // compatibility
+ Object.defineProperties(FS.FSStream.prototype, {
+ object: {
+ get: function() { return this.node; },
+ set: function(val) { this.node = val; }
+ },
+ isRead: {
+ get: function() { return (this.flags & 2097155) !== 1; }
+ },
+ isWrite: {
+ get: function() { return (this.flags & 2097155) !== 0; }
+ },
+ isAppend: {
+ get: function() { return (this.flags & 1024); }
+ }
+ });
+ }
+ // clone it, so we can return an instance of FSStream
+ var newStream = new FS.FSStream();
+ for (var p in stream) {
+ newStream[p] = stream[p];
+ }
+ stream = newStream;
+ var fd = FS.nextfd(fd_start, fd_end);
+ stream.fd = fd;
+ FS.streams[fd] = stream;
+ return stream;
+ },closeStream:function (fd) {
+ FS.streams[fd] = null;
+ },chrdev_stream_ops:{open:function (stream) {
+ var device = FS.getDevice(stream.node.rdev);
+ // override node's stream ops with the device's
+ stream.stream_ops = device.stream_ops;
+ // forward the open call
+ if (stream.stream_ops.open) {
+ stream.stream_ops.open(stream);
+ }
+ },llseek:function () {
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
+ }},major:function (dev) {
+ return ((dev) >> 8);
+ },minor:function (dev) {
+ return ((dev) & 0xff);
+ },makedev:function (ma, mi) {
+ return ((ma) << 8 | (mi));
+ },registerDevice:function (dev, ops) {
+ FS.devices[dev] = { stream_ops: ops };
+ },getDevice:function (dev) {
+ return FS.devices[dev];
+ },getMounts:function (mount) {
+ var mounts = [];
+ var check = [mount];
+
+ while (check.length) {
+ var m = check.pop();
+
+ mounts.push(m);
+
+ check.push.apply(check, m.mounts);
+ }
+
+ return mounts;
+ },syncfs:function (populate, callback) {
+ if (typeof(populate) === 'function') {
+ callback = populate;
+ populate = false;
+ }
+
+ FS.syncFSRequests++;
+
+ if (FS.syncFSRequests > 1) {
+ console.log('warning: ' + FS.syncFSRequests + ' FS.syncfs operations in flight at once, probably just doing extra work');
+ }
+
+ var mounts = FS.getMounts(FS.root.mount);
+ var completed = 0;
+
+ function doCallback(err) {
+ assert(FS.syncFSRequests > 0);
+ FS.syncFSRequests--;
+ return callback(err);
+ }
+
+ function done(err) {
+ if (err) {
+ if (!done.errored) {
+ done.errored = true;
+ return doCallback(err);
+ }
+ return;
+ }
+ if (++completed >= mounts.length) {
+ doCallback(null);
+ }
+ };
+
+ // sync all mounts
+ mounts.forEach(function (mount) {
+ if (!mount.type.syncfs) {
+ return done(null);
+ }
+ mount.type.syncfs(mount, populate, done);
+ });
+ },mount:function (type, opts, mountpoint) {
+ var root = mountpoint === '/';
+ var pseudo = !mountpoint;
+ var node;
+
+ if (root && FS.root) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
+ } else if (!root && !pseudo) {
+ var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
+
+ mountpoint = lookup.path; // use the absolute path
+ node = lookup.node;
+
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
+ }
+
+ if (!FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
+ }
+ }
+
+ var mount = {
+ type: type,
+ opts: opts,
+ mountpoint: mountpoint,
+ mounts: []
+ };
+
+ // create a root node for the fs
+ var mountRoot = type.mount(mount);
+ mountRoot.mount = mount;
+ mount.root = mountRoot;
+
+ if (root) {
+ FS.root = mountRoot;
+ } else if (node) {
+ // set as a mountpoint
+ node.mounted = mount;
+
+ // add the new mount to the current mount's children
+ if (node.mount) {
+ node.mount.mounts.push(mount);
+ }
+ }
+
+ return mountRoot;
+ },unmount:function (mountpoint) {
+ var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
+
+ if (!FS.isMountpoint(lookup.node)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+
+ // destroy the nodes for this mount, and all its child mounts
+ var node = lookup.node;
+ var mount = node.mounted;
+ var mounts = FS.getMounts(mount);
+
+ Object.keys(FS.nameTable).forEach(function (hash) {
+ var current = FS.nameTable[hash];
+
+ while (current) {
+ var next = current.name_next;
+
+ if (mounts.indexOf(current.mount) !== -1) {
+ FS.destroyNode(current);
+ }
+
+ current = next;
+ }
+ });
+
+ // no longer a mountpoint
+ node.mounted = null;
+
+ // remove this mount from the child mounts
+ var idx = node.mount.mounts.indexOf(mount);
+ assert(idx !== -1);
+ node.mount.mounts.splice(idx, 1);
+ },lookup:function (parent, name) {
+ return parent.node_ops.lookup(parent, name);
+ },mknod:function (path, mode, dev) {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ if (!name || name === '.' || name === '..') {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ var err = FS.mayCreate(parent, name);
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ if (!parent.node_ops.mknod) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ return parent.node_ops.mknod(parent, name, mode, dev);
+ },create:function (path, mode) {
+ mode = mode !== undefined ? mode : 438 /* 0666 */;
+ mode &= 4095;
+ mode |= 32768;
+ return FS.mknod(path, mode, 0);
+ },mkdir:function (path, mode) {
+ mode = mode !== undefined ? mode : 511 /* 0777 */;
+ mode &= 511 | 512;
+ mode |= 16384;
+ return FS.mknod(path, mode, 0);
+ },mkdirTree:function (path, mode) {
+ var dirs = path.split('/');
+ var d = '';
+ for (var i = 0; i < dirs.length; ++i) {
+ if (!dirs[i]) continue;
+ d += '/' + dirs[i];
+ try {
+ FS.mkdir(d, mode);
+ } catch(e) {
+ if (e.errno != ERRNO_CODES.EEXIST) throw e;
+ }
+ }
+ },mkdev:function (path, mode, dev) {
+ if (typeof(dev) === 'undefined') {
+ dev = mode;
+ mode = 438 /* 0666 */;
+ }
+ mode |= 8192;
+ return FS.mknod(path, mode, dev);
+ },symlink:function (oldpath, newpath) {
+ if (!PATH.resolve(oldpath)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ }
+ var lookup = FS.lookupPath(newpath, { parent: true });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ }
+ var newname = PATH.basename(newpath);
+ var err = FS.mayCreate(parent, newname);
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ if (!parent.node_ops.symlink) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ return parent.node_ops.symlink(parent, newname, oldpath);
+ },rename:function (old_path, new_path) {
+ var old_dirname = PATH.dirname(old_path);
+ var new_dirname = PATH.dirname(new_path);
+ var old_name = PATH.basename(old_path);
+ var new_name = PATH.basename(new_path);
+ // parents must exist
+ var lookup, old_dir, new_dir;
+ try {
+ lookup = FS.lookupPath(old_path, { parent: true });
+ old_dir = lookup.node;
+ lookup = FS.lookupPath(new_path, { parent: true });
+ new_dir = lookup.node;
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
+ }
+ if (!old_dir || !new_dir) throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ // need to be part of the same mount
+ if (old_dir.mount !== new_dir.mount) {
+ throw new FS.ErrnoError(ERRNO_CODES.EXDEV);
+ }
+ // source must exist
+ var old_node = FS.lookupNode(old_dir, old_name);
+ // old path should not be an ancestor of the new path
+ var relative = PATH.relative(old_path, new_dirname);
+ if (relative.charAt(0) !== '.') {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ // new path should not be an ancestor of the old path
+ relative = PATH.relative(new_path, old_dirname);
+ if (relative.charAt(0) !== '.') {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
+ }
+ // see if the new path already exists
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {
+ // not fatal
+ }
+ // early out if nothing needs to change
+ if (old_node === new_node) {
+ return;
+ }
+ // we'll need to delete the old entry
+ var isdir = FS.isDir(old_node.mode);
+ var err = FS.mayDelete(old_dir, old_name, isdir);
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ // need delete permissions if we'll be overwriting.
+ // need create permissions if new doesn't already exist.
+ err = new_node ?
+ FS.mayDelete(new_dir, new_name, isdir) :
+ FS.mayCreate(new_dir, new_name);
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ if (!old_dir.node_ops.rename) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
+ }
+ // if we are going to change the parent, check write permissions
+ if (new_dir !== old_dir) {
+ err = FS.nodePermissions(old_dir, 'w');
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ }
+ try {
+ if (FS.trackingDelegate['willMovePath']) {
+ FS.trackingDelegate['willMovePath'](old_path, new_path);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
+ }
+ // remove the node from the lookup hash
+ FS.hashRemoveNode(old_node);
+ // do the underlying fs rename
+ try {
+ old_dir.node_ops.rename(old_node, new_dir, new_name);
+ } catch (e) {
+ throw e;
+ } finally {
+ // add the node back to the hash (in case node_ops.rename
+ // changed its name)
+ FS.hashAddNode(old_node);
+ }
+ try {
+ if (FS.trackingDelegate['onMovePath']) FS.trackingDelegate['onMovePath'](old_path, new_path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
+ }
+ },rmdir:function (path) {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var err = FS.mayDelete(parent, name, true);
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ if (!parent.node_ops.rmdir) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
+ }
+ try {
+ if (FS.trackingDelegate['willDeletePath']) {
+ FS.trackingDelegate['willDeletePath'](path);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ parent.node_ops.rmdir(parent, name);
+ FS.destroyNode(node);
+ try {
+ if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ },readdir:function (path) {
+ var lookup = FS.lookupPath(path, { follow: true });
+ var node = lookup.node;
+ if (!node.node_ops.readdir) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
+ }
+ return node.node_ops.readdir(node);
+ },unlink:function (path) {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var err = FS.mayDelete(parent, name, false);
+ if (err) {
+ // According to POSIX, we should map EISDIR to EPERM, but
+ // we instead do what Linux does (and we must, as we use
+ // the musl linux libc).
+ throw new FS.ErrnoError(err);
+ }
+ if (!parent.node_ops.unlink) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
+ }
+ try {
+ if (FS.trackingDelegate['willDeletePath']) {
+ FS.trackingDelegate['willDeletePath'](path);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ parent.node_ops.unlink(parent, name);
+ FS.destroyNode(node);
+ try {
+ if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ },readlink:function (path) {
+ var lookup = FS.lookupPath(path);
+ var link = lookup.node;
+ if (!link) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ }
+ if (!link.node_ops.readlink) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ return PATH.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));
+ },stat:function (path, dontFollow) {
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
+ var node = lookup.node;
+ if (!node) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ }
+ if (!node.node_ops.getattr) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ return node.node_ops.getattr(node);
+ },lstat:function (path) {
+ return FS.stat(path, true);
+ },chmod:function (path, mode, dontFollow) {
+ var node;
+ if (typeof path === 'string') {
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ if (!node.node_ops.setattr) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ node.node_ops.setattr(node, {
+ mode: (mode & 4095) | (node.mode & ~4095),
+ timestamp: Date.now()
+ });
+ },lchmod:function (path, mode) {
+ FS.chmod(path, mode, true);
+ },fchmod:function (fd, mode) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ }
+ FS.chmod(stream.node, mode);
+ },chown:function (path, uid, gid, dontFollow) {
+ var node;
+ if (typeof path === 'string') {
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ if (!node.node_ops.setattr) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ node.node_ops.setattr(node, {
+ timestamp: Date.now()
+ // we ignore the uid / gid for now
+ });
+ },lchown:function (path, uid, gid) {
+ FS.chown(path, uid, gid, true);
+ },fchown:function (fd, uid, gid) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ }
+ FS.chown(stream.node, uid, gid);
+ },truncate:function (path, len) {
+ if (len < 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ var node;
+ if (typeof path === 'string') {
+ var lookup = FS.lookupPath(path, { follow: true });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ if (!node.node_ops.setattr) {
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
+ }
+ if (FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
+ }
+ if (!FS.isFile(node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ var err = FS.nodePermissions(node, 'w');
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ node.node_ops.setattr(node, {
+ size: len,
+ timestamp: Date.now()
+ });
+ },ftruncate:function (fd, len) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ FS.truncate(stream.node, len);
+ },utime:function (path, atime, mtime) {
+ var lookup = FS.lookupPath(path, { follow: true });
+ var node = lookup.node;
+ node.node_ops.setattr(node, {
+ timestamp: Math.max(atime, mtime)
+ });
+ },open:function (path, flags, mode, fd_start, fd_end) {
+ if (path === "") {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ }
+ flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
+ mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode;
+ if ((flags & 64)) {
+ mode = (mode & 4095) | 32768;
+ } else {
+ mode = 0;
+ }
+ var node;
+ if (typeof path === 'object') {
+ node = path;
+ } else {
+ path = PATH.normalize(path);
+ try {
+ var lookup = FS.lookupPath(path, {
+ follow: !(flags & 131072)
+ });
+ node = lookup.node;
+ } catch (e) {
+ // ignore
+ }
+ }
+ // perhaps we need to create the node
+ var created = false;
+ if ((flags & 64)) {
+ if (node) {
+ // if O_CREAT and O_EXCL are set, error out if the node already exists
+ if ((flags & 128)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EEXIST);
+ }
+ } else {
+ // node doesn't exist, try to create it
+ node = FS.mknod(path, mode, 0);
+ created = true;
+ }
+ }
+ if (!node) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ }
+ // can't truncate a device
+ if (FS.isChrdev(node.mode)) {
+ flags &= ~512;
+ }
+ // if asked only for a directory, then this must be one
+ if ((flags & 65536) && !FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
+ }
+ // check permissions, if this is not a file we just created now (it is ok to
+ // create and write to a file with read-only permissions; it is read-only
+ // for later use)
+ if (!created) {
+ var err = FS.mayOpen(node, flags);
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ }
+ // do truncation if necessary
+ if ((flags & 512)) {
+ FS.truncate(node, 0);
+ }
+ // we've already handled these, don't pass down to the underlying vfs
+ flags &= ~(128 | 512);
+
+ // register the stream with the filesystem
+ var stream = FS.createStream({
+ node: node,
+ path: FS.getPath(node), // we want the absolute path to the node
+ flags: flags,
+ seekable: true,
+ position: 0,
+ stream_ops: node.stream_ops,
+ // used by the file family libc calls (fopen, fwrite, ferror, etc.)
+ ungotten: [],
+ error: false
+ }, fd_start, fd_end);
+ // call the new stream's open function
+ if (stream.stream_ops.open) {
+ stream.stream_ops.open(stream);
+ }
+ if (Module['logReadFiles'] && !(flags & 1)) {
+ if (!FS.readFiles) FS.readFiles = {};
+ if (!(path in FS.readFiles)) {
+ FS.readFiles[path] = 1;
+ Module['printErr']('read file: ' + path);
+ }
+ }
+ try {
+ if (FS.trackingDelegate['onOpenFile']) {
+ var trackingFlags = 0;
+ if ((flags & 2097155) !== 1) {
+ trackingFlags |= FS.tracking.openFlags.READ;
+ }
+ if ((flags & 2097155) !== 0) {
+ trackingFlags |= FS.tracking.openFlags.WRITE;
+ }
+ FS.trackingDelegate['onOpenFile'](path, trackingFlags);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: " + e.message);
+ }
+ return stream;
+ },close:function (stream) {
+ if (stream.getdents) stream.getdents = null; // free readdir state
+ try {
+ if (stream.stream_ops.close) {
+ stream.stream_ops.close(stream);
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ FS.closeStream(stream.fd);
+ }
+ },llseek:function (stream, offset, whence) {
+ if (!stream.seekable || !stream.stream_ops.llseek) {
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
+ }
+ stream.position = stream.stream_ops.llseek(stream, offset, whence);
+ stream.ungotten = [];
+ return stream.position;
+ },read:function (stream, buffer, offset, length, position) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
+ }
+ if (!stream.stream_ops.read) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ var seeking = typeof position !== 'undefined';
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
+ }
+ var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
+ if (!seeking) stream.position += bytesRead;
+ return bytesRead;
+ },write:function (stream, buffer, offset, length, position, canOwn) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
+ }
+ if (!stream.stream_ops.write) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ if (stream.flags & 1024) {
+ // seek to the end before writing in append mode
+ FS.llseek(stream, 0, 2);
+ }
+ var seeking = typeof position !== 'undefined';
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
+ }
+ var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
+ if (!seeking) stream.position += bytesWritten;
+ try {
+ if (stream.path && FS.trackingDelegate['onWriteToFile']) FS.trackingDelegate['onWriteToFile'](stream.path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onWriteToFile']('"+path+"') threw an exception: " + e.message);
+ }
+ return bytesWritten;
+ },allocate:function (stream, offset, length) {
+ if (offset < 0 || length <= 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ }
+ if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
+ }
+ if (!stream.stream_ops.allocate) {
+ throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP);
+ }
+ stream.stream_ops.allocate(stream, offset, length);
+ },mmap:function (stream, buffer, offset, length, position, prot, flags) {
+ // TODO if PROT is PROT_WRITE, make sure we have write access
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(ERRNO_CODES.EACCES);
+ }
+ if (!stream.stream_ops.mmap) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
+ }
+ return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags);
+ },msync:function (stream, buffer, offset, length, mmapFlags) {
+ if (!stream || !stream.stream_ops.msync) {
+ return 0;
+ }
+ return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
+ },munmap:function (stream) {
+ return 0;
+ },ioctl:function (stream, cmd, arg) {
+ if (!stream.stream_ops.ioctl) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTTY);
+ }
+ return stream.stream_ops.ioctl(stream, cmd, arg);
+ },readFile:function (path, opts) {
+ opts = opts || {};
+ opts.flags = opts.flags || 'r';
+ opts.encoding = opts.encoding || 'binary';
+ if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
+ throw new Error('Invalid encoding type "' + opts.encoding + '"');
+ }
+ var ret;
+ var stream = FS.open(path, opts.flags);
+ var stat = FS.stat(path);
+ var length = stat.size;
+ var buf = new Uint8Array(length);
+ FS.read(stream, buf, 0, length, 0);
+ if (opts.encoding === 'utf8') {
+ ret = UTF8ArrayToString(buf, 0);
+ } else if (opts.encoding === 'binary') {
+ ret = buf;
+ }
+ FS.close(stream);
+ return ret;
+ },writeFile:function (path, data, opts) {
+ opts = opts || {};
+ opts.flags = opts.flags || 'w';
+ var stream = FS.open(path, opts.flags, opts.mode);
+ if (typeof data === 'string') {
+ var buf = new Uint8Array(lengthBytesUTF8(data)+1);
+ var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
+ FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
+ } else if (ArrayBuffer.isView(data)) {
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
+ } else {
+ throw new Error('Unsupported data type');
+ }
+ FS.close(stream);
+ },cwd:function () {
+ return FS.currentPath;
+ },chdir:function (path) {
+ var lookup = FS.lookupPath(path, { follow: true });
+ if (lookup.node === null) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ }
+ if (!FS.isDir(lookup.node.mode)) {
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
+ }
+ var err = FS.nodePermissions(lookup.node, 'x');
+ if (err) {
+ throw new FS.ErrnoError(err);
+ }
+ FS.currentPath = lookup.path;
+ },createDefaultDirectories:function () {
+ FS.mkdir('/tmp');
+ FS.mkdir('/home');
+ FS.mkdir('/home/web_user');
+ },createDefaultDevices:function () {
+ // create /dev
+ FS.mkdir('/dev');
+ // setup /dev/null
+ FS.registerDevice(FS.makedev(1, 3), {
+ read: function() { return 0; },
+ write: function(stream, buffer, offset, length, pos) { return length; }
+ });
+ FS.mkdev('/dev/null', FS.makedev(1, 3));
+ // setup /dev/tty and /dev/tty1
+ // stderr needs to print output using Module['printErr']
+ // so we register a second tty just for it.
+ TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
+ TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
+ FS.mkdev('/dev/tty', FS.makedev(5, 0));
+ FS.mkdev('/dev/tty1', FS.makedev(6, 0));
+ // setup /dev/[u]random
+ var random_device;
+ if (typeof crypto !== 'undefined') {
+ // for modern web browsers
+ var randomBuffer = new Uint8Array(1);
+ random_device = function() { crypto.getRandomValues(randomBuffer); return randomBuffer[0]; };
+ } else if (ENVIRONMENT_IS_NODE) {
+ // for nodejs
+ random_device = function() { return require('crypto')['randomBytes'](1)[0]; };
+ } else {
+ // default for ES5 platforms
+ random_device = function() { return (Math.random()*256)|0; };
+ }
+ FS.createDevice('/dev', 'random', random_device);
+ FS.createDevice('/dev', 'urandom', random_device);
+ // we're not going to emulate the actual shm device,
+ // just create the tmp dirs that reside in it commonly
+ FS.mkdir('/dev/shm');
+ FS.mkdir('/dev/shm/tmp');
+ },createSpecialDirectories:function () {
+ // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the name of the stream for fd 6 (see test_unistd_ttyname)
+ FS.mkdir('/proc');
+ FS.mkdir('/proc/self');
+ FS.mkdir('/proc/self/fd');
+ FS.mount({
+ mount: function() {
+ var node = FS.createNode('/proc/self', 'fd', 16384 | 511 /* 0777 */, 73);
+ node.node_ops = {
+ lookup: function(parent, name) {
+ var fd = +name;
+ var stream = FS.getStream(fd);
+ if (!stream) throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ var ret = {
+ parent: null,
+ mount: { mountpoint: 'fake' },
+ node_ops: { readlink: function() { return stream.path } }
+ };
+ ret.parent = ret; // make it look like a simple root node
+ return ret;
+ }
+ };
+ return node;
+ }
+ }, {}, '/proc/self/fd');
+ },createStandardStreams:function () {
+ // TODO deprecate the old functionality of a single
+ // input / output callback and that utilizes FS.createDevice
+ // and instead require a unique set of stream ops
+
+ // by default, we symlink the standard streams to the
+ // default tty devices. however, if the standard streams
+ // have been overwritten we create a unique device for
+ // them instead.
+ if (Module['stdin']) {
+ FS.createDevice('/dev', 'stdin', Module['stdin']);
+ } else {
+ FS.symlink('/dev/tty', '/dev/stdin');
+ }
+ if (Module['stdout']) {
+ FS.createDevice('/dev', 'stdout', null, Module['stdout']);
+ } else {
+ FS.symlink('/dev/tty', '/dev/stdout');
+ }
+ if (Module['stderr']) {
+ FS.createDevice('/dev', 'stderr', null, Module['stderr']);
+ } else {
+ FS.symlink('/dev/tty1', '/dev/stderr');
+ }
+
+ // open default streams for the stdin, stdout and stderr devices
+ var stdin = FS.open('/dev/stdin', 'r');
+ assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')');
+
+ var stdout = FS.open('/dev/stdout', 'w');
+ assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')');
+
+ var stderr = FS.open('/dev/stderr', 'w');
+ assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')');
+ },ensureErrnoError:function () {
+ if (FS.ErrnoError) return;
+ FS.ErrnoError = function ErrnoError(errno, node) {
+ //Module.printErr(stackTrace()); // useful for debugging
+ this.node = node;
+ this.setErrno = function(errno) {
+ this.errno = errno;
+ for (var key in ERRNO_CODES) {
+ if (ERRNO_CODES[key] === errno) {
+ this.code = key;
+ break;
+ }
+ }
+ };
+ this.setErrno(errno);
+ this.message = ERRNO_MESSAGES[errno];
+ // Node.js compatibility: assigning on this.stack fails on Node 4 (but fixed on Node 8)
+ if (this.stack) Object.defineProperty(this, "stack", { value: (new Error).stack, writable: true });
+ if (this.stack) this.stack = demangleAll(this.stack);
+ };
+ FS.ErrnoError.prototype = new Error();
+ FS.ErrnoError.prototype.constructor = FS.ErrnoError;
+ // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info)
+ [ERRNO_CODES.ENOENT].forEach(function(code) {
+ FS.genericErrors[code] = new FS.ErrnoError(code);
+ FS.genericErrors[code].stack = '<generic error, no stack>';
+ });
+ },staticInit:function () {
+ FS.ensureErrnoError();
+
+ FS.nameTable = new Array(4096);
+
+ FS.mount(MEMFS, {}, '/');
+
+ FS.createDefaultDirectories();
+ FS.createDefaultDevices();
+ FS.createSpecialDirectories();
+
+ FS.filesystems = {
+ 'MEMFS': MEMFS,
+ 'IDBFS': IDBFS,
+ 'NODEFS': NODEFS,
+ 'WORKERFS': WORKERFS,
+ };
+ },init:function (input, output, error) {
+ assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
+ FS.init.initialized = true;
+
+ FS.ensureErrnoError();
+
+ // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
+ Module['stdin'] = input || Module['stdin'];
+ Module['stdout'] = output || Module['stdout'];
+ Module['stderr'] = error || Module['stderr'];
+
+ FS.createStandardStreams();
+ },quit:function () {
+ FS.init.initialized = false;
+ // force-flush all streams, so we get musl std streams printed out
+ var fflush = Module['_fflush'];
+ if (fflush) fflush(0);
+ // close all of our streams
+ for (var i = 0; i < FS.streams.length; i++) {
+ var stream = FS.streams[i];
+ if (!stream) {
+ continue;
+ }
+ FS.close(stream);
+ }
+ },getMode:function (canRead, canWrite) {
+ var mode = 0;
+ if (canRead) mode |= 292 | 73;
+ if (canWrite) mode |= 146;
+ return mode;
+ },joinPath:function (parts, forceRelative) {
+ var path = PATH.join.apply(null, parts);
+ if (forceRelative && path[0] == '/') path = path.substr(1);
+ return path;
+ },absolutePath:function (relative, base) {
+ return PATH.resolve(base, relative);
+ },standardizePath:function (path) {
+ return PATH.normalize(path);
+ },findObject:function (path, dontResolveLastLink) {
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (ret.exists) {
+ return ret.object;
+ } else {
+ ___setErrNo(ret.error);
+ return null;
+ }
+ },analyzePath:function (path, dontResolveLastLink) {
+ // operate from within the context of the symlink's target
+ try {
+ var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
+ path = lookup.path;
+ } catch (e) {
+ }
+ var ret = {
+ isRoot: false, exists: false, error: 0, name: null, path: null, object: null,
+ parentExists: false, parentPath: null, parentObject: null
+ };
+ try {
+ var lookup = FS.lookupPath(path, { parent: true });
+ ret.parentExists = true;
+ ret.parentPath = lookup.path;
+ ret.parentObject = lookup.node;
+ ret.name = PATH.basename(path);
+ lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
+ ret.exists = true;
+ ret.path = lookup.path;
+ ret.object = lookup.node;
+ ret.name = lookup.node.name;
+ ret.isRoot = lookup.path === '/';
+ } catch (e) {
+ ret.error = e.errno;
+ };
+ return ret;
+ },createFolder:function (parent, name, canRead, canWrite) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var mode = FS.getMode(canRead, canWrite);
+ return FS.mkdir(path, mode);
+ },createPath:function (parent, path, canRead, canWrite) {
+ parent = typeof parent === 'string' ? parent : FS.getPath(parent);
+ var parts = path.split('/').reverse();
+ while (parts.length) {
+ var part = parts.pop();
+ if (!part) continue;
+ var current = PATH.join2(parent, part);
+ try {
+ FS.mkdir(current);
+ } catch (e) {
+ // ignore EEXIST
+ }
+ parent = current;
+ }
+ return current;
+ },createFile:function (parent, name, properties, canRead, canWrite) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var mode = FS.getMode(canRead, canWrite);
+ return FS.create(path, mode);
+ },createDataFile:function (parent, name, data, canRead, canWrite, canOwn) {
+ var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
+ var mode = FS.getMode(canRead, canWrite);
+ var node = FS.create(path, mode);
+ if (data) {
+ if (typeof data === 'string') {
+ var arr = new Array(data.length);
+ for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
+ data = arr;
+ }
+ // make sure we can write to the file
+ FS.chmod(node, mode | 146);
+ var stream = FS.open(node, 'w');
+ FS.write(stream, data, 0, data.length, 0, canOwn);
+ FS.close(stream);
+ FS.chmod(node, mode);
+ }
+ return node;
+ },createDevice:function (parent, name, input, output) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var mode = FS.getMode(!!input, !!output);
+ if (!FS.createDevice.major) FS.createDevice.major = 64;
+ var dev = FS.makedev(FS.createDevice.major++, 0);
+ // Create a fake device that a set of stream ops to emulate
+ // the old behavior.
+ FS.registerDevice(dev, {
+ open: function(stream) {
+ stream.seekable = false;
+ },
+ close: function(stream) {
+ // flush any pending line data
+ if (output && output.buffer && output.buffer.length) {
+ output(10);
+ }
+ },
+ read: function(stream, buffer, offset, length, pos /* ignored */) {
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = input();
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset+i] = result;
+ }
+ if (bytesRead) {
+ stream.node.timestamp = Date.now();
+ }
+ return bytesRead;
+ },
+ write: function(stream, buffer, offset, length, pos) {
+ for (var i = 0; i < length; i++) {
+ try {
+ output(buffer[offset+i]);
+ } catch (e) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ }
+ if (length) {
+ stream.node.timestamp = Date.now();
+ }
+ return i;
+ }
+ });
+ return FS.mkdev(path, mode, dev);
+ },createLink:function (parent, name, target, canRead, canWrite) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ return FS.symlink(target, path);
+ },forceLoadFile:function (obj) {
+ if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
+ var success = true;
+ if (typeof XMLHttpRequest !== 'undefined') {
+ throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
+ } else if (Module['read']) {
+ // Command-line.
+ try {
+ // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
+ // read() will try to parse UTF8.
+ obj.contents = intArrayFromString(Module['read'](obj.url), true);
+ obj.usedBytes = obj.contents.length;
+ } catch (e) {
+ success = false;
+ }
+ } else {
+ throw new Error('Cannot load without read() or XMLHttpRequest.');
+ }
+ if (!success) ___setErrNo(ERRNO_CODES.EIO);
+ return success;
+ },createLazyFile:function (parent, name, url, canRead, canWrite) {
+ // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
+ function LazyUint8Array() {
+ this.lengthKnown = false;
+ this.chunks = []; // Loaded chunks. Index is the chunk number
+ }
+ LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {
+ if (idx > this.length-1 || idx < 0) {
+ return undefined;
+ }
+ var chunkOffset = idx % this.chunkSize;
+ var chunkNum = (idx / this.chunkSize)|0;
+ return this.getter(chunkNum)[chunkOffset];
+ }
+ LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
+ this.getter = getter;
+ }
+ LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
+ // Find length
+ var xhr = new XMLHttpRequest();
+ xhr.open('HEAD', url, false);
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ var datalength = Number(xhr.getResponseHeader("Content-length"));
+ var header;
+ var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
+ var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
+
+ var chunkSize = 1024*1024; // Chunk size in bytes
+
+ if (!hasByteServing) chunkSize = datalength;
+
+ // Function to get a range from the remote URL.
+ var doXHR = (function(from, to) {
+ if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
+ if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
+
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
+
+ // Some hints to the browser that we want binary data.
+ if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
+ if (xhr.overrideMimeType) {
+ xhr.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ if (xhr.response !== undefined) {
+ return new Uint8Array(xhr.response || []);
+ } else {
+ return intArrayFromString(xhr.responseText || '', true);
+ }
+ });
+ var lazyArray = this;
+ lazyArray.setDataGetter(function(chunkNum) {
+ var start = chunkNum * chunkSize;
+ var end = (chunkNum+1) * chunkSize - 1; // including this byte
+ end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
+ lazyArray.chunks[chunkNum] = doXHR(start, end);
+ }
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
+ return lazyArray.chunks[chunkNum];
+ });
+
+ if (usesGzip || !datalength) {
+ // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
+ chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file
+ datalength = this.getter(0).length;
+ chunkSize = datalength;
+ console.log("LazyFiles on gzip forces download of the whole file when length is accessed");
+ }
+
+ this._length = datalength;
+ this._chunkSize = chunkSize;
+ this.lengthKnown = true;
+ }
+ if (typeof XMLHttpRequest !== 'undefined') {
+ if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
+ var lazyArray = new LazyUint8Array();
+ Object.defineProperties(lazyArray, {
+ length: {
+ get: function() {
+ if(!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._length;
+ }
+ },
+ chunkSize: {
+ get: function() {
+ if(!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._chunkSize;
+ }
+ }
+ });
+
+ var properties = { isDevice: false, contents: lazyArray };
+ } else {
+ var properties = { isDevice: false, url: url };
+ }
+
+ var node = FS.createFile(parent, name, properties, canRead, canWrite);
+ // This is a total hack, but I want to get this lazy file code out of the
+ // core of MEMFS. If we want to keep this lazy file concept I feel it should
+ // be its own thin LAZYFS proxying calls to MEMFS.
+ if (properties.contents) {
+ node.contents = properties.contents;
+ } else if (properties.url) {
+ node.contents = null;
+ node.url = properties.url;
+ }
+ // Add a function that defers querying the file size until it is asked the first time.
+ Object.defineProperties(node, {
+ usedBytes: {
+ get: function() { return this.contents.length; }
+ }
+ });
+ // override each stream op with one that tries to force load the lazy file first
+ var stream_ops = {};
+ var keys = Object.keys(node.stream_ops);
+ keys.forEach(function(key) {
+ var fn = node.stream_ops[key];
+ stream_ops[key] = function forceLoadLazyFile() {
+ if (!FS.forceLoadFile(node)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ return fn.apply(null, arguments);
+ };
+ });
+ // use a custom read function
+ stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) {
+ if (!FS.forceLoadFile(node)) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ var contents = stream.node.contents;
+ if (position >= contents.length)
+ return 0;
+ var size = Math.min(contents.length - position, length);
+ assert(size >= 0);
+ if (contents.slice) { // normal array
+ for (var i = 0; i < size; i++) {
+ buffer[offset + i] = contents[position + i];
+ }
+ } else {
+ for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR
+ buffer[offset + i] = contents.get(position + i);
+ }
+ }
+ return size;
+ };
+ node.stream_ops = stream_ops;
+ return node;
+ },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
+ Browser.init(); // XXX perhaps this method should move onto Browser?
+ // TODO we should allow people to just pass in a complete filename instead
+ // of parent and name being that we just join them anyways
+ var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent;
+ var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same fullname
+ function processData(byteArray) {
+ function finish(byteArray) {
+ if (preFinish) preFinish();
+ if (!dontCreateFile) {
+ FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
+ }
+ if (onload) onload();
+ removeRunDependency(dep);
+ }
+ var handled = false;
+ Module['preloadPlugins'].forEach(function(plugin) {
+ if (handled) return;
+ if (plugin['canHandle'](fullname)) {
+ plugin['handle'](byteArray, fullname, finish, function() {
+ if (onerror) onerror();
+ removeRunDependency(dep);
+ });
+ handled = true;
+ }
+ });
+ if (!handled) finish(byteArray);
+ }
+ addRunDependency(dep);
+ if (typeof url == 'string') {
+ Browser.asyncLoad(url, function(byteArray) {
+ processData(byteArray);
+ }, onerror);
+ } else {
+ processData(url);
+ }
+ },indexedDB:function () {
+ return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
+ },DB_NAME:function () {
+ return 'EM_FS_' + window.location.pathname;
+ },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function (paths, onload, onerror) {
+ onload = onload || function(){};
+ onerror = onerror || function(){};
+ var indexedDB = FS.indexedDB();
+ try {
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
+ } catch (e) {
+ return onerror(e);
+ }
+ openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
+ console.log('creating db');
+ var db = openRequest.result;
+ db.createObjectStore(FS.DB_STORE_NAME);
+ };
+ openRequest.onsuccess = function openRequest_onsuccess() {
+ var db = openRequest.result;
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
+ var ok = 0, fail = 0, total = paths.length;
+ function finish() {
+ if (fail == 0) onload(); else onerror();
+ }
+ paths.forEach(function(path) {
+ var putRequest = files.put(FS.analyzePath(path).object.contents, path);
+ putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() };
+ putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() };
+ });
+ transaction.onerror = onerror;
+ };
+ openRequest.onerror = onerror;
+ },loadFilesFromDB:function (paths, onload, onerror) {
+ onload = onload || function(){};
+ onerror = onerror || function(){};
+ var indexedDB = FS.indexedDB();
+ try {
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
+ } catch (e) {
+ return onerror(e);
+ }
+ openRequest.onupgradeneeded = onerror; // no database to load from
+ openRequest.onsuccess = function openRequest_onsuccess() {
+ var db = openRequest.result;
+ try {
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
+ } catch(e) {
+ onerror(e);
+ return;
+ }
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
+ var ok = 0, fail = 0, total = paths.length;
+ function finish() {
+ if (fail == 0) onload(); else onerror();
+ }
+ paths.forEach(function(path) {
+ var getRequest = files.get(path);
+ getRequest.onsuccess = function getRequest_onsuccess() {
+ if (FS.analyzePath(path).exists) {
+ FS.unlink(path);
+ }
+ FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
+ ok++;
+ if (ok + fail == total) finish();
+ };
+ getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() };
+ });
+ transaction.onerror = onerror;
+ };
+ openRequest.onerror = onerror;
+ }};var SYSCALLS={DEFAULT_POLLMASK:5,mappings:{},umask:511,calculateAt:function (dirfd, path) {
+ if (path[0] !== '/') {
+ // relative path
+ var dir;
+ if (dirfd === -100) {
+ dir = FS.cwd();
+ } else {
+ var dirstream = FS.getStream(dirfd);
+ if (!dirstream) throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ dir = dirstream.path;
+ }
+ path = PATH.join2(dir, path);
+ }
+ return path;
+ },doStat:function (func, path, buf) {
+ try {
+ var stat = func(path);
+ } catch (e) {
+ if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
+ // an error occurred while trying to look up the path; we should just report ENOTDIR
+ return -ERRNO_CODES.ENOTDIR;
+ }
+ throw e;
+ }
+ HEAP32[((buf)>>2)]=stat.dev;
+ HEAP32[(((buf)+(4))>>2)]=0;
+ HEAP32[(((buf)+(8))>>2)]=stat.ino;
+ HEAP32[(((buf)+(12))>>2)]=stat.mode;
+ HEAP32[(((buf)+(16))>>2)]=stat.nlink;
+ HEAP32[(((buf)+(20))>>2)]=stat.uid;
+ HEAP32[(((buf)+(24))>>2)]=stat.gid;
+ HEAP32[(((buf)+(28))>>2)]=stat.rdev;
+ HEAP32[(((buf)+(32))>>2)]=0;
+ HEAP32[(((buf)+(36))>>2)]=stat.size;
+ HEAP32[(((buf)+(40))>>2)]=4096;
+ HEAP32[(((buf)+(44))>>2)]=stat.blocks;
+ HEAP32[(((buf)+(48))>>2)]=(stat.atime.getTime() / 1000)|0;
+ HEAP32[(((buf)+(52))>>2)]=0;
+ HEAP32[(((buf)+(56))>>2)]=(stat.mtime.getTime() / 1000)|0;
+ HEAP32[(((buf)+(60))>>2)]=0;
+ HEAP32[(((buf)+(64))>>2)]=(stat.ctime.getTime() / 1000)|0;
+ HEAP32[(((buf)+(68))>>2)]=0;
+ HEAP32[(((buf)+(72))>>2)]=stat.ino;
+ return 0;
+ },doMsync:function (addr, stream, len, flags) {
+ var buffer = new Uint8Array(HEAPU8.subarray(addr, addr + len));
+ FS.msync(stream, buffer, 0, len, flags);
+ },doMkdir:function (path, mode) {
+ // remove a trailing slash, if one - /a/b/ has basename of '', but
+ // we want to create b in the context of this function
+ path = PATH.normalize(path);
+ if (path[path.length-1] === '/') path = path.substr(0, path.length-1);
+ FS.mkdir(path, mode, 0);
+ return 0;
+ },doMknod:function (path, mode, dev) {
+ // we don't want this in the JS API as it uses mknod to create all nodes.
+ switch (mode & 61440) {
+ case 32768:
+ case 8192:
+ case 24576:
+ case 4096:
+ case 49152:
+ break;
+ default: return -ERRNO_CODES.EINVAL;
+ }
+ FS.mknod(path, mode, dev);
+ return 0;
+ },doReadlink:function (path, buf, bufsize) {
+ if (bufsize <= 0) return -ERRNO_CODES.EINVAL;
+ var ret = FS.readlink(path);
+
+ var len = Math.min(bufsize, lengthBytesUTF8(ret));
+ var endChar = HEAP8[buf+len];
+ stringToUTF8(ret, buf, bufsize+1);
+ // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
+ // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
+ HEAP8[buf+len] = endChar;
+
+ return len;
+ },doAccess:function (path, amode) {
+ if (amode & ~7) {
+ // need a valid mode
+ return -ERRNO_CODES.EINVAL;
+ }
+ var node;
+ var lookup = FS.lookupPath(path, { follow: true });
+ node = lookup.node;
+ var perms = '';
+ if (amode & 4) perms += 'r';
+ if (amode & 2) perms += 'w';
+ if (amode & 1) perms += 'x';
+ if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) {
+ return -ERRNO_CODES.EACCES;
+ }
+ return 0;
+ },doDup:function (path, flags, suggestFD) {
+ var suggest = FS.getStream(suggestFD);
+ if (suggest) FS.close(suggest);
+ return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
+ },doReadv:function (stream, iov, iovcnt, offset) {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAP32[(((iov)+(i*8))>>2)];
+ var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
+ var curr = FS.read(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) break; // nothing more to read
+ }
+ return ret;
+ },doWritev:function (stream, iov, iovcnt, offset) {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAP32[(((iov)+(i*8))>>2)];
+ var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
+ var curr = FS.write(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ }
+ return ret;
+ },varargs:0,get:function (varargs) {
+ SYSCALLS.varargs += 4;
+ var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
+ return ret;
+ },getStr:function () {
+ var ret = Pointer_stringify(SYSCALLS.get());
+ return ret;
+ },getStreamFromFD:function () {
+ var stream = FS.getStream(SYSCALLS.get());
+ if (!stream) throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ return stream;
+ },getSocketFromFD:function () {
+ var socket = SOCKFS.getSocket(SYSCALLS.get());
+ if (!socket) throw new FS.ErrnoError(ERRNO_CODES.EBADF);
+ return socket;
+ },getSocketAddress:function (allowNull) {
+ var addrp = SYSCALLS.get(), addrlen = SYSCALLS.get();
+ if (allowNull && addrp === 0) return null;
+ var info = __read_sockaddr(addrp, addrlen);
+ if (info.errno) throw new FS.ErrnoError(info.errno);
+ info.addr = DNS.lookup_addr(info.addr) || info.addr;
+ return info;
+ },get64:function () {
+ var low = SYSCALLS.get(), high = SYSCALLS.get();
+ if (low >= 0) assert(high === 0);
+ else assert(high === -1);
+ return low;
+ },getZero:function () {
+ assert(SYSCALLS.get() === 0);
+ }};function ___syscall10(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // unlink
+ var path = SYSCALLS.getStr();
+ FS.unlink(path);
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall140(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // llseek
+ var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get();
+ // NOTE: offset_high is unused - Emscripten's off_t is 32-bit
+ var offset = offset_low;
+ FS.llseek(stream, offset, whence);
+ HEAP32[((result)>>2)]=stream.position;
+ if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall145(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // readv
+ var stream = SYSCALLS.getStreamFromFD(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get();
+ return SYSCALLS.doReadv(stream, iov, iovcnt);
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall146(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // writev
+ var stream = SYSCALLS.getStreamFromFD(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get();
+ return SYSCALLS.doWritev(stream, iov, iovcnt);
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall195(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // SYS_stat64
+ var path = SYSCALLS.getStr(), buf = SYSCALLS.get();
+ return SYSCALLS.doStat(FS.stat, path, buf);
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall220(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // SYS_getdents64
+ var stream = SYSCALLS.getStreamFromFD(), dirp = SYSCALLS.get(), count = SYSCALLS.get();
+ if (!stream.getdents) {
+ stream.getdents = FS.readdir(stream.path);
+ }
+ var pos = 0;
+ while (stream.getdents.length > 0 && pos + 268 <= count) {
+ var id;
+ var type;
+ var name = stream.getdents.pop();
+ if (name[0] === '.') {
+ id = 1;
+ type = 4; // DT_DIR
+ } else {
+ var child = FS.lookupNode(stream.node, name);
+ id = child.id;
+ type = FS.isChrdev(child.mode) ? 2 : // DT_CHR, character device.
+ FS.isDir(child.mode) ? 4 : // DT_DIR, directory.
+ FS.isLink(child.mode) ? 10 : // DT_LNK, symbolic link.
+ 8; // DT_REG, regular file.
+ }
+ HEAP32[((dirp + pos)>>2)]=id;
+ HEAP32[(((dirp + pos)+(4))>>2)]=stream.position;
+ HEAP16[(((dirp + pos)+(8))>>1)]=268;
+ HEAP8[(((dirp + pos)+(10))>>0)]=type;
+ stringToUTF8(name, dirp + pos + 11, 256);
+ pos += 268;
+ }
+ return pos;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall221(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // fcntl64
+ var stream = SYSCALLS.getStreamFromFD(), cmd = SYSCALLS.get();
+ switch (cmd) {
+ case 0: {
+ var arg = SYSCALLS.get();
+ if (arg < 0) {
+ return -ERRNO_CODES.EINVAL;
+ }
+ var newStream;
+ newStream = FS.open(stream.path, stream.flags, 0, arg);
+ return newStream.fd;
+ }
+ case 1:
+ case 2:
+ return 0; // FD_CLOEXEC makes no sense for a single process.
+ case 3:
+ return stream.flags;
+ case 4: {
+ var arg = SYSCALLS.get();
+ stream.flags |= arg;
+ return 0;
+ }
+ case 12:
+ case 12: {
+ var arg = SYSCALLS.get();
+ var offset = 0;
+ // We're always unlocked.
+ HEAP16[(((arg)+(offset))>>1)]=2;
+ return 0;
+ }
+ case 13:
+ case 14:
+ case 13:
+ case 14:
+ return 0; // Pretend that the locking is successful.
+ case 16:
+ case 8:
+ return -ERRNO_CODES.EINVAL; // These are for sockets. We don't have them fully implemented yet.
+ case 9:
+ // musl trusts getown return values, due to a bug where they must be, as they overlap with errors. just return -1 here, so fnctl() returns that, and we set errno ourselves.
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ default: {
+ return -ERRNO_CODES.EINVAL;
+ }
+ }
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall40(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // rmdir
+ var path = SYSCALLS.getStr();
+ FS.rmdir(path);
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall5(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // open
+ var pathname = SYSCALLS.getStr(), flags = SYSCALLS.get(), mode = SYSCALLS.get() // optional TODO
+ var stream = FS.open(pathname, flags, mode);
+ return stream.fd;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall54(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // ioctl
+ var stream = SYSCALLS.getStreamFromFD(), op = SYSCALLS.get();
+ switch (op) {
+ case 21509:
+ case 21505: {
+ if (!stream.tty) return -ERRNO_CODES.ENOTTY;
+ return 0;
+ }
+ case 21510:
+ case 21511:
+ case 21512:
+ case 21506:
+ case 21507:
+ case 21508: {
+ if (!stream.tty) return -ERRNO_CODES.ENOTTY;
+ return 0; // no-op, not actually adjusting terminal settings
+ }
+ case 21519: {
+ if (!stream.tty) return -ERRNO_CODES.ENOTTY;
+ var argp = SYSCALLS.get();
+ HEAP32[((argp)>>2)]=0;
+ return 0;
+ }
+ case 21520: {
+ if (!stream.tty) return -ERRNO_CODES.ENOTTY;
+ return -ERRNO_CODES.EINVAL; // not supported
+ }
+ case 21531: {
+ var argp = SYSCALLS.get();
+ return FS.ioctl(stream, op, argp);
+ }
+ case 21523: {
+ // TODO: in theory we should write to the winsize struct that gets
+ // passed in, but for now musl doesn't read anything on it
+ if (!stream.tty) return -ERRNO_CODES.ENOTTY;
+ return 0;
+ }
+ default: abort('bad ioctl syscall ' + op);
+ }
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall6(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // close
+ var stream = SYSCALLS.getStreamFromFD();
+ FS.close(stream);
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___syscall91(which, varargs) {SYSCALLS.varargs = varargs;
+ try {
+ // munmap
+ var addr = SYSCALLS.get(), len = SYSCALLS.get();
+ // TODO: support unmmap'ing parts of allocations
+ var info = SYSCALLS.mappings[addr];
+ if (!info) return 0;
+ if (len === info.len) {
+ var stream = FS.getStream(info.fd);
+ SYSCALLS.doMsync(addr, stream, len, info.flags)
+ FS.munmap(stream);
+ SYSCALLS.mappings[addr] = null;
+ if (info.allocated) {
+ _free(info.malloc);
+ }
+ }
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___unlock() {}
+
+
+ function __exit(status) {
+ // void _exit(int status);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
+ Module['exit'](status);
+ }function _exit(status) {
+ __exit(status);
+ }
+
+
+
+
+
+ var _environ=STATICTOP; STATICTOP += 16;;var ___environ=_environ;function ___buildEnvironment(env) {
+ // WARNING: Arbitrary limit!
+ var MAX_ENV_VALUES = 64;
+ var TOTAL_ENV_SIZE = 1024;
+
+ // Statically allocate memory for the environment.
+ var poolPtr;
+ var envPtr;
+ if (!___buildEnvironment.called) {
+ ___buildEnvironment.called = true;
+ // Set default values. Use string keys for Closure Compiler compatibility.
+ ENV['USER'] = ENV['LOGNAME'] = 'web_user';
+ ENV['PATH'] = '/';
+ ENV['PWD'] = '/';
+ ENV['HOME'] = '/home/web_user';
+ ENV['LANG'] = 'C.UTF-8';
+ ENV['_'] = Module['thisProgram'];
+ // Allocate memory.
+ poolPtr = staticAlloc(TOTAL_ENV_SIZE);
+ envPtr = staticAlloc(MAX_ENV_VALUES * 4);
+ HEAP32[((envPtr)>>2)]=poolPtr;
+ HEAP32[((_environ)>>2)]=envPtr;
+ } else {
+ envPtr = HEAP32[((_environ)>>2)];
+ poolPtr = HEAP32[((envPtr)>>2)];
+ }
+
+ // Collect key=value lines.
+ var strings = [];
+ var totalSize = 0;
+ for (var key in env) {
+ if (typeof env[key] === 'string') {
+ var line = key + '=' + env[key];
+ strings.push(line);
+ totalSize += line.length;
+ }
+ }
+ if (totalSize > TOTAL_ENV_SIZE) {
+ throw new Error('Environment size exceeded TOTAL_ENV_SIZE!');
+ }
+
+ // Make new.
+ var ptrSize = 4;
+ for (var i = 0; i < strings.length; i++) {
+ var line = strings[i];
+ writeAsciiToMemory(line, poolPtr);
+ HEAP32[(((envPtr)+(i * ptrSize))>>2)]=poolPtr;
+ poolPtr += line.length + 1;
+ }
+ HEAP32[(((envPtr)+(strings.length * ptrSize))>>2)]=0;
+ }var ENV={};function _getenv(name) {
+ // char *getenv(const char *name);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html
+ if (name === 0) return 0;
+ name = Pointer_stringify(name);
+ if (!ENV.hasOwnProperty(name)) return 0;
+
+ if (_getenv.ret) _free(_getenv.ret);
+ _getenv.ret = allocateUTF8(ENV[name]);
+ return _getenv.ret;
+ }
+
+
+
+ var _llvm_pow_f64=Math_pow;
+
+
+ function _emscripten_memcpy_big(dest, src, num) {
+ HEAPU8.set(HEAPU8.subarray(src, src+num), dest);
+ return dest;
+ }
+
+
+
+
+
+ function _system(command) {
+ // int system(const char *command);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/system.html
+ // Can't call external programs.
+ ___setErrNo(ERRNO_CODES.EAGAIN);
+ return -1;
+ }
+
+if (ENVIRONMENT_IS_NODE) {
+ _emscripten_get_now = function _emscripten_get_now_actual() {
+ var t = process['hrtime']();
+ return t[0] * 1e3 + t[1] / 1e6;
+ };
+ } else if (typeof dateNow !== 'undefined') {
+ _emscripten_get_now = dateNow;
+ } else if (typeof self === 'object' && self['performance'] && typeof self['performance']['now'] === 'function') {
+ _emscripten_get_now = function() { return self['performance']['now'](); };
+ } else if (typeof performance === 'object' && typeof performance['now'] === 'function') {
+ _emscripten_get_now = function() { return performance['now'](); };
+ } else {
+ _emscripten_get_now = Date.now;
+ };
+FS.staticInit();__ATINIT__.unshift(function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() });__ATMAIN__.push(function() { FS.ignorePermissions = false });__ATEXIT__.push(function() { FS.quit() });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice;Module["FS_unlink"] = FS.unlink;;
+__ATINIT__.unshift(function() { TTY.init() });__ATEXIT__.push(function() { TTY.shutdown() });;
+if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); var NODEJS_PATH = require("path"); NODEFS.staticInit(); };
+___buildEnvironment(ENV);;
+DYNAMICTOP_PTR = staticAlloc(4);
+
+STACK_BASE = STACKTOP = alignMemory(STATICTOP);
+
+STACK_MAX = STACK_BASE + TOTAL_STACK;
+
+DYNAMIC_BASE = alignMemory(STACK_MAX);
+
+HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE;
+
+staticSealed = true; // seal the static portion of memory
+
+assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack");
+
+var ASSERTIONS = true;
+
+/** @type {function(string, boolean=, number=)} */
+function intArrayFromString(stringy, dontAddNull, length) {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+}
+
+function intArrayToString(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+ var chr = array[i];
+ if (chr > 0xFF) {
+ if (ASSERTIONS) {
+ assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
+ }
+ chr &= 0xFF;
+ }
+ ret.push(String.fromCharCode(chr));
+ }
+ return ret.join('');
+}
+
+
+
+function nullFunc_ii(x) { Module["printErr"]("Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); Module["printErr"]("Build with ASSERTIONS=2 for more info.");abort(x) }
+
+function nullFunc_iii(x) { Module["printErr"]("Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); Module["printErr"]("Build with ASSERTIONS=2 for more info.");abort(x) }
+
+function nullFunc_iiii(x) { Module["printErr"]("Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); Module["printErr"]("Build with ASSERTIONS=2 for more info.");abort(x) }
+
+function nullFunc_v(x) { Module["printErr"]("Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); Module["printErr"]("Build with ASSERTIONS=2 for more info.");abort(x) }
+
+Module['wasmTableSize'] = 84;
+
+Module['wasmMaxTableSize'] = 84;
+
+function invoke_ii(index,a1) {
+ try {
+ return Module["dynCall_ii"](index,a1);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
+ }
+}
+
+function jsCall_ii(index,a1) {
+ return functionPointers[index](a1);
+}
+
+function invoke_iii(index,a1,a2) {
+ try {
+ return Module["dynCall_iii"](index,a1,a2);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
+ }
+}
+
+function jsCall_iii(index,a1,a2) {
+ return functionPointers[index](a1,a2);
+}
+
+function invoke_iiii(index,a1,a2,a3) {
+ try {
+ return Module["dynCall_iiii"](index,a1,a2,a3);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
+ }
+}
+
+function jsCall_iiii(index,a1,a2,a3) {
+ return functionPointers[index](a1,a2,a3);
+}
+
+function invoke_v(index) {
+ try {
+ Module["dynCall_v"](index);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ Module["setThrew"](1, 0);
+ }
+}
+
+function jsCall_v(index) {
+ functionPointers[index]();
+}
+
+Module.asmGlobalArg = {};
+
+Module.asmLibraryArg = { "abort": abort, "assert": assert, "enlargeMemory": enlargeMemory, "getTotalMemory": getTotalMemory, "abortOnCannotGrowMemory": abortOnCannotGrowMemory, "abortStackOverflow": abortStackOverflow, "nullFunc_ii": nullFunc_ii, "nullFunc_iii": nullFunc_iii, "nullFunc_iiii": nullFunc_iiii, "nullFunc_v": nullFunc_v, "invoke_ii": invoke_ii, "jsCall_ii": jsCall_ii, "invoke_iii": invoke_iii, "jsCall_iii": jsCall_iii, "invoke_iiii": invoke_iiii, "jsCall_iiii": jsCall_iiii, "invoke_v": invoke_v, "jsCall_v": jsCall_v, "__ZSt18uncaught_exceptionv": __ZSt18uncaught_exceptionv, "___buildEnvironment": ___buildEnvironment, "___clock_gettime": ___clock_gettime, "___cxa_find_matching_catch": ___cxa_find_matching_catch, "___gxx_personality_v0": ___gxx_personality_v0, "___lock": ___lock, "___map_file": ___map_file, "___resumeException": ___resumeException, "___setErrNo": ___setErrNo, "___syscall10": ___syscall10, "___syscall140": ___syscall140, "___syscall145": ___syscall145, "___syscall146": ___syscall146, "___syscall195": ___syscall195, "___syscall220": ___syscall220, "___syscall221": ___syscall221, "___syscall40": ___syscall40, "___syscall5": ___syscall5, "___syscall54": ___syscall54, "___syscall6": ___syscall6, "___syscall91": ___syscall91, "___unlock": ___unlock, "__exit": __exit, "_clock_gettime": _clock_gettime, "_emscripten_get_now": _emscripten_get_now, "_emscripten_get_now_is_monotonic": _emscripten_get_now_is_monotonic, "_emscripten_memcpy_big": _emscripten_memcpy_big, "_exit": _exit, "_getenv": _getenv, "_llvm_pow_f64": _llvm_pow_f64, "_system": _system, "DYNAMICTOP_PTR": DYNAMICTOP_PTR, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX };
+// EMSCRIPTEN_START_ASM
+var asm =Module["asm"]// EMSCRIPTEN_END_ASM
+(Module.asmGlobalArg, Module.asmLibraryArg, buffer);
+
+var real____errno_location = asm["___errno_location"]; asm["___errno_location"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real____errno_location.apply(null, arguments);
+};
+
+var real__emscripten_bind_VoidPtr___destroy___0 = asm["_emscripten_bind_VoidPtr___destroy___0"]; asm["_emscripten_bind_VoidPtr___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_VoidPtr___destroy___0.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker___destroy___0 = asm["_emscripten_bind_eSpeakNGWorker___destroy___0"]; asm["_emscripten_bind_eSpeakNGWorker___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker___destroy___0.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0 = asm["_emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0"]; asm["_emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0 = asm["_emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0"]; asm["_emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_get_pitch_0 = asm["_emscripten_bind_eSpeakNGWorker_get_pitch_0"]; asm["_emscripten_bind_eSpeakNGWorker_get_pitch_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_get_pitch_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_get_rate_0 = asm["_emscripten_bind_eSpeakNGWorker_get_rate_0"]; asm["_emscripten_bind_eSpeakNGWorker_get_rate_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_get_rate_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_get_samplerate_0 = asm["_emscripten_bind_eSpeakNGWorker_get_samplerate_0"]; asm["_emscripten_bind_eSpeakNGWorker_get_samplerate_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_get_samplerate_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_get_voices_1 = asm["_emscripten_bind_eSpeakNGWorker_get_voices_1"]; asm["_emscripten_bind_eSpeakNGWorker_get_voices_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_get_voices_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_set_pitch_1 = asm["_emscripten_bind_eSpeakNGWorker_set_pitch_1"]; asm["_emscripten_bind_eSpeakNGWorker_set_pitch_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_set_pitch_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_set_rate_1 = asm["_emscripten_bind_eSpeakNGWorker_set_rate_1"]; asm["_emscripten_bind_eSpeakNGWorker_set_rate_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_set_rate_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_set_voice_2 = asm["_emscripten_bind_eSpeakNGWorker_set_voice_2"]; asm["_emscripten_bind_eSpeakNGWorker_set_voice_2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_set_voice_2.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_set_voice_3 = asm["_emscripten_bind_eSpeakNGWorker_set_voice_3"]; asm["_emscripten_bind_eSpeakNGWorker_set_voice_3"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_set_voice_3.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_set_voice_4 = asm["_emscripten_bind_eSpeakNGWorker_set_voice_4"]; asm["_emscripten_bind_eSpeakNGWorker_set_voice_4"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_set_voice_4.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_set_voice_5 = asm["_emscripten_bind_eSpeakNGWorker_set_voice_5"]; asm["_emscripten_bind_eSpeakNGWorker_set_voice_5"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_set_voice_5.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_set_voices_2 = asm["_emscripten_bind_eSpeakNGWorker_set_voices_2"]; asm["_emscripten_bind_eSpeakNGWorker_set_voices_2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_set_voices_2.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_synth__2 = asm["_emscripten_bind_eSpeakNGWorker_synth__2"]; asm["_emscripten_bind_eSpeakNGWorker_synth__2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_synth__2.apply(null, arguments);
+};
+
+var real__emscripten_bind_eSpeakNGWorker_synth_ipa__2 = asm["_emscripten_bind_eSpeakNGWorker_synth_ipa__2"]; asm["_emscripten_bind_eSpeakNGWorker_synth_ipa__2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_eSpeakNGWorker_synth_ipa__2.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT___destroy___0 = asm["_emscripten_bind_espeak_EVENT___destroy___0"]; asm["_emscripten_bind_espeak_EVENT___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT___destroy___0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT_get_audio_position_0 = asm["_emscripten_bind_espeak_EVENT_get_audio_position_0"]; asm["_emscripten_bind_espeak_EVENT_get_audio_position_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT_get_audio_position_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT_get_length_0 = asm["_emscripten_bind_espeak_EVENT_get_length_0"]; asm["_emscripten_bind_espeak_EVENT_get_length_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT_get_length_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT_get_sample_0 = asm["_emscripten_bind_espeak_EVENT_get_sample_0"]; asm["_emscripten_bind_espeak_EVENT_get_sample_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT_get_sample_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT_get_text_position_0 = asm["_emscripten_bind_espeak_EVENT_get_text_position_0"]; asm["_emscripten_bind_espeak_EVENT_get_text_position_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT_get_text_position_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT_get_type_0 = asm["_emscripten_bind_espeak_EVENT_get_type_0"]; asm["_emscripten_bind_espeak_EVENT_get_type_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT_get_type_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT_get_unique_identifier_0 = asm["_emscripten_bind_espeak_EVENT_get_unique_identifier_0"]; asm["_emscripten_bind_espeak_EVENT_get_unique_identifier_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT_get_unique_identifier_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_EVENT_get_user_data_0 = asm["_emscripten_bind_espeak_EVENT_get_user_data_0"]; asm["_emscripten_bind_espeak_EVENT_get_user_data_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_EVENT_get_user_data_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE___destroy___0 = asm["_emscripten_bind_espeak_VOICE___destroy___0"]; asm["_emscripten_bind_espeak_VOICE___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE___destroy___0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_age_0 = asm["_emscripten_bind_espeak_VOICE_get_age_0"]; asm["_emscripten_bind_espeak_VOICE_get_age_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_age_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_gender_0 = asm["_emscripten_bind_espeak_VOICE_get_gender_0"]; asm["_emscripten_bind_espeak_VOICE_get_gender_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_gender_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_identifier_0 = asm["_emscripten_bind_espeak_VOICE_get_identifier_0"]; asm["_emscripten_bind_espeak_VOICE_get_identifier_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_identifier_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_languages_1 = asm["_emscripten_bind_espeak_VOICE_get_languages_1"]; asm["_emscripten_bind_espeak_VOICE_get_languages_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_languages_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_name_0 = asm["_emscripten_bind_espeak_VOICE_get_name_0"]; asm["_emscripten_bind_espeak_VOICE_get_name_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_name_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_score_0 = asm["_emscripten_bind_espeak_VOICE_get_score_0"]; asm["_emscripten_bind_espeak_VOICE_get_score_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_score_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_spare_0 = asm["_emscripten_bind_espeak_VOICE_get_spare_0"]; asm["_emscripten_bind_espeak_VOICE_get_spare_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_spare_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_variant_0 = asm["_emscripten_bind_espeak_VOICE_get_variant_0"]; asm["_emscripten_bind_espeak_VOICE_get_variant_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_variant_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_get_xx1_0 = asm["_emscripten_bind_espeak_VOICE_get_xx1_0"]; asm["_emscripten_bind_espeak_VOICE_get_xx1_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_get_xx1_0.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_age_1 = asm["_emscripten_bind_espeak_VOICE_set_age_1"]; asm["_emscripten_bind_espeak_VOICE_set_age_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_age_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_gender_1 = asm["_emscripten_bind_espeak_VOICE_set_gender_1"]; asm["_emscripten_bind_espeak_VOICE_set_gender_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_gender_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_identifier_1 = asm["_emscripten_bind_espeak_VOICE_set_identifier_1"]; asm["_emscripten_bind_espeak_VOICE_set_identifier_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_identifier_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_name_1 = asm["_emscripten_bind_espeak_VOICE_set_name_1"]; asm["_emscripten_bind_espeak_VOICE_set_name_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_name_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_score_1 = asm["_emscripten_bind_espeak_VOICE_set_score_1"]; asm["_emscripten_bind_espeak_VOICE_set_score_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_score_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_spare_1 = asm["_emscripten_bind_espeak_VOICE_set_spare_1"]; asm["_emscripten_bind_espeak_VOICE_set_spare_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_spare_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_variant_1 = asm["_emscripten_bind_espeak_VOICE_set_variant_1"]; asm["_emscripten_bind_espeak_VOICE_set_variant_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_variant_1.apply(null, arguments);
+};
+
+var real__emscripten_bind_espeak_VOICE_set_xx1_1 = asm["_emscripten_bind_espeak_VOICE_set_xx1_1"]; asm["_emscripten_bind_espeak_VOICE_set_xx1_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_bind_espeak_VOICE_set_xx1_1.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE.apply(null, arguments);
+};
+
+var real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD = asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD"]; asm["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD.apply(null, arguments);
+};
+
+var real__fflush = asm["_fflush"]; asm["_fflush"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__fflush.apply(null, arguments);
+};
+
+var real__free = asm["_free"]; asm["_free"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__free.apply(null, arguments);
+};
+
+var real__llvm_bswap_i32 = asm["_llvm_bswap_i32"]; asm["_llvm_bswap_i32"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__llvm_bswap_i32.apply(null, arguments);
+};
+
+var real__malloc = asm["_malloc"]; asm["_malloc"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__malloc.apply(null, arguments);
+};
+
+var real__sbrk = asm["_sbrk"]; asm["_sbrk"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real__sbrk.apply(null, arguments);
+};
+
+var real_establishStackSpace = asm["establishStackSpace"]; asm["establishStackSpace"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real_establishStackSpace.apply(null, arguments);
+};
+
+var real_getTempRet0 = asm["getTempRet0"]; asm["getTempRet0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real_getTempRet0.apply(null, arguments);
+};
+
+var real_setTempRet0 = asm["setTempRet0"]; asm["setTempRet0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real_setTempRet0.apply(null, arguments);
+};
+
+var real_setThrew = asm["setThrew"]; asm["setThrew"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real_setThrew.apply(null, arguments);
+};
+
+var real_stackAlloc = asm["stackAlloc"]; asm["stackAlloc"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real_stackAlloc.apply(null, arguments);
+};
+
+var real_stackRestore = asm["stackRestore"]; asm["stackRestore"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real_stackRestore.apply(null, arguments);
+};
+
+var real_stackSave = asm["stackSave"]; asm["stackSave"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return real_stackSave.apply(null, arguments);
+};
+Module["asm"] = asm;
+var ___errno_location = Module["___errno_location"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["___errno_location"].apply(null, arguments) };
+var _emscripten_bind_VoidPtr___destroy___0 = Module["_emscripten_bind_VoidPtr___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_VoidPtr___destroy___0"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker___destroy___0 = Module["_emscripten_bind_eSpeakNGWorker___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker___destroy___0"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0 = Module["_emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0 = Module["_emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_get_pitch_0 = Module["_emscripten_bind_eSpeakNGWorker_get_pitch_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_get_pitch_0"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_get_rate_0 = Module["_emscripten_bind_eSpeakNGWorker_get_rate_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_get_rate_0"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_get_samplerate_0 = Module["_emscripten_bind_eSpeakNGWorker_get_samplerate_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_get_samplerate_0"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_get_voices_1 = Module["_emscripten_bind_eSpeakNGWorker_get_voices_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_get_voices_1"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_set_pitch_1 = Module["_emscripten_bind_eSpeakNGWorker_set_pitch_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_set_pitch_1"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_set_rate_1 = Module["_emscripten_bind_eSpeakNGWorker_set_rate_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_set_rate_1"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_set_voice_2 = Module["_emscripten_bind_eSpeakNGWorker_set_voice_2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_set_voice_2"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_set_voice_3 = Module["_emscripten_bind_eSpeakNGWorker_set_voice_3"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_set_voice_3"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_set_voice_4 = Module["_emscripten_bind_eSpeakNGWorker_set_voice_4"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_set_voice_4"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_set_voice_5 = Module["_emscripten_bind_eSpeakNGWorker_set_voice_5"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_set_voice_5"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_set_voices_2 = Module["_emscripten_bind_eSpeakNGWorker_set_voices_2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_set_voices_2"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_synth__2 = Module["_emscripten_bind_eSpeakNGWorker_synth__2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_synth__2"].apply(null, arguments) };
+var _emscripten_bind_eSpeakNGWorker_synth_ipa__2 = Module["_emscripten_bind_eSpeakNGWorker_synth_ipa__2"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_eSpeakNGWorker_synth_ipa__2"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT___destroy___0 = Module["_emscripten_bind_espeak_EVENT___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT___destroy___0"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT_get_audio_position_0 = Module["_emscripten_bind_espeak_EVENT_get_audio_position_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT_get_audio_position_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT_get_length_0 = Module["_emscripten_bind_espeak_EVENT_get_length_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT_get_length_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT_get_sample_0 = Module["_emscripten_bind_espeak_EVENT_get_sample_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT_get_sample_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT_get_text_position_0 = Module["_emscripten_bind_espeak_EVENT_get_text_position_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT_get_text_position_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT_get_type_0 = Module["_emscripten_bind_espeak_EVENT_get_type_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT_get_type_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT_get_unique_identifier_0 = Module["_emscripten_bind_espeak_EVENT_get_unique_identifier_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT_get_unique_identifier_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_EVENT_get_user_data_0 = Module["_emscripten_bind_espeak_EVENT_get_user_data_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_EVENT_get_user_data_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE___destroy___0 = Module["_emscripten_bind_espeak_VOICE___destroy___0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE___destroy___0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_age_0 = Module["_emscripten_bind_espeak_VOICE_get_age_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_age_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_gender_0 = Module["_emscripten_bind_espeak_VOICE_get_gender_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_gender_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_identifier_0 = Module["_emscripten_bind_espeak_VOICE_get_identifier_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_identifier_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_languages_1 = Module["_emscripten_bind_espeak_VOICE_get_languages_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_languages_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_name_0 = Module["_emscripten_bind_espeak_VOICE_get_name_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_name_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_score_0 = Module["_emscripten_bind_espeak_VOICE_get_score_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_score_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_spare_0 = Module["_emscripten_bind_espeak_VOICE_get_spare_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_spare_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_variant_0 = Module["_emscripten_bind_espeak_VOICE_get_variant_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_variant_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_get_xx1_0 = Module["_emscripten_bind_espeak_VOICE_get_xx1_0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_get_xx1_0"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_age_1 = Module["_emscripten_bind_espeak_VOICE_set_age_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_age_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_gender_1 = Module["_emscripten_bind_espeak_VOICE_set_gender_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_gender_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_identifier_1 = Module["_emscripten_bind_espeak_VOICE_set_identifier_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_identifier_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_name_1 = Module["_emscripten_bind_espeak_VOICE_set_name_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_name_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_score_1 = Module["_emscripten_bind_espeak_VOICE_set_score_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_score_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_spare_1 = Module["_emscripten_bind_espeak_VOICE_set_spare_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_spare_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_variant_1 = Module["_emscripten_bind_espeak_VOICE_set_variant_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_variant_1"].apply(null, arguments) };
+var _emscripten_bind_espeak_VOICE_set_xx1_1 = Module["_emscripten_bind_espeak_VOICE_set_xx1_1"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_bind_espeak_VOICE_set_xx1_1"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE"].apply(null, arguments) };
+var _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD = Module["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD"].apply(null, arguments) };
+var _fflush = Module["_fflush"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_fflush"].apply(null, arguments) };
+var _free = Module["_free"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_free"].apply(null, arguments) };
+var _llvm_bswap_i32 = Module["_llvm_bswap_i32"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_llvm_bswap_i32"].apply(null, arguments) };
+var _malloc = Module["_malloc"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_malloc"].apply(null, arguments) };
+var _memcpy = Module["_memcpy"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_memcpy"].apply(null, arguments) };
+var _memset = Module["_memset"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_memset"].apply(null, arguments) };
+var _sbrk = Module["_sbrk"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["_sbrk"].apply(null, arguments) };
+var establishStackSpace = Module["establishStackSpace"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["establishStackSpace"].apply(null, arguments) };
+var getTempRet0 = Module["getTempRet0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["getTempRet0"].apply(null, arguments) };
+var runPostSets = Module["runPostSets"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["runPostSets"].apply(null, arguments) };
+var setTempRet0 = Module["setTempRet0"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["setTempRet0"].apply(null, arguments) };
+var setThrew = Module["setThrew"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["setThrew"].apply(null, arguments) };
+var stackAlloc = Module["stackAlloc"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["stackAlloc"].apply(null, arguments) };
+var stackRestore = Module["stackRestore"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["stackRestore"].apply(null, arguments) };
+var stackSave = Module["stackSave"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["stackSave"].apply(null, arguments) };
+var dynCall_ii = Module["dynCall_ii"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["dynCall_ii"].apply(null, arguments) };
+var dynCall_iii = Module["dynCall_iii"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["dynCall_iii"].apply(null, arguments) };
+var dynCall_iiii = Module["dynCall_iiii"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["dynCall_iiii"].apply(null, arguments) };
+var dynCall_v = Module["dynCall_v"] = function() {
+ assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');
+ assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
+ return Module["asm"]["dynCall_v"].apply(null, arguments) };
+;
+
+
+
+// === Auto-generated postamble setup entry stuff ===
+
+Module['asm'] = asm;
+
+if (!Module["intArrayFromString"]) Module["intArrayFromString"] = function() { abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["intArrayToString"]) Module["intArrayToString"] = function() { abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["ccall"]) Module["ccall"] = function() { abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["cwrap"]) Module["cwrap"] = function() { abort("'cwrap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["setValue"]) Module["setValue"] = function() { abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["getValue"]) Module["getValue"] = function() { abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["allocate"]) Module["allocate"] = function() { abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+Module["getMemory"] = getMemory;
+if (!Module["Pointer_stringify"]) Module["Pointer_stringify"] = function() { abort("'Pointer_stringify' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["AsciiToString"]) Module["AsciiToString"] = function() { abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stringToAscii"]) Module["stringToAscii"] = function() { abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["UTF8ArrayToString"]) Module["UTF8ArrayToString"] = function() { abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["UTF8ToString"]) Module["UTF8ToString"] = function() { abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stringToUTF8Array"]) Module["stringToUTF8Array"] = function() { abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stringToUTF8"]) Module["stringToUTF8"] = function() { abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["lengthBytesUTF8"]) Module["lengthBytesUTF8"] = function() { abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["UTF16ToString"]) Module["UTF16ToString"] = function() { abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stringToUTF16"]) Module["stringToUTF16"] = function() { abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["lengthBytesUTF16"]) Module["lengthBytesUTF16"] = function() { abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["UTF32ToString"]) Module["UTF32ToString"] = function() { abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stringToUTF32"]) Module["stringToUTF32"] = function() { abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["lengthBytesUTF32"]) Module["lengthBytesUTF32"] = function() { abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["allocateUTF8"]) Module["allocateUTF8"] = function() { abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stackTrace"]) Module["stackTrace"] = function() { abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["addOnPreRun"]) Module["addOnPreRun"] = function() { abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["addOnInit"]) Module["addOnInit"] = function() { abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["addOnPreMain"]) Module["addOnPreMain"] = function() { abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["addOnExit"]) Module["addOnExit"] = function() { abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["addOnPostRun"]) Module["addOnPostRun"] = function() { abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["writeStringToMemory"]) Module["writeStringToMemory"] = function() { abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["writeArrayToMemory"]) Module["writeArrayToMemory"] = function() { abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["writeAsciiToMemory"]) Module["writeAsciiToMemory"] = function() { abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+Module["addRunDependency"] = addRunDependency;
+Module["removeRunDependency"] = removeRunDependency;
+if (!Module["FS"]) Module["FS"] = function() { abort("'FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+Module["FS_createFolder"] = FS.createFolder;
+Module["FS_createPath"] = FS.createPath;
+Module["FS_createDataFile"] = FS.createDataFile;
+Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
+Module["FS_createLazyFile"] = FS.createLazyFile;
+Module["FS_createLink"] = FS.createLink;
+Module["FS_createDevice"] = FS.createDevice;
+Module["FS_unlink"] = FS.unlink;
+if (!Module["GL"]) Module["GL"] = function() { abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["staticAlloc"]) Module["staticAlloc"] = function() { abort("'staticAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["dynamicAlloc"]) Module["dynamicAlloc"] = function() { abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["warnOnce"]) Module["warnOnce"] = function() { abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["loadDynamicLibrary"]) Module["loadDynamicLibrary"] = function() { abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["loadWebAssemblyModule"]) Module["loadWebAssemblyModule"] = function() { abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["getLEB"]) Module["getLEB"] = function() { abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["getFunctionTables"]) Module["getFunctionTables"] = function() { abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["alignFunctionTables"]) Module["alignFunctionTables"] = function() { abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["registerFunctions"]) Module["registerFunctions"] = function() { abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["addFunction"]) Module["addFunction"] = function() { abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["removeFunction"]) Module["removeFunction"] = function() { abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["getFuncWrapper"]) Module["getFuncWrapper"] = function() { abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["prettyPrint"]) Module["prettyPrint"] = function() { abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["makeBigInt"]) Module["makeBigInt"] = function() { abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["dynCall"]) Module["dynCall"] = function() { abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["getCompilerSetting"]) Module["getCompilerSetting"] = function() { abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stackSave"]) Module["stackSave"] = function() { abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stackRestore"]) Module["stackRestore"] = function() { abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Module["stackAlloc"]) Module["stackAlloc"] = function() { abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };if (!Module["ALLOC_NORMAL"]) Object.defineProperty(Module, "ALLOC_NORMAL", { get: function() { abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
+if (!Module["ALLOC_STACK"]) Object.defineProperty(Module, "ALLOC_STACK", { get: function() { abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
+if (!Module["ALLOC_STATIC"]) Object.defineProperty(Module, "ALLOC_STATIC", { get: function() { abort("'ALLOC_STATIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
+if (!Module["ALLOC_DYNAMIC"]) Object.defineProperty(Module, "ALLOC_DYNAMIC", { get: function() { abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
+if (!Module["ALLOC_NONE"]) Object.defineProperty(Module, "ALLOC_NONE", { get: function() { abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
+
+
+
+
+/**
+ * @constructor
+ * @extends {Error}
+ * @this {ExitStatus}
+ */
+function ExitStatus(status) {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+};
+ExitStatus.prototype = new Error();
+ExitStatus.prototype.constructor = ExitStatus;
+
+var initialStackTop;
+var calledMain = false;
+
+dependenciesFulfilled = function runCaller() {
+ // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
+ if (!Module['calledRun']) run();
+ if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
+}
+
+
+
+
+
+/** @type {function(Array=)} */
+function run(args) {
+ args = args || Module['arguments'];
+
+ if (runDependencies > 0) {
+ return;
+ }
+
+ writeStackCookie();
+
+ preRun();
+
+ if (runDependencies > 0) return; // a preRun added a dependency, run will be called later
+ if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame
+
+ function doRun() {
+ if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening
+ Module['calledRun'] = true;
+
+ if (ABORT) return;
+
+ ensureInitRuntime();
+
+ preMain();
+
+ if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
+
+ assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');
+
+ postRun();
+ }
+
+ if (Module['setStatus']) {
+ Module['setStatus']('Running...');
+ setTimeout(function() {
+ setTimeout(function() {
+ Module['setStatus']('');
+ }, 1);
+ doRun();
+ }, 1);
+ } else {
+ doRun();
+ }
+ checkStackCookie();
+}
+Module['run'] = run;
+
+function checkUnflushedContent() {
+ // Compiler settings do not allow exiting the runtime, so flushing
+ // the streams is not possible. but in ASSERTIONS mode we check
+ // if there was something to flush, and if so tell the user they
+ // should request that the runtime be exitable.
+ // Normally we would not even include flush() at all, but in ASSERTIONS
+ // builds we do so just for this check, and here we see if there is any
+ // content to flush, that is, we check if there would have been
+ // something a non-ASSERTIONS build would have not seen.
+ // How we flush the streams depends on whether we are in NO_FILESYSTEM
+ // mode (which has its own special function for this; otherwise, all
+ // the code is inside libc)
+ var print = Module['print'];
+ var printErr = Module['printErr'];
+ var has = false;
+ Module['print'] = Module['printErr'] = function(x) {
+ has = true;
+ }
+ try { // it doesn't matter if it fails
+ var flush = Module['_fflush'];
+ if (flush) flush(0);
+ // also flush in the JS FS layer
+ var hasFS = true;
+ if (hasFS) {
+ ['stdout', 'stderr'].forEach(function(name) {
+ var info = FS.analyzePath('/dev/' + name);
+ if (!info) return;
+ var stream = info.object;
+ var rdev = stream.rdev;
+ var tty = TTY.ttys[rdev];
+ if (tty && tty.output && tty.output.length) {
+ has = true;
+ }
+ });
+ }
+ } catch(e) {}
+ Module['print'] = print;
+ Module['printErr'] = printErr;
+ if (has) {
+ warnOnce('stdio streams had content in them that was not flushed. you should set NO_EXIT_RUNTIME to 0 (see the FAQ), or make sure to emit a newline when you printf etc.');
+ }
+}
+
+function exit(status, implicit) {
+ checkUnflushedContent();
+
+ // if this is just main exit-ing implicitly, and the status is 0, then we
+ // don't need to do anything here and can just leave. if the status is
+ // non-zero, though, then we need to report it.
+ // (we may have warned about this earlier, if a situation justifies doing so)
+ if (implicit && Module['noExitRuntime'] && status === 0) {
+ return;
+ }
+
+ if (Module['noExitRuntime']) {
+ // if exit() was called, we may warn the user if the runtime isn't actually being shut down
+ if (!implicit) {
+ Module.printErr('exit(' + status + ') called, but NO_EXIT_RUNTIME is set, so halting execution but not exiting the runtime or preventing further async execution (build with NO_EXIT_RUNTIME=0, if you want a true shutdown)');
+ }
+ } else {
+
+ ABORT = true;
+ EXITSTATUS = status;
+ STACKTOP = initialStackTop;
+
+ exitRuntime();
+
+ if (Module['onExit']) Module['onExit'](status);
+ }
+
+ if (ENVIRONMENT_IS_NODE) {
+ process['exit'](status);
+ }
+ Module['quit'](status, new ExitStatus(status));
+}
+Module['exit'] = exit;
+
+var abortDecorators = [];
+
+function abort(what) {
+ if (Module['onAbort']) {
+ Module['onAbort'](what);
+ }
+
+ if (what !== undefined) {
+ Module.print(what);
+ Module.printErr(what);
+ what = JSON.stringify(what)
+ } else {
+ what = '';
+ }
+
+ ABORT = true;
+ EXITSTATUS = 1;
+
+ var extra = '';
+ var output = 'abort(' + what + ') at ' + stackTrace() + extra;
+ if (abortDecorators) {
+ abortDecorators.forEach(function(decorator) {
+ output = decorator(output, what);
+ });
+ }
+ throw output;
+}
+Module['abort'] = abort;
+
+// {{PRE_RUN_ADDITIONS}}
+
+if (Module['preInit']) {
+ if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
+ while (Module['preInit'].length > 0) {
+ Module['preInit'].pop()();
+ }
+}
+
+
+Module["noExitRuntime"] = true;
+
+run();
+
+// {{POST_RUN_ADDITIONS}}
+
+
+
+
+
+// {{MODULE_ADDITIONS}}
+
+
+
+
+// Bindings utilities
+
+function WrapperObject() {
+}
+WrapperObject.prototype = Object.create(WrapperObject.prototype);
+WrapperObject.prototype.constructor = WrapperObject;
+WrapperObject.prototype.__class__ = WrapperObject;
+WrapperObject.__cache__ = {};
+Module['WrapperObject'] = WrapperObject;
+
+function getCache(__class__) {
+ return (__class__ || WrapperObject).__cache__;
+}
+Module['getCache'] = getCache;
+
+function wrapPointer(ptr, __class__) {
+ var cache = getCache(__class__);
+ var ret = cache[ptr];
+ if (ret) return ret;
+ ret = Object.create((__class__ || WrapperObject).prototype);
+ ret.ptr = ptr;
+ return cache[ptr] = ret;
+}
+Module['wrapPointer'] = wrapPointer;
+
+function castObject(obj, __class__) {
+ return wrapPointer(obj.ptr, __class__);
+}
+Module['castObject'] = castObject;
+
+Module['NULL'] = wrapPointer(0);
+
+function destroy(obj) {
+ if (!obj['__destroy__']) throw 'Error: Cannot destroy object. (Did you create it yourself?)';
+ obj['__destroy__']();
+ // Remove from cache, so the object can be GC'd and refs added onto it released
+ delete getCache(obj.__class__)[obj.ptr];
+}
+Module['destroy'] = destroy;
+
+function compare(obj1, obj2) {
+ return obj1.ptr === obj2.ptr;
+}
+Module['compare'] = compare;
+
+function getPointer(obj) {
+ return obj.ptr;
+}
+Module['getPointer'] = getPointer;
+
+function getClass(obj) {
+ return obj.__class__;
+}
+Module['getClass'] = getClass;
+
+// Converts big (string or array) values into a C-style storage, in temporary space
+
+var ensureCache = {
+ buffer: 0, // the main buffer of temporary storage
+ size: 0, // the size of buffer
+ pos: 0, // the next free offset in buffer
+ temps: [], // extra allocations
+ needed: 0, // the total size we need next time
+
+ prepare: function() {
+ if (ensureCache.needed) {
+ // clear the temps
+ for (var i = 0; i < ensureCache.temps.length; i++) {
+ Module['_free'](ensureCache.temps[i]);
+ }
+ ensureCache.temps.length = 0;
+ // prepare to allocate a bigger buffer
+ Module['_free'](ensureCache.buffer);
+ ensureCache.buffer = 0;
+ ensureCache.size += ensureCache.needed;
+ // clean up
+ ensureCache.needed = 0;
+ }
+ if (!ensureCache.buffer) { // happens first time, or when we need to grow
+ ensureCache.size += 128; // heuristic, avoid many small grow events
+ ensureCache.buffer = Module['_malloc'](ensureCache.size);
+ assert(ensureCache.buffer);
+ }
+ ensureCache.pos = 0;
+ },
+ alloc: function(array, view) {
+ assert(ensureCache.buffer);
+ var bytes = view.BYTES_PER_ELEMENT;
+ var len = array.length * bytes;
+ len = (len + 7) & -8; // keep things aligned to 8 byte boundaries
+ var ret;
+ if (ensureCache.pos + len >= ensureCache.size) {
+ // we failed to allocate in the buffer, ensureCache time around :(
+ assert(len > 0); // null terminator, at least
+ ensureCache.needed += len;
+ ret = Module['_malloc'](len);
+ ensureCache.temps.push(ret);
+ } else {
+ // we can allocate in the buffer
+ ret = ensureCache.buffer + ensureCache.pos;
+ ensureCache.pos += len;
+ }
+ return ret;
+ },
+ copy: function(array, view, offset) {
+ var offsetShifted = offset;
+ var bytes = view.BYTES_PER_ELEMENT;
+ switch (bytes) {
+ case 2: offsetShifted >>= 1; break;
+ case 4: offsetShifted >>= 2; break;
+ case 8: offsetShifted >>= 3; break;
+ }
+ for (var i = 0; i < array.length; i++) {
+ view[offsetShifted + i] = array[i];
+ }
+ },
+};
+
+function ensureString(value) {
+ if (typeof value === 'string') {
+ var intArray = intArrayFromString(value);
+ var offset = ensureCache.alloc(intArray, HEAP8);
+ ensureCache.copy(intArray, HEAP8, offset);
+ return offset;
+ }
+ return value;
+}
+function ensureInt8(value) {
+ if (typeof value === 'object') {
+ var offset = ensureCache.alloc(value, HEAP8);
+ ensureCache.copy(value, HEAP8, offset);
+ return offset;
+ }
+ return value;
+}
+function ensureInt16(value) {
+ if (typeof value === 'object') {
+ var offset = ensureCache.alloc(value, HEAP16);
+ ensureCache.copy(value, HEAP16, offset);
+ return offset;
+ }
+ return value;
+}
+function ensureInt32(value) {
+ if (typeof value === 'object') {
+ var offset = ensureCache.alloc(value, HEAP32);
+ ensureCache.copy(value, HEAP32, offset);
+ return offset;
+ }
+ return value;
+}
+function ensureFloat32(value) {
+ if (typeof value === 'object') {
+ var offset = ensureCache.alloc(value, HEAPF32);
+ ensureCache.copy(value, HEAPF32, offset);
+ return offset;
+ }
+ return value;
+}
+function ensureFloat64(value) {
+ if (typeof value === 'object') {
+ var offset = ensureCache.alloc(value, HEAPF64);
+ ensureCache.copy(value, HEAPF64, offset);
+ return offset;
+ }
+ return value;
+}
+
+
+// eSpeakNGWorker
+/** @suppress {undefinedVars, duplicate} */function eSpeakNGWorker() {
+ this.ptr = _emscripten_bind_eSpeakNGWorker_eSpeakNGWorker_0();
+ getCache(eSpeakNGWorker)[this.ptr] = this;
+};;
+eSpeakNGWorker.prototype = Object.create(WrapperObject.prototype);
+eSpeakNGWorker.prototype.constructor = eSpeakNGWorker;
+eSpeakNGWorker.prototype.__class__ = eSpeakNGWorker;
+eSpeakNGWorker.__cache__ = {};
+Module['eSpeakNGWorker'] = eSpeakNGWorker;
+
+eSpeakNGWorker.prototype['synth_'] = eSpeakNGWorker.prototype.synth_ = /** @suppress {undefinedVars, duplicate} */function(arg0, arg1) {
+ var self = this.ptr;
+ ensureCache.prepare();
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ else arg0 = ensureString(arg0);
+ if (arg1 && typeof arg1 === 'object') arg1 = arg1.ptr;
+ _emscripten_bind_eSpeakNGWorker_synth__2(self, arg0, arg1);
+};;
+
+eSpeakNGWorker.prototype['synth_ipa_'] = eSpeakNGWorker.prototype.synth_ipa_ = /** @suppress {undefinedVars, duplicate} */function(arg0, arg1) {
+ var self = this.ptr;
+ ensureCache.prepare();
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ else arg0 = ensureString(arg0);
+ if (arg1 && typeof arg1 === 'object') arg1 = arg1.ptr;
+ else arg1 = ensureString(arg1);
+ return _emscripten_bind_eSpeakNGWorker_synth_ipa__2(self, arg0, arg1);
+};;
+
+eSpeakNGWorker.prototype['getSizeOfEventStruct_'] = eSpeakNGWorker.prototype.getSizeOfEventStruct_ = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_eSpeakNGWorker_getSizeOfEventStruct__0(self);
+};;
+
+eSpeakNGWorker.prototype['set_voice'] = eSpeakNGWorker.prototype.set_voice = /** @suppress {undefinedVars, duplicate} */function(arg0, arg1, arg2, arg3, arg4) {
+ var self = this.ptr;
+ ensureCache.prepare();
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ else arg0 = ensureString(arg0);
+ if (arg1 && typeof arg1 === 'object') arg1 = arg1.ptr;
+ else arg1 = ensureString(arg1);
+ if (arg2 && typeof arg2 === 'object') arg2 = arg2.ptr;
+ if (arg3 && typeof arg3 === 'object') arg3 = arg3.ptr;
+ if (arg4 && typeof arg4 === 'object') arg4 = arg4.ptr;
+ if (arg2 === undefined) { return _emscripten_bind_eSpeakNGWorker_set_voice_2(self, arg0, arg1) }
+ if (arg3 === undefined) { return _emscripten_bind_eSpeakNGWorker_set_voice_3(self, arg0, arg1, arg2) }
+ if (arg4 === undefined) { return _emscripten_bind_eSpeakNGWorker_set_voice_4(self, arg0, arg1, arg2, arg3) }
+ return _emscripten_bind_eSpeakNGWorker_set_voice_5(self, arg0, arg1, arg2, arg3, arg4);
+};;
+
+ eSpeakNGWorker.prototype['get_voices'] = eSpeakNGWorker.prototype.get_voices = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ return wrapPointer(_emscripten_bind_eSpeakNGWorker_get_voices_1(self, arg0), espeak_VOICE);
+};
+ eSpeakNGWorker.prototype['set_voices'] = eSpeakNGWorker.prototype.set_voices = /** @suppress {undefinedVars, duplicate} */function(arg0, arg1) {
+ var self = this.ptr;
+ ensureCache.prepare();
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ if (arg1 && typeof arg1 === 'object') arg1 = arg1.ptr;
+ _emscripten_bind_eSpeakNGWorker_set_voices_2(self, arg0, arg1);
+};
+ eSpeakNGWorker.prototype['get_samplerate'] = eSpeakNGWorker.prototype.get_samplerate = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_eSpeakNGWorker_get_samplerate_0(self);
+};
+ eSpeakNGWorker.prototype['get_rate'] = eSpeakNGWorker.prototype.get_rate = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_eSpeakNGWorker_get_rate_0(self);
+};
+ eSpeakNGWorker.prototype['set_rate'] = eSpeakNGWorker.prototype.set_rate = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_eSpeakNGWorker_set_rate_1(self, arg0);
+};
+ eSpeakNGWorker.prototype['get_pitch'] = eSpeakNGWorker.prototype.get_pitch = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_eSpeakNGWorker_get_pitch_0(self);
+};
+ eSpeakNGWorker.prototype['set_pitch'] = eSpeakNGWorker.prototype.set_pitch = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_eSpeakNGWorker_set_pitch_1(self, arg0);
+};
+ eSpeakNGWorker.prototype['__destroy__'] = eSpeakNGWorker.prototype.__destroy__ = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ _emscripten_bind_eSpeakNGWorker___destroy___0(self);
+};
+// espeak_VOICE
+function espeak_VOICE() { throw "cannot construct a espeak_VOICE, no constructor in IDL" }
+espeak_VOICE.prototype = Object.create(WrapperObject.prototype);
+espeak_VOICE.prototype.constructor = espeak_VOICE;
+espeak_VOICE.prototype.__class__ = espeak_VOICE;
+espeak_VOICE.__cache__ = {};
+Module['espeak_VOICE'] = espeak_VOICE;
+
+ espeak_VOICE.prototype['get_name'] = espeak_VOICE.prototype.get_name = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return Pointer_stringify(_emscripten_bind_espeak_VOICE_get_name_0(self));
+};
+ espeak_VOICE.prototype['set_name'] = espeak_VOICE.prototype.set_name = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ ensureCache.prepare();
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ else arg0 = ensureString(arg0);
+ _emscripten_bind_espeak_VOICE_set_name_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_languages'] = espeak_VOICE.prototype.get_languages = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ return _emscripten_bind_espeak_VOICE_get_languages_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_identifier'] = espeak_VOICE.prototype.get_identifier = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return Pointer_stringify(_emscripten_bind_espeak_VOICE_get_identifier_0(self));
+};
+ espeak_VOICE.prototype['set_identifier'] = espeak_VOICE.prototype.set_identifier = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ ensureCache.prepare();
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ else arg0 = ensureString(arg0);
+ _emscripten_bind_espeak_VOICE_set_identifier_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_gender'] = espeak_VOICE.prototype.get_gender = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_VOICE_get_gender_0(self);
+};
+ espeak_VOICE.prototype['set_gender'] = espeak_VOICE.prototype.set_gender = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_espeak_VOICE_set_gender_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_age'] = espeak_VOICE.prototype.get_age = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_VOICE_get_age_0(self);
+};
+ espeak_VOICE.prototype['set_age'] = espeak_VOICE.prototype.set_age = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_espeak_VOICE_set_age_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_variant'] = espeak_VOICE.prototype.get_variant = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_VOICE_get_variant_0(self);
+};
+ espeak_VOICE.prototype['set_variant'] = espeak_VOICE.prototype.set_variant = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_espeak_VOICE_set_variant_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_xx1'] = espeak_VOICE.prototype.get_xx1 = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_VOICE_get_xx1_0(self);
+};
+ espeak_VOICE.prototype['set_xx1'] = espeak_VOICE.prototype.set_xx1 = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_espeak_VOICE_set_xx1_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_score'] = espeak_VOICE.prototype.get_score = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_VOICE_get_score_0(self);
+};
+ espeak_VOICE.prototype['set_score'] = espeak_VOICE.prototype.set_score = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_espeak_VOICE_set_score_1(self, arg0);
+};
+ espeak_VOICE.prototype['get_spare'] = espeak_VOICE.prototype.get_spare = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_VOICE_get_spare_0(self);
+};
+ espeak_VOICE.prototype['set_spare'] = espeak_VOICE.prototype.set_spare = /** @suppress {undefinedVars, duplicate} */function(arg0) {
+ var self = this.ptr;
+ if (arg0 && typeof arg0 === 'object') arg0 = arg0.ptr;
+ _emscripten_bind_espeak_VOICE_set_spare_1(self, arg0);
+};
+ espeak_VOICE.prototype['__destroy__'] = espeak_VOICE.prototype.__destroy__ = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ _emscripten_bind_espeak_VOICE___destroy___0(self);
+};
+// VoidPtr
+function VoidPtr() { throw "cannot construct a VoidPtr, no constructor in IDL" }
+VoidPtr.prototype = Object.create(WrapperObject.prototype);
+VoidPtr.prototype.constructor = VoidPtr;
+VoidPtr.prototype.__class__ = VoidPtr;
+VoidPtr.__cache__ = {};
+Module['VoidPtr'] = VoidPtr;
+
+ VoidPtr.prototype['__destroy__'] = VoidPtr.prototype.__destroy__ = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ _emscripten_bind_VoidPtr___destroy___0(self);
+};
+// espeak_EVENT
+function espeak_EVENT() { throw "cannot construct a espeak_EVENT, no constructor in IDL" }
+espeak_EVENT.prototype = Object.create(WrapperObject.prototype);
+espeak_EVENT.prototype.constructor = espeak_EVENT;
+espeak_EVENT.prototype.__class__ = espeak_EVENT;
+espeak_EVENT.__cache__ = {};
+Module['espeak_EVENT'] = espeak_EVENT;
+
+ espeak_EVENT.prototype['get_type'] = espeak_EVENT.prototype.get_type = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_EVENT_get_type_0(self);
+};
+ espeak_EVENT.prototype['get_unique_identifier'] = espeak_EVENT.prototype.get_unique_identifier = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_EVENT_get_unique_identifier_0(self);
+};
+ espeak_EVENT.prototype['get_text_position'] = espeak_EVENT.prototype.get_text_position = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_EVENT_get_text_position_0(self);
+};
+ espeak_EVENT.prototype['get_length'] = espeak_EVENT.prototype.get_length = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_EVENT_get_length_0(self);
+};
+ espeak_EVENT.prototype['get_audio_position'] = espeak_EVENT.prototype.get_audio_position = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_EVENT_get_audio_position_0(self);
+};
+ espeak_EVENT.prototype['get_sample'] = espeak_EVENT.prototype.get_sample = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_EVENT_get_sample_0(self);
+};
+ espeak_EVENT.prototype['get_user_data'] = espeak_EVENT.prototype.get_user_data = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ return _emscripten_bind_espeak_EVENT_get_user_data_0(self);
+};
+ espeak_EVENT.prototype['__destroy__'] = espeak_EVENT.prototype.__destroy__ = /** @suppress {undefinedVars, duplicate} */function() {
+ var self = this.ptr;
+ _emscripten_bind_espeak_EVENT___destroy___0(self);
+};
+(function() {
+ function setupEnums() {
+
+
+ // espeak_EVENT_TYPE
+
+ Module['espeakEVENT_LIST_TERMINATED'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_LIST_TERMINATED();
+
+ Module['espeakEVENT_WORD'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_WORD();
+
+ Module['espeakEVENT_SENTENCE'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SENTENCE();
+
+ Module['espeakEVENT_MARK'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MARK();
+
+ Module['espeakEVENT_PLAY'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PLAY();
+
+ Module['espeakEVENT_END'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_END();
+
+ Module['espeakEVENT_MSG_TERMINATED'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_MSG_TERMINATED();
+
+ Module['espeakEVENT_PHONEME'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_PHONEME();
+
+ Module['espeakEVENT_SAMPLERATE'] = _emscripten_enum_espeak_EVENT_TYPE_espeakEVENT_SAMPLERATE();
+
+ }
+ if (Module['calledRun']) setupEnums();
+ else addOnPreMain(setupEnums);
+})();
+
+/*
+ * Copyright (C) 2014-2017 Eitan Isaacson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see: <http://www.gnu.org/licenses/>.
+ */
+
+eSpeakNGWorker.prototype.list_voices = function() {
+ var voices = [];
+ var i;
+ for (var voice = this.get_voices(i = 0); voice.ptr != 0; voice = this.get_voices(++i)) {
+ var v = {
+ name: voice.get_name(),
+ identifier: voice.get_identifier(),
+ languages: [],
+ }
+
+ var ii = 0;
+ var byte = voice.get_languages(ii);
+
+ function nullTerminatedString(offset) {
+ var str = '';
+ var index = offset;
+ var b = voice.get_languages(index++);
+ while (b != 0) {
+ str += String.fromCharCode(b);
+ b = voice.get_languages(index++);
+ }
+
+ return str;
+ }
+
+ while (byte != 0) {
+ var lang = { priority: byte, name: nullTerminatedString(++ii) }
+ v.languages.push(lang);
+ ii += lang.name.length + 1;
+ byte = voice.get_languages(ii);
+ }
+
+ voices.push(v);
+
+ }
+ return voices;
+};
+
+var eventTypes = [
+ 'list_terminated',
+ 'word',
+ 'sentence',
+ 'mark',
+ 'play',
+ 'end',
+ 'msg_terminated',
+ 'phoneme',
+ 'samplerate'
+]
+
+eSpeakNGWorker.prototype.synthesize = function (aText, aCallback) {
+ var eventStructSize = this.getSizeOfEventStruct_();
+ function cb(ptr, length, events_pointer) {
+ var data = new Float32Array(length*2);
+ for (var i = 0; i < length; i++) {
+ data[i*2] = Math.max(-1, Math.min(1, getValue(ptr + i*2, 'i16') / 32768));
+ data[i*2+1] = data[i*2];
+ }
+ var events = [];
+ var ptr = events_pointer;
+ for (ev = wrapPointer(ptr, espeak_EVENT);
+ ev.get_type() != Module.espeakEVENT_LIST_TERMINATED;
+ ev = wrapPointer((ptr += eventStructSize), espeak_EVENT)) {
+ events.push({
+ type: eventTypes[ev.get_type()],
+ text_position: ev.get_text_position(),
+ word_length: ev.get_length(),
+ audio_position: ev.get_audio_position()
+ });
+ }
+ return aCallback(data, events) ? 1 : 0;
+ }
+
+ var fp = addFunction(cb); // Runtime.addFunction(cb);
+ this.synth_(aText, fp);
+ removeFunction(fp); // Runtime.removeFunction(fp);
+};
+
+eSpeakNGWorker.prototype.synthesize_ipa = function (aText, aCallback) {
+
+ // Use a unique temp file for the worker. Avoid collisions, just in case.
+ var ipaVirtualFileName = "espeak-ng-ipa-tmp-" + Math.random().toString().substring(2);
+
+ var res = "";
+ var code = this.synth_ipa_(aText, ipaVirtualFileName);
+
+ if(code == 0)
+ res = FS.readFile(ipaVirtualFileName, { encoding: 'utf8' })
+
+ // Clean up the tmp file
+ FS.unlink(ipaVirtualFileName);
+
+ var ret = {
+ code: code,
+ ipa: res
+ }
+
+ return ret;
+};
+
+// Make this a worker
+
+if (typeof WorkerGlobalScope !== 'undefined') {
+ var worker;
+
+ Module.postRun.push(function () {
+ worker = new eSpeakNGWorker();
+ postMessage('ready');
+ });
+
+ onmessage = function(e) {
+
+ if (!worker) {
+ throw 'eSpeakNGWorker worker not initialized';
+ }
+ var args = e.data.args;
+ var message = { callback: e.data.callback, done: true };
+ if (e.data.method == 'synthesize') {
+ args.push(function(samples, events) {
+ postMessage(
+ { callback: e.data.callback,
+ result: [samples.buffer, events] }, [samples.buffer]);
+ });
+ }
+ message.result = [worker[e.data.method].apply(worker, args)];
+ if (e.data.callback)
+ postMessage(message);
+ }
+}
+
diff --git a/chrome-extension/js/espeakng.worker.wasm b/chrome-extension/js/espeakng.worker.wasm
new file mode 100644
index 0000000..50aa1d8
--- /dev/null
+++ b/chrome-extension/js/espeakng.worker.wasm
Binary files differ
diff --git a/chrome-extension/language_defaults.js b/chrome-extension/language_defaults.js
new file mode 100644
index 0000000..e0b1483
--- /dev/null
+++ b/chrome-extension/language_defaults.js
@@ -0,0 +1,126 @@
+function isEspeakLanguageEnabledByDefault(espeakLangInfo) {
+ switch (espeakLangInfo.identifier) {
+ // Redundant.
+ //
+ // Don't enable these languages by default because
+ // they duplicatea a language provided by Google's engine.
+ case "inc/hi": // Hindi
+ case "poz/id": // Indonesian
+ case "gmw/nl": // Dutch
+ case "ko": // Korean
+ case "roa/it": // Italian
+ case "roa/fr-BE": // French (Belgium)
+ case "roa/fr-CH": // French (Switzerland)
+ case "roa/fr": // French (France)
+ case "roa/es": // Spanish (Spain)
+ case "roa/es-419": // Spanish (Latin America)
+ case "roa/pt": // Portuguese (Portugal)
+ case "roa/pt-BR": // Portuguese (Brazil)
+ case "gmw/de": // German
+ case "gmw/en-029": // English (Caribbean)
+ case "gmw/en": // English (Great Britain)
+ case "gmw/en-GB-scotland": // English (Scotland)
+ case "gmw/en-GB-x-gbclan": // English (Lancaster)
+ case "gmw/en-GB-x-gbcwmd": // English (West Midlands)
+ case "gmw/en-GB-x-rp": // English (Received Pronunciation)
+ case "gmw/en-US": // English (America)
+ return false;
+
+ // Allowed languages.
+ case "gmw/af": // Afrikaans
+ case "sem/am": // Amharic
+ case "roa/an": // Aragonese
+ case "sem/ar": // Arabic
+ case "inc/as": // Assamese
+ case "trk/az": // Azerbaijani
+ case "zls/bg": // Bulgarian
+ case "inc/bn": // Bengali
+ case "inc/bpy": // Bishnupriya Manipuri
+ case "zls/bs": // Bosnian
+ case "roa/ca": // Catalan
+ case "sit/cmn": // Chinese (Mandarin)
+ case "zlw/cs": // Czech
+ case "cel/cy": // Welsh
+ case "gmq/da": // Danish
+ case "grk/el": // Greek
+ case "art/eo": // Esperanto
+ case "urj/et": // Estonian
+ case "eu": // Basque
+ case "ira/fa": // Persian
+ case "ira/fa-Latn": // Persian (Pinglish)
+ case "urj/fi": // Finnish
+ case "cel/ga": // Gaelic (Irish)
+ case "cel/gd": // Gaelic (Scottish)
+ case "sai/gn": // Guarani
+ case "grk/grc": // Greek (Ancient)
+ case "inc/gu": // Gujarati
+ case "sit/hak": // Hakka Chinese
+ case "zls/hr": // Croatian
+ case "urj/hu": // Hungarian
+ case "ine/hy": // Armenian (East Armenia)
+ case "ine/hyw": // Armenian (West Armenia)
+ case "art/ia": // Interlingua
+ case "gmq/is": // Icelandic
+ case "jpx/ja": // Japanese
+ case "art/jbo": // Lojban
+ case "ccs/ka": // Georgian
+ case "esx/kl": // Greenlandic
+ case "dra/kn": // Kannada
+ case "inc/kok": // Konkani
+ case "ira/ku": // Kurdish
+ case "trk/ky": // Kyrgyz
+ case "itc/la": // Latin
+ case "art/lfn": // Lingua Franca Nova
+ case "bat/lt": // Lithuanian
+ case "bat/lv": // Latvian
+ case "poz/mi": // Māori
+ case "zls/mk": // Macedonian
+ case "dra/ml": // Malayalam
+ case "inc/mr": // Marathi
+ case "poz/ms": // Malay
+ case "sem/mt": // Maltese
+ case "sit/my": // Myanmar (Burmese)
+ case "gmq/nb": // Norwegian Bokmål
+ case "azc/nci": // Nahuatl (Classical)
+ case "inc/ne": // Nepali
+ case "cus/om": // Oromo
+ case "inc/or": // Oriya
+ case "inc/pa": // Punjabi
+ case "roa/pap": // Papiamento
+ case "zlw/pl": // Polish
+ case "roa/ro": // Romanian
+ case "zle/ru": // Russian
+ case "inc/sd": // Sindhi
+ case "inc/si": // Sinhala
+ case "zlw/sk": // Slovak
+ case "zls/sl": // Slovenian
+ case "ine/sq": // Albanian
+ case "zls/sr": // Serbian
+ case "gmq/sv": // Swedish
+ case "bnt/sw": // Swahili
+ case "dra/ta": // Tamil
+ case "dra/te": // Telugu
+ case "bnt/tn": // Setswana
+ case "trk/tr": // Turkish
+ case "trk/tt": // Tatar
+ case "inc/ur": // Urdu
+ case "aav/vi": // Vietnamese (Northern)
+ case "aav/vi-VN-x-central": // Vietnamese (Central)
+ case "aav/vi-VN-x-south": // Vietnamese (Southern)
+ case "sit/yue": // Chinese (Cantonese)
+ return true;
+ }
+
+ console.error('Language ' + espeakLangInfo.identifier +
+ ' (' + espeakLangInfo.name + ') should be handled ' +
+ 'in switch.');
+}
+
+function isEspeakLanguageEnabled(langInfo, callback) {
+ var defaultValue = isEspeakLanguageEnabledByDefault(langInfo);
+
+ var key = langInfo.identifier;
+ chrome.storage.local.get(key, (function(result) {
+ callback(result[key] !== undefined ? result[key] : defaultValue);
+ }).bind(this));
+}
diff --git a/chrome-extension/manifest.json b/chrome-extension/manifest.json
new file mode 100644
index 0000000..e767e1b
--- /dev/null
+++ b/chrome-extension/manifest.json
@@ -0,0 +1,23 @@
+{
+ "name": "eSpeakNG text-to-speech extension",
+ "manifest_version": 2,
+ "version": "0.0.1",
+ "options_page": "options.html",
+ "background": {
+ "scripts": [
+ "language_defaults.js",
+ "js/espeakng.js",
+ "espeak_tts_engine.js"
+ ],
+ "persistent": false
+ },
+ "permissions": [
+ "storage",
+ "ttsEngine"
+ ],
+ "description": "A free text-to-speech engine that supports many languages.",
+ "tts_engine": {
+ "voices": [
+ ]
+ }
+}
diff --git a/chrome-extension/manifest_guest.json b/chrome-extension/manifest_guest.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome-extension/manifest_guest.json
diff --git a/chrome-extension/options.css b/chrome-extension/options.css
new file mode 100644
index 0000000..e45ea27
--- /dev/null
+++ b/chrome-extension/options.css
@@ -0,0 +1,101 @@
+/* Copyright 2018 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a GPL license that can be
+ * found in the LICENSE file. */
+
+@import url(https://fonts.googleapis.com/css?family=Roboto);
+
+body {
+ margin: 0 0 20px 0;
+ padding: 0;
+}
+
+body,
+button,
+input,
+select {
+ background-color: rgb(241, 241, 241);
+ font-family: Roboto;
+}
+
+h1 {
+ background: rgb(217, 27, 27);
+ color: white;
+ display: block;
+ font-size: 16px;
+ height: 56px;
+ line-height: 56px;
+ text-align: center;
+ width: 100%;
+}
+
+h2 {
+ color: rgb(97, 97, 97);
+ font-size: 13px;
+ height: 15px;
+ margin-top: 21px;
+}
+
+.container {
+ margin-left: auto;
+ margin-right: auto;
+ width: 646px;
+}
+
+.option {
+ background-color: #fff;
+ border: 1px solid #ddd;
+ font-size: 13px;
+ line-height: 60px;
+ min-height: 60px;
+ padding: 0 20px;
+ vertical-align: middle;
+ width: 646px;
+}
+
+.option input[type='checkbox'] {
+ -webkit-appearance: none;
+ background-color: #fff;
+ background-image: url(unchecked.png);
+ background-position: center center;
+ background-repeat: no-repeat;
+ border: 0;
+ float: right;
+ height: 60px;
+ margin: 0;
+ padding: 0;
+ width: 40px;
+}
+
+.option input[type='checkbox']:checked {
+ background-image: url(checked.png);
+}
+
+.option select {
+ background-color: #fff;
+ border-color: #ddd;
+ border-width: 0 0 1px 0;
+ height: 20px;
+ line-height: 60px;
+ margin: 20px 0;
+ padding: 0;
+}
+
+.option input {
+ background-color: #fff;
+ border-color: #ddd;
+ border-width: 0 0 2px 0;
+ outline: none;
+}
+
+.option input:focus {
+ border-color: rgb(0, 0, 255);
+}
+
+.option button {
+ background-color: #ddd;
+ border-width: 0;
+ font-weight: bold;
+ height: 30px;
+ margin-left: 20px;
+ padding: 0 20px;
+}
diff --git a/chrome-extension/options.js b/chrome-extension/options.js
new file mode 100644
index 0000000..0e82e12
--- /dev/null
+++ b/chrome-extension/options.js
@@ -0,0 +1,82 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a the GPL license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Options page for the eSpeak text-to-speech extension.
+ */
+
+'use strict';
+
+function $(id) {
+ return document.getElementById(id);
+}
+
+/**
+ * @constructor
+ */
+var EspeakTtsOptions = function() {
+ chrome.runtime.getBackgroundPage((function(background) {
+ this.engine_ = background.engine;
+ this.langInfoArray_ = this.engine_.getLangInfoArray();
+ this.init();
+ }).bind(this));
+};
+
+EspeakTtsOptions.prototype.init = function() {
+ this.langInfoArray_.forEach((function(langInfo) {
+ var row = document.createElement('div');
+ row.className = 'option';
+ var label = document.createElement('label');
+ row.appendChild(label);
+ var checkbox = document.createElement('input');
+ checkbox.id = langInfo.identifier;
+ checkbox.type = 'checkbox';
+ checkbox.className = 'checkbox pref';
+ label.appendChild(checkbox);
+ var text = document.createElement('span');
+ text.innerText = langInfo.name;
+ label.appendChild(text);
+ $('languages').appendChild(row);
+ }).bind(this));
+
+ this.update();
+
+ document.addEventListener('change', this.onChange.bind(this), false);
+};
+
+EspeakTtsOptions.prototype.update = function() {
+ this.langInfoArray_.forEach((function(langInfo) {
+ isEspeakLanguageEnabled(langInfo, function(enabled) {
+ var key = langInfo.identifier;
+ $(key).checked = enabled;
+ });
+ }).bind(this));
+};
+
+EspeakTtsOptions.prototype.onChange = function(event) {
+ var target = event.target;
+ if (target.tagName != 'INPUT' || target.className != 'checkbox pref')
+ return;
+
+ var obj = {};
+ obj[target.id] = target.checked;
+ chrome.storage.local.set(obj);
+ console.log('updating voices');
+ this.engine_.updateVoices();
+};
+
+function addTranslatedMessagesToDom() {
+ var elts = root.querySelectorAll('*[msgid]');
+ for (var i = 0; i < elts.length; i++) {
+ var msgid = elts[i].getAttribute('msgid');
+ if (!msgid) {
+ throw new Error('Element has no msgid attribute: ' + elts[i]);
+ }
+ elts[i].textContent = chrome.i18n.getMessage(msgid);
+ }
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+ var options = new EspeakTtsOptions();
+}, false);
diff --git a/chrome-extension/unchecked.png b/chrome-extension/unchecked.png
new file mode 100644
index 0000000..3ae9a42
--- /dev/null
+++ b/chrome-extension/unchecked.png
Binary files differ