Fix quickjs build on win64
Add back script system and fix build error on windows 64 bit system.master
parent
c3ba1ed871
commit
ec80f7bacd
31
dust3d.pro
31
dust3d.pro
|
@ -398,6 +398,21 @@ HEADERS += src/preferences.h
|
||||||
|
|
||||||
HEADERS += src/shadervertex.h
|
HEADERS += src/shadervertex.h
|
||||||
|
|
||||||
|
SOURCES += src/scripteditwidget.cpp
|
||||||
|
HEADERS += src/scripteditwidget.h
|
||||||
|
|
||||||
|
SOURCES += src/scriptvariableswidget.cpp
|
||||||
|
HEADERS += src/scriptvariableswidget.h
|
||||||
|
|
||||||
|
SOURCES += src/scriptwidget.cpp
|
||||||
|
HEADERS += src/scriptwidget.h
|
||||||
|
|
||||||
|
SOURCES += src/scriptrunner.cpp
|
||||||
|
HEADERS += src/scriptrunner.h
|
||||||
|
|
||||||
|
SOURCES += src/variablesxml.cpp
|
||||||
|
HEADERS += src/variablesxml.h
|
||||||
|
|
||||||
SOURCES += src/updateschecker.cpp
|
SOURCES += src/updateschecker.cpp
|
||||||
HEADERS += src/updateschecker.h
|
HEADERS += src/updateschecker.h
|
||||||
|
|
||||||
|
@ -741,6 +756,22 @@ HEADERS += thirdparty/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2
|
||||||
SOURCES += thirdparty/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.cpp
|
SOURCES += thirdparty/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.cpp
|
||||||
HEADERS += thirdparty/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.h
|
HEADERS += thirdparty/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.h
|
||||||
|
|
||||||
|
INCLUDEPATH += thirdparty/quickjs/quickjs-2019-07-09-dust3d
|
||||||
|
|
||||||
|
DEFINES += "CONFIG_VERSION=\"\\\"2019-07-09\\\"\""
|
||||||
|
|
||||||
|
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/quickjs.c
|
||||||
|
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/quickjs.h
|
||||||
|
|
||||||
|
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/cutils.c
|
||||||
|
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/cutils.h
|
||||||
|
|
||||||
|
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libunicode.c
|
||||||
|
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libunicode.h
|
||||||
|
|
||||||
|
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libregexp.c
|
||||||
|
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libregexp.h
|
||||||
|
|
||||||
INCLUDEPATH += thirdparty/crc64
|
INCLUDEPATH += thirdparty/crc64
|
||||||
|
|
||||||
SOURCES += thirdparty/crc64/crc64.c
|
SOURCES += thirdparty/crc64/crc64.c
|
||||||
|
|
|
@ -398,6 +398,10 @@ Tips:
|
||||||
<source>Toggle Color</source>
|
<source>Toggle Color</source>
|
||||||
<translation>打开/关闭颜色</translation>
|
<translation>打开/关闭颜色</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Script</source>
|
||||||
|
<translation>脚本</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ExportPreviewWidget</name>
|
<name>ExportPreviewWidget</name>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<file>resources/model-meerkat.ds3</file>
|
<file>resources/model-meerkat.ds3</file>
|
||||||
<file>resources/model-mosquito.ds3</file>
|
<file>resources/model-mosquito.ds3</file>
|
||||||
<file>resources/model-seagull.ds3</file>
|
<file>resources/model-seagull.ds3</file>
|
||||||
|
<file>resources/model-procedural-tree.ds3</file>
|
||||||
<file>resources/triangle.png</file>
|
<file>resources/triangle.png</file>
|
||||||
<file>resources/quad.png</file>
|
<file>resources/quad.png</file>
|
||||||
<file>resources/pentagon.png</file>
|
<file>resources/pentagon.png</file>
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
<file>shaders/default.frag</file>
|
<file>shaders/default.frag</file>
|
||||||
<file>shaders/default.core.vert</file>
|
<file>shaders/default.core.vert</file>
|
||||||
<file>shaders/default.core.frag</file>
|
<file>shaders/default.core.frag</file>
|
||||||
|
<file>thirdparty/three.js/dust3d.three.js</file>
|
||||||
<file>languages/dust3d_zh_CN.qm</file>
|
<file>languages/dust3d_zh_CN.qm</file>
|
||||||
<file>ACKNOWLEDGEMENTS.html</file>
|
<file>ACKNOWLEDGEMENTS.html</file>
|
||||||
<file>AUTHORS</file>
|
<file>AUTHORS</file>
|
||||||
|
|
|
@ -0,0 +1,881 @@
|
||||||
|
DUST3D 1.0 xml 0000000257
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ds3>
|
||||||
|
<model name="model.xml" offset="0" size="117317"/>
|
||||||
|
<script name="model.js" offset="117317" size="8514"/>
|
||||||
|
<variable name="variables.xml" offset="125831" size="1793"/>
|
||||||
|
</ds3>
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<canvas originX="0.506767" originY="0.615943" originZ="1.08543" rigType="None">
|
||||||
|
<nodes>
|
||||||
|
<node id="{001eb845-4bed-4de5-9803-ba8ca7faafaf}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0" x="0.624675" y="0.232533" z="1.08441"/>
|
||||||
|
<node id="{021bd224-eaac-49a1-a91f-0f2406f26f8a}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.00829716" x="0.529162" y="0.319461" z="0.834381"/>
|
||||||
|
<node id="{02b8c92c-3aad-43b4-b2d6-eb0659a8a206}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0094301" x="0.58636" y="0.281492" z="0.751192"/>
|
||||||
|
<node id="{0390d0a1-814a-4705-999e-5932354f0244}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.00841411" x="0.518194" y="0.26891" z="1.02987"/>
|
||||||
|
<node id="{0402a0e9-9712-4d9c-b022-ea25f2ed64d0}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0" x="0.508304" y="0.322731" z="0.792632"/>
|
||||||
|
<node id="{0434ac30-312c-4b70-984e-5a0971e9eb75}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.00817509" x="0.50548" y="0.256846" z="1.00709"/>
|
||||||
|
<node id="{052c2ec6-ad61-40af-b659-14a23612734d}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0" x="0.593867" y="0.274461" z="0.741533"/>
|
||||||
|
<node id="{05438075-6182-4f45-80c2-35625897b718}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.00541154" x="0.497586" y="0.140403" z="1.00711"/>
|
||||||
|
<node id="{0582fcb5-78cf-4f27-bd85-0ccd279e8713}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.0112927" x="0.50664" y="0.338481" z="0.812135"/>
|
||||||
|
<node id="{05c483ea-2649-48b1-80f9-f23a57335a5f}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.00121829" x="0.540098" y="0.379707" z="0.858939"/>
|
||||||
|
<node id="{067095a4-8e69-40d7-bc00-9c0a7f4e1e3c}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.0036703" x="0.518194" y="0.26891" z="1.02987"/>
|
||||||
|
<node id="{06f82254-ab2d-44f4-bc96-3814316535a9}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.00804375" x="0.540098" y="0.379707" z="0.858939"/>
|
||||||
|
<node id="{0711915a-a413-42b5-8022-35668c45d39b}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0192266" x="0.52941" y="0.945103" z="1.02527"/>
|
||||||
|
<node id="{071305c7-8044-4c28-8ccc-4f74cffb61cc}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0205617" x="0.526812" y="1.00058" z="1.01213"/>
|
||||||
|
<node id="{096379fc-4ca1-4c6d-b242-e353a20ffc88}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.0114691" x="0.61185" y="0.235283" z="1.07547"/>
|
||||||
|
<node id="{09f3f5fa-46f1-476c-aa35-3df95debd16f}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.00705143" x="0.733929" y="0.0905315" z="1.08278"/>
|
||||||
|
<node id="{0a8e8fb2-9858-49d2-8686-6ed728dccbc2}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00743484" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{0b4f4946-8ff1-4efe-bdfe-0b611af6a655}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.00854656" x="0.763122" y="0.056545" z="1.12847"/>
|
||||||
|
<node id="{0b58ba98-f204-40ee-be03-f62292b2d250}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0" x="0.431781" y="0.219264" z="0.994834"/>
|
||||||
|
<node id="{0bd7865d-7f8d-46cb-a1ba-4ed601bf62fe}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.0117866" x="0.747991" y="0.0634021" z="1.10862"/>
|
||||||
|
<node id="{0c131c2e-c763-4239-aae8-c71e219bb2ff}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0120206" x="0.517528" y="0.197616" z="1.01863"/>
|
||||||
|
<node id="{0c3ed74f-ee80-41a9-8568-1487fe0cfd7c}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.0165943" x="0.52147" y="0.327551" z="0.829132"/>
|
||||||
|
<node id="{0e5d29f3-fb8f-4d5c-b156-e4a3e028d97d}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.0136131" x="0.462094" y="0.0440756" z="0.990634"/>
|
||||||
|
<node id="{0f14d7ef-6d9e-42aa-afea-17e850abd25d}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.00665101" x="0.436937" y="0.226714" z="0.995019"/>
|
||||||
|
<node id="{0f798576-2812-4db6-b605-9ef70f713c8b}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.0181634" x="0.478383" y="0.0799667" z="0.997972"/>
|
||||||
|
<node id="{10582ab2-cd50-47a0-bb86-9272f251af03}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0" x="0.511773" y="0.247377" z="1.00342"/>
|
||||||
|
<node id="{105d5ada-f06b-474f-82a7-34fbfa628526}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0" x="0.490709" y="0.279837" z="1.03157"/>
|
||||||
|
<node id="{10d61f38-3849-4852-9dd1-2be2ad90d468}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0" x="0.794786" y="0.0436219" z="1.08823"/>
|
||||||
|
<node id="{117ef567-17a0-425e-9fcb-ae1610e91539}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0113278" x="0.435208" y="-0.122352" z="0.947148"/>
|
||||||
|
<node id="{1207414b-6386-42f4-b3b4-e774497e4fa9}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0" x="0.741845" y="0.083804" z="1.08452"/>
|
||||||
|
<node id="{14a0dfc1-38c0-4544-b5d4-65bdbe60b622}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.0151557" x="0.514648" y="0.144772" z="1.01763"/>
|
||||||
|
<node id="{14a9c743-142c-43a6-8962-5dbf6514c38a}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.00908169" x="0.481651" y="0.106262" z="0.991808"/>
|
||||||
|
<node id="{15283e25-d483-44c6-b530-113073ae54d0}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.00829716" x="0.506086" y="0.343731" z="0.818635"/>
|
||||||
|
<node id="{15d886b0-181e-4e8d-84c4-21da599037c1}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.00684339" x="0.690864" y="0.148628" z="1.10365"/>
|
||||||
|
<node id="{164fc21c-131b-42a2-a47b-3b2d930222c6}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.00625545" x="0.499048" y="0.16079" z="1.02006"/>
|
||||||
|
<node id="{172dd203-fbf9-4d7f-aafe-b751b7f943de}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.000446346" x="0.492055" y="0.304378" z="0.779797"/>
|
||||||
|
<node id="{173d8166-2d8d-4792-9187-d1f0dccb3713}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.0172223" x="0.507138" y="0.138639" z="1.03023"/>
|
||||||
|
<node id="{17408e0e-5237-45ce-8f5c-de1034fcf23c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00241779" x="0.639106" y="0.195709" z="1.06841"/>
|
||||||
|
<node id="{17722f68-bf1b-49d6-a22a-44a5fd7cd1f4}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0" x="0.633481" y="0.217282" z="1.08241"/>
|
||||||
|
<node id="{18a7f970-0d2e-4d47-a307-32c94a9105a3}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00147754" x="0.549438" y="0.337811" z="0.818152"/>
|
||||||
|
<node id="{1957320f-7dec-4069-a2b2-502d9a18442e}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.0125109" x="0.497234" y="0.142519" z="1.01624"/>
|
||||||
|
<node id="{199423e1-60c0-4b3c-b65a-3ab127cadf99}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00211381" x="0.459929" y="0.0522857" z="0.985105"/>
|
||||||
|
<node id="{1ad678c9-b640-43d5-af1c-92ddfc540416}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0138378" x="0.514346" y="0.194111" z="1.00654"/>
|
||||||
|
<node id="{1b515278-0117-48fe-a1fe-e772057573d9}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00127211" x="0.453427" y="-0.0558037" z="0.967476"/>
|
||||||
|
<node id="{1c85074d-db26-4962-9694-26df45d957c6}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00167325" x="0.465511" y="-0.00179739" z="0.96585"/>
|
||||||
|
<node id="{1d21ff2c-ba5f-4997-98db-a1ed63d01db3}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00246233" x="0.481651" y="0.106262" z="0.991808"/>
|
||||||
|
<node id="{1f0d5b25-4f21-4fd6-9142-0d56a594dd2c}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.00937295" x="0.520745" y="0.486083" z="0.929637"/>
|
||||||
|
<node id="{2015db8c-2d22-40d9-8605-073117da143a}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.0190246" x="0.530833" y="0.31094" z="1.03841"/>
|
||||||
|
<node id="{21a051be-53a6-442c-8c87-e5572e6ff05e}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0" x="0.523872" y="0.173925" z="0.975074"/>
|
||||||
|
<node id="{221a1797-ed67-4cfd-9cd8-34823e651ed3}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.000920665" x="0.506086" y="0.343731" z="0.818635"/>
|
||||||
|
<node id="{24b1db2c-8e14-4670-a523-bd31ab7758aa}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0" x="0.475115" y="0.0536713" z="1.00414"/>
|
||||||
|
<node id="{2501c90c-247d-42a1-b2fb-411d88b95e3a}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0188602" x="0.578853" y="0.288523" z="0.760851"/>
|
||||||
|
<node id="{27430d2c-0651-4361-a581-d304fcd67e22}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.0151221" x="0.574997" y="0.329256" z="0.826992"/>
|
||||||
|
<node id="{28381152-78fe-4c2d-8c3c-c776138efa17}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0113278" x="0.438589" y="-0.115943" z="0.942864"/>
|
||||||
|
<node id="{29686a15-7ddb-4717-a196-0412164025ef}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0055478" x="0.621696" y="0.233828" z="1.06758"/>
|
||||||
|
<node id="{2acf141a-f327-4469-bde3-ea54de99f8d6}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0" x="0.49542" y="0.124248" z="1.01241"/>
|
||||||
|
<node id="{2b2d6ee4-f105-491c-b098-4de0613fd37c}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.00652467" x="0.541733" y="0.286743" z="0.791092"/>
|
||||||
|
<node id="{2cc27239-bf74-49d5-b82d-0998c0103d6d}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0146973" x="0.517154" y="0.661798" z="1.02082"/>
|
||||||
|
<node id="{2ebd2648-14b0-4a21-b97b-7b34f021991b}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.0112927" x="0.507195" y="0.333231" z="0.805634"/>
|
||||||
|
<node id="{308ce17b-2a9a-4e10-b3f6-aaed5190c957}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.0116368" x="0.551163" y="0.337131" z="0.830778"/>
|
||||||
|
<node id="{31a4515c-5fd8-4e34-923e-750b726395f2}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.00985783" x="0.452406" y="0.249066" z="0.995575"/>
|
||||||
|
<node id="{32cc74f0-3f2c-450d-845d-9baabb852655}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0060103" x="0.520059" y="0.18953" z="1.0216"/>
|
||||||
|
<node id="{33cae706-74fd-423d-a240-a32c23657dcf}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.0187459" x="0.520931" y="0.493208" z="0.941731"/>
|
||||||
|
<node id="{3424cf20-48a1-4e64-be63-5890321cdbcd}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.00623232" x="0.505899" y="0.186592" z="1.01412"/>
|
||||||
|
<node id="{353010d5-28a2-4ce3-a465-12289cbadb21}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.0152136" x="0.570093" y="0.29639" z="0.772941"/>
|
||||||
|
<node id="{3547bb94-25b4-4740-a5e9-15046267f0f9}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.0124646" x="0.508088" y="0.195657" z="1.01365"/>
|
||||||
|
<node id="{35bf1780-fe7c-46dd-a93e-99896e097cf2}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.00908169" x="0.476749" y="0.066819" z="1.00105"/>
|
||||||
|
<node id="{36e6565b-5c7c-4203-9757-b7afa6731c57}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.0114691" x="0.605438" y="0.236659" z="1.071"/>
|
||||||
|
<node id="{379bec20-9be3-4a64-b259-d3ed4e84ebbc}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.00684339" x="0.675597" y="0.153363" z="1.08021"/>
|
||||||
|
<node id="{3932e31f-34f7-47da-8a0d-032bec47e53c}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.00804375" x="0.568858" y="0.358377" z="0.853901"/>
|
||||||
|
<node id="{39e3219e-a74d-4dd0-bedd-eb4fa010f34a}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0" x="0.530247" y="0.128753" z="1.01521"/>
|
||||||
|
<node id="{3b94ce3c-27ef-41af-87d1-4227ca2045f1}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.00625545" x="0.496327" y="0.133384" z="1.01432"/>
|
||||||
|
<node id="{3cce2c34-9aab-46dc-bbd3-3a73327a8875}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.440492" y="0.329685" z="0.713406"/>
|
||||||
|
<node id="{4029708e-b1f7-4f53-832e-d0983bfcd651}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.0167333" x="0.499882" y="0.295433" z="0.775861"/>
|
||||||
|
<node id="{404cdbf7-ef7b-4529-b04b-d775162d0edb}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.0147381" x="0.616253" y="0.227658" z="1.07447"/>
|
||||||
|
<node id="{408119ac-6fc0-40f5-b60c-99b7cc9517ae}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00288021" x="0.599025" y="0.238034" z="1.06653"/>
|
||||||
|
<node id="{40b1d9b4-f4ee-4c7d-8172-a9e0fc4d5654}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0111563" x="0.524322" y="0.493489" z="1.03635"/>
|
||||||
|
<node id="{427a3b1a-021e-4685-b78b-6080d8585450}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0" x="0.534364" y="0.281462" z="0.794733"/>
|
||||||
|
<node id="{442d48bd-1797-45dc-8e4f-d121fb89237c}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.0124646" x="0.510277" y="0.204723" z="1.01318"/>
|
||||||
|
<node id="{44dfeb44-b697-4c87-b313-325d3826cc63}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00955646" x="0.52" y="0.437582" z="1.01435"/>
|
||||||
|
<node id="{44e13dd8-a3d2-4d4f-af81-372da15218d2}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.00699227" x="0.755476" y="0.0488206" z="1.07007"/>
|
||||||
|
<node id="{4684632b-e51c-414e-aa21-df1ee91ea834}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.0175657" x="0.484479" y="0.285846" z="0.796773"/>
|
||||||
|
<node id="{48417392-2b8f-49a5-a628-ab7fc4c944d4}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.00564634" x="0.506086" y="0.343731" z="0.818635"/>
|
||||||
|
<node id="{491add8b-4be8-4171-b647-24334b050892}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.00547236" x="0.474945" y="0.0887811" z="0.976214"/>
|
||||||
|
<node id="{4b7f18aa-704e-4f55-9f69-16b0f38237ce}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0" x="0.428445" y="-0.135171" z="0.955714"/>
|
||||||
|
<node id="{4c81714b-6ac4-45d8-b4f0-c98539911521}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.0159439" x="0.402189" y="0.341997" z="0.713406"/>
|
||||||
|
<node id="{4d0f2620-8a2a-496f-ad0a-4d8002493035}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0060103" x="0.512466" y="0.213789" z="1.01271"/>
|
||||||
|
<node id="{5064c6c5-783a-44e5-8e70-49c8c9cc2416}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.0107256" x="0.528141" y="0.30701" z="1.0341"/>
|
||||||
|
<node id="{511c7a39-b0e7-4502-8bd3-730ae05506f0}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.00861113" x="0.511183" y="0.127563" z="1.03531"/>
|
||||||
|
<node id="{516a356a-f5a0-4c65-9f17-8d186eeccaa2}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.0172223" x="0.503093" y="0.149714" z="1.02514"/>
|
||||||
|
<node id="{516d36d9-b1db-4de8-8503-7ea829120487}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0" x="0.537046" y="0.325127" z="0.849158"/>
|
||||||
|
<node id="{528a1707-5b77-4963-a34e-db9dba558205}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.0187459" x="0.521116" y="0.500333" z="0.953824"/>
|
||||||
|
<node id="{52cc908a-1fa5-415d-9d64-51bb469706d7}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00089087" x="0.755719" y="0.068247" z="1.0946"/>
|
||||||
|
<node id="{5399b1af-6473-4df5-96cc-13e6e28784c1}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.0125641" x="0.516931" y="0.31407" z="1.03225"/>
|
||||||
|
<node id="{53f27881-5a75-4c22-b2cf-7b2d05ee1d8e}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0" x="0.505946" y="0.310252" z="1.07969"/>
|
||||||
|
<node id="{55340a9c-d66d-4d5d-a189-6d658d599e53}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0" x="0.572779" y="0.393653" z="0.869869"/>
|
||||||
|
<node id="{55b5bb5d-d614-4cd3-b331-8819186ed572}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0127438" x="0.50217" y="0.607202" z="1.02431"/>
|
||||||
|
<node id="{567a286a-bf1d-4291-b979-ba69733646f5}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.0152136" x="0.576346" y="0.290194" z="0.765713"/>
|
||||||
|
<node id="{567bcfd4-255f-478d-a9fe-362f2f832ff6}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0" x="0.629253" y="0.232427" z="1.06793"/>
|
||||||
|
<node id="{58321009-70bf-48ba-bbe7-f5afcd9e56f3}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.00581841" x="0.541752" y="0.329128" z="0.843031"/>
|
||||||
|
<node id="{58bd7c83-b479-4e17-b4df-754316eef264}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.000961544" x="0.44197" y="-0.109533" z="0.938581"/>
|
||||||
|
<node id="{593f1c87-b152-41e0-98b6-07acf061f646}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.00536282" x="0.531694" y="0.299966" z="1.03276"/>
|
||||||
|
<node id="{59fe931d-cbf2-47e6-b35e-0edcf8ad6830}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.00861113" x="0.499048" y="0.16079" z="1.02006"/>
|
||||||
|
<node id="{5a7cf847-a78d-4877-9d4f-94cd9bb9eca8}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0" x="0.578445" y="0.351266" z="0.852222"/>
|
||||||
|
<node id="{5df7e38f-b9da-4c41-800c-56b5d25952b6}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.00736903" x="0.624867" y="0.22247" z="1.07844"/>
|
||||||
|
<node id="{5e465c5c-fdc5-4c81-95dc-4729f981df5c}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.00660156" x="0.437669" y="0.226572" z="0.991136"/>
|
||||||
|
<node id="{5eb9bd01-2f33-4a6d-bb01-4a8a6cc7469c}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.0160875" x="0.559272" y="0.365487" z="0.85558"/>
|
||||||
|
<node id="{61ba80ab-f761-4889-a07e-7b2b7ff91e5c}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0094301" x="0.563839" y="0.302585" z="0.780169"/>
|
||||||
|
<node id="{6394e5cc-a367-4664-a9af-753d41b82ba6}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.0157834" x="0.775252" y="0.0559345" z="1.09142"/>
|
||||||
|
<node id="{644464d2-775c-42ec-8544-206fe7d11fe7}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.00885373" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{651c39df-7b14-4fd3-beb3-592efcb25842}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0202136" x="0.471153" y="0.0252876" z="0.992578"/>
|
||||||
|
<node id="{66c32673-0a5b-4c93-8dd8-26ea2e206aa9}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.018684" x="0.508007" y="0.30584" z="1.01773"/>
|
||||||
|
<node id="{68be0242-2557-4881-b306-25936e0ac472}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00374236" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{6a16e994-9730-49a8-81f7-d9bcaf0d3614}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0" x="0.56023" y="0.280472" z="1.04329"/>
|
||||||
|
<node id="{6b2ab6a9-c11c-4c88-b4f9-b66df3f09e4f}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.0117866" x="0.751855" y="0.0658246" z="1.10161"/>
|
||||||
|
<node id="{6b586d8c-e5a3-4405-b346-0d07c1fc587b}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.0146164" x="0.561272" y="0.296321" z="0.771565"/>
|
||||||
|
<node id="{6c9d6544-ff34-4259-8d31-72393a4d7629}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.0108231" x="0.498074" y="0.147199" z="1.01143"/>
|
||||||
|
<node id="{6cbb96e6-231d-4ac1-b9ec-75b258b16a1e}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0" x="0.504622" y="0.292991" z="1.01866"/>
|
||||||
|
<node id="{6d108c14-4e3d-4273-8cee-084390309386}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0" x="0.55357" y="0.277529" z="0.745752"/>
|
||||||
|
<node id="{6d6619eb-70e2-48e4-b8a6-0ff52d14584b}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.00757784" x="0.499048" y="0.16079" z="1.02006"/>
|
||||||
|
<node id="{6dea3dfc-6305-4221-81f8-d59379db1f8c}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00562501" x="0.521301" y="0.507458" z="0.965918"/>
|
||||||
|
<node id="{6e591cdf-09bd-478c-a604-ac7d19acf528}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.00836663" x="0.515537" y="0.277544" z="0.767988"/>
|
||||||
|
<node id="{6ef80ba2-4d3c-4a6e-a901-e5ddc913a272}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.0160875" x="0.549685" y="0.372597" z="0.85726"/>
|
||||||
|
<node id="{6fd6b2c1-ab1f-4904-ac30-2f800bbfc95a}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00439503" x="0.51987" y="0.465217" z="0.933138"/>
|
||||||
|
<node id="{7057282d-6ae5-4d7e-b10e-85ae69c7f72a}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.00699227" x="0.755719" y="0.068247" z="1.0946"/>
|
||||||
|
<node id="{70da7060-9223-4ac9-b6ca-ea16eeb20d45}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0101068" x="0.459929" y="0.0522857" z="0.985105"/>
|
||||||
|
<node id="{7153e3f6-ba74-4b9a-9a48-1f6b454b3678}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.0168282" x="0.518851" y="0.256622" z="1.02709"/>
|
||||||
|
<node id="{71b98c98-8654-42d8-b58a-22688b722630}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.0130493" x="0.549102" y="0.292024" z="0.787451"/>
|
||||||
|
<node id="{7285fcb8-4779-4e60-a474-4641c0943463}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.016105" x="0.533222" y="0.721447" z="1.02103"/>
|
||||||
|
<node id="{7293a322-fbad-4c7b-a059-606020ff09bf}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.00564634" x="0.507749" y="0.327981" z="0.799133"/>
|
||||||
|
<node id="{734ab0d5-d4d8-485a-b521-ebd36a3a8720}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0" x="0.516227" y="0.174434" z="1.00037"/>
|
||||||
|
<node id="{7351a5f6-983d-4fdf-83c9-be734363f2ca}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.0173385" x="0.544025" y="0.414478" z="0.884335"/>
|
||||||
|
<node id="{73951d38-c2aa-4577-927b-7e9429d1f0db}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.0132031" x="0.442581" y="0.23407" z="0.992616"/>
|
||||||
|
<node id="{73b1a616-30a5-44a9-a246-76ff142d228b}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0" x="0.52259" y="0.181444" z="1.02456"/>
|
||||||
|
<node id="{743d083e-3e96-4eb7-9c5f-0f0cee310915}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.0132031" x="0.447494" y="0.241568" z="0.994095"/>
|
||||||
|
<node id="{74620eab-e43b-44e3-be3a-68f3838cda88}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.0166743" x="0.51349" y="0.315674" z="1.05824"/>
|
||||||
|
<node id="{751fee8a-4d20-44bf-b68f-24b908abf032}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00140585" x="0.710183" y="0.110714" z="1.07757"/>
|
||||||
|
<node id="{75239010-9a3d-434c-a036-a8a59a0fe3d6}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.0125641" x="0.512828" y="0.307044" z="1.02772"/>
|
||||||
|
<node id="{75d10124-3ee1-47f1-8e95-b397c0f35fe9}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.00652467" x="0.563839" y="0.302585" z="0.780169"/>
|
||||||
|
<node id="{76a160cd-60d5-4010-bd9a-6032c97f67b8}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.00789172" x="0.755719" y="0.068247" z="1.0946"/>
|
||||||
|
<node id="{78b55011-5b1b-4c44-9240-71968c7ad7f8}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0" x="0.695953" y="0.147049" z="1.11147"/>
|
||||||
|
<node id="{78daab6a-4bd3-44b5-b9a8-785d8e08bb78}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0069189" x="0.515287" y="0.184273" z="1.00346"/>
|
||||||
|
<node id="{796b1ebe-9414-4ec1-b58b-f3cdf6006d6e}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.0175657" x="0.488267" y="0.295112" z="0.788285"/>
|
||||||
|
<node id="{7a7cf872-03e0-4655-92e7-0af10466cc83}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.473324" y="0.317373" z="0.713406"/>
|
||||||
|
<node id="{7b04a282-03d9-4a06-bec2-b48417956ce9}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.0124613" x="0.49815" y="0.536441" z="1.01508"/>
|
||||||
|
<node id="{7b4bad9a-3192-479a-bc39-3d486444fe72}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.0124613" x="0.50195" y="0.541687" z="1.00836"/>
|
||||||
|
<node id="{7c5da7e3-9eab-47f1-9736-c53bcf1e8efa}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.00589328" x="0.744128" y="0.0609797" z="1.11563"/>
|
||||||
|
<node id="{7dfc521a-3f80-4e32-93c9-85fe7b84dd93}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0" x="0.482376" y="-0.00171058" z="1.00005"/>
|
||||||
|
<node id="{7e3c29a3-b4f3-466d-a888-a05b5e1704e6}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.00833715" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{7e6244ae-8921-4012-9dfd-badac7408adb}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.0033768" x="0.53444" y="0.421419" z="0.889157"/>
|
||||||
|
<node id="{7e852b72-9d70-4dfd-9bfc-f857d3dbbb16}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.00623065" x="0.50575" y="0.546933" z="1.00164"/>
|
||||||
|
<node id="{7f3333db-755a-4a86-a2d7-2126da8f6a49}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0" x="0.47453" y="0.202963" z="0.972421"/>
|
||||||
|
<node id="{80e3c868-985f-4c6d-a57d-34e359987138}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.00665101" x="0.452406" y="0.249066" z="0.995575"/>
|
||||||
|
<node id="{80faa256-324d-4c76-b4e6-491956155230}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.0109447" x="0.479416" y="0.100435" z="0.98661"/>
|
||||||
|
<node id="{818b69e5-7a8b-41dd-970a-90348c5b766c}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.00866923" x="0.563195" y="0.400594" z="0.874691"/>
|
||||||
|
<node id="{833ad6bd-3219-4093-9689-2f7cbe8ac8fc}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.00934199" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{8471ffad-53be-4a68-ab72-97d32d7308fc}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0138378" x="0.513406" y="0.20395" z="1.00963"/>
|
||||||
|
<node id="{84db1f93-1858-4a96-be7f-7a383a1430df}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.0173385" x="0.55361" y="0.407536" z="0.879513"/>
|
||||||
|
<node id="{84e6a0cf-c4e1-478c-8fed-a5cc25d9be5f}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.00573453" x="0.618263" y="0.233908" z="1.07994"/>
|
||||||
|
<node id="{8540d159-7f70-44d7-86d2-471873be9bdb}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00407143" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{85cd375b-8df3-4653-855e-2a7bb3f623fe}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.00756106" x="0.555869" y="0.341132" z="0.824651"/>
|
||||||
|
<node id="{85fceff6-5c5b-4882-9f92-e45d6c5613fe}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0" x="0.535248" y="0.292922" z="1.03142"/>
|
||||||
|
<node id="{8626c044-fef3-47d2-a38f-944010bdef05}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.00581841" x="0.555869" y="0.341132" z="0.824651"/>
|
||||||
|
<node id="{869cd102-81cd-4c15-b377-955b61d44d30}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.0165943" x="0.513778" y="0.335641" z="0.823884"/>
|
||||||
|
<node id="{86a40600-8eac-4094-81a0-a1d698c94d2d}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.00760679" x="0.563839" y="0.302585" z="0.780169"/>
|
||||||
|
<node id="{86e86e5e-2ee3-46e3-ae87-6f88b27d3855}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0069189" x="0.512466" y="0.213789" z="1.01271"/>
|
||||||
|
<node id="{878d0098-c6f5-4a98-8e1e-d469396b6b4d}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0110956" x="0.606582" y="0.236632" z="1.06688"/>
|
||||||
|
<node id="{881104c8-1859-4bd6-8bc1-fe2f5e807e98}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.00623065" x="0.494351" y="0.531195" z="1.0218"/>
|
||||||
|
<node id="{8b37e76a-099c-4b5d-af5c-26c1fe4f55ab}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0" x="0.76559" y="0.0526443" z="1.13977"/>
|
||||||
|
<node id="{8ba09bc4-ac19-42ad-8b41-31683e1dc872}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0" x="0.494981" y="0.290583" z="0.998667"/>
|
||||||
|
<node id="{8dc941af-cffe-4f7b-aa0a-b0db5a0e5e1d}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.314637" y="0.336525" z="0.713406"/>
|
||||||
|
<node id="{8e43cbd3-2aa9-4265-95b8-92056c4c4737}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.00536282" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{8f367bd2-114c-4d04-96c5-bbb53a16d8ba}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0120206" x="0.514997" y="0.205702" z="1.01567"/>
|
||||||
|
<node id="{90999c8b-a2c9-459f-847e-0fde4493fbff}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.00757784" x="0.522448" y="0.136762" z="1.01642"/>
|
||||||
|
<node id="{927f0b23-db5a-49e7-8d0f-bcc811f7752e}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.0151221" x="0.565433" y="0.335194" z="0.825821"/>
|
||||||
|
<node id="{9362b987-f419-4f31-bfaf-9539700ad242}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.0168282" x="0.519508" y="0.244335" z="1.0243"/>
|
||||||
|
<node id="{94362d37-639a-40ff-b191-5c0a6e19f664}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.0197157" x="0.457937" y="0.23754" z="0.989787"/>
|
||||||
|
<node id="{9530cb12-6d41-4bd3-8175-1ba24943e21b}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.000272999" x="0.569785" y="0.264018" z="0.742748"/>
|
||||||
|
<node id="{95ad6172-babb-45c4-a96d-4d734ba6a25e}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.00943412" x="0.52102" y="0.183891" z="0.984483"/>
|
||||||
|
<node id="{973af58c-b3f5-4346-b614-413eb42ca621}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.00736903" x="0.599025" y="0.238034" z="1.06653"/>
|
||||||
|
<node id="{979a9d6c-f734-4f25-a0fc-04310bd4646b}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00903996" x="0.513921" y="0.377636" z="1.03506"/>
|
||||||
|
<node id="{9a7851b9-a7e8-4666-a13e-5cb7a8cc09c4}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0188602" x="0.571346" y="0.295554" z="0.77051"/>
|
||||||
|
<node id="{9bf0c1e8-8582-442c-90a4-5037d7219b21}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.000953281" x="0.555869" y="0.341132" z="0.824651"/>
|
||||||
|
<node id="{9c766968-443b-4e52-88ce-f1f20d377b5c}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.00836663" x="0.492055" y="0.304378" z="0.779797"/>
|
||||||
|
<node id="{9c857bb2-10b3-45e0-8271-3272e88a8bd7}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0" x="0.490551" y="0.525949" z="1.02853"/>
|
||||||
|
<node id="{9d65e303-67cf-4bbb-ab6a-09120b410c7b}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0194515" x="0.519038" y="0.887627" z="1.02668"/>
|
||||||
|
<node id="{9db4d842-ce14-4854-a532-d10650139dfc}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.0170931" x="0.758187" y="0.0643464" z="1.10589"/>
|
||||||
|
<node id="{9e8b06ca-12a6-4927-bd46-4d3f479230ae}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.00943412" x="0.512466" y="0.213789" z="1.01271"/>
|
||||||
|
<node id="{a08ef2a3-d98f-44ab-9765-c725baf366dc}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0182872" x="0.515107" y="0.833052" z="1.01116"/>
|
||||||
|
<node id="{a0a9a94a-672a-45e8-a0bb-31be9300b41f}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00391173" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{a1101b66-19df-47af-9d58-822ff9eb26b9}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.0170931" x="0.760655" y="0.0604457" z="1.11718"/>
|
||||||
|
<node id="{a242b2bf-afe5-4672-aa61-e97e99e68a4c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00193612" x="0.675597" y="0.153363" z="1.08021"/>
|
||||||
|
<node id="{a370ab3d-5136-42d7-9aa9-ac3bed89d137}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.00841411" x="0.520166" y="0.232048" z="1.02152"/>
|
||||||
|
<node id="{a3e0771b-c680-4c0c-8fcf-acd03fab6785}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00268242" x="0.452406" y="0.249066" z="0.995575"/>
|
||||||
|
<node id="{a3e169ff-fc5f-4dcd-b7c5-0a14fa29b73e}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.00730822" x="0.556137" y="0.283793" z="0.754356"/>
|
||||||
|
<node id="{a6209995-831e-4084-afeb-32704ca086bf}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.0141029" x="0.726014" y="0.097259" z="1.08104"/>
|
||||||
|
<node id="{a7137baa-7fe5-4d1c-b9f2-11b8bf6be38a}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.00854656" x="0.755719" y="0.068247" z="1.0946"/>
|
||||||
|
<node id="{a88191b2-a7cd-4b7a-be30-d5d97c3a0b48}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.0166743" x="0.517262" y="0.318385" z="1.04751"/>
|
||||||
|
<node id="{a9746f2b-b2ba-40a7-a405-d34b982c683f}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.0024147" x="0.540098" y="0.379707" z="0.858939"/>
|
||||||
|
<node id="{aa1e35db-d9de-48a1-9b6a-e18a54ac4435}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.013302" x="0.44725" y="0.241616" z="0.99539"/>
|
||||||
|
<node id="{aac479ee-6f32-4c7a-b2e6-5e2c1df8c251}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00682936" x="0.50575" y="0.546933" z="1.00164"/>
|
||||||
|
<node id="{adbd9948-2566-46d3-8603-0d4ecf4c9fa4}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.00878287" x="0.492055" y="0.304378" z="0.779797"/>
|
||||||
|
<node id="{adda25df-58c1-4e63-ba09-c05ec91ac643}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00123233" x="0.385379" y="0.176643" z="0.939178"/>
|
||||||
|
<node id="{aefc096e-5901-425f-a831-6a0ddbd50399}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.0157834" x="0.765485" y="0.0620907" z="1.09301"/>
|
||||||
|
<node id="{b1a5e801-c4b0-4478-aad0-41c40133502e}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0" x="0.497099" y="0.133608" z="1.0028"/>
|
||||||
|
<node id="{b1d0b918-225b-4399-a8d8-e90b84b5f5be}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.0107256" x="0.524587" y="0.314053" z="1.03544"/>
|
||||||
|
<node id="{b256069f-8463-4f7d-b6e0-30af0bbf2898}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.0136868" x="0.685775" y="0.150206" z="1.09584"/>
|
||||||
|
<node id="{b31ca9d5-5b56-4c42-bebf-4d2d6aef739f}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.00136076" x="0.524949" y="0.382805" z="0.856618"/>
|
||||||
|
<node id="{b4b3a668-fd69-4887-ba98-abe5dae57101}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.00866923" x="0.53444" y="0.421419" z="0.889157"/>
|
||||||
|
<node id="{b71171d7-1d32-46f7-8fca-fcc3a7a5a46e}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0101068" x="0.476764" y="0.0117885" z="0.996314"/>
|
||||||
|
<node id="{ba04e35f-5b85-46bf-84f6-f4b253125471}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0" x="0.588853" y="0.277802" z="0.751257"/>
|
||||||
|
<node id="{ba05b4f6-6652-449b-ad37-d4b09bda988b}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.0136868" x="0.680686" y="0.151785" z="1.08803"/>
|
||||||
|
<node id="{ba2664a7-be02-420f-b744-931e66efefe0}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.0147381" x="0.607639" y="0.232846" z="1.0705"/>
|
||||||
|
<node id="{baa52d8a-ed0e-4138-bc8b-6a72054cfe95}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.0146164" x="0.558704" y="0.290057" z="0.76296"/>
|
||||||
|
<node id="{bbab93bd-50a6-47f4-b608-00091b262e97}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.0188682" x="0.515317" y="0.203823" z="1.0033"/>
|
||||||
|
<node id="{bbdd82a9-286b-4c1c-b007-745c306e4f14}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0" x="0.594126" y="0.31738" z="0.829333"/>
|
||||||
|
<node id="{bd244a0f-1d5e-4307-85b7-f764e6c1304b}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.00760679" x="0.5826" y="0.283998" z="0.758485"/>
|
||||||
|
<node id="{c1052900-009d-4ab3-9734-684f91bdab25}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.00589328" x="0.755719" y="0.068247" z="1.0946"/>
|
||||||
|
<node id="{c1a57de4-5129-46f3-ace2-c662a6c079b8}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.00756106" x="0.584562" y="0.323318" z="0.828163"/>
|
||||||
|
<node id="{c319f392-3b4d-4f01-a0f8-50ef45168844}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0" x="0.476903" y="0.267313" z="0.813748"/>
|
||||||
|
<node id="{c42a3e99-b6aa-4c26-8579-44228dd34b4b}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.00680655" x="0.466423" y="0.0276555" z="1.00169"/>
|
||||||
|
<node id="{c5cfd17f-ec0b-433b-b36b-f126b540b6a6}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00304648" x="0.512466" y="0.213789" z="1.01271"/>
|
||||||
|
<node id="{c62e9181-4388-4e00-a10a-8a61eb93c4ae}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0055478" x="0.599025" y="0.238034" z="1.06653"/>
|
||||||
|
<node id="{c78986e6-a263-42cf-b5f1-8b9fdc6f74a8}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.0116368" x="0.546458" y="0.33313" z="0.836904"/>
|
||||||
|
<node id="{c7bd203d-7b04-47a9-a394-d7d1f18555c4}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.0109447" x="0.47718" y="0.0946081" z="0.981412"/>
|
||||||
|
<node id="{c8d861a6-491b-42d4-8e07-73e5df7c019b}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00318423" x="0.486602" y="0.285251" z="1.0181"/>
|
||||||
|
<node id="{c9174f26-59b1-4382-8214-bc4a91f1759e}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.00951228" x="0.550431" y="0.290628" z="1.04166"/>
|
||||||
|
<node id="{ccd8ef94-281b-4dfb-ab29-b50dfe17a770}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.0136131" x="0.464259" y="0.0358656" z="0.996163"/>
|
||||||
|
<node id="{ce3ca970-0d64-4ee1-92ef-8720f608f05f}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0056639" x="0.431826" y="-0.128762" z="0.951431"/>
|
||||||
|
<node id="{ce8a93e4-e574-4e93-82b1-fbd2ca77ef0f}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0" x="0.520823" y="0.219761" z="1.01874"/>
|
||||||
|
<node id="{cea888e7-491c-40e5-be50-e60137d4c8a4}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.00547236" x="0.481651" y="0.106262" z="0.991808"/>
|
||||||
|
<node id="{cede8a6a-4e51-4c07-8581-0999b4705616}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.0177075" x="0.513452" y="0.310782" z="1.03548"/>
|
||||||
|
<node id="{cf6b2e2b-89ef-442c-87ca-74d86de7afdc}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00349248" x="0.572339" y="0.280627" z="1.0527"/>
|
||||||
|
<node id="{cf75b27e-3656-4130-8543-d07cbc98b9c9}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.377565" y="0.340629" z="0.713406"/>
|
||||||
|
<node id="{d043181f-393b-4e20-8ad5-bc2c04e61bfd}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.00878287" x="0.480691" y="0.27658" z="0.80526"/>
|
||||||
|
<node id="{d1325b2e-e338-4239-9988-1d1dc6c44a6d}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.00573453" x="0.599025" y="0.238034" z="1.06653"/>
|
||||||
|
<node id="{d2de90d6-ac0c-4bdd-b5e3-573960fad70c}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00622413" x="0.53858" y="0.264806" z="1.03477"/>
|
||||||
|
<node id="{d2f4e68c-bc10-46d3-b82c-aadf00fa23e2}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.00730822" x="0.563839" y="0.302585" z="0.780169"/>
|
||||||
|
<node id="{d36ed08a-2202-41de-9601-76d275344502}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.0167333" x="0.507709" y="0.286489" z="0.771924"/>
|
||||||
|
<node id="{d5be35fe-16ec-40bd-b41b-d92171f18a01}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0" x="0.50371" y="0.177526" z="1.0146"/>
|
||||||
|
<node id="{d69b0b89-1efb-4918-baf5-d0cc0d5b972c}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.00680655" x="0.459929" y="0.0522857" z="0.985105"/>
|
||||||
|
<node id="{d7bf67d3-f4df-45b3-8a40-2dabc5e41d32}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0" x="0.523364" y="0.268599" z="0.764051"/>
|
||||||
|
<node id="{d866de28-dae4-40ce-b547-81e4cf5c1bfc}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0" x="0.740264" y="0.0585572" z="1.12263"/>
|
||||||
|
<node id="{da2809c9-3b46-4621-a9da-abfa3839f9f5}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0" x="0.755395" y="0.0423452" z="1.0619"/>
|
||||||
|
<node id="{daa6e549-8d8c-4219-b312-84b523aa4f51}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.00660156" x="0.452406" y="0.249066" z="0.995575"/>
|
||||||
|
<node id="{dc0aaf45-eb00-49b6-8e81-fa979245ac09}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0124874" x="0.50575" y="0.546933" z="1.00164"/>
|
||||||
|
<node id="{dedcce23-b5ab-4e30-a62a-29155b8d5e2a}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0056639" x="0.44197" y="-0.109533" z="0.938581"/>
|
||||||
|
<node id="{df693fdf-c112-4501-afcc-243afa0c4611}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.00934199" x="0.501494" y="0.298212" z="1.0082"/>
|
||||||
|
<node id="{dfd92d67-a666-4f9e-a606-217795b284cc}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00284921" x="0.499048" y="0.16079" z="1.02006"/>
|
||||||
|
<node id="{e04cf7e6-1351-49fc-acd7-67ea3641d678}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.00985783" x="0.468999" y="0.214489" z="0.97821"/>
|
||||||
|
<node id="{e08afd53-006d-4434-9905-0ef150d16cd9}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.00541154" x="0.499048" y="0.16079" z="1.02006"/>
|
||||||
|
<node id="{e2bae992-d1d2-4fdd-9a30-dba9c62f5322}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.00885373" x="0.49829" y="0.290152" z="1.03287"/>
|
||||||
|
<node id="{e2f0521a-2b2d-4c9b-b806-d6f4c2d078f4}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.0188682" x="0.518169" y="0.193857" z="0.993893"/>
|
||||||
|
<node id="{e3592e6e-2c54-4f3c-8745-e35f79c472d2}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.00174188" x="0.53444" y="0.421419" z="0.889157"/>
|
||||||
|
<node id="{e3a311f1-ab14-4e80-80dc-9f882721d9a8}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00196966" x="0.419713" y="0.213334" z="0.965049"/>
|
||||||
|
<node id="{e5a7a6e8-c4de-4ea6-a175-93b87b709bee}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.0108231" x="0.498561" y="0.153995" z="1.01574"/>
|
||||||
|
<node id="{e5afd1fe-e4a7-4e2a-90cf-1cb2a55fe07e}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0" x="0.536854" y="0.311372" z="0.83963"/>
|
||||||
|
<node id="{e5cbc93e-98eb-45b3-9046-1d60f009b382}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.00833715" x="0.509718" y="0.312963" z="1.06896"/>
|
||||||
|
<node id="{e785bb5a-3352-4545-a008-17d16d82c906}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.0130493" x="0.55647" y="0.297305" z="0.78381"/>
|
||||||
|
<node id="{e79795d5-e758-4acb-8559-7f1033c9b02f}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.343365" y="0.340629" z="0.713406"/>
|
||||||
|
<node id="{e7bc4edf-781b-4916-8abe-a304cda6ae75}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.0139845" x="0.755557" y="0.0552961" z="1.07825"/>
|
||||||
|
<node id="{e90118b2-e7ef-4ebc-ba06-784613255d46}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.018684" x="0.51452" y="0.313468" z="1.02725"/>
|
||||||
|
<node id="{e94df7f8-d0ca-478e-aed1-25fa8d60b9fd}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.0125109" x="0.498141" y="0.151655" z="1.01815"/>
|
||||||
|
<node id="{eb4fb92f-f8ea-49ef-b132-ae6b72fa6ea4}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0202136" x="0.465541" y="0.0387866" z="0.988842"/>
|
||||||
|
<node id="{eb6898b8-464b-4d10-9c56-9479d47438af}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0" x="0.47271" y="0.0829541" z="0.971016"/>
|
||||||
|
<node id="{ebe51975-e81f-45a6-aa7d-ca216cc56c8b}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.0163502" x="0.499188" y="0.266314" z="1.01076"/>
|
||||||
|
<node id="{ebe6c9ed-8cd5-4d44-acda-3846acf13ec1}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.00817509" x="0.486602" y="0.285251" z="1.0181"/>
|
||||||
|
<node id="{edb9977c-0dd1-4472-8534-dbeb127c9d16}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.00705143" x="0.710183" y="0.110714" z="1.07757"/>
|
||||||
|
<node id="{eddf44c5-0c61-446b-a724-4456c024978a}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0" x="0.432757" y="0.219074" z="0.989657"/>
|
||||||
|
<node id="{ee43d10c-d4f1-4315-a3c2-618c2ce40d6a}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0" x="0.52056" y="0.478958" z="0.917544"/>
|
||||||
|
<node id="{f06b2588-283a-4bcc-a9e5-00f5cb6c9c57}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.0181634" x="0.480017" y="0.0931144" z="0.99489"/>
|
||||||
|
<node id="{f17183a2-5ecc-4b81-9399-5d3cfbb2eea2}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0" x="0.468588" y="0.0194454" z="1.00722"/>
|
||||||
|
<node id="{f1d52a81-d771-49f4-96f7-079e891415be}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.0139845" x="0.755638" y="0.0617716" z="1.08642"/>
|
||||||
|
<node id="{f2778fa6-19d7-47dd-afc8-1e4f355c6475}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.00628206" x="0.508725" y="0.300017" z="1.02319"/>
|
||||||
|
<node id="{f419bd71-f788-4382-9479-6cc8b7e240c4}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.00951228" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{f5692d54-1eb7-4c3c-8e99-5323bd0046d4}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.0190246" x="0.540632" y="0.300784" z="1.04004"/>
|
||||||
|
<node id="{f5c1ef85-7999-4224-845f-cfc4e07e2ef3}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0051308" x="0.53799" y="0.208533" z="1.01087"/>
|
||||||
|
<node id="{f6050cf2-105d-43b6-ade2-625e690e55f8}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.0163502" x="0.492895" y="0.275783" z="1.01443"/>
|
||||||
|
<node id="{f650f5b5-094c-41d1-b3b2-ece8be532cc1}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.0197157" x="0.463468" y="0.226014" z="0.983998"/>
|
||||||
|
<node id="{f738f338-39e1-495e-a94e-5e914d4d5317}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0" x="0.515228" y="0.116487" z="1.0404"/>
|
||||||
|
<node id="{f797fc7d-48c3-4a02-8215-11b2575f7982}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.00623232" x="0.512466" y="0.213789" z="1.01271"/>
|
||||||
|
<node id="{f7984a7e-fd12-4428-8e71-9b9e913492fb}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.013302" x="0.442093" y="0.234165" z="0.995204"/>
|
||||||
|
<node id="{f7c408de-4dc2-4201-8ab9-f02c04a19893}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0169183" x="0.509819" y="0.77672" z="1.03141"/>
|
||||||
|
<node id="{f7c9ef1b-11cc-4f1e-b217-322279b063b3}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.00789172" x="0.785019" y="0.0497782" z="1.08983"/>
|
||||||
|
<node id="{f8e96450-96e9-4f56-b89c-3c74d76de271}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.0141029" x="0.718098" y="0.103986" z="1.07931"/>
|
||||||
|
<node id="{fb5b878a-9ef0-4869-9dc9-4e8d6f623440}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0110956" x="0.614139" y="0.23523" z="1.06723"/>
|
||||||
|
<node id="{fcba37c4-7372-43df-9d2e-5404cc9a1b91}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.00937295" x="0.521301" y="0.507458" z="0.965918"/>
|
||||||
|
<node id="{fd311c21-d781-4437-bfd3-414ae999f244}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.0177075" x="0.505871" y="0.300467" z="1.03418"/>
|
||||||
|
<node id="{fd8dd98f-7c73-48e4-bdf0-904f2e2271e5}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.000615901" x="0.563839" y="0.302585" z="0.780169"/>
|
||||||
|
<node id="{fda59363-53f2-4d4d-a6ad-dce8aee17257}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.00628206" x="0.521034" y="0.321097" z="1.03678"/>
|
||||||
|
<node id="{fe831613-5b6a-43f2-a789-b7c0ce027d0a}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.0151557" x="0.506848" y="0.152781" z="1.01884"/>
|
||||||
|
</nodes>
|
||||||
|
<edges>
|
||||||
|
<edge from="{6c9d6544-ff34-4259-8d31-72393a4d7629}" id="{0096dcff-d08a-41e2-9c15-cc57943d039f}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{05438075-6182-4f45-80c2-35625897b718}"/>
|
||||||
|
<edge from="{067095a4-8e69-40d7-bc00-9c0a7f4e1e3c}" id="{01176b68-f37c-4738-9f49-ba5b00869789}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{c5cfd17f-ec0b-433b-b36b-f126b540b6a6}"/>
|
||||||
|
<edge from="{86e86e5e-2ee3-46e3-ae87-6f88b27d3855}" id="{020cc0b2-ca8d-44ee-86aa-69b35311fdfa}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{8471ffad-53be-4a68-ab72-97d32d7308fc}"/>
|
||||||
|
<edge from="{e2f0521a-2b2d-4c9b-b806-d6f4c2d078f4}" id="{033ddc37-8b89-4f86-b344-0955e617f39e}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{95ad6172-babb-45c4-a96d-4d734ba6a25e}"/>
|
||||||
|
<edge from="{df693fdf-c112-4501-afcc-243afa0c4611}" id="{0359760c-8bbe-4290-88e6-ac58b26abc87}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{8ba09bc4-ac19-42ad-8b41-31683e1dc872}"/>
|
||||||
|
<edge from="{3932e31f-34f7-47da-8a0d-032bec47e53c}" id="{03e45417-242e-4896-b1f5-2e2c3354943e}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{5a7cf847-a78d-4877-9d4f-94cd9bb9eca8}"/>
|
||||||
|
<edge from="{78daab6a-4bd3-44b5-b9a8-785d8e08bb78}" id="{047b1783-1287-4175-91cd-771c9f57e81e}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{734ab0d5-d4d8-485a-b521-ebd36a3a8720}"/>
|
||||||
|
<edge from="{b31ca9d5-5b56-4c42-bebf-4d2d6aef739f}" id="{05675c45-4b4d-4ca1-9ef9-34dc12c16a9d}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" to="{221a1797-ed67-4cfd-9cd8-34823e651ed3}"/>
|
||||||
|
<edge from="{28381152-78fe-4c2d-8c3c-c776138efa17}" id="{059c952e-c740-42a3-b8b9-201b71f59f88}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{117ef567-17a0-425e-9fcb-ae1610e91539}"/>
|
||||||
|
<edge from="{a1101b66-19df-47af-9d58-822ff9eb26b9}" id="{08183a72-f98a-486c-a5fc-1fbdd8388ce4}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{0b4f4946-8ff1-4efe-bdfe-0b611af6a655}"/>
|
||||||
|
<edge from="{dedcce23-b5ab-4e30-a62a-29155b8d5e2a}" id="{09104af4-aaaa-476b-a2ca-14037f001996}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{28381152-78fe-4c2d-8c3c-c776138efa17}"/>
|
||||||
|
<edge from="{071305c7-8044-4c28-8ccc-4f74cffb61cc}" id="{096d65ab-e733-487d-9134-a295c3cad472}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{0711915a-a413-42b5-8022-35668c45d39b}"/>
|
||||||
|
<edge from="{55b5bb5d-d614-4cd3-b331-8819186ed572}" id="{0a23f811-2056-415d-83fa-d7c16be92cc2}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{dc0aaf45-eb00-49b6-8e81-fa979245ac09}"/>
|
||||||
|
<edge from="{4c81714b-6ac4-45d8-b4f0-c98539911521}" id="{0a325591-d1f0-490b-a602-57396ad4d84e}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{3cce2c34-9aab-46dc-bbd3-3a73327a8875}"/>
|
||||||
|
<edge from="{d1325b2e-e338-4239-9988-1d1dc6c44a6d}" id="{0b95966e-58f0-48f9-b474-8d6af804f41f}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{36e6565b-5c7c-4203-9757-b7afa6731c57}"/>
|
||||||
|
<edge from="{cf75b27e-3656-4130-8543-d07cbc98b9c9}" id="{0b9bf276-d38e-44bb-a0ed-47037621de51}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{4c81714b-6ac4-45d8-b4f0-c98539911521}"/>
|
||||||
|
<edge from="{1b515278-0117-48fe-a1fe-e772057573d9}" id="{0c223e7d-82d3-40d2-b5e9-47a11ac3f7d6}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{58bd7c83-b479-4e17-b4df-754316eef264}"/>
|
||||||
|
<edge from="{c78986e6-a263-42cf-b5f1-8b9fdc6f74a8}" id="{0d097ed2-6598-46f3-ac76-381fecf64297}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{58321009-70bf-48ba-bbe7-f5afcd9e56f3}"/>
|
||||||
|
<edge from="{9c766968-443b-4e52-88ce-f1f20d377b5c}" id="{0d263e4e-5038-4640-bbab-e9f346dde7fc}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{4029708e-b1f7-4f53-832e-d0983bfcd651}"/>
|
||||||
|
<edge from="{a242b2bf-afe5-4672-aa61-e97e99e68a4c}" id="{0e574fe6-7f52-4218-bdd0-4a2950e2a97f}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{751fee8a-4d20-44bf-b68f-24b908abf032}"/>
|
||||||
|
<edge from="{e94df7f8-d0ca-478e-aed1-25fa8d60b9fd}" id="{0fda6aea-37d5-4b90-9848-c5bcdb037f5e}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{1957320f-7dec-4069-a2b2-502d9a18442e}"/>
|
||||||
|
<edge from="{1c85074d-db26-4962-9694-26df45d957c6}" id="{0ff4697b-f1cf-4ba4-9980-21185fc9346b}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{1b515278-0117-48fe-a1fe-e772057573d9}"/>
|
||||||
|
<edge from="{e08afd53-006d-4434-9905-0ef150d16cd9}" id="{11530bb9-039f-4978-add5-ac73b953a642}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{e5a7a6e8-c4de-4ea6-a175-93b87b709bee}"/>
|
||||||
|
<edge from="{74620eab-e43b-44e3-be3a-68f3838cda88}" id="{13ed1669-4641-4c72-b633-c689cf72774b}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{e5cbc93e-98eb-45b3-9046-1d60f009b382}"/>
|
||||||
|
<edge from="{751fee8a-4d20-44bf-b68f-24b908abf032}" id="{143d5474-8a3d-4dcc-a628-d6a248c14426}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{52cc908a-1fa5-415d-9d64-51bb469706d7}"/>
|
||||||
|
<edge from="{ce3ca970-0d64-4ee1-92ef-8720f608f05f}" id="{15b5d349-7cae-47c2-84a9-c453a3b9525d}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{4b7f18aa-704e-4f55-9f69-16b0f38237ce}"/>
|
||||||
|
<edge from="{94362d37-639a-40ff-b191-5c0a6e19f664}" id="{164e77ed-3ed5-4eae-bb17-95fc1050d41c}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{f650f5b5-094c-41d1-b3b2-ece8be532cc1}"/>
|
||||||
|
<edge from="{979a9d6c-f734-4f25-a0fc-04310bd4646b}" id="{16adf7ad-d523-471c-bf19-7f7061996f65}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{0a8e8fb2-9858-49d2-8686-6ed728dccbc2}"/>
|
||||||
|
<edge from="{8540d159-7f70-44d7-86d2-471873be9bdb}" id="{17b22263-b406-4709-b49a-a678eff4c7ed}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{067095a4-8e69-40d7-bc00-9c0a7f4e1e3c}"/>
|
||||||
|
<edge from="{9db4d842-ce14-4854-a532-d10650139dfc}" id="{194e24c6-3018-4ae0-b9df-661cfdaeaf8a}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{a1101b66-19df-47af-9d58-822ff9eb26b9}"/>
|
||||||
|
<edge from="{aac479ee-6f32-4c7a-b2e6-5e2c1df8c251}" id="{1e0061ef-fe00-4405-9933-f6c47df15f7d}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{6dea3dfc-6305-4221-81f8-d59379db1f8c}"/>
|
||||||
|
<edge from="{e7bc4edf-781b-4916-8abe-a304cda6ae75}" id="{1e13cfd6-41dd-4eb3-a927-a5f4eadec2c4}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{44e13dd8-a3d2-4d4f-af81-372da15218d2}"/>
|
||||||
|
<edge from="{353010d5-28a2-4ce3-a465-12289cbadb21}" id="{1e500235-b08c-40a9-84ae-50884a9cebaa}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{567a286a-bf1d-4291-b979-ba69733646f5}"/>
|
||||||
|
<edge from="{7285fcb8-4779-4e60-a474-4641c0943463}" id="{1ec67251-fbda-4557-b1e7-571366b78c01}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{2cc27239-bf74-49d5-b82d-0998c0103d6d}"/>
|
||||||
|
<edge from="{cede8a6a-4e51-4c07-8581-0999b4705616}" id="{206685c9-6f62-42e1-a882-b8c77b81d8c1}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{fd311c21-d781-4437-bfd3-414ae999f244}"/>
|
||||||
|
<edge from="{7153e3f6-ba74-4b9a-9a48-1f6b454b3678}" id="{21503cae-2040-4dca-804b-6121ad0c87f4}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{9362b987-f419-4f31-bfaf-9539700ad242}"/>
|
||||||
|
<edge from="{199423e1-60c0-4b3c-b65a-3ab127cadf99}" id="{228c7b8d-ee59-401d-8ad9-ad209eed864a}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{1c85074d-db26-4962-9694-26df45d957c6}"/>
|
||||||
|
<edge from="{aa1e35db-d9de-48a1-9b6a-e18a54ac4435}" id="{23248007-e8ab-41b9-a06e-b7e2030b7737}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{f7984a7e-fd12-4428-8e71-9b9e913492fb}"/>
|
||||||
|
<edge from="{ba2664a7-be02-420f-b744-931e66efefe0}" id="{2334c6c9-8937-4ca3-8ba3-fadf7bf22add}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{404cdbf7-ef7b-4529-b04b-d775162d0edb}"/>
|
||||||
|
<edge from="{80e3c868-985f-4c6d-a57d-34e359987138}" id="{23d3917a-6afd-4d2e-9e7e-3d5192bad5bc}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{aa1e35db-d9de-48a1-9b6a-e18a54ac4435}"/>
|
||||||
|
<edge from="{f797fc7d-48c3-4a02-8215-11b2575f7982}" id="{25d4d757-7c7a-4e49-91c1-1c1331da8631}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{442d48bd-1797-45dc-8e4f-d121fb89237c}"/>
|
||||||
|
<edge from="{379bec20-9be3-4a64-b259-d3ed4e84ebbc}" id="{263c2d30-e148-4a3c-bc8d-a5288a19b0d2}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{ba05b4f6-6652-449b-ad37-d4b09bda988b}"/>
|
||||||
|
<edge from="{491add8b-4be8-4171-b647-24334b050892}" id="{26f34c35-7953-4d1d-9817-69bdcc8407ad}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{eb6898b8-464b-4d10-9c56-9479d47438af}"/>
|
||||||
|
<edge from="{a08ef2a3-d98f-44ab-9765-c725baf366dc}" id="{286131bc-5708-43b9-b354-24b62c64954c}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{f7c408de-4dc2-4201-8ab9-f02c04a19893}"/>
|
||||||
|
<edge from="{b1d0b918-225b-4399-a8d8-e90b84b5f5be}" id="{286e9d03-480a-4fbc-aeaf-db6df72b15dd}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{5064c6c5-783a-44e5-8e70-49c8c9cc2416}"/>
|
||||||
|
<edge from="{7b4bad9a-3192-479a-bc39-3d486444fe72}" id="{2920953c-c0ce-42ec-9ed4-6260647a45f0}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{7b04a282-03d9-4a06-bec2-b48417956ce9}"/>
|
||||||
|
<edge from="{f7c9ef1b-11cc-4f1e-b217-322279b063b3}" id="{2a4d76e0-cffe-40d0-a0d0-68880c787890}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{10d61f38-3849-4852-9dd1-2be2ad90d468}"/>
|
||||||
|
<edge from="{cf6b2e2b-89ef-442c-87ca-74d86de7afdc}" id="{2abfe96f-0c4b-41c3-8985-9525a5d0598c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{408119ac-6fc0-40f5-b60c-99b7cc9517ae}"/>
|
||||||
|
<edge from="{15283e25-d483-44c6-b530-113073ae54d0}" id="{2b9ff78a-67ef-4314-ae2e-6ff837fa5dfe}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{869cd102-81cd-4c15-b377-955b61d44d30}"/>
|
||||||
|
<edge from="{aefc096e-5901-425f-a831-6a0ddbd50399}" id="{2bd8eed2-1818-42ff-a5bc-5a69c04c9710}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{6394e5cc-a367-4664-a9af-753d41b82ba6}"/>
|
||||||
|
<edge from="{a0a9a94a-672a-45e8-a0bb-31be9300b41f}" id="{2fa4feb6-24c7-42a4-9747-d3b9a86047fc}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{cf6b2e2b-89ef-442c-87ca-74d86de7afdc}"/>
|
||||||
|
<edge from="{4684632b-e51c-414e-aa21-df1ee91ea834}" id="{30ee3f2e-eda0-4038-b30e-13f2635a5b24}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{d043181f-393b-4e20-8ad5-bc2c04e61bfd}"/>
|
||||||
|
<edge from="{796b1ebe-9414-4ec1-b58b-f3cdf6006d6e}" id="{32b0e144-7a1b-4ccf-9c59-05e1b504344b}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{4684632b-e51c-414e-aa21-df1ee91ea834}"/>
|
||||||
|
<edge from="{44e13dd8-a3d2-4d4f-af81-372da15218d2}" id="{3375cef7-ad82-44fc-b7a9-1eade3908a5d}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{da2809c9-3b46-4621-a9da-abfa3839f9f5}"/>
|
||||||
|
<edge from="{6fd6b2c1-ab1f-4904-ac30-2f800bbfc95a}" id="{338bc346-e040-404b-be5d-d986734f8055}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{7e6244ae-8921-4012-9dfd-badac7408adb}"/>
|
||||||
|
<edge from="{9d65e303-67cf-4bbb-ab6a-09120b410c7b}" id="{33b9ba1c-f491-4ac4-95f1-b5db2ba17afd}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{a08ef2a3-d98f-44ab-9765-c725baf366dc}"/>
|
||||||
|
<edge from="{e04cf7e6-1351-49fc-acd7-67ea3641d678}" id="{34179ba5-9481-4bb6-984a-390c87e013c9}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{7f3333db-755a-4a86-a2d7-2126da8f6a49}"/>
|
||||||
|
<edge from="{973af58c-b3f5-4346-b614-413eb42ca621}" id="{34c6b443-96c5-4c99-bfe5-8e78332609e4}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{ba2664a7-be02-420f-b744-931e66efefe0}"/>
|
||||||
|
<edge from="{6d6619eb-70e2-48e4-b8a6-0ff52d14584b}" id="{35e4a4db-5369-409e-977d-4c58ea33a724}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{fe831613-5b6a-43f2-a789-b7c0ce027d0a}"/>
|
||||||
|
<edge from="{927f0b23-db5a-49e7-8d0f-bcc811f7752e}" id="{365ffd29-e221-4516-9156-775ed09c8f04}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{27430d2c-0651-4361-a581-d304fcd67e22}"/>
|
||||||
|
<edge from="{84e6a0cf-c4e1-478c-8fed-a5cc25d9be5f}" id="{39385155-0aff-47ae-a9b5-f0d9a78424a8}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{001eb845-4bed-4de5-9803-ba8ca7faafaf}"/>
|
||||||
|
<edge from="{80faa256-324d-4c76-b4e6-491956155230}" id="{39b7e869-e586-4943-b6e5-76214e99d6b4}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{c7bd203d-7b04-47a9-a394-d7d1f18555c4}"/>
|
||||||
|
<edge from="{3547bb94-25b4-4740-a5e9-15046267f0f9}" id="{3a2dab82-5eb6-46db-b4b8-1afe92b105f7}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{3424cf20-48a1-4e64-be63-5890321cdbcd}"/>
|
||||||
|
<edge from="{05438075-6182-4f45-80c2-35625897b718}" id="{3b7d0700-ee48-4c52-8713-e89755f6ec41}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{b1a5e801-c4b0-4478-aad0-41c40133502e}"/>
|
||||||
|
<edge from="{2501c90c-247d-42a1-b2fb-411d88b95e3a}" id="{3cc889ef-5ff2-4655-abe0-fa4878665305}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{02b8c92c-3aad-43b4-b2d6-eb0659a8a206}"/>
|
||||||
|
<edge from="{833ad6bd-3219-4093-9689-2f7cbe8ac8fc}" id="{3cf1514d-d956-4da8-99b4-71606e8e63ef}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{e90118b2-e7ef-4ebc-ba06-784613255d46}"/>
|
||||||
|
<edge from="{15d886b0-181e-4e8d-84c4-21da599037c1}" id="{3eb0a7d3-a446-44b5-aab5-aaefb5d1c4ab}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{78b55011-5b1b-4c44-9240-71968c7ad7f8}"/>
|
||||||
|
<edge from="{8471ffad-53be-4a68-ab72-97d32d7308fc}" id="{3f4c2320-2fa7-4e68-877c-14b3f2e654d4}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{1ad678c9-b640-43d5-af1c-92ddfc540416}"/>
|
||||||
|
<edge from="{3cce2c34-9aab-46dc-bbd3-3a73327a8875}" id="{3ffc3ed2-4a9b-4b83-ab9f-52d4e3ba1384}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{7a7cf872-03e0-4655-92e7-0af10466cc83}"/>
|
||||||
|
<edge from="{8f367bd2-114c-4d04-96c5-bbb53a16d8ba}" id="{4180a4e0-22b4-474e-8fcf-cb78f8798906}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{0c131c2e-c763-4239-aae8-c71e219bb2ff}"/>
|
||||||
|
<edge from="{869cd102-81cd-4c15-b377-955b61d44d30}" id="{41fa76f3-3cbc-4858-a1c2-a2f037f4be88}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{0c3ed74f-ee80-41a9-8568-1487fe0cfd7c}"/>
|
||||||
|
<edge from="{b256069f-8463-4f7d-b6e0-30af0bbf2898}" id="{438257ce-1dbc-45c7-bf9f-360907a4b00e}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{15d886b0-181e-4e8d-84c4-21da599037c1}"/>
|
||||||
|
<edge from="{f5692d54-1eb7-4c3c-8e99-5323bd0046d4}" id="{45ba05df-2fcc-4a3b-86dd-13711499cf8d}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{c9174f26-59b1-4382-8214-bc4a91f1759e}"/>
|
||||||
|
<edge from="{651c39df-7b14-4fd3-beb3-592efcb25842}" id="{46be5837-af25-4f49-b837-c7b3fc309c37}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{b71171d7-1d32-46f7-8fca-fcc3a7a5a46e}"/>
|
||||||
|
<edge from="{e3592e6e-2c54-4f3c-8745-e35f79c472d2}" id="{47fa200b-6705-4cb5-bc1b-cb45fcc18270}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" to="{b31ca9d5-5b56-4c42-bebf-4d2d6aef739f}"/>
|
||||||
|
<edge from="{e3a311f1-ab14-4e80-80dc-9f882721d9a8}" id="{48a71f2a-4ad8-482d-b933-906b736c0cc6}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{adda25df-58c1-4e63-ba09-c05ec91ac643}"/>
|
||||||
|
<edge from="{14a9c743-142c-43a6-8962-5dbf6514c38a}" id="{49d839bf-7531-4776-b435-bc2a21782b46}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{f06b2588-283a-4bcc-a9e5-00f5cb6c9c57}"/>
|
||||||
|
<edge from="{e90118b2-e7ef-4ebc-ba06-784613255d46}" id="{4c297f88-7c9a-4e36-a0ff-d295a505eb02}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{66c32673-0a5b-4c93-8dd8-26ea2e206aa9}"/>
|
||||||
|
<edge from="{fda59363-53f2-4d4d-a6ad-dce8aee17257}" id="{4ec12ae8-59aa-4aea-8ae5-9adcc1c67b3f}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{5399b1af-6473-4df5-96cc-13e6e28784c1}"/>
|
||||||
|
<edge from="{e5cbc93e-98eb-45b3-9046-1d60f009b382}" id="{4ef7427a-44a6-4fbe-8a22-83b42145a363}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{53f27881-5a75-4c22-b2cf-7b2d05ee1d8e}"/>
|
||||||
|
<edge from="{73951d38-c2aa-4577-927b-7e9429d1f0db}" id="{539667f3-9c26-4d41-9730-4059d5a6c8fc}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{5e465c5c-fdc5-4c81-95dc-4729f981df5c}"/>
|
||||||
|
<edge from="{ccd8ef94-281b-4dfb-ab29-b50dfe17a770}" id="{5705b308-086e-4ea6-81cf-f78578bff77e}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{c42a3e99-b6aa-4c26-8579-44228dd34b4b}"/>
|
||||||
|
<edge from="{2cc27239-bf74-49d5-b82d-0998c0103d6d}" id="{576f4162-98f4-47f5-98a5-eba433e68ffa}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{55b5bb5d-d614-4cd3-b331-8819186ed572}"/>
|
||||||
|
<edge from="{7293a322-fbad-4c7b-a059-606020ff09bf}" id="{588e7c89-c53e-48e5-953e-4bd17eafe928}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{0402a0e9-9712-4d9c-b022-ea25f2ed64d0}"/>
|
||||||
|
<edge from="{bd244a0f-1d5e-4307-85b7-f764e6c1304b}" id="{58a164c5-d67e-4597-92aa-31bf56c6b16b}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{ba04e35f-5b85-46bf-84f6-f4b253125471}"/>
|
||||||
|
<edge from="{878d0098-c6f5-4a98-8e1e-d469396b6b4d}" id="{599287d2-a889-4443-a149-304f130c7e9e}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{fb5b878a-9ef0-4869-9dc9-4e8d6f623440}"/>
|
||||||
|
<edge from="{b71171d7-1d32-46f7-8fca-fcc3a7a5a46e}" id="{5b8dcc57-24a0-4e1d-92fb-630579900ff7}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{7dfc521a-3f80-4e32-93c9-85fe7b84dd93}"/>
|
||||||
|
<edge from="{71b98c98-8654-42d8-b58a-22688b722630}" id="{5bc071b7-b164-480a-82ca-729c0a445d3a}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{2b2d6ee4-f105-491c-b098-4de0613fd37c}"/>
|
||||||
|
<edge from="{70da7060-9223-4ac9-b6ca-ea16eeb20d45}" id="{5e30a9e5-db47-4b49-8c3f-601afaab621a}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{eb4fb92f-f8ea-49ef-b132-ae6b72fa6ea4}"/>
|
||||||
|
<edge from="{7c5da7e3-9eab-47f1-9736-c53bcf1e8efa}" id="{5faa9c7b-f509-4106-aeee-cbb81c2aa3a3}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{d866de28-dae4-40ce-b547-81e4cf5c1bfc}"/>
|
||||||
|
<edge from="{29686a15-7ddb-4717-a196-0412164025ef}" id="{60dcc41c-64d1-4c2b-ae3f-467026314d1e}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{567bcfd4-255f-478d-a9fe-362f2f832ff6}"/>
|
||||||
|
<edge from="{096379fc-4ca1-4c6d-b242-e353a20ffc88}" id="{61540c56-b89f-4001-b8a2-6dcc7315b687}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{84e6a0cf-c4e1-478c-8fed-a5cc25d9be5f}"/>
|
||||||
|
<edge from="{1ad678c9-b640-43d5-af1c-92ddfc540416}" id="{64323832-f151-4a98-9a2e-24041c1a43c3}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{78daab6a-4bd3-44b5-b9a8-785d8e08bb78}"/>
|
||||||
|
<edge from="{644464d2-775c-42ec-8544-206fe7d11fe7}" id="{69c93b35-b766-4ee8-a0ad-7eab683e6695}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{cede8a6a-4e51-4c07-8581-0999b4705616}"/>
|
||||||
|
<edge from="{308ce17b-2a9a-4e10-b3f6-aaed5190c957}" id="{6a9b4c34-ad0a-4deb-a02e-d72827a5da23}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{c78986e6-a263-42cf-b5f1-8b9fdc6f74a8}"/>
|
||||||
|
<edge from="{59fe931d-cbf2-47e6-b35e-0edcf8ad6830}" id="{6b38b65e-ab44-4303-a8c7-968005637564}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{516a356a-f5a0-4c65-9f17-8d186eeccaa2}"/>
|
||||||
|
<edge from="{a7137baa-7fe5-4d1c-b9f2-11b8bf6be38a}" id="{6b4abfec-cf01-42b3-8a19-f8761917760d}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{9db4d842-ce14-4854-a532-d10650139dfc}"/>
|
||||||
|
<edge from="{36e6565b-5c7c-4203-9757-b7afa6731c57}" id="{6da3668f-63de-4950-a7b4-5682d201c02f}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{096379fc-4ca1-4c6d-b242-e353a20ffc88}"/>
|
||||||
|
<edge from="{221a1797-ed67-4cfd-9cd8-34823e651ed3}" id="{6e701462-7cf7-4666-90e8-f4b2ed413d33}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" to="{172dd203-fbf9-4d7f-aafe-b751b7f943de}"/>
|
||||||
|
<edge from="{5df7e38f-b9da-4c41-800c-56b5d25952b6}" id="{70368d24-9515-4d8f-9bb6-b143f4d3d8c8}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{17722f68-bf1b-49d6-a22a-44a5fd7cd1f4}"/>
|
||||||
|
<edge from="{fb5b878a-9ef0-4869-9dc9-4e8d6f623440}" id="{70970648-a7b5-4260-9623-61db470328df}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{29686a15-7ddb-4717-a196-0412164025ef}"/>
|
||||||
|
<edge from="{d36ed08a-2202-41de-9601-76d275344502}" id="{724ad440-1f0d-404c-b441-558e58fd6c93}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{6e591cdf-09bd-478c-a604-ac7d19acf528}"/>
|
||||||
|
<edge from="{8626c044-fef3-47d2-a38f-944010bdef05}" id="{74862140-774e-4429-838c-223ccff72d7e}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{308ce17b-2a9a-4e10-b3f6-aaed5190c957}"/>
|
||||||
|
<edge from="{7e6244ae-8921-4012-9dfd-badac7408adb}" id="{74c25298-da73-43bc-a7fe-40c75eed6b34}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{a9746f2b-b2ba-40a7-a405-d34b982c683f}"/>
|
||||||
|
<edge from="{7e3c29a3-b4f3-466d-a888-a05b5e1704e6}" id="{777c6a01-f0be-4cb6-a74f-cb950c3e8b5f}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{a88191b2-a7cd-4b7a-be30-d5d97c3a0b48}"/>
|
||||||
|
<edge from="{593f1c87-b152-41e0-98b6-07acf061f646}" id="{7799b90a-9c5e-4b32-a610-ec181002a01f}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{85fceff6-5c5b-4882-9f92-e45d6c5613fe}"/>
|
||||||
|
<edge from="{02b8c92c-3aad-43b4-b2d6-eb0659a8a206}" id="{7c86ab40-166d-4f83-af3f-63d90d17e638}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{052c2ec6-ad61-40af-b659-14a23612734d}"/>
|
||||||
|
<edge from="{1957320f-7dec-4069-a2b2-502d9a18442e}" id="{7dbfa944-373a-4c17-8ea1-f548966712ee}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{3b94ce3c-27ef-41af-87d1-4227ca2045f1}"/>
|
||||||
|
<edge from="{f8e96450-96e9-4f56-b89c-3c74d76de271}" id="{7e253ecf-5b0a-45b2-892c-71af785070c8}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{a6209995-831e-4084-afeb-32704ca086bf}"/>
|
||||||
|
<edge from="{4d0f2620-8a2a-496f-ad0a-4d8002493035}" id="{81331cbb-946a-4bfc-b4b6-37a13584570c}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{8f367bd2-114c-4d04-96c5-bbb53a16d8ba}"/>
|
||||||
|
<edge from="{ebe51975-e81f-45a6-aa7d-ca216cc56c8b}" id="{81430c8e-0e44-4045-8f2d-67c76fc7b496}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{0434ac30-312c-4b70-984e-5a0971e9eb75}"/>
|
||||||
|
<edge from="{17408e0e-5237-45ce-8f5c-de1034fcf23c}" id="{84411218-19f4-449c-815c-48c6c9eac63f}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{a242b2bf-afe5-4672-aa61-e97e99e68a4c}"/>
|
||||||
|
<edge from="{e785bb5a-3352-4545-a008-17d16d82c906}" id="{84ecd97a-3e83-4722-bdcd-ed3777f960fc}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{71b98c98-8654-42d8-b58a-22688b722630}"/>
|
||||||
|
<edge from="{c62e9181-4388-4e00-a10a-8a61eb93c4ae}" id="{87e83f14-914d-47a6-848a-7faac287e6ec}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{878d0098-c6f5-4a98-8e1e-d469396b6b4d}"/>
|
||||||
|
<edge from="{a3e169ff-fc5f-4dcd-b7c5-0a14fa29b73e}" id="{87f83f97-ef97-4fad-a5ac-8dc0e87ec74a}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{6d108c14-4e3d-4273-8cee-084390309386}"/>
|
||||||
|
<edge from="{fcba37c4-7372-43df-9d2e-5404cc9a1b91}" id="{87fb7488-2d6c-44ab-ab6f-849defa74481}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{528a1707-5b77-4963-a34e-db9dba558205}"/>
|
||||||
|
<edge from="{0e5d29f3-fb8f-4d5c-b156-e4a3e028d97d}" id="{88268c31-32ea-4652-b405-6a18ed797fcc}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{ccd8ef94-281b-4dfb-ab29-b50dfe17a770}"/>
|
||||||
|
<edge from="{567a286a-bf1d-4291-b979-ba69733646f5}" id="{88ea2f4a-6869-4854-b25c-0b7e9068214e}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{bd244a0f-1d5e-4307-85b7-f764e6c1304b}"/>
|
||||||
|
<edge from="{a6209995-831e-4084-afeb-32704ca086bf}" id="{892c5570-841f-4c08-b2e2-dca141c94647}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{09f3f5fa-46f1-476c-aa35-3df95debd16f}"/>
|
||||||
|
<edge from="{0390d0a1-814a-4705-999e-5932354f0244}" id="{8b156381-67cb-4b5f-834b-cd3164b438c0}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{7153e3f6-ba74-4b9a-9a48-1f6b454b3678}"/>
|
||||||
|
<edge from="{06f82254-ab2d-44f4-bc96-3814316535a9}" id="{8f0ae77f-31d4-45aa-b9b2-67e4a2424a6c}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{6ef80ba2-4d3c-4a6e-a901-e5ddc913a272}"/>
|
||||||
|
<edge from="{ba05b4f6-6652-449b-ad37-d4b09bda988b}" id="{8facd603-513f-4464-baa8-9fbddf383931}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{b256069f-8463-4f7d-b6e0-30af0bbf2898}"/>
|
||||||
|
<edge from="{9bf0c1e8-8582-442c-90a4-5037d7219b21}" id="{8fd42582-c37b-4ad6-b305-c53c448357d8}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" to="{fd8dd98f-7c73-48e4-bdf0-904f2e2271e5}"/>
|
||||||
|
<edge from="{bbab93bd-50a6-47f4-b608-00091b262e97}" id="{92be512b-2aab-4800-909a-372e1ea994bf}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{e2f0521a-2b2d-4c9b-b806-d6f4c2d078f4}"/>
|
||||||
|
<edge from="{1d21ff2c-ba5f-4997-98db-a1ed63d01db3}" id="{94f01483-83a8-499a-9204-e6d996cb7920}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{199423e1-60c0-4b3c-b65a-3ab127cadf99}"/>
|
||||||
|
<edge from="{117ef567-17a0-425e-9fcb-ae1610e91539}" id="{94fcf07d-3754-4aff-b22f-ac4f25db5310}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{ce3ca970-0d64-4ee1-92ef-8720f608f05f}"/>
|
||||||
|
<edge from="{edb9977c-0dd1-4472-8534-dbeb127c9d16}" id="{951d69e2-6b90-4309-8ebb-625c64bf41ca}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{f8e96450-96e9-4f56-b89c-3c74d76de271}"/>
|
||||||
|
<edge from="{0582fcb5-78cf-4f27-bd85-0ccd279e8713}" id="{955971a0-2720-4c00-b3f7-f4a41ab9a1b7}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{2ebd2648-14b0-4a21-b97b-7b34f021991b}"/>
|
||||||
|
<edge from="{c1a57de4-5129-46f3-ace2-c662a6c079b8}" id="{95a75753-93fa-448d-b09e-aaaada89a7ab}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{bbdd82a9-286b-4c1c-b007-745c306e4f14}"/>
|
||||||
|
<edge from="{32cc74f0-3f2c-450d-845d-9baabb852655}" id="{987d4d6f-4043-47e3-a976-c629cc2062f1}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{73b1a616-30a5-44a9-a246-76ff142d228b}"/>
|
||||||
|
<edge from="{adbd9948-2566-46d3-8603-0d4ecf4c9fa4}" id="{9895d412-df9a-4104-8fce-f3d53239004b}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{796b1ebe-9414-4ec1-b58b-f3cdf6006d6e}"/>
|
||||||
|
<edge from="{44dfeb44-b697-4c87-b313-325d3826cc63}" id="{98d6c9f1-6c28-4435-a265-9a54df595469}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{979a9d6c-f734-4f25-a0fc-04310bd4646b}"/>
|
||||||
|
<edge from="{442d48bd-1797-45dc-8e4f-d121fb89237c}" id="{9989d0ed-422a-44f4-94f1-91f57780b3f8}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{3547bb94-25b4-4740-a5e9-15046267f0f9}"/>
|
||||||
|
<edge from="{0c3ed74f-ee80-41a9-8568-1487fe0cfd7c}" id="{9a9a11fe-79e1-4d05-9856-abb5b9d19da1}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{021bd224-eaac-49a1-a91f-0f2406f26f8a}"/>
|
||||||
|
<edge from="{58321009-70bf-48ba-bbe7-f5afcd9e56f3}" id="{9bdbe3b2-ed09-40a3-b026-2d073bdcadf0}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{516d36d9-b1db-4de8-8503-7ea829120487}"/>
|
||||||
|
<edge from="{0bd7865d-7f8d-46cb-a1ba-4ed601bf62fe}" id="{9c70d61b-38d4-482b-9f5f-5876a612c8b8}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{7c5da7e3-9eab-47f1-9736-c53bcf1e8efa}"/>
|
||||||
|
<edge from="{3b94ce3c-27ef-41af-87d1-4227ca2045f1}" id="{9cd7f215-eedb-4a42-a5b1-eb4322f39973}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{2acf141a-f327-4469-bde3-ea54de99f8d6}"/>
|
||||||
|
<edge from="{c5cfd17f-ec0b-433b-b36b-f126b540b6a6}" id="{9d29af4f-1e74-4358-a054-f9bc0c4ce8aa}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{dfd92d67-a666-4f9e-a606-217795b284cc}"/>
|
||||||
|
<edge from="{6dea3dfc-6305-4221-81f8-d59379db1f8c}" id="{9d54a330-6f53-4548-9363-090295d98651}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{6fd6b2c1-ab1f-4904-ac30-2f800bbfc95a}"/>
|
||||||
|
<edge from="{fd311c21-d781-4437-bfd3-414ae999f244}" id="{9e035778-7556-47f9-b600-198c358f2c7d}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{e2bae992-d1d2-4fdd-9a30-dba9c62f5322}"/>
|
||||||
|
<edge from="{f06b2588-283a-4bcc-a9e5-00f5cb6c9c57}" id="{9e64da63-f984-4c9b-a5f9-fbcf357c6b5c}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{0f798576-2812-4db6-b605-9ef70f713c8b}"/>
|
||||||
|
<edge from="{0f798576-2812-4db6-b605-9ef70f713c8b}" id="{9ffe0695-a3f4-4b6c-951f-7af1d703912e}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{35bf1780-fe7c-46dd-a93e-99896e097cf2}"/>
|
||||||
|
<edge from="{f1d52a81-d771-49f4-96f7-079e891415be}" id="{a0515545-e378-4413-b6b3-a69f27ff7964}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{e7bc4edf-781b-4916-8abe-a304cda6ae75}"/>
|
||||||
|
<edge from="{c42a3e99-b6aa-4c26-8579-44228dd34b4b}" id="{a1d5fbbf-f1f8-4d5a-be27-51a976c01f7b}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{f17183a2-5ecc-4b81-9399-5d3cfbb2eea2}"/>
|
||||||
|
<edge from="{2b2d6ee4-f105-491c-b098-4de0613fd37c}" id="{a3ff149d-7d58-4018-aaf5-7549d6268a01}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{427a3b1a-021e-4685-b78b-6080d8585450}"/>
|
||||||
|
<edge from="{e2bae992-d1d2-4fdd-9a30-dba9c62f5322}" id="{a413f056-94b7-452f-bfca-3efb1edfba32}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{105d5ada-f06b-474f-82a7-34fbfa628526}"/>
|
||||||
|
<edge from="{3424cf20-48a1-4e64-be63-5890321cdbcd}" id="{a511fc12-06db-4e7f-813b-27c18254de84}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{d5be35fe-16ec-40bd-b41b-d92171f18a01}"/>
|
||||||
|
<edge from="{dfd92d67-a666-4f9e-a606-217795b284cc}" id="{a720b5ce-2b71-4922-81eb-9a9048241fce}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{1d21ff2c-ba5f-4997-98db-a1ed63d01db3}"/>
|
||||||
|
<edge from="{0c131c2e-c763-4239-aae8-c71e219bb2ff}" id="{a99420af-71a5-47da-a1f1-280601594b96}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{32cc74f0-3f2c-450d-845d-9baabb852655}"/>
|
||||||
|
<edge from="{95ad6172-babb-45c4-a96d-4d734ba6a25e}" id="{aa45882b-7149-41e8-9c8c-b2064f9dc5bd}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{21a051be-53a6-442c-8c87-e5572e6ff05e}"/>
|
||||||
|
<edge from="{9362b987-f419-4f31-bfaf-9539700ad242}" id="{aeff3443-032d-491f-b102-d07fedf66cd8}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{a370ab3d-5136-42d7-9aa9-ac3bed89d137}"/>
|
||||||
|
<edge from="{40b1d9b4-f4ee-4c7d-8172-a9e0fc4d5654}" id="{afc12d1a-ee5b-4598-939b-7209da2b2ab4}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{44dfeb44-b697-4c87-b313-325d3826cc63}"/>
|
||||||
|
<edge from="{68be0242-2557-4881-b306-25936e0ac472}" id="{afc5f18e-ff1d-43db-9df1-70059bab38c5}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{c8d861a6-491b-42d4-8e07-73e5df7c019b}"/>
|
||||||
|
<edge from="{84db1f93-1858-4a96-be7f-7a383a1430df}" id="{b02e4534-0081-493e-824b-ad04492ce590}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{818b69e5-7a8b-41dd-970a-90348c5b766c}"/>
|
||||||
|
<edge from="{404cdbf7-ef7b-4529-b04b-d775162d0edb}" id="{b0716ba4-19bc-476c-813b-8f536601ceeb}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{5df7e38f-b9da-4c41-800c-56b5d25952b6}"/>
|
||||||
|
<edge from="{c9174f26-59b1-4382-8214-bc4a91f1759e}" id="{b160c3bc-fe1d-4040-a7c4-4a540ae64e82}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{6a16e994-9730-49a8-81f7-d9bcaf0d3614}"/>
|
||||||
|
<edge from="{e79795d5-e758-4acb-8559-7f1033c9b02f}" id="{b16bd2b9-e95e-4f0c-b35d-32cc673ce53e}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{cf75b27e-3656-4130-8543-d07cbc98b9c9}"/>
|
||||||
|
<edge from="{818b69e5-7a8b-41dd-970a-90348c5b766c}" id="{b188cd7d-7287-4846-8a1b-868f8594860c}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{55340a9c-d66d-4d5d-a189-6d658d599e53}"/>
|
||||||
|
<edge from="{2ebd2648-14b0-4a21-b97b-7b34f021991b}" id="{b19db57a-f8c1-4e2f-84da-1c1163ef3e66}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{7293a322-fbad-4c7b-a059-606020ff09bf}"/>
|
||||||
|
<edge from="{66c32673-0a5b-4c93-8dd8-26ea2e206aa9}" id="{b1b253d9-ff12-4246-ae53-2a3bbe6159f2}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{df693fdf-c112-4501-afcc-243afa0c4611}"/>
|
||||||
|
<edge from="{f419bd71-f788-4382-9479-6cc8b7e240c4}" id="{b29f1338-5b75-40a5-aa9d-e980e1a0d4be}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{2015db8c-2d22-40d9-8605-073117da143a}"/>
|
||||||
|
<edge from="{b4b3a668-fd69-4887-ba98-abe5dae57101}" id="{b60e7df4-9557-452f-a82b-0bf1b7e10b65}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{7351a5f6-983d-4fdf-83c9-be734363f2ca}"/>
|
||||||
|
<edge from="{d69b0b89-1efb-4918-baf5-d0cc0d5b972c}" id="{b7637511-7819-4817-a2aa-684d31751971}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{0e5d29f3-fb8f-4d5c-b156-e4a3e028d97d}"/>
|
||||||
|
<edge from="{6e591cdf-09bd-478c-a604-ac7d19acf528}" id="{b7b19a9f-5357-481b-8bde-6c132b0ef1ec}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{d7bf67d3-f4df-45b3-8a40-2dabc5e41d32}"/>
|
||||||
|
<edge from="{75d10124-3ee1-47f1-8e95-b397c0f35fe9}" id="{b7deba2c-d4f7-4ab7-a493-4167c2b47e82}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{e785bb5a-3352-4545-a008-17d16d82c906}"/>
|
||||||
|
<edge from="{86a40600-8eac-4094-81a0-a1d698c94d2d}" id="{b7e1cf5e-679a-4a57-b03b-f4cf89e385d6}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{353010d5-28a2-4ce3-a465-12289cbadb21}"/>
|
||||||
|
<edge from="{daa6e549-8d8c-4219-b312-84b523aa4f51}" id="{b8d4df7a-100d-46d5-a0b9-bdf28af8dee4}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{743d083e-3e96-4eb7-9c5f-0f0cee310915}"/>
|
||||||
|
<edge from="{d043181f-393b-4e20-8ad5-bc2c04e61bfd}" id="{b9358ec5-b955-46f8-9ebf-7eb1b6ec89e8}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{c319f392-3b4d-4f01-a0f8-50ef45168844}"/>
|
||||||
|
<edge from="{5eb9bd01-2f33-4a6d-bb01-4a8a6cc7469c}" id="{b9a9fa2a-52d2-42d8-8da8-0a2921ed6330}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{3932e31f-34f7-47da-8a0d-032bec47e53c}"/>
|
||||||
|
<edge from="{516a356a-f5a0-4c65-9f17-8d186eeccaa2}" id="{ba8cc3fe-9fc3-48f5-be71-01f99c6b5adb}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{173d8166-2d8d-4792-9187-d1f0dccb3713}"/>
|
||||||
|
<edge from="{f6050cf2-105d-43b6-ade2-625e690e55f8}" id="{bb2739cf-bc85-45d7-85b8-b3bb86816606}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{ebe51975-e81f-45a6-aa7d-ca216cc56c8b}"/>
|
||||||
|
<edge from="{881104c8-1859-4bd6-8bc1-fe2f5e807e98}" id="{bd3f7038-40f5-47e0-9d2c-fb8c5796fbe4}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{9c857bb2-10b3-45e0-8271-3272e88a8bd7}"/>
|
||||||
|
<edge from="{164fc21c-131b-42a2-a47b-3b2d930222c6}" id="{bec2f05e-13b4-4fb2-b32e-cccfb9df0da8}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{e94df7f8-d0ca-478e-aed1-25fa8d60b9fd}"/>
|
||||||
|
<edge from="{05c483ea-2649-48b1-80f9-f23a57335a5f}" id="{c0e943e1-7110-48a5-b6ea-58197091125f}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" to="{9bf0c1e8-8582-442c-90a4-5037d7219b21}"/>
|
||||||
|
<edge from="{33cae706-74fd-423d-a240-a32c23657dcf}" id="{c4e74e61-c23d-4c76-b405-8575a3416335}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{1f0d5b25-4f21-4fd6-9142-0d56a594dd2c}"/>
|
||||||
|
<edge from="{6b586d8c-e5a3-4405-b346-0d07c1fc587b}" id="{c4fa0184-c3c9-4636-9796-f867e7501b66}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{baa52d8a-ed0e-4138-bc8b-6a72054cfe95}"/>
|
||||||
|
<edge from="{f650f5b5-094c-41d1-b3b2-ece8be532cc1}" id="{c5351932-3680-4e36-aad4-77223c267265}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{e04cf7e6-1351-49fc-acd7-67ea3641d678}"/>
|
||||||
|
<edge from="{0f14d7ef-6d9e-42aa-afea-17e850abd25d}" id="{c536a2b7-d8b1-4f86-8502-d26360c07d9c}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{0b58ba98-f204-40ee-be03-f62292b2d250}"/>
|
||||||
|
<edge from="{9a7851b9-a7e8-4666-a13e-5cb7a8cc09c4}" id="{c591e524-3459-48ae-8f64-10a3813d8bd5}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{2501c90c-247d-42a1-b2fb-411d88b95e3a}"/>
|
||||||
|
<edge from="{2015db8c-2d22-40d9-8605-073117da143a}" id="{c7db3e9f-8600-4de1-a430-250d66b6ca60}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{f5692d54-1eb7-4c3c-8e99-5323bd0046d4}"/>
|
||||||
|
<edge from="{31a4515c-5fd8-4e34-923e-750b726395f2}" id="{c852e5dd-7db7-413e-bb86-4ccccda5a010}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{94362d37-639a-40ff-b191-5c0a6e19f664}"/>
|
||||||
|
<edge from="{c8d861a6-491b-42d4-8e07-73e5df7c019b}" id="{c95cad57-e7b1-46b6-9c21-c3e8371533ff}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{a3e0771b-c680-4c0c-8fcf-acd03fab6785}"/>
|
||||||
|
<edge from="{173d8166-2d8d-4792-9187-d1f0dccb3713}" id="{c97dcd04-4d73-4291-9367-d50068436ad4}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{511c7a39-b0e7-4502-8bd3-730ae05506f0}"/>
|
||||||
|
<edge from="{f7c408de-4dc2-4201-8ab9-f02c04a19893}" id="{ca44b0a4-bccb-4b2b-b820-83568713cf31}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{7285fcb8-4779-4e60-a474-4641c0943463}"/>
|
||||||
|
<edge from="{cea888e7-491c-40e5-be50-e60137d4c8a4}" id="{ca857902-cc9f-46f4-bcc1-25f734a05a30}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{80faa256-324d-4c76-b4e6-491956155230}"/>
|
||||||
|
<edge from="{5e465c5c-fdc5-4c81-95dc-4729f981df5c}" id="{cf988d83-2aa7-4557-836f-950120aefdf6}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{eddf44c5-0c61-446b-a724-4456c024978a}"/>
|
||||||
|
<edge from="{75239010-9a3d-434c-a036-a8a59a0fe3d6}" id="{d294ab9c-f03e-4418-9b63-b38667d1547c}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{f2778fa6-19d7-47dd-afc8-1e4f355c6475}"/>
|
||||||
|
<edge from="{fe831613-5b6a-43f2-a789-b7c0ce027d0a}" id="{d2ff2167-9388-48dd-acf6-9a39d5365b0e}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{14a0dfc1-38c0-4544-b5d4-65bdbe60b622}"/>
|
||||||
|
<edge from="{c7bd203d-7b04-47a9-a394-d7d1f18555c4}" id="{d3533c27-bbec-46ec-b1be-e6d2b3f99483}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{491add8b-4be8-4171-b647-24334b050892}"/>
|
||||||
|
<edge from="{27430d2c-0651-4361-a581-d304fcd67e22}" id="{d3bdcb26-c20f-41c2-8f83-e671878868d3}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{c1a57de4-5129-46f3-ace2-c662a6c079b8}"/>
|
||||||
|
<edge from="{6ef80ba2-4d3c-4a6e-a901-e5ddc913a272}" id="{d3dd8af5-0d64-4e0c-909f-1835e73869f2}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{5eb9bd01-2f33-4a6d-bb01-4a8a6cc7469c}"/>
|
||||||
|
<edge from="{9e8b06ca-12a6-4927-bd46-4d3f479230ae}" id="{d71f8ba8-215b-4db7-a072-0aa70a39e0c6}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{bbab93bd-50a6-47f4-b608-00091b262e97}"/>
|
||||||
|
<edge from="{d2de90d6-ac0c-4bdd-b5e3-573960fad70c}" id="{d77a63b7-3f8d-41dd-8c7a-7d3457c15ac0}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{f5c1ef85-7999-4224-845f-cfc4e07e2ef3}"/>
|
||||||
|
<edge from="{48417392-2b8f-49a5-a628-ab7fc4c944d4}" id="{d8424bca-429b-4191-af90-d70007c0a43f}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{0582fcb5-78cf-4f27-bd85-0ccd279e8713}"/>
|
||||||
|
<edge from="{f7984a7e-fd12-4428-8e71-9b9e913492fb}" id="{d889afdc-6b4e-4c4b-b6ac-948322eeee04}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{0f14d7ef-6d9e-42aa-afea-17e850abd25d}"/>
|
||||||
|
<edge from="{85cd375b-8df3-4653-855e-2a7bb3f623fe}" id="{d96f650c-54d9-4dbe-8480-9d6a2575136f}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{927f0b23-db5a-49e7-8d0f-bcc811f7752e}"/>
|
||||||
|
<edge from="{c1052900-009d-4ab3-9734-684f91bdab25}" id="{dae048e5-f932-41ab-96b4-f1076f841b11}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{6b2ab6a9-c11c-4c88-b4f9-b66df3f09e4f}"/>
|
||||||
|
<edge from="{eb4fb92f-f8ea-49ef-b132-ae6b72fa6ea4}" id="{dca95f1a-8dd4-4853-afd0-584b1dff30b7}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{651c39df-7b14-4fd3-beb3-592efcb25842}"/>
|
||||||
|
<edge from="{7e852b72-9d70-4dfd-9bfc-f857d3dbbb16}" id="{dde69321-743f-4891-be2f-ee41ff885d65}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{7b4bad9a-3192-479a-bc39-3d486444fe72}"/>
|
||||||
|
<edge from="{14a0dfc1-38c0-4544-b5d4-65bdbe60b622}" id="{de3ae066-8d73-4237-8160-0bc1467455dc}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{90999c8b-a2c9-459f-847e-0fde4493fbff}"/>
|
||||||
|
<edge from="{511c7a39-b0e7-4502-8bd3-730ae05506f0}" id="{de62fbdf-534e-47d8-aa7b-3bcf18bb5be5}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{f738f338-39e1-495e-a94e-5e914d4d5317}"/>
|
||||||
|
<edge from="{0434ac30-312c-4b70-984e-5a0971e9eb75}" id="{deec6450-02ce-4334-bcb4-85d645bf8123}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{10582ab2-cd50-47a0-bb86-9272f251af03}"/>
|
||||||
|
<edge from="{4029708e-b1f7-4f53-832e-d0983bfcd651}" id="{df189878-271e-4d33-b894-42a6030c9669}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{d36ed08a-2202-41de-9601-76d275344502}"/>
|
||||||
|
<edge from="{a88191b2-a7cd-4b7a-be30-d5d97c3a0b48}" id="{dfeddf9e-4dd6-4c5a-8532-d6853a397e34}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{74620eab-e43b-44e3-be3a-68f3838cda88}"/>
|
||||||
|
<edge from="{f2778fa6-19d7-47dd-afc8-1e4f355c6475}" id="{e04fbabf-c764-45e0-8cab-67773b7c486d}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{6cbb96e6-231d-4ac1-b9ec-75b258b16a1e}"/>
|
||||||
|
<edge from="{408119ac-6fc0-40f5-b60c-99b7cc9517ae}" id="{e0796b97-0c3a-4b61-95cf-16bb0d8a626c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{17408e0e-5237-45ce-8f5c-de1034fcf23c}"/>
|
||||||
|
<edge from="{528a1707-5b77-4963-a34e-db9dba558205}" id="{e0d729c0-947d-4023-b868-b867cc109a77}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{33cae706-74fd-423d-a240-a32c23657dcf}"/>
|
||||||
|
<edge from="{61ba80ab-f761-4889-a07e-7b2b7ff91e5c}" id="{e0dfaeef-2435-49e2-a668-778a65525748}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{9a7851b9-a7e8-4666-a13e-5cb7a8cc09c4}"/>
|
||||||
|
<edge from="{d2f4e68c-bc10-46d3-b82c-aadf00fa23e2}" id="{e17b8625-9949-45ed-a25b-6856ea9c2aa4}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{6b586d8c-e5a3-4405-b346-0d07c1fc587b}"/>
|
||||||
|
<edge from="{e5a7a6e8-c4de-4ea6-a175-93b87b709bee}" id="{e1eaa489-de41-4b48-86cc-2b8fd2c4b854}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{6c9d6544-ff34-4259-8d31-72393a4d7629}"/>
|
||||||
|
<edge from="{0b4f4946-8ff1-4efe-bdfe-0b611af6a655}" id="{e22500cd-ea80-475c-a2ca-f371cf78694c}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{8b37e76a-099c-4b5d-af5c-26c1fe4f55ab}"/>
|
||||||
|
<edge from="{8dc941af-cffe-4f7b-aa0a-b0db5a0e5e1d}" id="{e24483fd-0908-43e6-81ba-745940875182}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{e79795d5-e758-4acb-8559-7f1033c9b02f}"/>
|
||||||
|
<edge from="{a9746f2b-b2ba-40a7-a405-d34b982c683f}" id="{e2f7b457-07f5-4cd3-a337-2e0443ef289d}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{18a7f970-0d2e-4d47-a307-32c94a9105a3}"/>
|
||||||
|
<edge from="{7b04a282-03d9-4a06-bec2-b48417956ce9}" id="{e3b99e51-e9f3-4813-99a3-bce3b61180c2}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{881104c8-1859-4bd6-8bc1-fe2f5e807e98}"/>
|
||||||
|
<edge from="{021bd224-eaac-49a1-a91f-0f2406f26f8a}" id="{e4d0eaf5-34e2-40d1-80d1-45206f32af10}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{e5afd1fe-e4a7-4e2a-90cf-1cb2a55fe07e}"/>
|
||||||
|
<edge from="{09f3f5fa-46f1-476c-aa35-3df95debd16f}" id="{e6181a81-6104-43cc-8385-b5d071f5a8d0}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{1207414b-6386-42f4-b3b4-e774497e4fa9}"/>
|
||||||
|
<edge from="{1f0d5b25-4f21-4fd6-9142-0d56a594dd2c}" id="{e76b9c52-1b59-443d-9387-c4b288bcb5e3}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{ee43d10c-d4f1-4315-a3c2-618c2ce40d6a}"/>
|
||||||
|
<edge from="{76a160cd-60d5-4010-bd9a-6032c97f67b8}" id="{e8fc682c-43b3-48f3-bec6-36ea99b084ed}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{aefc096e-5901-425f-a831-6a0ddbd50399}"/>
|
||||||
|
<edge from="{7351a5f6-983d-4fdf-83c9-be734363f2ca}" id="{e93802a7-1cc5-4dcd-a866-8d4466c8bfe6}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{84db1f93-1858-4a96-be7f-7a383a1430df}"/>
|
||||||
|
<edge from="{ebe6c9ed-8cd5-4d44-acda-3846acf13ec1}" id="{ed7ce0f7-2dd3-454c-80a5-c363d70babd9}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{f6050cf2-105d-43b6-ade2-625e690e55f8}"/>
|
||||||
|
<edge from="{8e43cbd3-2aa9-4265-95b8-92056c4c4737}" id="{effc5af7-3b9e-422f-9fa3-d9036143dfb9}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{b1d0b918-225b-4399-a8d8-e90b84b5f5be}"/>
|
||||||
|
<edge from="{7057282d-6ae5-4d7e-b10e-85ae69c7f72a}" id="{f09ef052-777c-4e4d-9726-623e7b5630f8}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{f1d52a81-d771-49f4-96f7-079e891415be}"/>
|
||||||
|
<edge from="{dc0aaf45-eb00-49b6-8e81-fa979245ac09}" id="{f2843cac-a688-4cf4-a8bf-cac168d7f9f3}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{40b1d9b4-f4ee-4c7d-8172-a9e0fc4d5654}"/>
|
||||||
|
<edge from="{0711915a-a413-42b5-8022-35668c45d39b}" id="{f2c70830-462e-4577-87a0-53f44a9bec08}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{9d65e303-67cf-4bbb-ab6a-09120b410c7b}"/>
|
||||||
|
<edge from="{743d083e-3e96-4eb7-9c5f-0f0cee310915}" id="{f3678ad5-32fd-4ff2-a2cf-2d04e4633cca}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{73951d38-c2aa-4577-927b-7e9429d1f0db}"/>
|
||||||
|
<edge from="{5399b1af-6473-4df5-96cc-13e6e28784c1}" id="{f389bf5a-f49b-42a8-91c3-691ef9b55456}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{75239010-9a3d-434c-a036-a8a59a0fe3d6}"/>
|
||||||
|
<edge from="{baa52d8a-ed0e-4138-bc8b-6a72054cfe95}" id="{f3fefe97-5b55-4f5b-a3f8-8cc92361df88}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{a3e169ff-fc5f-4dcd-b7c5-0a14fa29b73e}"/>
|
||||||
|
<edge from="{fd8dd98f-7c73-48e4-bdf0-904f2e2271e5}" id="{f4ef9157-7082-46aa-816b-3ab6932c871b}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" to="{9530cb12-6d41-4bd3-8175-1ba24943e21b}"/>
|
||||||
|
<edge from="{90999c8b-a2c9-459f-847e-0fde4493fbff}" id="{f6b257cd-db2e-4bb4-8c4e-35d87ab7f8f6}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{39e3219e-a74d-4dd0-bedd-eb4fa010f34a}"/>
|
||||||
|
<edge from="{5064c6c5-783a-44e5-8e70-49c8c9cc2416}" id="{f7e36eab-500f-4a28-902b-5a245aef422b}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{593f1c87-b152-41e0-98b6-07acf061f646}"/>
|
||||||
|
<edge from="{35bf1780-fe7c-46dd-a93e-99896e097cf2}" id="{fa61de23-5291-4464-81cb-802682d6a1c5}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{24b1db2c-8e14-4670-a523-bd31ab7758aa}"/>
|
||||||
|
<edge from="{6394e5cc-a367-4664-a9af-753d41b82ba6}" id="{faf0fae4-1daa-49e5-985f-24940e3324e9}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{f7c9ef1b-11cc-4f1e-b217-322279b063b3}"/>
|
||||||
|
<edge from="{0a8e8fb2-9858-49d2-8686-6ed728dccbc2}" id="{fbb032f0-d170-42cb-a5fc-0a57fd06a90f}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{d2de90d6-ac0c-4bdd-b5e3-573960fad70c}"/>
|
||||||
|
<edge from="{6b2ab6a9-c11c-4c88-b4f9-b66df3f09e4f}" id="{fbd20729-2f29-49fa-beac-66b2a0f7a406}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{0bd7865d-7f8d-46cb-a1ba-4ed601bf62fe}"/>
|
||||||
|
<edge from="{a3e0771b-c680-4c0c-8fcf-acd03fab6785}" id="{fc556933-a669-4975-9b1f-ebebc0b4b3de}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{e3a311f1-ab14-4e80-80dc-9f882721d9a8}"/>
|
||||||
|
<edge from="{a370ab3d-5136-42d7-9aa9-ac3bed89d137}" id="{fe75bbf6-fe0e-455c-9af5-2af84da68e3b}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{ce8a93e4-e574-4e93-82b1-fbd2ca77ef0f}"/>
|
||||||
|
</edges>
|
||||||
|
<parts>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#939297" disabled="false" id="{092b0f10-67c1-4032-9c49-168067836057}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#939297" disabled="false" id="{13988a54-a274-49e0-aaf3-e5de769e18c1}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{36c17734-cbeb-4637-822c-71f680aa5a49}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{389a356e-22e6-4172-8c0d-1b835462d7b5}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{3c4883ad-20db-4f7c-a728-e11bc72de231}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{46304293-800c-4e01-8fc2-5135561ecc2d}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{499562a3-978a-46b8-82ac-ad5a45c3288b}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#939297" disabled="false" id="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{524194d6-bde6-4708-b189-16535335dc5a}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#939297" disabled="false" id="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{62493532-0802-4e69-af81-89a1e382185d}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#939297" disabled="false" id="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{700ce49d-5978-4ae1-847e-404fdc912625}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#939297" disabled="false" id="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{80845e66-2299-48ca-8cbf-77b55a536c0c}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{8f49f8aa-cb67-4955-9063-92e33042cb02}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{9279a14a-691a-436c-ae9e-efd74fa28300}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{9b4be491-12d5-4eea-8ee9-87dff887b292}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{acdc210c-e671-486e-9611-b9244c016807}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{b5812967-d429-4214-a11c-f04918089461}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#939297" disabled="false" id="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{d049e679-f4f6-412e-963c-1019667439e8}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" disabled="false" id="{da7592eb-3353-4084-bff2-f31d92be4236}" locked="false" rounded="false" subdived="false" target="CutFace" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{deb52d1d-f439-4144-9284-6b990b239ae5}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{e47c18bd-1154-48f4-96d5-954787c54562}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{f0f8818f-5795-4520-b544-ca04abca2521}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
|
||||||
|
</parts>
|
||||||
|
<components>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{501e951b-cea7-4dc1-9f7e-89c464c11bb3}" linkData="{da7592eb-3353-4084-bff2-f31d92be4236}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{c8ac259f-5de6-454e-90be-4bbd8269808c}" linkData="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{49e68887-892b-4525-8763-a574313a87f3}" linkData="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{46a52d46-1320-4d54-8716-656192fcce32}" linkData="{acdc210c-e671-486e-9611-b9244c016807}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{f3b5c2f0-7190-496e-a3b1-45221cd9cddd}" linkData="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{87e47914-242e-47e1-aa23-d8fc87401a1e}" linkData="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{44c5c761-8483-40cb-9b15-8d904e233115}" linkData="{deb52d1d-f439-4144-9284-6b990b239ae5}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{37232b01-fdc1-4f59-a1d9-4921f4dd82e7}" linkData="{8f49f8aa-cb67-4955-9063-92e33042cb02}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{3c2fcff5-1412-41d8-9615-f8bb0c97d5dd}" linkData="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{6de4b520-3bb4-4391-a997-0d9b9a6bc446}" linkData="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{ec80b776-20d0-4508-93d7-ba911d250fdf}" linkData="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{4d72e4e9-6432-4d1f-8b82-01a8949809e4}" linkData="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{3e67b71b-5e85-4401-8f46-c241c6381d8b}" linkData="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{51764c7c-7118-47ca-a70e-08607cd54765}" linkData="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{40708ab9-7391-4735-83af-dad392e26f04}" linkData="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{e2866f4f-a2c5-45a4-a8f7-8d5dbf575700}" linkData="{36c17734-cbeb-4637-822c-71f680aa5a49}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{8aff815a-3592-4ea1-bee5-79b110a00686}" linkData="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{ddb43b75-a690-475c-acf9-7c6d7794e3e7}" linkData="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{32815245-bcca-4d29-81b9-be222920f67b}" linkData="{499562a3-978a-46b8-82ac-ad5a45c3288b}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{ec533680-f287-4914-8b85-536312088cb8}" linkData="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{f043c3d8-4ede-4ecf-9a21-0afb9efcd520}" linkData="{3c4883ad-20db-4f7c-a728-e11bc72de231}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{658043b1-0b8f-4c9a-aca8-d1fd44997995}" linkData="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{bcccd4d5-ae07-4ea2-9f33-8b8e8d8fdfd3}" linkData="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{ad417335-eeb9-45e8-acf1-10c89da5e4a0}" linkData="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{a3376bed-fd56-4d11-b0e6-e280bda88094}" linkData="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{2e0fe333-6638-4e95-89d5-862055009502}" linkData="{d049e679-f4f6-412e-963c-1019667439e8}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{792df41a-a26a-4555-bebb-d8ff32d4804f}" linkData="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{c4b28529-4d95-44dc-be3b-0ec6a67dfe9a}" linkData="{092b0f10-67c1-4032-9c49-168067836057}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{792a323a-8a14-4ee8-80e7-171cb263a6dd}" linkData="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{506c7834-d834-4af2-84cc-3566d0131327}" linkData="{e47c18bd-1154-48f4-96d5-954787c54562}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{eb8defd0-5d93-4676-95ec-5cda66da741e}" linkData="{46304293-800c-4e01-8fc2-5135561ecc2d}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{e8bd263c-3272-4e1a-9bbf-799ba60d1d1c}" linkData="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{a853e0f4-c525-40e3-b336-86570ad6af6d}" linkData="{9279a14a-691a-436c-ae9e-efd74fa28300}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{04bc8afe-1bb7-431d-a1c6-a9c255b67ae8}" linkData="{9b4be491-12d5-4eea-8ee9-87dff887b292}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{58545e99-3d7f-443f-8e60-0e96a69f5586}" linkData="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{6801e8c9-4494-48da-91cc-cf33b81811e4}" linkData="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{d38da8c4-2f06-4c8c-8ec9-51aaa244697b}" linkData="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{ad223702-121e-4855-9dc8-614d879292a1}" linkData="{f0f8818f-5795-4520-b544-ca04abca2521}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{0cf27234-4529-49b8-8729-4a515c190534}" linkData="{700ce49d-5978-4ae1-847e-404fdc912625}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{fa27ae40-b168-4860-bd1e-1dc356fade5d}" linkData="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{63785235-da1a-4da7-a896-1a91359ae978}" linkData="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{5b2932ca-f7ef-430f-9731-ffc91c0f3b75}" linkData="{389a356e-22e6-4172-8c0d-1b835462d7b5}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{240f4df6-3b56-4867-bc12-178171b1990f}" linkData="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{1ab51bc8-5e0d-4f6c-b90e-1179f0dc8068}" linkData="{13988a54-a274-49e0-aaf3-e5de769e18c1}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{5c618c7f-32eb-4e6f-9dfb-59b9458597ca}" linkData="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{f9dbb17f-89e8-4fb4-bbe8-e336da9fd57d}" linkData="{524194d6-bde6-4708-b189-16535335dc5a}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{7f5cd199-2903-48c7-823c-8f5824fc6ead}" linkData="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{95f7cee9-c33c-48f1-9386-c16e6bcb78f9}" linkData="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{e52ce4f8-7c3f-4741-8310-a2e5b5afde0e}" linkData="{80845e66-2299-48ca-8cbf-77b55a536c0c}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{b4ba271a-3e7f-44fe-86d4-dcabf6bd95da}" linkData="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{279a974e-5bea-4bfe-a3a4-462aa30d9c65}" linkData="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{e7c16696-24ee-43bc-9258-88bada7af5d6}" linkData="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{79d7a2f5-bcb3-4fe2-86b0-c4145b0b40e9}" linkData="{62493532-0802-4e69-af81-89a1e382185d}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{40c08780-2e4b-4711-9912-7e2b88e3afd3}" linkData="{b5812967-d429-4214-a11c-f04918089461}" linkDataType="partId"/>
|
||||||
|
<component combineMode="Normal" expanded="false" id="{1c05b9c2-d958-42b1-ac29-a3c38de9e959}" linkData="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" linkDataType="partId"/>
|
||||||
|
</components>
|
||||||
|
<materials/>
|
||||||
|
<poses/>
|
||||||
|
<motions/>
|
||||||
|
</canvas>
|
||||||
|
var SUBDIVED = document.createCheckInput("Subdived", false);
|
||||||
|
var MAX_RADIUS_OFFSET = document.createFloatInput("Max Radius Offset", 0.10, -1.0, 1.0);
|
||||||
|
var MAX_ORIGIN_OFFSET = document.createFloatInput("Max Origin Offset", 0.47, -1.0, 1.0);
|
||||||
|
var TREE_HEIGHT = document.createFloatInput("Height", 0.85, 0.1, 1.0);
|
||||||
|
var TRUNK_RADIUS = document.createFloatInput("Trunk Radius", 0.02, 0.01, 0.2);
|
||||||
|
var TRUNK_SEGMENTS = document.createIntInput("Trunk Segments", 15, 2, 30);
|
||||||
|
var TRUNK_COLOR = document.createColorInput("Trunk Color", "#939297");
|
||||||
|
var BRANCH_MIN_ANGLE = document.createFloatInput("Branch Min Angle", 10.72, 8, 30);
|
||||||
|
var BRANCH_MAX_ANGLE = document.createFloatInput("Branch Max Angle", 58.81, 50, 75);
|
||||||
|
var MAX_BRANCHES_PER_GROWTH = document.createIntInput("Max Branches", 7, 1, 7);
|
||||||
|
var BRANCH_LENGTH_MIN_RATIO = document.createFloatInput("Branch Length Min Ratio", 0.24, 0.2, 0.9);
|
||||||
|
var BRANCH_LENGTH_MAX_RATIO = document.createFloatInput("Branch Length Max Ratio", 0.78, 0.2, 0.9);
|
||||||
|
var LEAF_MIN_LENGTH = document.createFloatInput("Leaf Min Length", 0.05, 0.005, 0.1);
|
||||||
|
var LEAF_MAX_LENGTH = document.createFloatInput("Leaf Max Length", 0.08, 0.005, 0.2);
|
||||||
|
var LEAF_SEGMENTS = document.createIntInput("Leaf Segments", 5, 3, 6);
|
||||||
|
var LEAF_COLOR = document.createColorInput("Leaf Color", "#58834b");
|
||||||
|
|
||||||
|
var X = new THREE.Vector3( 1, 0, 0 );
|
||||||
|
var Y = new THREE.Vector3( 0, 1, 0 );
|
||||||
|
|
||||||
|
function createNode(part, origin, radius)
|
||||||
|
{
|
||||||
|
var node = document.createNode(part);
|
||||||
|
document.setAttribute(node, "x", origin.getComponent(0));
|
||||||
|
document.setAttribute(node, "y", origin.getComponent(1));
|
||||||
|
document.setAttribute(node, "z", origin.getComponent(2));
|
||||||
|
document.setAttribute(node, "radius", radius);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
THREE.Vector3.prototype.random = function (maxOffset)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < 3; ++i)
|
||||||
|
this.setComponent(i, this.getComponent(i) + maxOffset * Math.random());
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
function randInRange(min, max)
|
||||||
|
{
|
||||||
|
if (min > max) {
|
||||||
|
var tmp = min;
|
||||||
|
min = max;
|
||||||
|
max = tmp;
|
||||||
|
}
|
||||||
|
return (min + (max - min) * Math.random());
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLeafCutFace()
|
||||||
|
{
|
||||||
|
var component = document.createComponent();
|
||||||
|
var part = document.createPart(component);
|
||||||
|
document.setAttribute(part, "target", "CutFace");
|
||||||
|
var predefinesCutFace = [
|
||||||
|
{radius:"0.005", x:"0.314637", y:"0.336525", z:"0.713406"},
|
||||||
|
{radius:"0.005", x:"0.343365", y:"0.340629", z:"0.713406"},
|
||||||
|
{radius:"0.005", x:"0.377565", y:"0.340629", z:"0.713406"},
|
||||||
|
{radius:"0.0159439", x:"0.402189", y:"0.341997", z:"0.713406"},
|
||||||
|
{radius:"0.005", x:"0.440492", y:"0.329685", z:"0.713406"},
|
||||||
|
{radius:"0.005", x:"0.473324", y:"0.317373", z:"0.713406"},
|
||||||
|
];
|
||||||
|
var previousNode = undefined;
|
||||||
|
for (var i = 0; i < predefinesCutFace.length; ++i) {
|
||||||
|
var node = createNode(part,
|
||||||
|
new THREE.Vector3(parseFloat(predefinesCutFace[i]["x"]),
|
||||||
|
parseFloat(predefinesCutFace[i]["y"]),
|
||||||
|
parseFloat(predefinesCutFace[i]["z"])),
|
||||||
|
parseFloat(predefinesCutFace[i]["radius"]));
|
||||||
|
if (undefined != previousNode)
|
||||||
|
document.connect(previousNode, node);
|
||||||
|
previousNode = node;
|
||||||
|
}
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandChildDirection(parentDirection)
|
||||||
|
{
|
||||||
|
var rotationAxis = parentDirection.clone().cross(X);
|
||||||
|
var degree = randInRange(BRANCH_MIN_ANGLE, BRANCH_MAX_ANGLE);
|
||||||
|
var branchRotateQuaternion = new THREE.Quaternion();
|
||||||
|
branchRotateQuaternion.setFromAxisAngle(rotationAxis, degree * (Math.PI / 180));
|
||||||
|
var rotatedDirection = parentDirection.clone().applyQuaternion(branchRotateQuaternion);
|
||||||
|
|
||||||
|
var distributeQuaternion = new THREE.Quaternion();
|
||||||
|
distributeQuaternion.setFromAxisAngle(Y, 360 * Math.random() * (Math.PI / 180));
|
||||||
|
rotatedDirection = rotatedDirection.applyQuaternion(distributeQuaternion);
|
||||||
|
|
||||||
|
return rotatedDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
var CUTFACE_PART_ID = document.attribute(createLeafCutFace(), "id");
|
||||||
|
|
||||||
|
function createLeaf(leafRootPosition, parentDirection)
|
||||||
|
{
|
||||||
|
var direction = getRandChildDirection(parentDirection);
|
||||||
|
var component = document.createComponent();
|
||||||
|
var part = document.createPart(component);
|
||||||
|
document.setAttribute(part, "color", LEAF_COLOR);
|
||||||
|
document.setAttribute(part, "cutFace", CUTFACE_PART_ID);
|
||||||
|
var length = randInRange(LEAF_MIN_LENGTH, LEAF_MAX_LENGTH);
|
||||||
|
var segments = LEAF_SEGMENTS;
|
||||||
|
var maxRadius = length / 3;
|
||||||
|
var toPosition = leafRootPosition.clone().add(direction.clone().multiplyScalar(length));
|
||||||
|
var previousNode = undefined;
|
||||||
|
for (var i = 0; i < segments; ++i) {
|
||||||
|
var alpha = (i + 0.0) / segments;
|
||||||
|
var origin = leafRootPosition.clone().lerp(toPosition, alpha);
|
||||||
|
var radiusFactor = 1.0 - 2 * Math.abs(alpha - 0.3);
|
||||||
|
var radius = maxRadius * radiusFactor;
|
||||||
|
var node = createNode(part, origin, radius);
|
||||||
|
if (undefined != previousNode)
|
||||||
|
document.connect(previousNode, node);
|
||||||
|
previousNode = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBranch(branchRootPosition, radius, length, segments, parentDirection, maxRadius)
|
||||||
|
{
|
||||||
|
var rotatedDirection = getRandChildDirection(parentDirection);
|
||||||
|
var branchEndPosition = branchRootPosition.clone().add(rotatedDirection.multiplyScalar(length));
|
||||||
|
createTrunk(branchRootPosition, radius, branchEndPosition, segments, maxRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldGrowBranch(alpha, alreadyGrowedNum)
|
||||||
|
{
|
||||||
|
var factor = alpha * Math.random();
|
||||||
|
if (factor > 0.5 && factor < 0.8) {
|
||||||
|
if (alreadyGrowedNum > 0)
|
||||||
|
return true;
|
||||||
|
if (Math.random() > 0.5)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldGrowLeaf(alreadyGrowedNum)
|
||||||
|
{
|
||||||
|
var factor = Math.random();
|
||||||
|
if (factor > 0.5) {
|
||||||
|
if (alreadyGrowedNum > 0)
|
||||||
|
return true;
|
||||||
|
if (Math.random() > 0.5)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTrunk(fromPosition, fromRadius, toPosition, segments, maxRadius)
|
||||||
|
{
|
||||||
|
var component = document.createComponent();
|
||||||
|
var part = document.createPart(component);
|
||||||
|
if (SUBDIVED)
|
||||||
|
document.setAttribute(part, "subdived", "true");
|
||||||
|
document.setAttribute(part, "color", TRUNK_COLOR);
|
||||||
|
var previousNode = undefined;
|
||||||
|
var toRadius = fromRadius * 0.2;
|
||||||
|
var direction = toPosition.clone().sub(fromPosition).normalize();
|
||||||
|
var length = fromPosition.distanceTo(toPosition);
|
||||||
|
for (var i = 0; i < segments; ++i) {
|
||||||
|
var alpha = (i + 0.0) / segments;
|
||||||
|
var origin = fromPosition.clone().lerp(toPosition, alpha);
|
||||||
|
var radius = fromRadius * (1.0 - alpha) + toRadius * alpha;
|
||||||
|
radius += radius * MAX_RADIUS_OFFSET * Math.random();
|
||||||
|
if (undefined != maxRadius && radius > maxRadius)
|
||||||
|
radius = maxRadius;
|
||||||
|
var oldY = origin.y;
|
||||||
|
origin.random(length * 0.1 * MAX_ORIGIN_OFFSET);
|
||||||
|
origin.setY(oldY + radius * 0.5 * Math.random());
|
||||||
|
if (undefined != maxRadius && i == 0)
|
||||||
|
origin = fromPosition;
|
||||||
|
var node = createNode(part, origin, radius);
|
||||||
|
if (undefined != previousNode)
|
||||||
|
document.connect(previousNode, node);
|
||||||
|
|
||||||
|
var maxBranches = MAX_BRANCHES_PER_GROWTH * Math.random();
|
||||||
|
var alreadyGrowedBranchNum = 0;
|
||||||
|
var alreadyGrowedLeafNum = 0;
|
||||||
|
for (var j = 0; j < maxBranches; ++j) {
|
||||||
|
if (shouldGrowBranch(alpha, alreadyGrowedBranchNum)) {
|
||||||
|
var branchLength = length * randInRange(BRANCH_LENGTH_MIN_RATIO, BRANCH_LENGTH_MAX_RATIO);
|
||||||
|
var branchRadius = radius * 0.5;
|
||||||
|
var branchSegments = segments * (branchLength / length);
|
||||||
|
if (branchSegments >= 3 && branchRadius > TRUNK_RADIUS / 20) {
|
||||||
|
createBranch(origin, branchRadius, branchLength, branchSegments, direction, radius);
|
||||||
|
++alreadyGrowedBranchNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (undefined != maxRadius && shouldGrowLeaf(alreadyGrowedLeafNum)) {
|
||||||
|
createLeaf(origin, direction);
|
||||||
|
++alreadyGrowedLeafNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previousNode = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var treeRootPosition = new THREE.Vector3(0.5, 1.0, 1.0);
|
||||||
|
var treeTopPosition = treeRootPosition.clone();
|
||||||
|
treeTopPosition.add((new THREE.Vector3(0, -1, 0)).multiplyScalar(TREE_HEIGHT));
|
||||||
|
|
||||||
|
document.setAttribute(document.canvas, "originX", 0.506767);
|
||||||
|
document.setAttribute(document.canvas, "originY", 0.615943);
|
||||||
|
document.setAttribute(document.canvas, "originZ", 1.08543);
|
||||||
|
|
||||||
|
createTrunk(treeRootPosition, TRUNK_RADIUS, treeTopPosition, TRUNK_SEGMENTS);
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<variables>
|
||||||
|
<variable name="Branch Length Max Ratio" defaultValue="0.78" input="Float" maxValue="0.9" minValue="0.2" value="0.78"/>
|
||||||
|
<variable name="Branch Length Min Ratio" defaultValue="0.24" input="Float" maxValue="0.9" minValue="0.2" value="0.24"/>
|
||||||
|
<variable name="Branch Max Angle" defaultValue="58.81" input="Float" maxValue="75" minValue="50" value="58.81"/>
|
||||||
|
<variable name="Branch Min Angle" defaultValue="10.72" input="Float" maxValue="30" minValue="8" value="10.72"/>
|
||||||
|
<variable name="Height" defaultValue="0.85" input="Float" maxValue="1" minValue="0.1" value="0.85"/>
|
||||||
|
<variable name="Leaf Color" defaultValue="#58834b" input="Color" value="#a4f98d"/>
|
||||||
|
<variable name="Leaf Max Length" defaultValue="0.08" input="Float" maxValue="0.2" minValue="0.005" value="0.08"/>
|
||||||
|
<variable name="Leaf Min Length" defaultValue="0.05" input="Float" maxValue="0.1" minValue="0.005" value="0.04"/>
|
||||||
|
<variable name="Leaf Segments" defaultValue="5" input="Int" maxValue="6" minValue="3" value="5"/>
|
||||||
|
<variable name="Max Branches" defaultValue="7" input="Int" maxValue="7" minValue="1" value="7"/>
|
||||||
|
<variable name="Max Origin Offset" defaultValue="0.47" input="Float" maxValue="1" minValue="-1" value="0.47"/>
|
||||||
|
<variable name="Max Radius Offset" defaultValue="0.1" input="Float" maxValue="1" minValue="-1" value="0.1"/>
|
||||||
|
<variable name="Subdived" defaultValue="false" input="Check" value="false"/>
|
||||||
|
<variable name="Trunk Color" defaultValue="#939297" input="Color" value="#939297"/>
|
||||||
|
<variable name="Trunk Radius" defaultValue="0.02" input="Float" maxValue="0.2" minValue="0.01" value="0.02"/>
|
||||||
|
<variable name="Trunk Segments" defaultValue="15" input="Int" maxValue="30" minValue="2" value="15"/>
|
||||||
|
</variables>
|
210
src/document.cpp
210
src/document.cpp
|
@ -16,6 +16,7 @@
|
||||||
#include "materialpreviewsgenerator.h"
|
#include "materialpreviewsgenerator.h"
|
||||||
#include "motionsgenerator.h"
|
#include "motionsgenerator.h"
|
||||||
#include "skeletonside.h"
|
#include "skeletonside.h"
|
||||||
|
#include "scriptrunner.h"
|
||||||
#include "mousepicker.h"
|
#include "mousepicker.h"
|
||||||
#include "imageforever.h"
|
#include "imageforever.h"
|
||||||
#include "contourtopartconverter.h"
|
#include "contourtopartconverter.h"
|
||||||
|
@ -69,6 +70,8 @@ Document::Document() :
|
||||||
m_motionsGenerator(nullptr),
|
m_motionsGenerator(nullptr),
|
||||||
m_meshGenerationId(0),
|
m_meshGenerationId(0),
|
||||||
m_nextMeshGenerationId(1),
|
m_nextMeshGenerationId(1),
|
||||||
|
m_scriptRunner(nullptr),
|
||||||
|
m_isScriptResultObsolete(false),
|
||||||
m_mousePicker(nullptr),
|
m_mousePicker(nullptr),
|
||||||
m_isMouseTargetResultObsolete(false),
|
m_isMouseTargetResultObsolete(false),
|
||||||
m_paintMode(PaintMode::None),
|
m_paintMode(PaintMode::None),
|
||||||
|
@ -1866,6 +1869,15 @@ void Document::silentReset()
|
||||||
removeRigResults();
|
removeRigResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::silentResetScript()
|
||||||
|
{
|
||||||
|
m_script.clear();
|
||||||
|
m_mergedVariables.clear();
|
||||||
|
m_cachedVariables.clear();
|
||||||
|
m_scriptError.clear();
|
||||||
|
m_scriptConsoleLog.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Document::reset()
|
void Document::reset()
|
||||||
{
|
{
|
||||||
silentReset();
|
silentReset();
|
||||||
|
@ -1873,6 +1885,16 @@ void Document::reset()
|
||||||
emit skeletonChanged();
|
emit skeletonChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::resetScript()
|
||||||
|
{
|
||||||
|
silentResetScript();
|
||||||
|
emit cleanupScript();
|
||||||
|
emit scriptChanged();
|
||||||
|
emit scriptErrorChanged();
|
||||||
|
emit scriptConsoleLogChanged();
|
||||||
|
emit mergedVaraiblesChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void Document::fromSnapshot(const Snapshot &snapshot)
|
void Document::fromSnapshot(const Snapshot &snapshot)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
@ -3857,6 +3879,194 @@ void Document::copyNodes(std::set<QUuid> nodeIdSet) const
|
||||||
clipboard->setText(snapshotXml);
|
clipboard->setText(snapshotXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::initScript(const QString &script)
|
||||||
|
{
|
||||||
|
m_script = script;
|
||||||
|
emit scriptModifiedFromExternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::updateScript(const QString &script)
|
||||||
|
{
|
||||||
|
if (m_script == script)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_script = script;
|
||||||
|
emit scriptChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::updateVariable(const QString &name, const std::map<QString, QString> &value)
|
||||||
|
{
|
||||||
|
bool needRunScript = false;
|
||||||
|
auto variable = m_cachedVariables.find(name);
|
||||||
|
if (variable == m_cachedVariables.end()) {
|
||||||
|
m_cachedVariables[name] = value;
|
||||||
|
needRunScript = true;
|
||||||
|
} else if (variable->second != value) {
|
||||||
|
variable->second = value;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_mergedVariables[name] = value;
|
||||||
|
emit mergedVaraiblesChanged();
|
||||||
|
if (needRunScript)
|
||||||
|
runScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::updateVariableValue(const QString &name, const QString &value)
|
||||||
|
{
|
||||||
|
auto variable = m_cachedVariables.find(name);
|
||||||
|
if (variable == m_cachedVariables.end()) {
|
||||||
|
qDebug() << "Update a nonexist variable:" << name << "value:" << value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto &variableValue = variable->second["value"];
|
||||||
|
if (variableValue == value)
|
||||||
|
return;
|
||||||
|
variableValue = value;
|
||||||
|
m_mergedVariables[name] = variable->second;
|
||||||
|
runScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Document::updateDefaultVariables(const std::map<QString, std::map<QString, QString>> &defaultVariables)
|
||||||
|
{
|
||||||
|
bool updated = false;
|
||||||
|
for (const auto &it: defaultVariables) {
|
||||||
|
auto findMergedVariable = m_mergedVariables.find(it.first);
|
||||||
|
if (findMergedVariable != m_mergedVariables.end()) {
|
||||||
|
bool hasChangedAttribute = false;
|
||||||
|
for (const auto &attribute: it.second) {
|
||||||
|
if (attribute.first == "value")
|
||||||
|
continue;
|
||||||
|
const auto &findMatch = findMergedVariable->second.find(attribute.first);
|
||||||
|
if (findMatch != findMergedVariable->second.end()) {
|
||||||
|
if (findMatch->second == attribute.second)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hasChangedAttribute = true;
|
||||||
|
}
|
||||||
|
if (!hasChangedAttribute)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
updated = true;
|
||||||
|
auto findCached = m_cachedVariables.find(it.first);
|
||||||
|
if (findCached != m_cachedVariables.end()) {
|
||||||
|
m_mergedVariables[it.first] = it.second;
|
||||||
|
m_mergedVariables[it.first]["value"] = valueOfKeyInMapOrEmpty(findCached->second, "value");
|
||||||
|
} else {
|
||||||
|
m_mergedVariables[it.first] = it.second;
|
||||||
|
m_cachedVariables[it.first] = it.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<QString> eraseList;
|
||||||
|
for (const auto &it: m_mergedVariables) {
|
||||||
|
if (defaultVariables.end() == defaultVariables.find(it.first)) {
|
||||||
|
eraseList.push_back(it.first);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &it: eraseList) {
|
||||||
|
m_mergedVariables.erase(it);
|
||||||
|
}
|
||||||
|
if (updated) {
|
||||||
|
emit mergedVaraiblesChanged();
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::runScript()
|
||||||
|
{
|
||||||
|
if (nullptr != m_scriptRunner) {
|
||||||
|
m_isScriptResultObsolete = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_isScriptResultObsolete = false;
|
||||||
|
|
||||||
|
qDebug() << "Script running..";
|
||||||
|
|
||||||
|
QThread *thread = new QThread;
|
||||||
|
|
||||||
|
m_scriptRunner = new ScriptRunner();
|
||||||
|
m_scriptRunner->moveToThread(thread);
|
||||||
|
m_scriptRunner->setScript(new QString(m_script));
|
||||||
|
m_scriptRunner->setVariables(new std::map<QString, std::map<QString, QString>>(
|
||||||
|
m_mergedVariables.empty() ? m_cachedVariables : m_mergedVariables
|
||||||
|
));
|
||||||
|
connect(thread, &QThread::started, m_scriptRunner, &ScriptRunner::process);
|
||||||
|
connect(m_scriptRunner, &ScriptRunner::finished, this, &Document::scriptResultReady);
|
||||||
|
connect(m_scriptRunner, &ScriptRunner::finished, thread, &QThread::quit);
|
||||||
|
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
|
emit scriptRunning();
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::scriptResultReady()
|
||||||
|
{
|
||||||
|
Snapshot *snapshot = m_scriptRunner->takeResultSnapshot();
|
||||||
|
std::map<QString, std::map<QString, QString>> *defaultVariables = m_scriptRunner->takeDefaultVariables();
|
||||||
|
bool errorChanged = false;
|
||||||
|
bool consoleLogChanged = false;
|
||||||
|
bool mergedVariablesChanged = false;
|
||||||
|
|
||||||
|
const QString &scriptError = m_scriptRunner->scriptError();
|
||||||
|
if (m_scriptError != scriptError) {
|
||||||
|
m_scriptError = scriptError;
|
||||||
|
errorChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &consoleLog = m_scriptRunner->consoleLog();
|
||||||
|
if (m_scriptConsoleLog != consoleLog) {
|
||||||
|
m_scriptConsoleLog = consoleLog;
|
||||||
|
consoleLogChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != snapshot) {
|
||||||
|
fromSnapshot(*snapshot);
|
||||||
|
delete snapshot;
|
||||||
|
saveSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != defaultVariables) {
|
||||||
|
mergedVariablesChanged = updateDefaultVariables(*defaultVariables);
|
||||||
|
delete defaultVariables;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete m_scriptRunner;
|
||||||
|
m_scriptRunner = nullptr;
|
||||||
|
|
||||||
|
if (errorChanged)
|
||||||
|
emit scriptErrorChanged();
|
||||||
|
|
||||||
|
if (consoleLogChanged)
|
||||||
|
emit scriptConsoleLogChanged();
|
||||||
|
|
||||||
|
qDebug() << "Script run done";
|
||||||
|
|
||||||
|
if (m_isScriptResultObsolete || mergedVariablesChanged) {
|
||||||
|
runScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &Document::script() const
|
||||||
|
{
|
||||||
|
return m_script;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::map<QString, std::map<QString, QString>> &Document::variables() const
|
||||||
|
{
|
||||||
|
return m_mergedVariables;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &Document::scriptError() const
|
||||||
|
{
|
||||||
|
return m_scriptError;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &Document::scriptConsoleLog() const
|
||||||
|
{
|
||||||
|
return m_scriptConsoleLog;
|
||||||
|
}
|
||||||
|
|
||||||
void Document::startPaint(void)
|
void Document::startPaint(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
class MaterialPreviewsGenerator;
|
class MaterialPreviewsGenerator;
|
||||||
class MotionsGenerator;
|
class MotionsGenerator;
|
||||||
|
class ScriptRunner;
|
||||||
class MousePicker;
|
class MousePicker;
|
||||||
|
|
||||||
class HistoryItem
|
class HistoryItem
|
||||||
|
@ -464,6 +465,7 @@ signals:
|
||||||
void partGridStateChanged(QUuid partId);
|
void partGridStateChanged(QUuid partId);
|
||||||
void componentCombineModeChanged(QUuid componentId);
|
void componentCombineModeChanged(QUuid componentId);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
void cleanupScript();
|
||||||
void originChanged();
|
void originChanged();
|
||||||
void xlockStateChanged();
|
void xlockStateChanged();
|
||||||
void ylockStateChanged();
|
void ylockStateChanged();
|
||||||
|
@ -507,6 +509,12 @@ signals:
|
||||||
void postProcessing();
|
void postProcessing();
|
||||||
void textureGenerating();
|
void textureGenerating();
|
||||||
void textureChanged();
|
void textureChanged();
|
||||||
|
void scriptChanged();
|
||||||
|
void scriptModifiedFromExternal();
|
||||||
|
void mergedVaraiblesChanged();
|
||||||
|
void scriptRunning();
|
||||||
|
void scriptErrorChanged();
|
||||||
|
void scriptConsoleLogChanged();
|
||||||
void mouseTargetChanged();
|
void mouseTargetChanged();
|
||||||
void mousePickRadiusChanged();
|
void mousePickRadiusChanged();
|
||||||
public: // need initialize
|
public: // need initialize
|
||||||
|
@ -576,6 +584,10 @@ public:
|
||||||
bool isMeshGenerating() const;
|
bool isMeshGenerating() const;
|
||||||
bool isPostProcessing() const;
|
bool isPostProcessing() const;
|
||||||
bool isTextureGenerating() const;
|
bool isTextureGenerating() const;
|
||||||
|
const QString &script() const;
|
||||||
|
const std::map<QString, std::map<QString, QString>> &variables() const;
|
||||||
|
const QString &scriptError() const;
|
||||||
|
const QString &scriptConsoleLog() const;
|
||||||
const QVector3D &mouseTargetPosition() const;
|
const QVector3D &mouseTargetPosition() const;
|
||||||
float mousePickRadius() const;
|
float mousePickRadius() const;
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -686,8 +698,10 @@ public slots:
|
||||||
void batchChangeBegin();
|
void batchChangeBegin();
|
||||||
void batchChangeEnd();
|
void batchChangeEnd();
|
||||||
void reset();
|
void reset();
|
||||||
|
void resetScript();
|
||||||
void clearHistories();
|
void clearHistories();
|
||||||
void silentReset();
|
void silentReset();
|
||||||
|
void silentResetScript();
|
||||||
void breakEdge(QUuid edgeId);
|
void breakEdge(QUuid edgeId);
|
||||||
void setXlockState(bool locked);
|
void setXlockState(bool locked);
|
||||||
void setYlockState(bool locked);
|
void setYlockState(bool locked);
|
||||||
|
@ -716,6 +730,12 @@ public slots:
|
||||||
void renameMaterial(QUuid materialId, QString name);
|
void renameMaterial(QUuid materialId, QString name);
|
||||||
void applyPreferencePartColorChange();
|
void applyPreferencePartColorChange();
|
||||||
void applyPreferenceFlatShadingChange();
|
void applyPreferenceFlatShadingChange();
|
||||||
|
void initScript(const QString &script);
|
||||||
|
void updateScript(const QString &script);
|
||||||
|
void runScript();
|
||||||
|
void scriptResultReady();
|
||||||
|
void updateVariable(const QString &name, const std::map<QString, QString> &value);
|
||||||
|
void updateVariableValue(const QString &name, const QString &value);
|
||||||
void startPaint(void);
|
void startPaint(void);
|
||||||
void stopPaint(void);
|
void stopPaint(void);
|
||||||
void setMousePickMaskNodeIds(const std::set<QUuid> &nodeIds);
|
void setMousePickMaskNodeIds(const std::set<QUuid> &nodeIds);
|
||||||
|
@ -772,6 +792,8 @@ private: // need initialize
|
||||||
quint64 m_nextMeshGenerationId;
|
quint64 m_nextMeshGenerationId;
|
||||||
std::map<QString, std::map<QString, QString>> m_cachedVariables;
|
std::map<QString, std::map<QString, QString>> m_cachedVariables;
|
||||||
std::map<QString, std::map<QString, QString>> m_mergedVariables;
|
std::map<QString, std::map<QString, QString>> m_mergedVariables;
|
||||||
|
ScriptRunner *m_scriptRunner;
|
||||||
|
bool m_isScriptResultObsolete;
|
||||||
MousePicker *m_mousePicker;
|
MousePicker *m_mousePicker;
|
||||||
bool m_isMouseTargetResultObsolete;
|
bool m_isMouseTargetResultObsolete;
|
||||||
PaintMode m_paintMode;
|
PaintMode m_paintMode;
|
||||||
|
@ -786,6 +808,9 @@ private:
|
||||||
QVector3D m_mouseRayNear;
|
QVector3D m_mouseRayNear;
|
||||||
QVector3D m_mouseRayFar;
|
QVector3D m_mouseRayFar;
|
||||||
QVector3D m_mouseTargetPosition;
|
QVector3D m_mouseTargetPosition;
|
||||||
|
QString m_scriptError;
|
||||||
|
QString m_scriptConsoleLog;
|
||||||
|
QString m_script;
|
||||||
std::set<QUuid> m_mousePickMaskNodeIds;
|
std::set<QUuid> m_mousePickMaskNodeIds;
|
||||||
std::set<QUuid> m_intermediatePaintImageIds;
|
std::set<QUuid> m_intermediatePaintImageIds;
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#include "shortcuts.h"
|
#include "shortcuts.h"
|
||||||
#include "floatnumberwidget.h"
|
#include "floatnumberwidget.h"
|
||||||
#include "cutfacelistwidget.h"
|
#include "cutfacelistwidget.h"
|
||||||
|
#include "scriptwidget.h"
|
||||||
|
#include "variablesxml.h"
|
||||||
#include "updatescheckwidget.h"
|
#include "updatescheckwidget.h"
|
||||||
|
|
||||||
int DocumentWindow::m_modelRenderWidgetInitialX = 16;
|
int DocumentWindow::m_modelRenderWidgetInitialX = 16;
|
||||||
|
@ -400,10 +402,17 @@ DocumentWindow::DocumentWindow() :
|
||||||
connect(motionManageWidget, &MotionManageWidget::unregisterDialog, this, &DocumentWindow::unregisterDialog);
|
connect(motionManageWidget, &MotionManageWidget::unregisterDialog, this, &DocumentWindow::unregisterDialog);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, motionDocker);
|
addDockWidget(Qt::RightDockWidgetArea, motionDocker);
|
||||||
|
|
||||||
|
QDockWidget *scriptDocker = new QDockWidget(tr("Script"), this);
|
||||||
|
scriptDocker->setAllowedAreas(Qt::RightDockWidgetArea);
|
||||||
|
ScriptWidget *scriptWidget = new ScriptWidget(m_document, scriptDocker);
|
||||||
|
scriptDocker->setWidget(scriptWidget);
|
||||||
|
addDockWidget(Qt::RightDockWidgetArea, scriptDocker);
|
||||||
|
|
||||||
tabifyDockWidget(partTreeDocker, materialDocker);
|
tabifyDockWidget(partTreeDocker, materialDocker);
|
||||||
tabifyDockWidget(materialDocker, rigDocker);
|
tabifyDockWidget(materialDocker, rigDocker);
|
||||||
tabifyDockWidget(rigDocker, poseDocker);
|
tabifyDockWidget(rigDocker, poseDocker);
|
||||||
tabifyDockWidget(poseDocker, motionDocker);
|
tabifyDockWidget(poseDocker, motionDocker);
|
||||||
|
tabifyDockWidget(motionDocker, scriptDocker);
|
||||||
|
|
||||||
partTreeDocker->raise();
|
partTreeDocker->raise();
|
||||||
|
|
||||||
|
@ -442,7 +451,8 @@ DocumentWindow::DocumentWindow() :
|
||||||
"Giraffe",
|
"Giraffe",
|
||||||
"Meerkat",
|
"Meerkat",
|
||||||
"Mosquito",
|
"Mosquito",
|
||||||
"Seagull"
|
"Seagull",
|
||||||
|
"Procedural Tree"
|
||||||
};
|
};
|
||||||
for (const auto &model: exampleModels) {
|
for (const auto &model: exampleModels) {
|
||||||
QAction *openModelAction = new QAction(model, this);
|
QAction *openModelAction = new QAction(model, this);
|
||||||
|
@ -794,6 +804,13 @@ DocumentWindow::DocumentWindow() :
|
||||||
});
|
});
|
||||||
m_windowMenu->addAction(m_showMotionsAction);
|
m_windowMenu->addAction(m_showMotionsAction);
|
||||||
|
|
||||||
|
m_showScriptAction = new QAction(tr("Script"), this);
|
||||||
|
connect(m_showScriptAction, &QAction::triggered, [=]() {
|
||||||
|
scriptDocker->show();
|
||||||
|
scriptDocker->raise();
|
||||||
|
});
|
||||||
|
m_windowMenu->addAction(m_showScriptAction);
|
||||||
|
|
||||||
QMenu *dialogsMenu = m_windowMenu->addMenu(tr("Dialogs"));
|
QMenu *dialogsMenu = m_windowMenu->addMenu(tr("Dialogs"));
|
||||||
connect(dialogsMenu, &QMenu::aboutToShow, [=]() {
|
connect(dialogsMenu, &QMenu::aboutToShow, [=]() {
|
||||||
dialogsMenu->clear();
|
dialogsMenu->clear();
|
||||||
|
@ -1125,6 +1142,7 @@ DocumentWindow::DocumentWindow() :
|
||||||
connect(m_document, &Document::turnaroundChanged, this, &DocumentWindow::documentChanged);
|
connect(m_document, &Document::turnaroundChanged, this, &DocumentWindow::documentChanged);
|
||||||
connect(m_document, &Document::optionsChanged, this, &DocumentWindow::documentChanged);
|
connect(m_document, &Document::optionsChanged, this, &DocumentWindow::documentChanged);
|
||||||
connect(m_document, &Document::rigChanged, this, &DocumentWindow::documentChanged);
|
connect(m_document, &Document::rigChanged, this, &DocumentWindow::documentChanged);
|
||||||
|
connect(m_document, &Document::scriptChanged, this, &DocumentWindow::documentChanged);
|
||||||
|
|
||||||
connect(m_modelRenderWidget, &ModelWidget::customContextMenuRequested, [=](const QPoint &pos) {
|
connect(m_modelRenderWidget, &ModelWidget::customContextMenuRequested, [=](const QPoint &pos) {
|
||||||
graphicsWidget->showContextMenu(graphicsWidget->mapFromGlobal(m_modelRenderWidget->mapToGlobal(pos)));
|
graphicsWidget->showContextMenu(graphicsWidget->mapFromGlobal(m_modelRenderWidget->mapToGlobal(pos)));
|
||||||
|
@ -1164,6 +1182,9 @@ DocumentWindow::DocumentWindow() :
|
||||||
m_document->generateMaterialPreviews();
|
m_document->generateMaterialPreviews();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(m_document, &Document::scriptChanged, m_document, &Document::runScript);
|
||||||
|
connect(m_document, &Document::scriptModifiedFromExternal, m_document, &Document::runScript);
|
||||||
|
|
||||||
initShortCuts(this, m_graphicsWidget);
|
initShortCuts(this, m_graphicsWidget);
|
||||||
|
|
||||||
connect(this, &DocumentWindow::initialized, m_document, &Document::uiReady);
|
connect(this, &DocumentWindow::initialized, m_document, &Document::uiReady);
|
||||||
|
@ -1264,6 +1285,7 @@ void DocumentWindow::newDocument()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_document->clearHistories();
|
m_document->clearHistories();
|
||||||
|
m_document->resetScript();
|
||||||
m_document->reset();
|
m_document->reset();
|
||||||
m_document->saveSnapshot();
|
m_document->saveSnapshot();
|
||||||
}
|
}
|
||||||
|
@ -1410,6 +1432,20 @@ void DocumentWindow::saveTo(const QString &saveAsFilename)
|
||||||
ds3Writer.add("canvas.png", "asset", &m_document->turnaroundPngByteArray);
|
ds3Writer.add("canvas.png", "asset", &m_document->turnaroundPngByteArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_document->script().isEmpty()) {
|
||||||
|
auto script = m_document->script().toUtf8();
|
||||||
|
ds3Writer.add("model.js", "script", &script);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &variables = m_document->variables();
|
||||||
|
if (!variables.empty()) {
|
||||||
|
QByteArray variablesXml;
|
||||||
|
QXmlStreamWriter variablesXmlStream(&variablesXml);
|
||||||
|
saveVariablesToXmlStream(variables, &variablesXmlStream);
|
||||||
|
if (variablesXml.size() > 0)
|
||||||
|
ds3Writer.add("variables.xml", "variable", &variablesXml);
|
||||||
|
}
|
||||||
|
|
||||||
std::set<QUuid> imageIds;
|
std::set<QUuid> imageIds;
|
||||||
|
|
||||||
for (const auto &material: snapshot.materials) {
|
for (const auto &material: snapshot.materials) {
|
||||||
|
@ -1460,6 +1496,7 @@ void DocumentWindow::openPathAs(const QString &path, const QString &asName)
|
||||||
Ds3FileReader ds3Reader(path);
|
Ds3FileReader ds3Reader(path);
|
||||||
|
|
||||||
m_document->clearHistories();
|
m_document->clearHistories();
|
||||||
|
m_document->resetScript();
|
||||||
m_document->reset();
|
m_document->reset();
|
||||||
m_document->saveSnapshot();
|
m_document->saveSnapshot();
|
||||||
|
|
||||||
|
@ -1497,6 +1534,22 @@ void DocumentWindow::openPathAs(const QString &path, const QString &asName)
|
||||||
QImage image = QImage::fromData(data, "PNG");
|
QImage image = QImage::fromData(data, "PNG");
|
||||||
m_document->updateTurnaround(image);
|
m_document->updateTurnaround(image);
|
||||||
}
|
}
|
||||||
|
} else if (item.type == "script") {
|
||||||
|
if (item.name == "model.js") {
|
||||||
|
QByteArray script;
|
||||||
|
ds3Reader.loadItem(item.name, &script);
|
||||||
|
m_document->initScript(QString::fromUtf8(script.constData()));
|
||||||
|
}
|
||||||
|
} else if (item.type == "variable") {
|
||||||
|
if (item.name == "variables.xml") {
|
||||||
|
QByteArray data;
|
||||||
|
ds3Reader.loadItem(item.name, &data);
|
||||||
|
QXmlStreamReader stream(data);
|
||||||
|
std::map<QString, std::map<QString, QString>> variables;
|
||||||
|
loadVariablesFromXmlStream(&variables, stream);
|
||||||
|
for (const auto &it: variables)
|
||||||
|
m_document->updateVariable(it.first, it.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QApplication::restoreOverrideCursor();
|
QApplication::restoreOverrideCursor();
|
||||||
|
|
|
@ -179,6 +179,7 @@ private:
|
||||||
QAction *m_showRigAction;
|
QAction *m_showRigAction;
|
||||||
QAction *m_showPosesAction;
|
QAction *m_showPosesAction;
|
||||||
QAction *m_showMotionsAction;
|
QAction *m_showMotionsAction;
|
||||||
|
QAction *m_showScriptAction;
|
||||||
|
|
||||||
QMenu *m_helpMenu;
|
QMenu *m_helpMenu;
|
||||||
QAction *m_gotoHomepageAction;
|
QAction *m_gotoHomepageAction;
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||||
|
** contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <QtWidgets>
|
||||||
|
#include "theme.h"
|
||||||
|
#include "scripteditwidget.h"
|
||||||
|
|
||||||
|
|
||||||
|
ScriptEditWidget::ScriptEditWidget(QWidget *parent) : QPlainTextEdit(parent)
|
||||||
|
{
|
||||||
|
connect(this, &QPlainTextEdit::textChanged, this, [&]() {
|
||||||
|
emit scriptChanged(toPlainText());
|
||||||
|
});
|
||||||
|
|
||||||
|
m_lineNumberArea = new LineNumberArea(this);
|
||||||
|
|
||||||
|
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
||||||
|
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
|
||||||
|
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
|
||||||
|
|
||||||
|
updateLineNumberAreaWidth(0);
|
||||||
|
highlightCurrentLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int ScriptEditWidget::lineNumberAreaWidth()
|
||||||
|
{
|
||||||
|
int digits = 1;
|
||||||
|
int max = qMax(1, blockCount());
|
||||||
|
while (max >= 10) {
|
||||||
|
max /= 10;
|
||||||
|
++digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
|
||||||
|
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ScriptEditWidget::updateLineNumberAreaWidth(int /* newBlockCount */)
|
||||||
|
{
|
||||||
|
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ScriptEditWidget::updateLineNumberArea(const QRect &rect, int dy)
|
||||||
|
{
|
||||||
|
if (dy)
|
||||||
|
m_lineNumberArea->scroll(0, dy);
|
||||||
|
else
|
||||||
|
m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height());
|
||||||
|
|
||||||
|
if (rect.contains(viewport()->rect()))
|
||||||
|
updateLineNumberAreaWidth(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ScriptEditWidget::resizeEvent(QResizeEvent *e)
|
||||||
|
{
|
||||||
|
QPlainTextEdit::resizeEvent(e);
|
||||||
|
|
||||||
|
QRect cr = contentsRect();
|
||||||
|
m_lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ScriptEditWidget::highlightCurrentLine()
|
||||||
|
{
|
||||||
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
||||||
|
|
||||||
|
if (!isReadOnly()) {
|
||||||
|
QTextEdit::ExtraSelection selection;
|
||||||
|
|
||||||
|
QColor lineColor = QColor(0x24, 0x24, 0x24).lighter(160);
|
||||||
|
|
||||||
|
selection.format.setBackground(lineColor);
|
||||||
|
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||||
|
selection.cursor = textCursor();
|
||||||
|
selection.cursor.clearSelection();
|
||||||
|
extraSelections.append(selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
setExtraSelections(extraSelections);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEditWidget::lineNumberAreaPaintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
QPainter painter(m_lineNumberArea);
|
||||||
|
painter.fillRect(event->rect(), QColor(0x24, 0x24, 0x24));
|
||||||
|
|
||||||
|
|
||||||
|
QTextBlock block = firstVisibleBlock();
|
||||||
|
int blockNumber = block.blockNumber();
|
||||||
|
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
|
||||||
|
int bottom = top + (int) blockBoundingRect(block).height();
|
||||||
|
|
||||||
|
while (block.isValid() && top <= event->rect().bottom()) {
|
||||||
|
if (block.isVisible() && bottom >= event->rect().top()) {
|
||||||
|
QString number = QString::number(blockNumber + 1);
|
||||||
|
painter.setPen(Theme::white);
|
||||||
|
painter.drawText(0, top, m_lineNumberArea->width(), fontMetrics().height(),
|
||||||
|
Qt::AlignRight, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
block = block.next();
|
||||||
|
top = bottom;
|
||||||
|
bottom = top + (int) blockBoundingRect(block).height();
|
||||||
|
++blockNumber;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||||
|
** contributors may be used to endorse or promote products derived
|
||||||
|
** from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CODEEDITOR_H
|
||||||
|
#define CODEEDITOR_H
|
||||||
|
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QPaintEvent;
|
||||||
|
class QResizeEvent;
|
||||||
|
class QSize;
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
|
class LineNumberArea;
|
||||||
|
|
||||||
|
class ScriptEditWidget : public QPlainTextEdit
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void scriptChanged(const QString &script);
|
||||||
|
public:
|
||||||
|
ScriptEditWidget(QWidget *parent=0);
|
||||||
|
|
||||||
|
void lineNumberAreaPaintEvent(QPaintEvent *event);
|
||||||
|
int lineNumberAreaWidth();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateLineNumberAreaWidth(int newBlockCount);
|
||||||
|
void highlightCurrentLine();
|
||||||
|
void updateLineNumberArea(const QRect &, int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWidget *m_lineNumberArea;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LineNumberArea : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LineNumberArea(ScriptEditWidget *editor) : QWidget(editor) {
|
||||||
|
m_codeEditor = editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize sizeHint() const {
|
||||||
|
return QSize(m_codeEditor->lineNumberAreaWidth(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event) {
|
||||||
|
m_codeEditor->lineNumberAreaPaintEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ScriptEditWidget *m_codeEditor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,884 @@
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QFile>
|
||||||
|
#include "scriptrunner.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
JSClassID ScriptRunner::js_canvasClassId = 0;
|
||||||
|
JSClassID ScriptRunner::js_partClassId = 0;
|
||||||
|
JSClassID ScriptRunner::js_componentClassId = 0;
|
||||||
|
JSClassID ScriptRunner::js_nodeClassId = 0;
|
||||||
|
|
||||||
|
static JSValue js_print(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
if (i != 0)
|
||||||
|
runner->consoleLog() += ' ';
|
||||||
|
str = JS_ToCString(context, argv[i]);
|
||||||
|
if (!str)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
runner->consoleLog() += str;
|
||||||
|
JS_FreeCString(context, str);
|
||||||
|
}
|
||||||
|
runner->consoleLog() += '\n';
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ScriptRunner::DocumentElement *GetElementFromArg(JSValueConst arg)
|
||||||
|
{
|
||||||
|
ScriptRunner::DocumentElement *element = nullptr;
|
||||||
|
if (nullptr == element) {
|
||||||
|
ScriptRunner::DocumentNode *node = (ScriptRunner::DocumentNode *)JS_GetOpaque(arg,
|
||||||
|
ScriptRunner::js_nodeClassId);
|
||||||
|
if (nullptr != node) {
|
||||||
|
element = (ScriptRunner::DocumentElement *)node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nullptr == element) {
|
||||||
|
ScriptRunner::DocumentPart *part = (ScriptRunner::DocumentPart *)JS_GetOpaque(arg,
|
||||||
|
ScriptRunner::js_partClassId);
|
||||||
|
if (nullptr != part) {
|
||||||
|
element = (ScriptRunner::DocumentElement *)part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nullptr == element) {
|
||||||
|
ScriptRunner::DocumentComponent *component = (ScriptRunner::DocumentComponent *)JS_GetOpaque(arg,
|
||||||
|
ScriptRunner::js_componentClassId);
|
||||||
|
if (nullptr != component) {
|
||||||
|
element = (ScriptRunner::DocumentElement *)component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nullptr == element) {
|
||||||
|
ScriptRunner::DocumentCanvas *canvas = (ScriptRunner::DocumentCanvas *)JS_GetOpaque(arg,
|
||||||
|
ScriptRunner::js_canvasClassId);
|
||||||
|
if (nullptr != canvas) {
|
||||||
|
element = (ScriptRunner::DocumentElement *)canvas;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_setAttribute(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 3) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: element, attributeName, attributeValue\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentElement *element = GetElementFromArg(argv[0]);
|
||||||
|
if (nullptr == element) {
|
||||||
|
runner->consoleLog() += "Parameters error\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
const char *attributeName = nullptr;
|
||||||
|
const char *attributeValue = nullptr;
|
||||||
|
attributeName = JS_ToCString(context, argv[1]);
|
||||||
|
if (!attributeName)
|
||||||
|
goto fail;
|
||||||
|
attributeValue = JS_ToCString(context, argv[2]);
|
||||||
|
if (!attributeValue)
|
||||||
|
goto fail;
|
||||||
|
runner->setAttribute(element, attributeName, attributeValue);
|
||||||
|
JS_FreeCString(context, attributeName);
|
||||||
|
JS_FreeCString(context, attributeValue);
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
fail:
|
||||||
|
JS_FreeCString(context, attributeName);
|
||||||
|
JS_FreeCString(context, attributeValue);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_attribute(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 2) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: element, attributeName\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentElement *element = GetElementFromArg(argv[0]);
|
||||||
|
if (nullptr == element) {
|
||||||
|
runner->consoleLog() += "Parameters error\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
QString attributeValue;
|
||||||
|
const char *attributeName = nullptr;
|
||||||
|
attributeName = JS_ToCString(context, argv[1]);
|
||||||
|
if (!attributeName)
|
||||||
|
goto fail;
|
||||||
|
attributeValue = runner->attribute(element, attributeName);
|
||||||
|
JS_FreeCString(context, attributeName);
|
||||||
|
return JS_NewString(context, attributeValue.toUtf8().constData());
|
||||||
|
fail:
|
||||||
|
JS_FreeCString(context, attributeName);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_connect(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 2) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: firstNode, secondNode\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentElement *firstElement = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
|
||||||
|
ScriptRunner::js_nodeClassId);
|
||||||
|
if (nullptr == firstElement ||
|
||||||
|
ScriptRunner::DocumentElementType::Node != firstElement->type) {
|
||||||
|
runner->consoleLog() += "First parameter must be node\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentElement *secondElement = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[1],
|
||||||
|
ScriptRunner::js_nodeClassId);
|
||||||
|
if (nullptr == secondElement ||
|
||||||
|
ScriptRunner::DocumentElementType::Node != secondElement->type) {
|
||||||
|
runner->consoleLog() += "Second parameter must be node\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentNode *firstNode = (ScriptRunner::DocumentNode *)firstElement;
|
||||||
|
ScriptRunner::DocumentNode *secondNode = (ScriptRunner::DocumentNode *)secondElement;
|
||||||
|
if (firstNode->part != secondNode->part) {
|
||||||
|
runner->consoleLog() += "Cannot connect nodes come from different parts\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
runner->connect(firstNode, secondNode);
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createComponent(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
ScriptRunner::DocumentComponent *parentComponent = nullptr;
|
||||||
|
if (argc >= 1) {
|
||||||
|
ScriptRunner::DocumentElement *element = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
|
||||||
|
ScriptRunner::js_componentClassId);
|
||||||
|
if (nullptr == element ||
|
||||||
|
ScriptRunner::DocumentElementType::Component != element->type) {
|
||||||
|
runner->consoleLog() += "First parameter must be null or component\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
parentComponent = (ScriptRunner::DocumentComponent *)element;
|
||||||
|
}
|
||||||
|
JSValue component = JS_NewObjectClass(context, ScriptRunner::js_componentClassId);
|
||||||
|
JS_SetOpaque(component, runner->createComponent(parentComponent));
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createPart(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 1) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: component\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentElement *element = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
|
||||||
|
ScriptRunner::js_componentClassId);
|
||||||
|
if (nullptr == element ||
|
||||||
|
ScriptRunner::DocumentElementType::Component != element->type) {
|
||||||
|
runner->consoleLog() += "First parameter must be component\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentComponent *component = (ScriptRunner::DocumentComponent *)element;
|
||||||
|
JSValue part = JS_NewObjectClass(context, ScriptRunner::js_partClassId);
|
||||||
|
JS_SetOpaque(part, runner->createPart(component));
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createNode(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 1) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: part\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentElement *element = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
|
||||||
|
ScriptRunner::js_partClassId);
|
||||||
|
if (nullptr == element ||
|
||||||
|
ScriptRunner::DocumentElementType::Part != element->type) {
|
||||||
|
runner->consoleLog() += "First parameter must be part\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
ScriptRunner::DocumentPart *part = (ScriptRunner::DocumentPart *)element;
|
||||||
|
JSValue node = JS_NewObjectClass(context, ScriptRunner::js_nodeClassId);
|
||||||
|
JS_SetOpaque(node, runner->createNode(part));
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createFloatInput(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 4) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, minValue, maxValue\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
double mergedValue = 0.0;
|
||||||
|
|
||||||
|
const char *name = nullptr;
|
||||||
|
double defaultValue = 0.0;
|
||||||
|
double minValue = 0.0;
|
||||||
|
double maxValue = 0.0;
|
||||||
|
|
||||||
|
name = JS_ToCString(context, argv[0]);
|
||||||
|
if (!name)
|
||||||
|
goto fail;
|
||||||
|
JS_ToFloat64(context, &defaultValue, argv[1]);
|
||||||
|
JS_ToFloat64(context, &minValue, argv[2]);
|
||||||
|
JS_ToFloat64(context, &maxValue, argv[3]);
|
||||||
|
|
||||||
|
mergedValue = runner->createFloatInput(name, defaultValue, minValue, maxValue);
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
|
||||||
|
return JS_NewFloat64(context, mergedValue);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createIntInput(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 4) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, minValue, maxValue\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t mergedValue = 0.0;
|
||||||
|
|
||||||
|
const char *name = nullptr;
|
||||||
|
int64_t defaultValue = 0;
|
||||||
|
int64_t minValue = 0;
|
||||||
|
int64_t maxValue = 0;
|
||||||
|
|
||||||
|
name = JS_ToCString(context, argv[0]);
|
||||||
|
if (!name)
|
||||||
|
goto fail;
|
||||||
|
JS_ToInt64(context, &defaultValue, argv[1]);
|
||||||
|
JS_ToInt64(context, &minValue, argv[2]);
|
||||||
|
JS_ToInt64(context, &maxValue, argv[3]);
|
||||||
|
|
||||||
|
mergedValue = runner->createIntInput(name, defaultValue, minValue, maxValue);
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
|
||||||
|
return JS_NewInt64(context, mergedValue);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createColorInput(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 2) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor mergeValue;
|
||||||
|
|
||||||
|
const char *name = nullptr;
|
||||||
|
const char *defaultValue = nullptr;
|
||||||
|
|
||||||
|
name = JS_ToCString(context, argv[0]);
|
||||||
|
if (!name)
|
||||||
|
goto fail;
|
||||||
|
defaultValue = JS_ToCString(context, argv[1]);
|
||||||
|
if (!defaultValue)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
mergeValue = runner->createColorInput(name, defaultValue);
|
||||||
|
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
JS_FreeCString(context, defaultValue);
|
||||||
|
|
||||||
|
return JS_NewString(context, mergeValue.name().toUtf8().constData());
|
||||||
|
|
||||||
|
fail:
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
JS_FreeCString(context, defaultValue);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createCheckInput(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 2) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mergedValue = false;
|
||||||
|
|
||||||
|
const char *name = nullptr;
|
||||||
|
const char *value = nullptr;
|
||||||
|
bool defaultValue = false;
|
||||||
|
|
||||||
|
name = JS_ToCString(context, argv[0]);
|
||||||
|
if (!name)
|
||||||
|
goto fail;
|
||||||
|
value = JS_ToCString(context, argv[1]);
|
||||||
|
if (!value)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
defaultValue = isTrueValueString(value);
|
||||||
|
mergedValue = runner->createCheckInput(name, defaultValue);
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
JS_FreeCString(context, value);
|
||||||
|
|
||||||
|
return JS_NewBool(context, mergedValue);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
JS_FreeCString(context, value);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_createSelectInput(JSContext *context, JSValueConst thisValue,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
|
||||||
|
if (argc < 3) {
|
||||||
|
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, options\r\n";
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name = nullptr;
|
||||||
|
int32_t defaultValue = 0;
|
||||||
|
int32_t mergedValue = 0;
|
||||||
|
JSValue *arrayItems = nullptr;
|
||||||
|
uint32_t arrayLength = 0;
|
||||||
|
QStringList options;
|
||||||
|
|
||||||
|
name = JS_ToCString(context, argv[0]);
|
||||||
|
if (!name)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
JS_ToInt32(context, &defaultValue, argv[1]);
|
||||||
|
|
||||||
|
if (true != JS_IsArray(context, argv[2])) {
|
||||||
|
runner->consoleLog() += "Expect array as the third parameter\r\n";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!js_get_fast_array(context, argv[2], &arrayItems, &arrayLength)) {
|
||||||
|
runner->consoleLog() += "Read third parameter as array failed\r\n";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < arrayLength; ++i) {
|
||||||
|
const char *optionValue = JS_ToCString(context, arrayItems[i]);
|
||||||
|
if (nullptr != optionValue) {
|
||||||
|
options.append(optionValue);
|
||||||
|
JS_FreeCString(context, optionValue);
|
||||||
|
} else {
|
||||||
|
options.append("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedValue = runner->createSelectInput(name, defaultValue, options);
|
||||||
|
if (mergedValue < 0)
|
||||||
|
mergedValue = 0;
|
||||||
|
else if (mergedValue >= options.size())
|
||||||
|
mergedValue = options.size() - 1;
|
||||||
|
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
|
||||||
|
return JS_NewInt32(context, mergedValue);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
JS_FreeCString(context, name);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptRunner::ScriptRunner()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptRunner::~ScriptRunner()
|
||||||
|
{
|
||||||
|
delete m_resultSnapshot;
|
||||||
|
delete m_defaultVariables;
|
||||||
|
for (auto &it: m_parts)
|
||||||
|
delete it;
|
||||||
|
for (auto &it: m_components)
|
||||||
|
delete it;
|
||||||
|
for (auto &it: m_nodes)
|
||||||
|
delete it;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString &ScriptRunner::consoleLog()
|
||||||
|
{
|
||||||
|
return m_consoleLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &ScriptRunner::scriptError()
|
||||||
|
{
|
||||||
|
return m_scriptError;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptRunner::DocumentPart *ScriptRunner::createPart(DocumentComponent *component)
|
||||||
|
{
|
||||||
|
ScriptRunner::DocumentPart *part = new ScriptRunner::DocumentPart;
|
||||||
|
part->component = component;
|
||||||
|
m_parts.push_back(part);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptRunner::DocumentComponent *ScriptRunner::createComponent(DocumentComponent *parentComponent)
|
||||||
|
{
|
||||||
|
ScriptRunner::DocumentComponent *component = new ScriptRunner::DocumentComponent;
|
||||||
|
component->parentComponent = parentComponent;
|
||||||
|
m_components.push_back(component);
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptRunner::DocumentNode *ScriptRunner::createNode(DocumentPart *part)
|
||||||
|
{
|
||||||
|
ScriptRunner::DocumentNode *node = new ScriptRunner::DocumentNode;
|
||||||
|
node->part = part;
|
||||||
|
m_nodes.push_back(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptRunner::setAttribute(DocumentElement *element, const QString &name, const QString &value)
|
||||||
|
{
|
||||||
|
element->attributes[name] = value;
|
||||||
|
|
||||||
|
// TODO: Validate attribute name and value
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptRunner::attribute(DocumentElement *element, const QString &name)
|
||||||
|
{
|
||||||
|
auto findAttribute = element->attributes.find(name);
|
||||||
|
if (findAttribute == element->attributes.end())
|
||||||
|
return QString();
|
||||||
|
return findAttribute->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptRunner::connect(DocumentNode *firstNode, DocumentNode *secondNode)
|
||||||
|
{
|
||||||
|
m_edges.push_back(std::make_pair(firstNode, secondNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_componentFinalizer(JSRuntime *runtime, JSValue value)
|
||||||
|
{
|
||||||
|
ScriptRunner::DocumentComponent *component = (ScriptRunner::DocumentComponent *)JS_GetOpaque(value,
|
||||||
|
ScriptRunner::js_componentClassId);
|
||||||
|
if (component) {
|
||||||
|
component->deleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSClassDef js_componentClass = {
|
||||||
|
"Component",
|
||||||
|
js_componentFinalizer,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void js_nodeFinalizer(JSRuntime *runtime, JSValue value)
|
||||||
|
{
|
||||||
|
ScriptRunner::DocumentNode *node = (ScriptRunner::DocumentNode *)JS_GetOpaque(value,
|
||||||
|
ScriptRunner::js_nodeClassId);
|
||||||
|
if (node) {
|
||||||
|
node->deleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSClassDef js_nodeClass = {
|
||||||
|
"Node",
|
||||||
|
js_nodeFinalizer,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void js_partFinalizer(JSRuntime *runtime, JSValue value)
|
||||||
|
{
|
||||||
|
ScriptRunner::DocumentPart *part = (ScriptRunner::DocumentPart *)JS_GetOpaque(value,
|
||||||
|
ScriptRunner::js_partClassId);
|
||||||
|
if (part) {
|
||||||
|
part->deleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSClassDef js_partClass = {
|
||||||
|
"Part",
|
||||||
|
js_partFinalizer,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ScriptRunner::run()
|
||||||
|
{
|
||||||
|
QElapsedTimer countTimeConsumed;
|
||||||
|
countTimeConsumed.start();
|
||||||
|
|
||||||
|
// Warning: Not thread safe, but we have only one script instance running, so it doesn't matter
|
||||||
|
js_canvasClassId = JS_NewClassID(&js_canvasClassId);
|
||||||
|
js_partClassId = JS_NewClassID(&js_partClassId);
|
||||||
|
js_componentClassId = JS_NewClassID(&js_componentClassId);
|
||||||
|
js_nodeClassId = JS_NewClassID(&js_nodeClassId);
|
||||||
|
|
||||||
|
m_defaultVariables = new std::map<QString, std::map<QString, QString>>;
|
||||||
|
|
||||||
|
JSRuntime *runtime = JS_NewRuntime();
|
||||||
|
JSContext *context = JS_NewContext(runtime);
|
||||||
|
|
||||||
|
JS_NewClass(runtime, js_partClassId, &js_partClass);
|
||||||
|
JS_NewClass(runtime, js_componentClassId, &js_componentClass);
|
||||||
|
JS_NewClass(runtime, js_nodeClassId, &js_nodeClass);
|
||||||
|
|
||||||
|
JS_SetContextOpaque(context, this);
|
||||||
|
|
||||||
|
if (nullptr != m_script &&
|
||||||
|
!m_script->trimmed().isEmpty()) {
|
||||||
|
auto buffer = m_script->toUtf8();
|
||||||
|
|
||||||
|
JSValue globalObject = JS_GetGlobalObject(context);
|
||||||
|
|
||||||
|
JSValue document = JS_NewObject(context);
|
||||||
|
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createComponent",
|
||||||
|
JS_NewCFunction(context, js_createComponent, "createComponent", 1));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createPart",
|
||||||
|
JS_NewCFunction(context, js_createPart, "createPart", 1));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createNode",
|
||||||
|
JS_NewCFunction(context, js_createNode, "createNode", 1));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createFloatInput",
|
||||||
|
JS_NewCFunction(context, js_createFloatInput, "createFloatInput", 4));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createIntInput",
|
||||||
|
JS_NewCFunction(context, js_createIntInput, "createIntInput", 4));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createColorInput",
|
||||||
|
JS_NewCFunction(context, js_createColorInput, "createColorInput", 2));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createCheckInput",
|
||||||
|
JS_NewCFunction(context, js_createCheckInput, "createCheckInput", 2));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "createSelectInput",
|
||||||
|
JS_NewCFunction(context, js_createSelectInput, "createSelectInput", 3));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "connect",
|
||||||
|
JS_NewCFunction(context, js_connect, "connect", 2));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "setAttribute",
|
||||||
|
JS_NewCFunction(context, js_setAttribute, "setAttribute", 3));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "attribute",
|
||||||
|
JS_NewCFunction(context, js_attribute, "attribute", 2));
|
||||||
|
|
||||||
|
JSValue canvas = JS_NewObjectClass(context, ScriptRunner::js_canvasClassId);
|
||||||
|
JS_SetOpaque(canvas, &m_canvas);
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
document, "canvas",
|
||||||
|
canvas);
|
||||||
|
|
||||||
|
JS_SetPropertyStr(context, globalObject, "document", document);
|
||||||
|
|
||||||
|
JSValue console = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
console, "log",
|
||||||
|
JS_NewCFunction(context, js_print, "log", 1));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
console, "warn",
|
||||||
|
JS_NewCFunction(context, js_print, "warn", 1));
|
||||||
|
JS_SetPropertyStr(context,
|
||||||
|
console, "error",
|
||||||
|
JS_NewCFunction(context, js_print, "error", 1));
|
||||||
|
JS_SetPropertyStr(context, globalObject, "console", console);
|
||||||
|
|
||||||
|
QFile file(":/thirdparty/three.js/dust3d.three.js");
|
||||||
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
|
QByteArray fileContent = file.readAll();
|
||||||
|
JSValue three = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, globalObject, "THREE", three);
|
||||||
|
JSValue object = JS_Eval(context, (char *)fileContent.constData(), fileContent.size(), "<thirdparty/three.js/dust3d.three.js>",
|
||||||
|
JS_EVAL_TYPE_GLOBAL);
|
||||||
|
JS_FreeValue(context, object);
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_FreeValue(context, globalObject);
|
||||||
|
|
||||||
|
JSValue object = JS_Eval(context, buffer.constData(), buffer.size(), "<input>",
|
||||||
|
JS_EVAL_TYPE_GLOBAL);
|
||||||
|
if (JS_IsException(object)) {
|
||||||
|
JSValue exceptionValue = JS_GetException(context);
|
||||||
|
bool isError = JS_IsError(context, exceptionValue);
|
||||||
|
if (isError) {
|
||||||
|
m_scriptError += "Throw: ";
|
||||||
|
const char *exceptionError = JS_ToCString(context, exceptionValue);
|
||||||
|
m_scriptError += exceptionError;
|
||||||
|
m_scriptError += "\r\n";
|
||||||
|
JS_FreeCString(context, exceptionError);
|
||||||
|
JSValue value = JS_GetPropertyStr(context, exceptionValue, "stack");
|
||||||
|
if (!JS_IsUndefined(value)) {
|
||||||
|
const char *stack = JS_ToCString(context, value);
|
||||||
|
m_scriptError += stack;
|
||||||
|
m_scriptError += "\r\n";
|
||||||
|
JS_FreeCString(context, stack);
|
||||||
|
}
|
||||||
|
JS_FreeValue(context, value);
|
||||||
|
|
||||||
|
qDebug() << "QuickJS" << m_scriptError;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
generateSnapshot();
|
||||||
|
const char *objectString = JS_ToCString(context, object);
|
||||||
|
qDebug() << "Result:" << objectString;
|
||||||
|
JS_FreeCString(context, objectString);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_FreeValue(context, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_FreeContext(context);
|
||||||
|
JS_FreeRuntime(runtime);
|
||||||
|
|
||||||
|
qDebug() << "The script run" << countTimeConsumed.elapsed() << "milliseconds";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptRunner::generateSnapshot()
|
||||||
|
{
|
||||||
|
m_resultSnapshot = new Snapshot;
|
||||||
|
std::map<void *, QString> pointerToIdMap;
|
||||||
|
|
||||||
|
std::map<void *, QStringList> componentChildrensMap;
|
||||||
|
|
||||||
|
QStringList rootChildren;
|
||||||
|
|
||||||
|
m_resultSnapshot->canvas = m_canvas.attributes;
|
||||||
|
|
||||||
|
for (const auto &it: m_components) {
|
||||||
|
QString idString = it->id;
|
||||||
|
pointerToIdMap[it] = idString;
|
||||||
|
auto &component = m_resultSnapshot->components[idString];
|
||||||
|
component = it->attributes;
|
||||||
|
component["id"] = idString;
|
||||||
|
componentChildrensMap[it->parentComponent].append(idString);
|
||||||
|
if (nullptr == it->parentComponent)
|
||||||
|
rootChildren.append(idString);
|
||||||
|
}
|
||||||
|
m_resultSnapshot->rootComponent["children"] = rootChildren.join(",");
|
||||||
|
|
||||||
|
for (const auto &it: m_components) {
|
||||||
|
const auto &idString = pointerToIdMap[it];
|
||||||
|
auto &component = m_resultSnapshot->components[idString];
|
||||||
|
auto &childrens = componentChildrensMap[it];
|
||||||
|
if (!childrens.empty())
|
||||||
|
component["children"] = childrens.join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &it: m_parts) {
|
||||||
|
auto findComponent = pointerToIdMap.find(it->component);
|
||||||
|
if (findComponent == pointerToIdMap.end()) {
|
||||||
|
m_scriptError += "Find component pointer failed, component maybe deleted\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString idString = it->id;
|
||||||
|
pointerToIdMap[it] = idString;
|
||||||
|
auto &part = m_resultSnapshot->parts[idString];
|
||||||
|
part = it->attributes;
|
||||||
|
part.insert({"visible", "true"});
|
||||||
|
part["id"] = idString;
|
||||||
|
|
||||||
|
auto &component = m_resultSnapshot->components[findComponent->second];
|
||||||
|
component["linkData"] = idString;
|
||||||
|
component["linkDataType"] = "partId";
|
||||||
|
}
|
||||||
|
for (const auto &it: m_nodes) {
|
||||||
|
auto findPart = pointerToIdMap.find(it->part);
|
||||||
|
if (findPart == pointerToIdMap.end()) {
|
||||||
|
m_scriptError += "Find part pointer failed, part maybe deleted\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString idString = it->id;
|
||||||
|
pointerToIdMap[it] = idString;
|
||||||
|
auto &node = m_resultSnapshot->nodes[idString];
|
||||||
|
node = it->attributes;
|
||||||
|
node["id"] = idString;
|
||||||
|
node["partId"] = findPart->second;
|
||||||
|
}
|
||||||
|
for (const auto &it: m_edges) {
|
||||||
|
if (it.first->part != it.second->part) {
|
||||||
|
m_scriptError += "Cannot connect nodes come from different parts\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto findFirstNode = pointerToIdMap.find(it.first);
|
||||||
|
if (findFirstNode == pointerToIdMap.end()) {
|
||||||
|
m_scriptError += "Find first node pointer failed, node maybe deleted\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto findSecondNode = pointerToIdMap.find(it.second);
|
||||||
|
if (findSecondNode == pointerToIdMap.end()) {
|
||||||
|
m_scriptError += "Find second node pointer failed, node maybe deleted\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto findPart = pointerToIdMap.find(it.first->part);
|
||||||
|
if (findPart == pointerToIdMap.end()) {
|
||||||
|
m_scriptError += "Find part pointer failed, part maybe deleted\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString idString = QUuid::createUuid().toString();
|
||||||
|
auto &edge = m_resultSnapshot->edges[idString];
|
||||||
|
edge["id"] = idString;
|
||||||
|
edge["from"] = findFirstNode->second;
|
||||||
|
edge["to"] = findSecondNode->second;
|
||||||
|
edge["partId"] = findPart->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &it: m_resultSnapshot->nodes) {
|
||||||
|
qDebug() << "Generated node:" << it.second;
|
||||||
|
}
|
||||||
|
for (const auto &it: m_resultSnapshot->edges) {
|
||||||
|
qDebug() << "Generated edge:" << it.second;
|
||||||
|
}
|
||||||
|
for (const auto &it: m_resultSnapshot->parts) {
|
||||||
|
qDebug() << "Generated part:" << it.second;
|
||||||
|
}
|
||||||
|
for (const auto &it: m_resultSnapshot->components) {
|
||||||
|
qDebug() << "Generated component:" << it.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptRunner::createInput(const QString &name, const std::map<QString, QString> &attributes)
|
||||||
|
{
|
||||||
|
if (nullptr != m_defaultVariables) {
|
||||||
|
if (m_defaultVariables->find(name) != m_defaultVariables->end()) {
|
||||||
|
m_scriptError += "Repeated variable name found: \"" + name + "\"\r\n";
|
||||||
|
}
|
||||||
|
(*m_defaultVariables)[name] = attributes;
|
||||||
|
}
|
||||||
|
if (nullptr != m_variables) {
|
||||||
|
auto findVariable = m_variables->find(name);
|
||||||
|
if (findVariable != m_variables->end()) {
|
||||||
|
auto findValue = findVariable->second.find("value");
|
||||||
|
if (findValue != findVariable->second.end())
|
||||||
|
return findValue->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto findValue = attributes.find("value");
|
||||||
|
if (findValue != attributes.end())
|
||||||
|
return findValue->second;
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
float ScriptRunner::createFloatInput(const QString &name, float defaultValue, float minValue, float maxValue)
|
||||||
|
{
|
||||||
|
std::map<QString, QString> attributes;
|
||||||
|
attributes["input"] = "Float";
|
||||||
|
attributes["value"] = QString::number(defaultValue);
|
||||||
|
attributes["defaultValue"] = attributes["value"];
|
||||||
|
attributes["minValue"] = QString::number(minValue);
|
||||||
|
attributes["maxValue"] = QString::number(maxValue);
|
||||||
|
auto inputValue = createInput(name, attributes);
|
||||||
|
return inputValue.toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScriptRunner::createIntInput(const QString &name, int defaultValue, int minValue, int maxValue)
|
||||||
|
{
|
||||||
|
std::map<QString, QString> attributes;
|
||||||
|
attributes["input"] = "Int";
|
||||||
|
attributes["value"] = QString::number(defaultValue);
|
||||||
|
attributes["defaultValue"] = attributes["value"];
|
||||||
|
attributes["minValue"] = QString::number(minValue);
|
||||||
|
attributes["maxValue"] = QString::number(maxValue);
|
||||||
|
auto inputValue = createInput(name, attributes);
|
||||||
|
return inputValue.toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor ScriptRunner::createColorInput(const QString &name, const QColor &defaultValue)
|
||||||
|
{
|
||||||
|
std::map<QString, QString> attributes;
|
||||||
|
attributes["input"] = "Color";
|
||||||
|
attributes["value"] = defaultValue.name();
|
||||||
|
attributes["defaultValue"] = attributes["value"];
|
||||||
|
auto inputValue = createInput(name, attributes);
|
||||||
|
return QColor(inputValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptRunner::createCheckInput(const QString &name, bool checked)
|
||||||
|
{
|
||||||
|
std::map<QString, QString> attributes;
|
||||||
|
attributes["input"] = "Check";
|
||||||
|
attributes["value"] = checked ? "true" : "false";
|
||||||
|
attributes["defaultValue"] = attributes["value"];
|
||||||
|
auto inputValue = createInput(name, attributes);
|
||||||
|
return isTrueValueString(inputValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScriptRunner::createSelectInput(const QString &name, int defaultSelectedIndex, const QStringList &options)
|
||||||
|
{
|
||||||
|
std::map<QString, QString> attributes;
|
||||||
|
attributes["input"] = "Select";
|
||||||
|
attributes["value"] = QString::number(defaultSelectedIndex);
|
||||||
|
attributes["defaultValue"] = attributes["value"];
|
||||||
|
attributes["length"] = QString::number(options.size());
|
||||||
|
for (int i = 0; i < options.size(); ++i) {
|
||||||
|
attributes["option" + QString::number(i)] = options[i];
|
||||||
|
}
|
||||||
|
auto inputValue = createInput(name, attributes);
|
||||||
|
int selectedIndex = inputValue.toInt();
|
||||||
|
if (selectedIndex >= options.size()) {
|
||||||
|
m_scriptError += QString("Selected index of select input \"%1\" is been reset to 0 because of out of range\r\n").arg(name);
|
||||||
|
selectedIndex = 0;
|
||||||
|
}
|
||||||
|
return selectedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptRunner::process()
|
||||||
|
{
|
||||||
|
run();
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptRunner::setScript(QString *script)
|
||||||
|
{
|
||||||
|
m_script = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptRunner::setVariables(std::map<QString, std::map<QString, QString>> *variables)
|
||||||
|
{
|
||||||
|
m_variables = variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
Snapshot *ScriptRunner::takeResultSnapshot()
|
||||||
|
{
|
||||||
|
Snapshot *snapshot = m_resultSnapshot;
|
||||||
|
m_resultSnapshot = nullptr;
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<QString, std::map<QString, QString>> *ScriptRunner::takeDefaultVariables()
|
||||||
|
{
|
||||||
|
std::map<QString, std::map<QString, QString>> *defaultVariables = m_defaultVariables;
|
||||||
|
m_defaultVariables = nullptr;
|
||||||
|
return defaultVariables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptRunner::mergeVaraibles(std::map<QString, std::map<QString, QString>> *target, const std::map<QString, std::map<QString, QString>> &source)
|
||||||
|
{
|
||||||
|
for (const auto &it: source) {
|
||||||
|
(*target)[it.first] = it.second;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef DUST3D_SCRIPT_RUNNER_H
|
||||||
|
#define DUST3D_SCRIPT_RUNNER_H
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QStringList>
|
||||||
|
#include "snapshot.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "quickjs.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScriptRunner : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum class DocumentElementType
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
Canvas,
|
||||||
|
Component,
|
||||||
|
Part,
|
||||||
|
Node
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DocumentElement
|
||||||
|
{
|
||||||
|
QString id = QUuid::createUuid().toString();
|
||||||
|
DocumentElementType type = DocumentElementType::Unknown;
|
||||||
|
bool deleted = false;
|
||||||
|
std::map<QString, QString> attributes = {std::make_pair("id", id)};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DocumentComponent : DocumentElement
|
||||||
|
{
|
||||||
|
DocumentComponent()
|
||||||
|
{
|
||||||
|
type = DocumentElementType::Component;
|
||||||
|
}
|
||||||
|
DocumentComponent *parentComponent = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DocumentPart : DocumentElement
|
||||||
|
{
|
||||||
|
DocumentPart()
|
||||||
|
{
|
||||||
|
type = DocumentElementType::Part;
|
||||||
|
}
|
||||||
|
DocumentComponent *component = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DocumentNode : DocumentElement
|
||||||
|
{
|
||||||
|
DocumentNode()
|
||||||
|
{
|
||||||
|
type = DocumentElementType::Node;
|
||||||
|
}
|
||||||
|
DocumentPart *part = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DocumentCanvas : DocumentElement
|
||||||
|
{
|
||||||
|
DocumentCanvas()
|
||||||
|
{
|
||||||
|
type = DocumentElementType::Canvas;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ScriptRunner();
|
||||||
|
~ScriptRunner();
|
||||||
|
void run();
|
||||||
|
void setScript(QString *script);
|
||||||
|
void setVariables(std::map<QString, std::map<QString, QString>> *variables);
|
||||||
|
Snapshot *takeResultSnapshot();
|
||||||
|
std::map<QString, std::map<QString, QString>> *takeDefaultVariables();
|
||||||
|
const QString &scriptError();
|
||||||
|
static void mergeVaraibles(std::map<QString, std::map<QString, QString>> *target, const std::map<QString, std::map<QString, QString>> &source);
|
||||||
|
DocumentPart *createPart(DocumentComponent *component);
|
||||||
|
DocumentComponent *createComponent(DocumentComponent *parentComponent);
|
||||||
|
DocumentNode *createNode(DocumentPart *part);
|
||||||
|
bool setAttribute(DocumentElement *element, const QString &name, const QString &value);
|
||||||
|
QString attribute(DocumentElement *element, const QString &name);
|
||||||
|
void connect(DocumentNode *firstNode, DocumentNode *secondNode);
|
||||||
|
QString &consoleLog();
|
||||||
|
QString createInput(const QString &name, const std::map<QString, QString> &attributes);
|
||||||
|
float createFloatInput(const QString &name, float defaultValue, float minValue, float maxValue);
|
||||||
|
int createIntInput(const QString &name, int defaultValue, int minValue, int maxValue);
|
||||||
|
QColor createColorInput(const QString &name, const QColor &defaultValue);
|
||||||
|
bool createCheckInput(const QString &name, bool checked);
|
||||||
|
int createSelectInput(const QString &name, int defaultSelectedIndex, const QStringList &options);
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
public slots:
|
||||||
|
void process();
|
||||||
|
private:
|
||||||
|
QString *m_script = nullptr;
|
||||||
|
Snapshot *m_resultSnapshot = nullptr;
|
||||||
|
std::map<QString, std::map<QString, QString>> *m_defaultVariables = nullptr;
|
||||||
|
std::map<QString, std::map<QString, QString>> *m_variables = nullptr;
|
||||||
|
std::vector<DocumentPart *> m_parts;
|
||||||
|
std::vector<DocumentComponent *> m_components;
|
||||||
|
std::vector<DocumentNode *> m_nodes;
|
||||||
|
std::vector<std::pair<DocumentNode *, DocumentNode *>> m_edges;
|
||||||
|
QString m_scriptError;
|
||||||
|
QString m_consoleLog;
|
||||||
|
DocumentCanvas m_canvas;
|
||||||
|
void generateSnapshot();
|
||||||
|
public:
|
||||||
|
static JSClassID js_canvasClassId;
|
||||||
|
static JSClassID js_partClassId;
|
||||||
|
static JSClassID js_componentClassId;
|
||||||
|
static JSClassID js_nodeClassId;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,194 @@
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QColorDialog>
|
||||||
|
#include "scriptvariableswidget.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "theme.h"
|
||||||
|
#include "floatnumberwidget.h"
|
||||||
|
#include "intnumberwidget.h"
|
||||||
|
|
||||||
|
ScriptVariablesWidget::ScriptVariablesWidget(const Document *document,
|
||||||
|
QWidget *parent) :
|
||||||
|
QScrollArea(parent),
|
||||||
|
m_document(document)
|
||||||
|
{
|
||||||
|
connect(this, &ScriptVariablesWidget::updateVariableValue, m_document, &Document::updateVariableValue);
|
||||||
|
|
||||||
|
setWidgetResizable(true);
|
||||||
|
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptVariablesWidget::reload()
|
||||||
|
{
|
||||||
|
QWidget *widget = new QWidget;
|
||||||
|
QFormLayout *formLayout = new QFormLayout;
|
||||||
|
for (const auto &variable: m_document->variables()) {
|
||||||
|
auto name = variable.first;
|
||||||
|
auto input = valueOfKeyInMapOrEmpty(variable.second, "input");
|
||||||
|
if ("Float" == input) {
|
||||||
|
auto minValue = valueOfKeyInMapOrEmpty(variable.second, "minValue").toFloat();
|
||||||
|
auto maxValue = valueOfKeyInMapOrEmpty(variable.second, "maxValue").toFloat();
|
||||||
|
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toFloat();
|
||||||
|
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toFloat();
|
||||||
|
FloatNumberWidget *floatWidget = new FloatNumberWidget;
|
||||||
|
floatWidget->setItemName(name);
|
||||||
|
floatWidget->setRange(minValue, maxValue);
|
||||||
|
floatWidget->setValue(value);
|
||||||
|
|
||||||
|
connect(floatWidget, &FloatNumberWidget::valueChanged, [=](float toValue) {
|
||||||
|
emit updateVariableValue(name, QString::number(toValue));
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton *floatEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeToolButton(floatEraser);
|
||||||
|
|
||||||
|
connect(floatEraser, &QPushButton::clicked, [=]() {
|
||||||
|
floatWidget->setValue(defaultValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
QHBoxLayout *floatLayout = new QHBoxLayout;
|
||||||
|
floatLayout->addWidget(floatEraser);
|
||||||
|
floatLayout->addWidget(floatWidget);
|
||||||
|
|
||||||
|
formLayout->addRow(floatLayout);
|
||||||
|
} else if ("Int" == input) {
|
||||||
|
auto minValue = valueOfKeyInMapOrEmpty(variable.second, "minValue").toInt();
|
||||||
|
auto maxValue = valueOfKeyInMapOrEmpty(variable.second, "maxValue").toInt();
|
||||||
|
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toInt();
|
||||||
|
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toInt();
|
||||||
|
IntNumberWidget *intWidget = new IntNumberWidget;
|
||||||
|
intWidget->setItemName(name);
|
||||||
|
intWidget->setRange(minValue, maxValue);
|
||||||
|
intWidget->setValue(value);
|
||||||
|
|
||||||
|
connect(intWidget, &IntNumberWidget::valueChanged, [=](int toValue) {
|
||||||
|
emit updateVariableValue(name, QString::number(toValue));
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton *intEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeToolButton(intEraser);
|
||||||
|
|
||||||
|
connect(intEraser, &QPushButton::clicked, [=]() {
|
||||||
|
intWidget->setValue(defaultValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
QHBoxLayout *intLayout = new QHBoxLayout;
|
||||||
|
intLayout->addWidget(intEraser);
|
||||||
|
intLayout->addWidget(intWidget);
|
||||||
|
|
||||||
|
formLayout->addRow(intLayout);
|
||||||
|
} else if ("Check" == input) {
|
||||||
|
auto value = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "value"));
|
||||||
|
auto defaultValue = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "defaultValue"));
|
||||||
|
|
||||||
|
QCheckBox *checkBox = new QCheckBox;
|
||||||
|
Theme::initCheckbox(checkBox);
|
||||||
|
checkBox->setText(name);
|
||||||
|
checkBox->setChecked(value);
|
||||||
|
|
||||||
|
connect(checkBox, &QCheckBox::stateChanged, [=](int) {
|
||||||
|
emit updateVariableValue(name, checkBox->isChecked() ? "true" : "false");
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton *checkEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeToolButton(checkEraser);
|
||||||
|
|
||||||
|
connect(checkEraser, &QPushButton::clicked, [=]() {
|
||||||
|
checkBox->setChecked(defaultValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
QHBoxLayout *checkLayout = new QHBoxLayout;
|
||||||
|
checkLayout->addWidget(checkEraser);
|
||||||
|
checkLayout->addWidget(checkBox);
|
||||||
|
|
||||||
|
formLayout->addRow(checkLayout);
|
||||||
|
} else if ("Select" == input) {
|
||||||
|
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toInt();
|
||||||
|
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toInt();
|
||||||
|
auto length = valueOfKeyInMapOrEmpty(variable.second, "length").toInt();
|
||||||
|
|
||||||
|
QComboBox *selectBox = new QComboBox;
|
||||||
|
selectBox->setEditable(false);
|
||||||
|
selectBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
|
for (auto i = 0; i < length; ++i) {
|
||||||
|
selectBox->addItem(valueOfKeyInMapOrEmpty(variable.second, "option" + QString::number(i)));
|
||||||
|
}
|
||||||
|
selectBox->setCurrentIndex(value);
|
||||||
|
|
||||||
|
connect(selectBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||||
|
emit updateVariableValue(name, QString::number(index));
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton *selectEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeToolButton(selectEraser);
|
||||||
|
|
||||||
|
connect(selectEraser, &QPushButton::clicked, [=]() {
|
||||||
|
selectBox->setCurrentIndex(defaultValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
QLabel *selectLabel = new QLabel;
|
||||||
|
selectLabel->setText(name);
|
||||||
|
|
||||||
|
QHBoxLayout *selectLayout = new QHBoxLayout;
|
||||||
|
selectLayout->addWidget(selectEraser);
|
||||||
|
selectLayout->addWidget(selectBox);
|
||||||
|
selectLayout->addWidget(selectLabel);
|
||||||
|
|
||||||
|
formLayout->addRow(selectLayout);
|
||||||
|
} else if ("Color" == input) {
|
||||||
|
auto value = valueOfKeyInMapOrEmpty(variable.second, "value");
|
||||||
|
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue");
|
||||||
|
|
||||||
|
QPushButton *colorEraser = new QPushButton(QChar(fa::eraser));
|
||||||
|
Theme::initAwesomeToolButton(colorEraser);
|
||||||
|
|
||||||
|
QPushButton *pickButton = new QPushButton();
|
||||||
|
Theme::initAwesomeToolButtonWithoutFont(pickButton);
|
||||||
|
|
||||||
|
auto updatePickButtonColor = [=](const QColor &color) {
|
||||||
|
QPalette palette = pickButton->palette();
|
||||||
|
palette.setColor(QPalette::Window, color);
|
||||||
|
palette.setColor(QPalette::Button, color);
|
||||||
|
pickButton->setPalette(palette);
|
||||||
|
};
|
||||||
|
updatePickButtonColor(QColor(value));
|
||||||
|
|
||||||
|
connect(colorEraser, &QPushButton::clicked, [=]() {
|
||||||
|
updatePickButtonColor(defaultValue);
|
||||||
|
emit updateVariableValue(name, defaultValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(pickButton, &QPushButton::clicked, [=]() {
|
||||||
|
QColor color = QColorDialog::getColor(value, this);
|
||||||
|
if (color.isValid()) {
|
||||||
|
updatePickButtonColor(color.name());
|
||||||
|
emit updateVariableValue(name, color.name());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QLabel *selectLabel = new QLabel;
|
||||||
|
selectLabel->setText(name);
|
||||||
|
|
||||||
|
QHBoxLayout *colorLayout = new QHBoxLayout;
|
||||||
|
colorLayout->addWidget(colorEraser);
|
||||||
|
colorLayout->addWidget(pickButton);
|
||||||
|
colorLayout->addWidget(selectLabel);
|
||||||
|
colorLayout->addStretch();
|
||||||
|
|
||||||
|
formLayout->addRow(colorLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
widget->setLayout(formLayout);
|
||||||
|
|
||||||
|
setWidget(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ScriptVariablesWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
return QSize(Theme::sidebarPreferredWidth, 0);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef DUST3D_SCRIPT_VARIABLES_WIDGET_H
|
||||||
|
#define DUST3D_SCRIPT_VARIABLES_WIDGET_H
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QString>
|
||||||
|
#include <map>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include "document.h"
|
||||||
|
|
||||||
|
class ScriptVariablesWidget : public QScrollArea
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void updateVariableValue(const QString &name, const QString &value);
|
||||||
|
public:
|
||||||
|
ScriptVariablesWidget(const Document *document,
|
||||||
|
QWidget *parent=nullptr);
|
||||||
|
public slots:
|
||||||
|
void reload();
|
||||||
|
protected:
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
private:
|
||||||
|
const Document *m_document = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include "scriptwidget.h"
|
||||||
|
#include "scripteditwidget.h"
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
|
ScriptWidget::ScriptWidget(const Document *document, QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
m_document(document)
|
||||||
|
{
|
||||||
|
m_consoleEdit = new QPlainTextEdit;
|
||||||
|
m_consoleEdit->setReadOnly(true);
|
||||||
|
m_consoleEdit->hide();
|
||||||
|
|
||||||
|
ScriptVariablesWidget *scriptVariablesWidget = new ScriptVariablesWidget(m_document);
|
||||||
|
scriptVariablesWidget->hide();
|
||||||
|
connect(m_document, &Document::mergedVaraiblesChanged, this, [=]() {
|
||||||
|
if (m_document->variables().empty())
|
||||||
|
scriptVariablesWidget->hide();
|
||||||
|
else
|
||||||
|
scriptVariablesWidget->show();
|
||||||
|
});
|
||||||
|
|
||||||
|
ScriptEditWidget *scriptEditWidget = new ScriptEditWidget;
|
||||||
|
|
||||||
|
connect(m_document, &Document::cleanupScript, scriptEditWidget, &ScriptEditWidget::clear);
|
||||||
|
connect(m_document, &Document::scriptModifiedFromExternal, this, [=]() {
|
||||||
|
scriptEditWidget->setPlainText(document->script());
|
||||||
|
});
|
||||||
|
connect(m_document, &Document::scriptErrorChanged, this, &ScriptWidget::updateScriptConsole);
|
||||||
|
connect(m_document, &Document::scriptConsoleLogChanged, this, &ScriptWidget::updateScriptConsole);
|
||||||
|
|
||||||
|
connect(scriptEditWidget, &ScriptEditWidget::scriptChanged, m_document, &Document::updateScript);
|
||||||
|
|
||||||
|
connect(m_document, &Document::mergedVaraiblesChanged, scriptVariablesWidget, &ScriptVariablesWidget::reload);
|
||||||
|
|
||||||
|
scriptEditWidget->setStyleSheet("color: white;");
|
||||||
|
m_consoleEdit->setStyleSheet("color: white;");
|
||||||
|
|
||||||
|
QSplitter *splitter = new QSplitter;
|
||||||
|
splitter->setOrientation(Qt::Vertical);
|
||||||
|
splitter->addWidget(scriptEditWidget);
|
||||||
|
splitter->addWidget(m_consoleEdit);
|
||||||
|
splitter->addWidget(scriptVariablesWidget);
|
||||||
|
splitter->setStretchFactor(2, 1);
|
||||||
|
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addWidget(splitter);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ScriptWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
return QSize(Theme::sidebarPreferredWidth, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptWidget::updateScriptConsole()
|
||||||
|
{
|
||||||
|
const auto &scriptError = m_document->scriptError();
|
||||||
|
const auto &scriptConsoleLog = m_document->scriptConsoleLog();
|
||||||
|
if (scriptError.isEmpty() && scriptConsoleLog.isEmpty()) {
|
||||||
|
m_consoleEdit->hide();
|
||||||
|
} else {
|
||||||
|
m_consoleEdit->setPlainText(scriptError + scriptConsoleLog);
|
||||||
|
m_consoleEdit->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef SCRIPT_WIDGET_H
|
||||||
|
#define SCRIPT_WIDGET_H
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include "document.h"
|
||||||
|
#include "scriptvariableswidget.h"
|
||||||
|
|
||||||
|
class ScriptWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ScriptWidget(const Document *document, QWidget *parent=nullptr);
|
||||||
|
public slots:
|
||||||
|
void updateScriptConsole();
|
||||||
|
protected:
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
private:
|
||||||
|
const Document *m_document = nullptr;
|
||||||
|
QPlainTextEdit *m_consoleEdit = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include <QDebug>
|
||||||
|
#include "variablesxml.h"
|
||||||
|
|
||||||
|
void saveVariablesToXmlStream(const std::map<QString, std::map<QString, QString>> &variables, QXmlStreamWriter *writer)
|
||||||
|
{
|
||||||
|
writer->setAutoFormatting(true);
|
||||||
|
writer->writeStartDocument();
|
||||||
|
|
||||||
|
writer->writeStartElement("variables");
|
||||||
|
for (const auto &it: variables) {
|
||||||
|
writer->writeStartElement("variable");
|
||||||
|
writer->writeAttribute("name", it.first);
|
||||||
|
for (const auto &subIt: it.second) {
|
||||||
|
if (subIt.first == "name")
|
||||||
|
continue;
|
||||||
|
writer->writeAttribute(subIt.first, subIt.second);
|
||||||
|
}
|
||||||
|
writer->writeEndElement();
|
||||||
|
}
|
||||||
|
writer->writeEndElement();
|
||||||
|
|
||||||
|
writer->writeEndDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadVariablesFromXmlStream(std::map<QString, std::map<QString, QString>> *variables, QXmlStreamReader &reader)
|
||||||
|
{
|
||||||
|
std::vector<QString> elementNameStack;
|
||||||
|
while (!reader.atEnd()) {
|
||||||
|
reader.readNext();
|
||||||
|
if (!reader.isStartElement() && !reader.isEndElement()) {
|
||||||
|
if (!reader.name().toString().isEmpty())
|
||||||
|
qDebug() << "Skip xml element:" << reader.name().toString() << " tokenType:" << reader.tokenType();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString baseName = reader.name().toString();
|
||||||
|
if (reader.isStartElement())
|
||||||
|
elementNameStack.push_back(baseName);
|
||||||
|
QStringList nameItems;
|
||||||
|
for (const auto &nameItem: elementNameStack) {
|
||||||
|
nameItems.append(nameItem);
|
||||||
|
}
|
||||||
|
QString fullName = nameItems.join(".");
|
||||||
|
if (reader.isEndElement())
|
||||||
|
elementNameStack.pop_back();
|
||||||
|
if (reader.isStartElement()) {
|
||||||
|
if (fullName == "variables.variable") {
|
||||||
|
QString variableName;
|
||||||
|
std::map<QString, QString> map;
|
||||||
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
||||||
|
auto attrNameString = attr.name().toString();
|
||||||
|
auto attrValueString = attr.value().toString();
|
||||||
|
if ("name" == attrNameString) {
|
||||||
|
variableName = attrValueString;
|
||||||
|
} else {
|
||||||
|
map[attrNameString] = attrValueString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!variableName.isEmpty()) {
|
||||||
|
(*variables)[variableName] = map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef DUST3D_VARIABLES_XML_H
|
||||||
|
#define DUST3D_VARIABLES_XML_H
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
void saveVariablesToXmlStream(const std::map<QString, std::map<QString, QString>> &variables, QXmlStreamWriter *writer);
|
||||||
|
void loadVariablesFromXmlStream(std::map<QString, std::map<QString, QString>> *variables, QXmlStreamReader &reader);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,463 @@
|
||||||
|
#
|
||||||
|
# QuickJS Javascript Engine
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017-2019 Fabrice Bellard
|
||||||
|
# Copyright (c) 2017-2019 Charlie Gordon
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
|
||||||
|
ifeq ($(shell uname -s),Darwin)
|
||||||
|
CONFIG_DARWIN=y
|
||||||
|
endif
|
||||||
|
# Windows cross compilation from Linux
|
||||||
|
#CONFIG_WIN32=y
|
||||||
|
# use link time optimization (smaller and faster executables but slower build)
|
||||||
|
CONFIG_LTO=y
|
||||||
|
# consider warnings as errors (for development)
|
||||||
|
#CONFIG_WERROR=y
|
||||||
|
|
||||||
|
ifndef CONFIG_WIN32
|
||||||
|
# force 32 bit build for some utilities
|
||||||
|
CONFIG_M32=y
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_DARWIN
|
||||||
|
# use clang instead of gcc
|
||||||
|
CONFIG_CLANG=y
|
||||||
|
CONFIG_DEFAULT_AR=y
|
||||||
|
endif
|
||||||
|
|
||||||
|
# installation directory
|
||||||
|
prefix=/usr/local
|
||||||
|
|
||||||
|
# use the gprof profiler
|
||||||
|
#CONFIG_PROFILE=y
|
||||||
|
# use address sanitizer
|
||||||
|
#CONFIG_ASAN=y
|
||||||
|
|
||||||
|
OBJDIR=.obj
|
||||||
|
|
||||||
|
ifdef CONFIG_WIN32
|
||||||
|
CROSS_PREFIX=i686-w64-mingw32-
|
||||||
|
EXE=.exe
|
||||||
|
else
|
||||||
|
CROSS_PREFIX=
|
||||||
|
EXE=
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_CLANG
|
||||||
|
CC=$(CROSS_PREFIX)clang
|
||||||
|
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
|
CFLAGS += -Wextra
|
||||||
|
CFLAGS += -Wno-sign-compare
|
||||||
|
CFLAGS += -Wno-missing-field-initializers
|
||||||
|
CFLAGS += -Wundef -Wuninitialized
|
||||||
|
CFLAGS += -Wunused -Wno-unused-parameter
|
||||||
|
CFLAGS += -Wwrite-strings
|
||||||
|
CFLAGS += -Wchar-subscripts -funsigned-char
|
||||||
|
CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
|
ifdef CONFIG_DEFAULT_AR
|
||||||
|
AR=$(CROSS_PREFIX)ar
|
||||||
|
else
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
AR=$(CROSS_PREFIX)llvm-ar
|
||||||
|
else
|
||||||
|
AR=$(CROSS_PREFIX)ar
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
CC=$(CROSS_PREFIX)gcc
|
||||||
|
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
|
CFLAGS += -Wno-array-bounds
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
AR=$(CROSS_PREFIX)gcc-ar
|
||||||
|
else
|
||||||
|
AR=$(CROSS_PREFIX)ar
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_WERROR
|
||||||
|
CFLAGS+=-Werror
|
||||||
|
endif
|
||||||
|
DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
|
||||||
|
CFLAGS+=$(DEFINES)
|
||||||
|
CFLAGS_DEBUG=$(CFLAGS) -O0
|
||||||
|
CFLAGS_SMALL=$(CFLAGS) -Os
|
||||||
|
CFLAGS_OPT=$(CFLAGS) -O2
|
||||||
|
CFLAGS_NOLTO:=$(CFLAGS_OPT)
|
||||||
|
LDFLAGS=-g
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
CFLAGS_SMALL+=-flto
|
||||||
|
CFLAGS_OPT+=-flto
|
||||||
|
LDFLAGS+=-flto
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_PROFILE
|
||||||
|
CFLAGS+=-p
|
||||||
|
LDFLAGS+=-p
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_ASAN
|
||||||
|
CFLAGS+=-fsanitize=address
|
||||||
|
LDFLAGS+=-fsanitize=address
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_WIN32
|
||||||
|
LDEXPORT=
|
||||||
|
else
|
||||||
|
LDEXPORT=-rdynamic
|
||||||
|
endif
|
||||||
|
|
||||||
|
PROGS=qjs$(EXE) qjsbn$(EXE) qjsc qjsbnc run-test262 run-test262-bn
|
||||||
|
ifndef CONFIG_WIN32
|
||||||
|
PROGS+=qjscalc
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_M32
|
||||||
|
PROGS+=qjs32 qjs32_s qjsbn32
|
||||||
|
endif
|
||||||
|
PROGS+=libquickjs.a libquickjs.bn.a
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
PROGS+=libquickjs.lto.a libquickjs.bn.lto.a
|
||||||
|
endif
|
||||||
|
# examples
|
||||||
|
ifdef CONFIG_ASAN
|
||||||
|
PROGS+=
|
||||||
|
else ifdef CONFIG_WIN32
|
||||||
|
PROGS+=
|
||||||
|
else
|
||||||
|
PROGS+=examples/hello examples/hello_module examples/c_module
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
|
||||||
|
|
||||||
|
QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o
|
||||||
|
|
||||||
|
QJSBN_LIB_OBJS=$(patsubst %.o, %.bn.o, $(QJS_LIB_OBJS)) $(OBJDIR)/libbf.bn.o
|
||||||
|
|
||||||
|
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
|
||||||
|
|
||||||
|
QJSBN_OBJS=$(OBJDIR)/qjs.bn.o $(OBJDIR)/repl-bn.bn.o $(OBJDIR)/qjscalc.bn.o $(QJSBN_LIB_OBJS)
|
||||||
|
|
||||||
|
LIBS=-lm
|
||||||
|
ifndef CONFIG_WIN32
|
||||||
|
LIBS+=-ldl
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir -p $(OBJDIR)
|
||||||
|
|
||||||
|
qjs$(EXE): $(QJS_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS))
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
qjsc: $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
qjsbnc: $(OBJDIR)/qjsc.bn.o $(QJSBN_LIB_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
QJSC_DEFINES:=-DCONFIG_CC=\"$(CC)\"
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
QJSC_DEFINES+=-DCONFIG_LTO
|
||||||
|
endif
|
||||||
|
QJSC_DEFINES+=-DCONFIG_PREFIX=\"$(prefix)\"
|
||||||
|
|
||||||
|
$(OBJDIR)/qjsc.o $(OBJDIR)/qjsc.bn.o: CFLAGS+=$(QJSC_DEFINES)
|
||||||
|
|
||||||
|
qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS))
|
||||||
|
$(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS))
|
||||||
|
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
@size $@
|
||||||
|
|
||||||
|
qjsbn$(EXE): $(QJSBN_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
qjsbn32: $(patsubst %.o, %.m32.o, $(QJSBN_OBJS))
|
||||||
|
$(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
qjscalc: qjsbn
|
||||||
|
ln -sf $< $@
|
||||||
|
|
||||||
|
qjsbn-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJSBN_OBJS))
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
LTOEXT=.lto
|
||||||
|
else
|
||||||
|
LTOEXT=
|
||||||
|
endif
|
||||||
|
|
||||||
|
libquickjs$(LTOEXT).a: $(QJS_LIB_OBJS)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
libquickjs.bn$(LTOEXT).a: $(QJSBN_LIB_OBJS)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
libquickjs.bn.a: $(patsubst %.o, %.nolto.o, $(QJSBN_LIB_OBJS))
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
endif # CONFIG_LTO
|
||||||
|
|
||||||
|
repl.c: qjsc repl.js
|
||||||
|
./qjsc -c -o $@ -m repl.js
|
||||||
|
|
||||||
|
repl-bn.c: qjsbnc repl.js
|
||||||
|
./qjsbnc -c -o $@ -m repl.js
|
||||||
|
|
||||||
|
qjscalc.c: qjsbnc qjscalc.js
|
||||||
|
./qjsbnc -c -o $@ qjscalc.js
|
||||||
|
|
||||||
|
ifneq ($(wildcard unicode/UnicodeData.txt),)
|
||||||
|
$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o $(OBJDIR)/libunicode.bn.o \
|
||||||
|
$(OBJDIR)/libunicode.nolto.o $(OBJDIR)/libunicode.bn.nolto.o: libunicode-table.h
|
||||||
|
|
||||||
|
libunicode-table.h: unicode_gen
|
||||||
|
./unicode_gen unicode $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread
|
||||||
|
|
||||||
|
run-test262-bn: $(OBJDIR)/run-test262.bn.o $(QJSBN_LIB_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread
|
||||||
|
|
||||||
|
run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread
|
||||||
|
|
||||||
|
run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
|
||||||
|
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread
|
||||||
|
|
||||||
|
run-test262-bn32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.bn.o $(QJSBN_LIB_OBJS))
|
||||||
|
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread
|
||||||
|
|
||||||
|
# object suffix order: bn, nolto, [m32|m32s]
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS_OPT) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.pic.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.bn.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.nolto.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS_NOLTO) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.bn.nolto.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS_NOLTO) -DCONFIG_BIGNUM -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.m32.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) -m32 $(CFLAGS_OPT) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.m32s.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) -m32 $(CFLAGS_SMALL) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.bn.m32.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) -m32 $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.debug.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS_DEBUG) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.bn.debug.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS_DEBUG) -DCONFIG_BIGNUM -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.check.o: %.c | $(OBJDIR)
|
||||||
|
$(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $<
|
||||||
|
|
||||||
|
regexp_test: libregexp.c libunicode.c cutils.c
|
||||||
|
$(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS)
|
||||||
|
|
||||||
|
jscompress: jscompress.c
|
||||||
|
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ jscompress.c
|
||||||
|
|
||||||
|
unicode_gen: unicode_gen.c cutils.c libunicode.c
|
||||||
|
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ unicode_gen.c cutils.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f repl.c repl-bn.c qjscalc.c out.c
|
||||||
|
rm -f *.a *.so *.o *.d *~ jscompress unicode_gen regexp_test $(PROGS)
|
||||||
|
rm -f hello.c hello_module.c c_module.c
|
||||||
|
rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug qjsbn-debug
|
||||||
|
rm -rf run-test262-debug run-test262-32 run-test262-bn32
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p "$(prefix)/bin"
|
||||||
|
install -m755 -s qjs qjsc qjsbn qjsbnc "$(prefix)/bin"
|
||||||
|
ln -sf qjsbn "$(prefix)/bin/qjscalc"
|
||||||
|
mkdir -p "$(prefix)/lib/quickjs"
|
||||||
|
install -m755 libquickjs.a libquickjs.bn.a "$(prefix)/lib/quickjs"
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
install -m755 libquickjs.lto.a libquickjs.bn.lto.a "$(prefix)/lib/quickjs"
|
||||||
|
endif
|
||||||
|
mkdir -p "$(prefix)/include/quickjs"
|
||||||
|
install -m755 quickjs.h quickjs-libc.h "$(prefix)/include/quickjs"
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# examples
|
||||||
|
|
||||||
|
# example of static JS compilation
|
||||||
|
HELLO_SRCS=examples/hello.js
|
||||||
|
HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
|
||||||
|
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy
|
||||||
|
|
||||||
|
hello.c: qjsc $(HELLO_SRCS)
|
||||||
|
./qjsc -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
|
||||||
|
|
||||||
|
ifdef CONFIG_M32
|
||||||
|
examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
|
||||||
|
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
else
|
||||||
|
examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# example of static JS compilation with modules
|
||||||
|
HELLO_MODULE_SRCS=examples/hello_module.js
|
||||||
|
HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
|
||||||
|
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy -m
|
||||||
|
examples/hello_module: qjsc libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS)
|
||||||
|
./qjsc $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS)
|
||||||
|
|
||||||
|
# use of an external C module (static compilation)
|
||||||
|
|
||||||
|
c_module.c: qjsc examples/c_module.js
|
||||||
|
./qjsc -e -M examples/fib.so,fib -m -o $@ examples/c_module.js
|
||||||
|
|
||||||
|
examples/c_module: $(OBJDIR)/c_module.o $(OBJDIR)/fib.o libquickjs$(LTOEXT).a
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
$(OBJDIR)/fib.o: examples/fib.c
|
||||||
|
$(CC) $(CFLAGS_OPT) -c -o $@ $<
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# documentation
|
||||||
|
|
||||||
|
DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html
|
||||||
|
|
||||||
|
build_doc: $(DOCS)
|
||||||
|
|
||||||
|
clean_doc:
|
||||||
|
rm -f $(DOCS)
|
||||||
|
|
||||||
|
doc/%.pdf: doc/%.texi
|
||||||
|
texi2pdf --clean -o $@ -q $<
|
||||||
|
|
||||||
|
doc/%.html: doc/%.texi
|
||||||
|
makeinfo --html --no-headers --no-split --number-sections -o $@ $<
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# tests
|
||||||
|
|
||||||
|
ifndef CONFIG_DARWIN
|
||||||
|
test: bjson.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
test: qjs qjsbn
|
||||||
|
./qjs tests/test_closure.js
|
||||||
|
./qjs tests/test_op.js
|
||||||
|
./qjs tests/test_builtin.js
|
||||||
|
./qjs tests/test_loop.js
|
||||||
|
./qjs -m tests/test_std.js
|
||||||
|
ifndef CONFIG_DARWIN
|
||||||
|
./qjs -m tests/test_bjson.js
|
||||||
|
endif
|
||||||
|
./qjsbn tests/test_closure.js
|
||||||
|
./qjsbn tests/test_op.js
|
||||||
|
./qjsbn tests/test_builtin.js
|
||||||
|
./qjsbn tests/test_loop.js
|
||||||
|
./qjsbn -m tests/test_std.js
|
||||||
|
./qjsbn --qjscalc tests/test_bignum.js
|
||||||
|
|
||||||
|
test-32: qjs32 qjsbn32
|
||||||
|
./qjs32 tests/test_closure.js
|
||||||
|
./qjs32 tests/test_op.js
|
||||||
|
./qjs32 tests/test_builtin.js
|
||||||
|
./qjs32 tests/test_loop.js
|
||||||
|
./qjs32 -m tests/test_std.js
|
||||||
|
./qjsbn32 tests/test_closure.js
|
||||||
|
./qjsbn32 tests/test_op.js
|
||||||
|
./qjsbn32 tests/test_builtin.js
|
||||||
|
./qjsbn32 tests/test_loop.js
|
||||||
|
./qjsbn32 -m tests/test_std.js
|
||||||
|
./qjsbn32 --qjscalc tests/test_bignum.js
|
||||||
|
|
||||||
|
stats: qjs qjs32
|
||||||
|
./qjs -qd
|
||||||
|
./qjs32 -qd
|
||||||
|
|
||||||
|
microbench: qjs
|
||||||
|
./qjs tests/microbench.js
|
||||||
|
|
||||||
|
microbench-32: qjs32
|
||||||
|
./qjs32 tests/microbench.js
|
||||||
|
|
||||||
|
# ES5 tests (obsolete)
|
||||||
|
test2o: run-test262
|
||||||
|
time ./run-test262 -m -c test262o.conf
|
||||||
|
|
||||||
|
test2o-32: run-test262-32
|
||||||
|
time ./run-test262-32 -m -c test262o.conf
|
||||||
|
|
||||||
|
test2o-update: run-test262
|
||||||
|
./run-test262 -u -c test262o.conf
|
||||||
|
|
||||||
|
# Test262 tests
|
||||||
|
test2-default: run-test262
|
||||||
|
time ./run-test262 -m -c test262.conf
|
||||||
|
|
||||||
|
test2: run-test262
|
||||||
|
time ./run-test262 -m -c test262.conf -a
|
||||||
|
|
||||||
|
test2-32: run-test262-32
|
||||||
|
time ./run-test262-32 -m -c test262.conf -a
|
||||||
|
|
||||||
|
test2-update: run-test262
|
||||||
|
./run-test262 -u -c test262.conf -a
|
||||||
|
|
||||||
|
test2-check: run-test262
|
||||||
|
time ./run-test262 -m -c test262.conf -E -a
|
||||||
|
|
||||||
|
# Test262 + BigInt tests
|
||||||
|
test2bn-default: run-test262-bn
|
||||||
|
time ./run-test262-bn -m -c test262bn.conf
|
||||||
|
|
||||||
|
test2bn: run-test262-bn
|
||||||
|
time ./run-test262-bn -m -c test262bn.conf -a
|
||||||
|
|
||||||
|
test2bn-32: run-test262-bn32
|
||||||
|
time ./run-test262-bn32 -m -c test262bn.conf -a
|
||||||
|
|
||||||
|
testall: all test microbench test2o test2 test2bn
|
||||||
|
|
||||||
|
testall-32: all test-32 microbench-32 test2o-32 test2-32 test2bn-32
|
||||||
|
|
||||||
|
testall-complete: testall testall-32
|
||||||
|
|
||||||
|
bench-v8: qjs qjs32
|
||||||
|
make -C tests/bench-v8
|
||||||
|
./qjs -d tests/bench-v8/combined.js
|
||||||
|
|
||||||
|
bjson.so: $(OBJDIR)/bjson.pic.o
|
||||||
|
$(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
-include $(wildcard $(OBJDIR)/*.d)
|
|
@ -0,0 +1,83 @@
|
||||||
|
- 64-bit atoms in 64-bit mode?
|
||||||
|
- rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ?
|
||||||
|
- unify coding style and naming conventions
|
||||||
|
- use names from the ECMA spec in library implementation
|
||||||
|
- modules: if no ".", use a well known module loading path ?
|
||||||
|
- use JSHoistedDef only for global variables (JSHoistedDef.var_name != JS_ATOM_NULL)
|
||||||
|
- add index in JSVarDef and is_arg flag to merge args and vars in JSFunctionDef
|
||||||
|
- replace most JSVarDef flags with var_type enumeration
|
||||||
|
- use byte code emitters with typed arguments (for clarity)
|
||||||
|
- use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing
|
||||||
|
and use the same wrappers in all phases
|
||||||
|
- use more generic method for line numbers in resolve_variables and resolve_labels
|
||||||
|
- bignum:
|
||||||
|
- fix div/pow div by zero exception in doc & code in bigint mode
|
||||||
|
- fix Atomics support
|
||||||
|
|
||||||
|
Memory:
|
||||||
|
- test border cases for max number of atoms, object properties, string length
|
||||||
|
- add emergency malloc mode for out of memory exceptions.
|
||||||
|
- test all DynBuf memory errors
|
||||||
|
- test all js_realloc memory errors
|
||||||
|
- bignum: handle memory errors
|
||||||
|
- use memory pools for objects, etc?
|
||||||
|
- improve JS_ComputeMemoryUsage() with more info
|
||||||
|
|
||||||
|
Optimizations:
|
||||||
|
- use auto-init properties for more global objects
|
||||||
|
- reuse stack slots for disjoint scopes, if strip
|
||||||
|
- optimize `for of` iterator for built-in array objects
|
||||||
|
- add heuristic to avoid some cycles in closures
|
||||||
|
- small String (0-2 charcodes) with immediate storage
|
||||||
|
- perform static string concatenation at compile time
|
||||||
|
- optimize string concatenation with ropes or miniropes?
|
||||||
|
- add implicit numeric strings for Uint32 numbers?
|
||||||
|
- optimize `s += a + b`, `s += a.b` and similar simple expressions
|
||||||
|
- ensure string canonical representation and optimise comparisons and hashes?
|
||||||
|
- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references
|
||||||
|
- optimize function storage with length and name accessors?
|
||||||
|
- property access optimization on the global object, functions,
|
||||||
|
prototypes and special non extensible objects.
|
||||||
|
- create object literals with the correct length by backpatching length argument
|
||||||
|
- remove redundant set_loc_uninitialized/check_uninitialized opcodes
|
||||||
|
- peephole optim: push_atom_value, to_propkey -> push_atom_value
|
||||||
|
- peephole optim: put_loc x, get_loc_check x -> set_loc x
|
||||||
|
- comparative performance benchmark
|
||||||
|
- use variable name when throwing uninitialized exception if available
|
||||||
|
- convert slow array to fast array when all properties != length are numeric
|
||||||
|
- optimize destructuring assignments for global and local variables
|
||||||
|
- implement some form of tail-call-optimization
|
||||||
|
- debugger keyword support
|
||||||
|
- optmize OP_apply
|
||||||
|
- optimize f(...b)
|
||||||
|
|
||||||
|
Extensions:
|
||||||
|
- support more features in [features] section
|
||||||
|
- add TC39 stage 3 proposals: String.prototype.matchAll, Symbol.matchAll
|
||||||
|
- fix preprocessor bug if nested #ifdef in jscompress.c
|
||||||
|
- add built-in preprocessor in compiler, get rid of jscompress
|
||||||
|
handle #if, #ifdef, #line, limited support for #define
|
||||||
|
- limited support for web assembly
|
||||||
|
- get rid of __loadScript, use more common name
|
||||||
|
- BSD sockets
|
||||||
|
- Process or thread control
|
||||||
|
- use custom printf to avoid C library compatibility issues
|
||||||
|
- use custom timezone support to avoid C library compatibility issues
|
||||||
|
|
||||||
|
REPL:
|
||||||
|
- strip internal functions from stack trace
|
||||||
|
- readline: support MS Windows terminal
|
||||||
|
- readline: handle dynamic terminal resizing
|
||||||
|
- multiline editing
|
||||||
|
- debugger
|
||||||
|
- runtime object and function inspectors
|
||||||
|
- interactive object browser
|
||||||
|
- use more generic approach to display evaluation results
|
||||||
|
- improve directive handling: dispatch, colorize, completion...
|
||||||
|
- save history
|
||||||
|
- close all predefined methods in repl.js and jscalc.js
|
||||||
|
|
||||||
|
Test262o: 0/11266 errors, 459 excluded
|
||||||
|
Test262: 0/55855 errors, 504 excluded, 1559 skipped
|
||||||
|
Test262bn: 0/57176 errors, 724 excluded, 675 skipped
|
||||||
|
test262 commit: 94b1e80ab3440413df916cd56d29c5a2fa2ac451
|
|
@ -0,0 +1 @@
|
||||||
|
2019-07-09
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* QuickJS: binary JSON module (test only)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2019 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "quickjs-libc.h"
|
||||||
|
#include "cutils.h"
|
||||||
|
|
||||||
|
static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
uint64_t pos, len;
|
||||||
|
JSValue obj;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (JS_ToIndex(ctx, &pos, argv[1]))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (JS_ToIndex(ctx, &len, argv[2]))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
buf = JS_GetArrayBuffer(ctx, &size, argv[0]);
|
||||||
|
if (!buf)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (pos + len > size)
|
||||||
|
return JS_ThrowRangeError(ctx, "array buffer overflow");
|
||||||
|
obj = JS_ReadObject(ctx, buf + pos, len, 0);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint8_t *buf;
|
||||||
|
JSValue array;
|
||||||
|
|
||||||
|
buf = JS_WriteObject(ctx, &len, argv[0], 0);
|
||||||
|
if (!buf)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
array = JS_NewArrayBufferCopy(ctx, buf, len);
|
||||||
|
js_free(ctx, buf);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_bjson_funcs[] = {
|
||||||
|
JS_CFUNC_DEF("read", 3, js_bjson_read ),
|
||||||
|
JS_CFUNC_DEF("write", 1, js_bjson_write ),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int js_bjson_init(JSContext *ctx, JSModuleDef *m)
|
||||||
|
{
|
||||||
|
return JS_SetModuleExportList(ctx, m, js_bjson_funcs,
|
||||||
|
countof(js_bjson_funcs));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JS_SHARED_LIBRARY
|
||||||
|
#define JS_INIT_MODULE js_init_module
|
||||||
|
#else
|
||||||
|
#define JS_INIT_MODULE js_init_module_bjson
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
|
||||||
|
{
|
||||||
|
JSModuleDef *m;
|
||||||
|
m = JS_NewCModule(ctx, module_name, js_bjson_init);
|
||||||
|
if (!m)
|
||||||
|
return NULL;
|
||||||
|
JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs));
|
||||||
|
return m;
|
||||||
|
}
|
|
@ -0,0 +1,642 @@
|
||||||
|
/*
|
||||||
|
* C utilities
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Fabrice Bellard
|
||||||
|
* Copyright (c) 2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
|
||||||
|
void pstrcpy(char *buf, int buf_size, const char *str)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
char *q = buf;
|
||||||
|
|
||||||
|
if (buf_size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
c = *str++;
|
||||||
|
if (c == 0 || q >= buf + buf_size - 1)
|
||||||
|
break;
|
||||||
|
*q++ = c;
|
||||||
|
}
|
||||||
|
*q = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strcat and truncate. */
|
||||||
|
char *pstrcat(char *buf, int buf_size, const char *s)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
len = strlen(buf);
|
||||||
|
if (len < buf_size)
|
||||||
|
pstrcpy(buf + len, buf_size - len, s);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strstart(const char *str, const char *val, const char **ptr)
|
||||||
|
{
|
||||||
|
const char *p, *q;
|
||||||
|
p = str;
|
||||||
|
q = val;
|
||||||
|
while (*q != '\0') {
|
||||||
|
if (*p != *q)
|
||||||
|
return 0;
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
if (ptr)
|
||||||
|
*ptr = p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int has_suffix(const char *str, const char *suffix)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
size_t slen = strlen(suffix);
|
||||||
|
return (len >= slen && !memcmp(str + len - slen, suffix, slen));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dynamic buffer package */
|
||||||
|
|
||||||
|
static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func)
|
||||||
|
{
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
if (!realloc_func)
|
||||||
|
realloc_func = dbuf_default_realloc;
|
||||||
|
s->opaque = opaque;
|
||||||
|
s->realloc_func = realloc_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_init(DynBuf *s)
|
||||||
|
{
|
||||||
|
dbuf_init2(s, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return < 0 if error */
|
||||||
|
int dbuf_realloc(DynBuf *s, size_t new_size)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
uint8_t *new_buf;
|
||||||
|
if (new_size > s->allocated_size) {
|
||||||
|
if (s->error)
|
||||||
|
return -1;
|
||||||
|
size = s->allocated_size * 3 / 2;
|
||||||
|
if (size > new_size)
|
||||||
|
new_size = size;
|
||||||
|
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
|
||||||
|
if (!new_buf) {
|
||||||
|
s->error = TRUE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->buf = new_buf;
|
||||||
|
s->allocated_size = new_size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
size_t end;
|
||||||
|
end = offset + len;
|
||||||
|
if (dbuf_realloc(s, end))
|
||||||
|
return -1;
|
||||||
|
memcpy(s->buf + offset, data, len);
|
||||||
|
if (end > s->size)
|
||||||
|
s->size = end;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
if (unlikely((s->size + len) > s->allocated_size)) {
|
||||||
|
if (dbuf_realloc(s, s->size + len))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(s->buf + s->size, data, len);
|
||||||
|
s->size += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
|
||||||
|
{
|
||||||
|
if (unlikely((s->size + len) > s->allocated_size)) {
|
||||||
|
if (dbuf_realloc(s, s->size + len))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(s->buf + s->size, s->buf + offset, len);
|
||||||
|
s->size += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_putc(DynBuf *s, uint8_t c)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_putstr(DynBuf *s, const char *str)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (const uint8_t *)str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
int dbuf_printf(DynBuf *s,
|
||||||
|
const char *fmt, ...)
|
||||||
|
#else
|
||||||
|
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
|
||||||
|
const char *fmt, ...)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buf[128];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (len < sizeof(buf)) {
|
||||||
|
/* fast case */
|
||||||
|
return dbuf_put(s, (uint8_t *)buf, len);
|
||||||
|
} else {
|
||||||
|
if (dbuf_realloc(s, s->size + len + 1))
|
||||||
|
return -1;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
|
||||||
|
fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
s->size += len;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_free(DynBuf *s)
|
||||||
|
{
|
||||||
|
/* we test s->buf as a fail safe to avoid crashing if dbuf_free()
|
||||||
|
is called twice */
|
||||||
|
if (s->buf) {
|
||||||
|
s->realloc_func(s->opaque, s->buf, 0);
|
||||||
|
}
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
|
||||||
|
are output. */
|
||||||
|
int unicode_to_utf8(uint8_t *buf, unsigned int c)
|
||||||
|
{
|
||||||
|
uint8_t *q = buf;
|
||||||
|
|
||||||
|
if (c < 0x80) {
|
||||||
|
*q++ = c;
|
||||||
|
} else {
|
||||||
|
if (c < 0x800) {
|
||||||
|
*q++ = (c >> 6) | 0xc0;
|
||||||
|
} else {
|
||||||
|
if (c < 0x10000) {
|
||||||
|
*q++ = (c >> 12) | 0xe0;
|
||||||
|
} else {
|
||||||
|
if (c < 0x00200000) {
|
||||||
|
*q++ = (c >> 18) | 0xf0;
|
||||||
|
} else {
|
||||||
|
if (c < 0x04000000) {
|
||||||
|
*q++ = (c >> 24) | 0xf8;
|
||||||
|
} else if (c < 0x80000000) {
|
||||||
|
*q++ = (c >> 30) | 0xfc;
|
||||||
|
*q++ = ((c >> 24) & 0x3f) | 0x80;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*q++ = ((c >> 18) & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
*q++ = ((c >> 12) & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
*q++ = ((c >> 6) & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
*q++ = (c & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
return q - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned int utf8_min_code[5] = {
|
||||||
|
0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char utf8_first_code_mask[5] = {
|
||||||
|
0x1f, 0xf, 0x7, 0x3, 0x1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* return -1 if error. *pp is not updated in this case. max_len must
|
||||||
|
be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */
|
||||||
|
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
|
||||||
|
{
|
||||||
|
int l, c, b, i;
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
if (c < 0x80) {
|
||||||
|
*pp = p;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
if (c >= 0xc0 && c <= 0xdf) {
|
||||||
|
l = 1;
|
||||||
|
} else if (c >= 0xe0 && c <= 0xef) {
|
||||||
|
l = 2;
|
||||||
|
} else if (c >= 0xf0 && c <= 0xf7) {
|
||||||
|
l = 3;
|
||||||
|
} else if (c >= 0xf8 && c <= 0xfb) {
|
||||||
|
l = 4;
|
||||||
|
} else if (c >= 0xfc && c <= 0xfd) {
|
||||||
|
l = 5;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
switch(c) {
|
||||||
|
case 0xc0 ... 0xdf:
|
||||||
|
l = 1;
|
||||||
|
break;
|
||||||
|
case 0xe0 ... 0xef:
|
||||||
|
l = 2;
|
||||||
|
break;
|
||||||
|
case 0xf0 ... 0xf7:
|
||||||
|
l = 3;
|
||||||
|
break;
|
||||||
|
case 0xf8 ... 0xfb:
|
||||||
|
l = 4;
|
||||||
|
break;
|
||||||
|
case 0xfc ... 0xfd:
|
||||||
|
l = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* check that we have enough characters */
|
||||||
|
if (l > (max_len - 1))
|
||||||
|
return -1;
|
||||||
|
c &= utf8_first_code_mask[l - 1];
|
||||||
|
for(i = 0; i < l; i++) {
|
||||||
|
b = *p++;
|
||||||
|
if (b < 0x80 || b >= 0xc0)
|
||||||
|
return -1;
|
||||||
|
c = (c << 6) | (b & 0x3f);
|
||||||
|
}
|
||||||
|
if (c < utf8_min_code[l - 1])
|
||||||
|
return -1;
|
||||||
|
*pp = p;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#if defined(EMSCRIPTEN) || defined(__ANDROID__)
|
||||||
|
|
||||||
|
static void *rqsort_arg;
|
||||||
|
static int (*rqsort_cmp)(const void *, const void *, void *);
|
||||||
|
|
||||||
|
static int rqsort_cmp2(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
return rqsort_cmp(p1, p2, rqsort_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not reentrant, but not needed with emscripten */
|
||||||
|
void rqsort(void *base, size_t nmemb, size_t size,
|
||||||
|
int (*cmp)(const void *, const void *, void *),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
rqsort_arg = arg;
|
||||||
|
rqsort_cmp = cmp;
|
||||||
|
qsort(base, nmemb, size, rqsort_cmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef void (*exchange_f)(void *a, void *b, size_t size);
|
||||||
|
typedef int (*cmp_f)(const void *, const void *, void *opaque);
|
||||||
|
|
||||||
|
static void exchange_bytes(void *a, void *b, size_t size) {
|
||||||
|
uint8_t *ap = (uint8_t *)a;
|
||||||
|
uint8_t *bp = (uint8_t *)b;
|
||||||
|
|
||||||
|
while (size-- != 0) {
|
||||||
|
uint8_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_byte(void *a, void *b, size_t size) {
|
||||||
|
uint8_t *ap = (uint8_t *)a;
|
||||||
|
uint8_t *bp = (uint8_t *)b;
|
||||||
|
uint8_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int16s(void *a, void *b, size_t size) {
|
||||||
|
uint16_t *ap = (uint16_t *)a;
|
||||||
|
uint16_t *bp = (uint16_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint16_t); size-- != 0;) {
|
||||||
|
uint16_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int16(void *a, void *b, size_t size) {
|
||||||
|
uint16_t *ap = (uint16_t *)a;
|
||||||
|
uint16_t *bp = (uint16_t *)b;
|
||||||
|
uint16_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int32s(void *a, void *b, size_t size) {
|
||||||
|
uint32_t *ap = (uint32_t *)a;
|
||||||
|
uint32_t *bp = (uint32_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint32_t); size-- != 0;) {
|
||||||
|
uint32_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int32(void *a, void *b, size_t size) {
|
||||||
|
uint32_t *ap = (uint32_t *)a;
|
||||||
|
uint32_t *bp = (uint32_t *)b;
|
||||||
|
uint32_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int64s(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint64_t); size-- != 0;) {
|
||||||
|
uint64_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int64(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
uint64_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int128s(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) {
|
||||||
|
uint64_t t = ap[0];
|
||||||
|
uint64_t u = ap[1];
|
||||||
|
ap[0] = bp[0];
|
||||||
|
ap[1] = bp[1];
|
||||||
|
bp[0] = t;
|
||||||
|
bp[1] = u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int128(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
uint64_t t = ap[0];
|
||||||
|
uint64_t u = ap[1];
|
||||||
|
ap[0] = bp[0];
|
||||||
|
ap[1] = bp[1];
|
||||||
|
bp[0] = t;
|
||||||
|
bp[1] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline exchange_f exchange_func(const void *base, size_t size) {
|
||||||
|
switch (((uintptr_t)base | (uintptr_t)size) & 15) {
|
||||||
|
case 0:
|
||||||
|
if (size == sizeof(uint64_t) * 2)
|
||||||
|
return exchange_one_int128;
|
||||||
|
else
|
||||||
|
return exchange_int128s;
|
||||||
|
case 8:
|
||||||
|
if (size == sizeof(uint64_t))
|
||||||
|
return exchange_one_int64;
|
||||||
|
else
|
||||||
|
return exchange_int64s;
|
||||||
|
case 4:
|
||||||
|
case 12:
|
||||||
|
if (size == sizeof(uint32_t))
|
||||||
|
return exchange_one_int32;
|
||||||
|
else
|
||||||
|
return exchange_int32s;
|
||||||
|
case 2:
|
||||||
|
case 6:
|
||||||
|
case 10:
|
||||||
|
case 14:
|
||||||
|
if (size == sizeof(uint16_t))
|
||||||
|
return exchange_one_int16;
|
||||||
|
else
|
||||||
|
return exchange_int16s;
|
||||||
|
default:
|
||||||
|
if (size == 1)
|
||||||
|
return exchange_one_byte;
|
||||||
|
else
|
||||||
|
return exchange_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
|
||||||
|
{
|
||||||
|
uint8_t *basep = (uint8_t *)base;
|
||||||
|
size_t i, n, c, r;
|
||||||
|
exchange_f swap = exchange_func(base, size);
|
||||||
|
|
||||||
|
if (nmemb > 1) {
|
||||||
|
i = (nmemb / 2) * size;
|
||||||
|
n = nmemb * size;
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
i -= size;
|
||||||
|
for (r = i; (c = r * 2 + size) < n; r = c) {
|
||||||
|
if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0)
|
||||||
|
c += size;
|
||||||
|
if (cmp(basep + r, basep + c, opaque) > 0)
|
||||||
|
break;
|
||||||
|
swap(basep + r, basep + c, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = n - size; i > 0; i -= size) {
|
||||||
|
swap(basep, basep + i, size);
|
||||||
|
|
||||||
|
for (r = 0; (c = r * 2 + size) < i; r = c) {
|
||||||
|
if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0)
|
||||||
|
c += size;
|
||||||
|
if (cmp(basep + r, basep + c, opaque) > 0)
|
||||||
|
break;
|
||||||
|
swap(basep + r, basep + c, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
|
||||||
|
{
|
||||||
|
return cmp(a, b, opaque) < 0 ?
|
||||||
|
(cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) :
|
||||||
|
(cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pointer based version with local stack and insertion sort threshhold */
|
||||||
|
void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
|
||||||
|
{
|
||||||
|
struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
|
||||||
|
uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
|
||||||
|
size_t m4, i, lt, gt, span, span2;
|
||||||
|
int c, depth;
|
||||||
|
exchange_f swap = exchange_func(base, size);
|
||||||
|
exchange_f swap_block = exchange_func(base, size | 128);
|
||||||
|
|
||||||
|
if (nmemb < 2 || size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sp->base = (uint8_t *)base;
|
||||||
|
sp->count = nmemb;
|
||||||
|
sp->depth = 0;
|
||||||
|
sp++;
|
||||||
|
|
||||||
|
while (sp > stack) {
|
||||||
|
sp--;
|
||||||
|
ptr = sp->base;
|
||||||
|
nmemb = sp->count;
|
||||||
|
depth = sp->depth;
|
||||||
|
|
||||||
|
while (nmemb > 6) {
|
||||||
|
if (++depth > 50) {
|
||||||
|
/* depth check to ensure worst case logarithmic time */
|
||||||
|
heapsortx(ptr, nmemb, size, cmp, opaque);
|
||||||
|
nmemb = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* select median of 3 from 1/4, 1/2, 3/4 positions */
|
||||||
|
/* should use median of 5 or 9? */
|
||||||
|
m4 = (nmemb >> 2) * size;
|
||||||
|
m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque);
|
||||||
|
swap(ptr, m, size); /* move the pivot to the start or the array */
|
||||||
|
i = lt = 1;
|
||||||
|
pi = plt = ptr + size;
|
||||||
|
gt = nmemb;
|
||||||
|
pj = pgt = top = ptr + nmemb * size;
|
||||||
|
for (;;) {
|
||||||
|
while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) {
|
||||||
|
if (c == 0) {
|
||||||
|
swap(plt, pi, size);
|
||||||
|
lt++;
|
||||||
|
plt += size;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
pi += size;
|
||||||
|
}
|
||||||
|
while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) {
|
||||||
|
if (c == 0) {
|
||||||
|
gt--;
|
||||||
|
pgt -= size;
|
||||||
|
swap(pgt, pj, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pi >= pj)
|
||||||
|
break;
|
||||||
|
swap(pi, pj, size);
|
||||||
|
i++;
|
||||||
|
pi += size;
|
||||||
|
}
|
||||||
|
/* array has 4 parts:
|
||||||
|
* from 0 to lt excluded: elements identical to pivot
|
||||||
|
* from lt to pi excluded: elements smaller than pivot
|
||||||
|
* from pi to gt excluded: elements greater than pivot
|
||||||
|
* from gt to n excluded: elements identical to pivot
|
||||||
|
*/
|
||||||
|
/* move elements identical to pivot in the middle of the array: */
|
||||||
|
/* swap values in ranges [0..lt[ and [i-lt..i[
|
||||||
|
swapping the smallest span between lt and i-lt is sufficient
|
||||||
|
*/
|
||||||
|
span = plt - ptr;
|
||||||
|
span2 = pi - plt;
|
||||||
|
plt = pi - span;
|
||||||
|
lt = i - lt;
|
||||||
|
if (span > span2)
|
||||||
|
span = span2;
|
||||||
|
swap_block(ptr, pi - span, span);
|
||||||
|
/* swap values in ranges [gt..top[ and [i..top-(top-gt)[
|
||||||
|
swapping the smallest span between top-gt and gt-i is sufficient
|
||||||
|
*/
|
||||||
|
span = top - pgt;
|
||||||
|
span2 = pgt - pi;
|
||||||
|
pgt = top - span2;
|
||||||
|
gt = nmemb - (gt - i);
|
||||||
|
if (span > span2)
|
||||||
|
span = span2;
|
||||||
|
swap_block(pi, top - span, span);
|
||||||
|
|
||||||
|
/* now array has 3 parts:
|
||||||
|
* from 0 to lt excluded: elements smaller than pivot
|
||||||
|
* from lt to gt excluded: elements identical to pivot
|
||||||
|
* from gt to n excluded: elements greater than pivot
|
||||||
|
*/
|
||||||
|
/* stack the larger segment and keep processing the smaller one
|
||||||
|
to minimize stack use for pathological distributions */
|
||||||
|
if (lt > nmemb - gt) {
|
||||||
|
sp->base = ptr;
|
||||||
|
sp->count = lt;
|
||||||
|
sp->depth = depth;
|
||||||
|
sp++;
|
||||||
|
ptr = pgt;
|
||||||
|
nmemb -= gt;
|
||||||
|
} else {
|
||||||
|
sp->base = pgt;
|
||||||
|
sp->count = nmemb - gt;
|
||||||
|
sp->depth = depth;
|
||||||
|
sp++;
|
||||||
|
nmemb = lt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Use insertion sort for small fragments */
|
||||||
|
for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) {
|
||||||
|
for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size)
|
||||||
|
swap(pj, pj - size, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,383 @@
|
||||||
|
/*
|
||||||
|
* C utilities
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Fabrice Bellard
|
||||||
|
* Copyright (c) 2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef CUTILS_H
|
||||||
|
#define CUTILS_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
/* set if CPU is big endian */
|
||||||
|
#undef WORDS_BIGENDIAN
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define likely(x) (x)
|
||||||
|
#define unlikely(x) (x)
|
||||||
|
#else
|
||||||
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
#endif
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define force_inline inline
|
||||||
|
#else
|
||||||
|
#define force_inline inline __attribute__((always_inline))
|
||||||
|
#endif
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define no_inline
|
||||||
|
#else
|
||||||
|
#define no_inline __attribute__((noinline))
|
||||||
|
#endif
|
||||||
|
//#if defined(_MSC_VER)
|
||||||
|
//#define _Atomic(type) type
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <BaseTsd.h>
|
||||||
|
typedef SSIZE_T ssize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define xglue(x, y) x ## y
|
||||||
|
#define glue(x, y) xglue(x, y)
|
||||||
|
#define stringify(s) tostring(s)
|
||||||
|
#define tostring(s) #s
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
|
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||||
|
#endif
|
||||||
|
#ifndef countof
|
||||||
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int BOOL;
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
enum {
|
||||||
|
FALSE = 0,
|
||||||
|
TRUE = 1,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void pstrcpy(char *buf, int buf_size, const char *str);
|
||||||
|
char *pstrcat(char *buf, int buf_size, const char *s);
|
||||||
|
int strstart(const char *str, const char *val, const char **ptr);
|
||||||
|
int has_suffix(const char *str, const char *suffix);
|
||||||
|
|
||||||
|
static inline int max_int(int a, int b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int min_int(int a, int b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t max_uint32(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t min_uint32(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t max_int64(int64_t a, int64_t b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t min_int64(int64_t a, int64_t b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int clz32(unsigned int a)
|
||||||
|
{
|
||||||
|
return __builtin_clz(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int clz64(uint64_t a)
|
||||||
|
{
|
||||||
|
return __builtin_clzll(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int ctz32(unsigned int a)
|
||||||
|
{
|
||||||
|
return __builtin_ctz(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int ctz64(uint64_t a)
|
||||||
|
{
|
||||||
|
return __builtin_ctzll(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct packed_u64 {
|
||||||
|
uint64_t v;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
#else
|
||||||
|
struct __attribute__((packed)) packed_u64 {
|
||||||
|
uint64_t v;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct packed_u32 {
|
||||||
|
uint32_t v;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
#else
|
||||||
|
struct __attribute__((packed)) packed_u32 {
|
||||||
|
uint32_t v;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct packed_u16 {
|
||||||
|
uint16_t v;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
#else
|
||||||
|
struct __attribute__((packed)) packed_u16 {
|
||||||
|
uint16_t v;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline uint64_t get_u64(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return ((const struct packed_u64 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t get_i64(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int64_t)((const struct packed_u64 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u64(uint8_t *tab, uint64_t val)
|
||||||
|
{
|
||||||
|
((struct packed_u64 *)tab)->v = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_u32(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return ((const struct packed_u32 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t get_i32(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int32_t)((const struct packed_u32 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u32(uint8_t *tab, uint32_t val)
|
||||||
|
{
|
||||||
|
((struct packed_u32 *)tab)->v = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_u16(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return ((const struct packed_u16 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t get_i16(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int16_t)((const struct packed_u16 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u16(uint8_t *tab, uint16_t val)
|
||||||
|
{
|
||||||
|
((struct packed_u16 *)tab)->v = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_u8(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return *tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t get_i8(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int8_t)*tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u8(uint8_t *tab, uint8_t val)
|
||||||
|
{
|
||||||
|
*tab = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t bswap16(uint16_t x)
|
||||||
|
{
|
||||||
|
return (x >> 8) | (x << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t bswap32(uint32_t v)
|
||||||
|
{
|
||||||
|
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
|
||||||
|
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t bswap64(uint64_t v)
|
||||||
|
{
|
||||||
|
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX: should take an extra argument to pass slack information to the caller */
|
||||||
|
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
|
||||||
|
|
||||||
|
typedef struct DynBuf {
|
||||||
|
uint8_t *buf;
|
||||||
|
size_t size;
|
||||||
|
size_t allocated_size;
|
||||||
|
BOOL error; /* true if a memory allocation error occurred */
|
||||||
|
DynBufReallocFunc *realloc_func;
|
||||||
|
void *opaque; /* for realloc_func */
|
||||||
|
} DynBuf;
|
||||||
|
|
||||||
|
void dbuf_init(DynBuf *s);
|
||||||
|
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
|
||||||
|
int dbuf_realloc(DynBuf *s, size_t new_size);
|
||||||
|
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
|
||||||
|
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
|
||||||
|
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
|
||||||
|
int dbuf_putc(DynBuf *s, uint8_t c);
|
||||||
|
int dbuf_putstr(DynBuf *s, const char *str);
|
||||||
|
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (uint8_t *)&val, 2);
|
||||||
|
}
|
||||||
|
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (uint8_t *)&val, 4);
|
||||||
|
}
|
||||||
|
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (uint8_t *)&val, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
int dbuf_printf(DynBuf *s, const char *fmt, ...);
|
||||||
|
#else
|
||||||
|
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
|
||||||
|
const char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void dbuf_free(DynBuf *s);
|
||||||
|
static inline BOOL dbuf_error(DynBuf *s) {
|
||||||
|
return s->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UTF8_CHAR_LEN_MAX 6
|
||||||
|
|
||||||
|
int unicode_to_utf8(uint8_t *buf, unsigned int c);
|
||||||
|
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
|
||||||
|
|
||||||
|
static inline int from_hex(int c)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
return c - 'A' + 10;
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 10;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rqsort(void *base, size_t nmemb, size_t size,
|
||||||
|
int (*cmp)(const void *, const void *, void *),
|
||||||
|
void *arg);
|
||||||
|
|
||||||
|
/* Definitions for builtins unavailable on MSVC */
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
#include <intrin.h>
|
||||||
|
|
||||||
|
uint32_t __inline __builtin_ctz(uint32_t value) {
|
||||||
|
unsigned long trailing_zero = 0;
|
||||||
|
if (_BitScanForward(&trailing_zero, value))
|
||||||
|
return trailing_zero;
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t __inline __builtin_clz(uint32_t value) {
|
||||||
|
unsigned long leading_zero = 0;
|
||||||
|
if (_BitScanReverse(&leading_zero, value))
|
||||||
|
return 31 - leading_zero;
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_M_ARM) || defined(_M_X64)
|
||||||
|
uint32_t __inline __builtin_clzll(uint64_t value) {
|
||||||
|
unsigned long leading_zero = 0;
|
||||||
|
if (_BitScanReverse64(&leading_zero, value))
|
||||||
|
return 63 - leading_zero;
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint32_t __inline __builtin_clzll(uint64_t value) {
|
||||||
|
if (value == 0)
|
||||||
|
return 64;
|
||||||
|
uint32_t msh = (uint32_t)(value >> 32);
|
||||||
|
uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF);
|
||||||
|
if (msh != 0)
|
||||||
|
return __builtin_clz(msh);
|
||||||
|
return 32 + __builtin_clz(lsh);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __builtin_clzl __builtin_clzll
|
||||||
|
#endif /* defined(_MSC_VER) && !defined(__clang__) */
|
||||||
|
|
||||||
|
#endif /* CUTILS_H */
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,844 @@
|
||||||
|
\input texinfo
|
||||||
|
|
||||||
|
@iftex
|
||||||
|
@afourpaper
|
||||||
|
@headings double
|
||||||
|
@end iftex
|
||||||
|
|
||||||
|
@titlepage
|
||||||
|
@afourpaper
|
||||||
|
@sp 7
|
||||||
|
@center @titlefont{Javascript Bignum Extensions}
|
||||||
|
@sp 3
|
||||||
|
@center Version 2018-06-16
|
||||||
|
@sp 3
|
||||||
|
@center Author: Fabrice Bellard
|
||||||
|
@end titlepage
|
||||||
|
|
||||||
|
@setfilename spec.info
|
||||||
|
@settitle Javascript Bignum Extensions
|
||||||
|
|
||||||
|
@contents
|
||||||
|
|
||||||
|
@chapter Introduction
|
||||||
|
|
||||||
|
The Bignum extensions add the following features to the Javascript
|
||||||
|
language while being 100% backward compatible:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item Overloading of the standard operators
|
||||||
|
to support new types such as complex numbers, fractions or matrixes.
|
||||||
|
|
||||||
|
@item Bigint mode where arbitrarily large integers are available by default (no @code{n} suffix is necessary as in the TC39 BigInt proposal@footnote{@url{https://tc39.github.io/proposal-bigint/}}).
|
||||||
|
|
||||||
|
@item Arbitrarily large floating point numbers (@code{BigFloat}) in base 2 using the IEEE 754 semantics.
|
||||||
|
|
||||||
|
@item Optional @code{math} mode which modifies the semantics of the division, modulo and power operator. The division and power operator return a fraction with integer operands and the modulo operator is defined as the Euclidian remainder.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
The extensions are independent from each other except the @code{math}
|
||||||
|
mode which relies on the bigint mode and the operator overloading.
|
||||||
|
|
||||||
|
@chapter Operator overloading
|
||||||
|
|
||||||
|
@section Introduction
|
||||||
|
|
||||||
|
If the operands of an operator have at least one object type, a custom
|
||||||
|
operator method is searched before doing the legacy Javascript
|
||||||
|
@code{ToNumber} conversion.
|
||||||
|
|
||||||
|
For unary operators, the custom function is looked up in the object
|
||||||
|
and has the following name:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item unary +
|
||||||
|
@code{Symbol.operatorPlus}
|
||||||
|
|
||||||
|
@item unary -
|
||||||
|
@code{Symbol.operatorNeg}
|
||||||
|
|
||||||
|
@item ++
|
||||||
|
@code{Symbol.operatorInc}
|
||||||
|
|
||||||
|
@item --
|
||||||
|
@code{Symbol.operatorDec}
|
||||||
|
|
||||||
|
@item ~
|
||||||
|
@code{Symbol.operatorNot}
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
For binary operators:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item
|
||||||
|
If both operands have the same constructor function, then the operator
|
||||||
|
is looked up in the constructor.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Otherwise, the property @code{Symbol.operatorOrder} is looked up in both
|
||||||
|
constructors and converted to @code{Int32}. The operator is then
|
||||||
|
looked in the constructor with the larger @code{Symbol.operatorOrder}
|
||||||
|
value. A @code{TypeError} is raised if both constructors have the same
|
||||||
|
@code{Symbol.operatorOrder} value.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
The operator is looked up with the following name:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item +
|
||||||
|
@code{Symbol.operatorAdd}
|
||||||
|
|
||||||
|
@item -
|
||||||
|
@code{Symbol.operatorSub}
|
||||||
|
|
||||||
|
@item *
|
||||||
|
@code{Symbol.operatorMul}
|
||||||
|
|
||||||
|
@item /
|
||||||
|
@code{Symbol.operatorDiv}
|
||||||
|
|
||||||
|
@item / (math mode)
|
||||||
|
@code{Symbol.operatorMathDiv}
|
||||||
|
|
||||||
|
@item %
|
||||||
|
@code{Symbol.operatorMod}
|
||||||
|
|
||||||
|
@item % (math mode)
|
||||||
|
@code{Symbol.operatorMathMod}
|
||||||
|
|
||||||
|
@item ^ (math mode)
|
||||||
|
@code{Symbol.operatorMathPow}
|
||||||
|
|
||||||
|
@item **
|
||||||
|
@code{Symbol.operatorPow}
|
||||||
|
|
||||||
|
@item |
|
||||||
|
@code{Symbol.operatorOr}
|
||||||
|
|
||||||
|
@item ^
|
||||||
|
@code{Symbol.operatorXor}
|
||||||
|
|
||||||
|
@item &
|
||||||
|
@code{Symbol.operatorAnd}
|
||||||
|
|
||||||
|
@item <<
|
||||||
|
@code{Symbol.operatorShl}
|
||||||
|
|
||||||
|
@item >>
|
||||||
|
@code{Symbol.operatorShr}
|
||||||
|
|
||||||
|
@item <
|
||||||
|
@code{Symbol.operatorCmpLT}
|
||||||
|
|
||||||
|
@item >
|
||||||
|
@code{Symbol.operatorCmpLT}, operands swapped
|
||||||
|
|
||||||
|
@item <=
|
||||||
|
@code{Symbol.operatorCmpLE}
|
||||||
|
|
||||||
|
@item >=
|
||||||
|
@code{Symbol.operatorCmpLE}, operands swapped
|
||||||
|
|
||||||
|
@item ==, !=
|
||||||
|
@code{Symbol.operatorCmpEQ}
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
The return value of @code{Symbol.operatorCmpLT}, @code{Symbol.operatorCmpLE} and
|
||||||
|
@code{Symbol.operatorCmpEQ} is converted to @code{Boolean}.
|
||||||
|
|
||||||
|
@section Builtin Object changes
|
||||||
|
|
||||||
|
@subsection @code{Symbol} constructor
|
||||||
|
|
||||||
|
The following global symbols are added for the operator overloading:
|
||||||
|
@table @code
|
||||||
|
@item operatorOrder
|
||||||
|
@item operatorAdd
|
||||||
|
@item operatorSub
|
||||||
|
@item operatorMul
|
||||||
|
@item operatorDiv
|
||||||
|
@item operatorMod
|
||||||
|
@item operatorPow
|
||||||
|
@item operatorShl
|
||||||
|
@item operatorShr
|
||||||
|
@item operatorAnd
|
||||||
|
@item operatorOr
|
||||||
|
@item operatorXor
|
||||||
|
@item operatorCmpLT
|
||||||
|
@item operatorCmpLE
|
||||||
|
@item operatorCmpEQ
|
||||||
|
@item operatorPlus
|
||||||
|
@item operatorNeg
|
||||||
|
@item operatorNot
|
||||||
|
@item operatorInc
|
||||||
|
@item operatorDec
|
||||||
|
@end table
|
||||||
|
|
||||||
|
|
||||||
|
@chapter The BigInt Mode
|
||||||
|
|
||||||
|
@section Introduction
|
||||||
|
|
||||||
|
The bigint mode is enabled with the @code{"use bigint"} directive. It
|
||||||
|
propagates the same way as the strict mode. In bigint mode, all
|
||||||
|
integers are considered as @code{bigint} (arbitrarily large integer,
|
||||||
|
similar to the TC39 BigInt
|
||||||
|
proposal@footnote{@url{https://tc39.github.io/proposal-bigint/}})
|
||||||
|
instead of @code{number} (floating point number). In order to be able
|
||||||
|
to exchange data between standard and bigint modes, numbers are
|
||||||
|
internally represented as 3 different types:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item Small integer (SmallInt): 32 bit integer@footnote{Could be extended to 53 bits without changing the principle.}.
|
||||||
|
|
||||||
|
@item Big integer (BigInt): arbitrarily large integer.
|
||||||
|
|
||||||
|
@item Floating point number (Float).
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
In standard mode, the semantics of each operation is modified so that
|
||||||
|
when it returns a @code{number}, it is either of SmallInt or
|
||||||
|
Float. But the difference between SmallInt and Float is not observable
|
||||||
|
in standard mode.
|
||||||
|
|
||||||
|
In bigint mode, each operation behaves differently whether its
|
||||||
|
operands are integer or float. The difference between SmallInt and
|
||||||
|
BigInt is not observable (i.e. they are both integers).
|
||||||
|
|
||||||
|
The following table summarizes the observable types:
|
||||||
|
|
||||||
|
@multitable @columnfractions .3 .3 .3
|
||||||
|
@headitem Internal type @tab Observable type@* (standard mode) @tab Observable type@* (bigint mode)
|
||||||
|
@item SmallInt @tab number @tab bigint
|
||||||
|
@item BigInt @tab bigint @tab bigint
|
||||||
|
@item Float @tab number @tab number
|
||||||
|
@end multitable
|
||||||
|
|
||||||
|
@section Changes that introduce incompatibilities with Javascript
|
||||||
|
|
||||||
|
@subsection Standard mode
|
||||||
|
|
||||||
|
There is no incompatibility with Javascript.
|
||||||
|
|
||||||
|
@subsection Bigint mode
|
||||||
|
|
||||||
|
The following changes are visible:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item Integer and Float are different types. Constants are typed. For example: @code{typeof 1.0 === "number"} and @code{typeof 1 === "bigint"}. Another consequence is that @code{1.0 === 1} is false.
|
||||||
|
|
||||||
|
@item The range of integers is unlimited. In standard mode: @code{2**53 + 1 === 2**53}. This is no longer true with the bignum extensions.
|
||||||
|
|
||||||
|
@item Binary bitwise operators do not truncate to 32 bits i.e. @code{0x800000000 | 1 === 0x800000001} while it gives @code{1} in standard mode.
|
||||||
|
|
||||||
|
@item Bitwise shift operators do not truncate to 32 bits and do not mask the shift count with @code{0x1f} i.e. @code{1 << 32 === 4294967296} while it gives @code{1} in standard mode. However, the @code{>>>} operator (unsigned right shift) which is useless with bignums keeps its standard mode behavior@footnote{The unsigned right right operator could be removed in bigint mode.}.
|
||||||
|
|
||||||
|
@item Operators with integer operands never return the minus zero floating point value as result. Hence @code{Object.is(0, -0) === true}. Use @code{-0.0} to create a minus zero floating point value.
|
||||||
|
|
||||||
|
@item Division or modulo with a zero integer dividend raises an exception i.e. @code{1/0} throws a @code{RangeError} exception. However, division by the floating point zero returns Infinity or NaN as in standard mode: @code{1/0.0 === Infinity}. The same holds for zero elevated to a negative integer power i.e. @code{0**-1} throws a @code{RangeError} exception.
|
||||||
|
|
||||||
|
@item The @code{ToPrimitive} abstract operation is called with the @code{"integer"} preferred type when an integer is required (e.g. for bitwise binary or shift operations).
|
||||||
|
|
||||||
|
@item The prototype of integers is no longer @code{Number.prototype}. Instead@* @code{Object.getPrototypeOf(1) === BigInt.prototype}. The prototype of floats remains Number.prototype.
|
||||||
|
|
||||||
|
@item If the TC39 BigInt proposal is supported, there is no observable difference between integers and @code{bigint}s.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section Operators
|
||||||
|
|
||||||
|
@subsection Arithmetic operators
|
||||||
|
|
||||||
|
The operands are converted to number values as in normal
|
||||||
|
Javascript. Then the general case is that an Integer is returned if
|
||||||
|
both operands are Integer. Otherwise, a float is returned.
|
||||||
|
|
||||||
|
The @code{+} operator also accepts strings as input and behaves like
|
||||||
|
standard Javascript in this case.
|
||||||
|
|
||||||
|
The binary operator @code{%} returns the truncated remainder of the
|
||||||
|
division.
|
||||||
|
|
||||||
|
The binary operator @code{%} in math mode returns the Euclidian
|
||||||
|
remainder of the division i.e. it is always positive.
|
||||||
|
|
||||||
|
The binary operator @code{/} returns a float.
|
||||||
|
|
||||||
|
The binary operator @code{/} in math mode returns a float if one of
|
||||||
|
the operands is float. Otherwise, @code{BigInt[Symbol.operatorMathDiv]} is
|
||||||
|
invoked (and returns a fraction for example).
|
||||||
|
|
||||||
|
When the result is an Integer type, a dividend of zero yields a
|
||||||
|
RangeError exception.
|
||||||
|
|
||||||
|
The returned type of @code{a ** b} or @code{a ^ b} (math mode) is
|
||||||
|
Float if @math{a} or @math{b} are Float. If @math{a} and @math{b} are
|
||||||
|
integers:
|
||||||
|
@itemize
|
||||||
|
@item @math{a = 0} and @math{b < 0} generates a RangeError exception
|
||||||
|
|
||||||
|
@item @math{|a| \geq 2} and @math{b < 0} returns a Float in bigint mode. In math mode, @code{BigInt[Symbol.operatorMathPow]} is invoked (and returns a fraction for example)
|
||||||
|
|
||||||
|
@item otherwise an integer is returned.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
The unary @code{-} and unary @code{+} return the same type as their
|
||||||
|
operand. They performs no floating point rounding when the result is a
|
||||||
|
float.
|
||||||
|
|
||||||
|
The unary operators @code{++} and @code{--} return the same type as
|
||||||
|
their operand.
|
||||||
|
|
||||||
|
In standard mode:
|
||||||
|
|
||||||
|
If the operator returns an Integer and that the result fits a
|
||||||
|
SmallInt, it is converted to SmallInt. Otherwise, the Integer is
|
||||||
|
converted to a Float.
|
||||||
|
|
||||||
|
In bigint mode:
|
||||||
|
|
||||||
|
If the operator returns an Integer and that the result fits a
|
||||||
|
SmallInt, it is converted to SmallInt. Otherwise it is a BigInt.
|
||||||
|
|
||||||
|
@subsection Logical operators
|
||||||
|
|
||||||
|
In standard mode:
|
||||||
|
|
||||||
|
The operands have their standard behavior. If the result fits a
|
||||||
|
SmallInt it is converted to a SmallInt. Otherwise it is a Float.
|
||||||
|
|
||||||
|
In bigint mode:
|
||||||
|
|
||||||
|
The operands are converted to integer values. The floating point
|
||||||
|
values are converted to integer by rounding them to zero.
|
||||||
|
|
||||||
|
The logical operators are defined assuming the integers are
|
||||||
|
represented in two complement notation.
|
||||||
|
|
||||||
|
For @code{<<} and @code{<<}, the shift can be positive or negative. So
|
||||||
|
@code{a << b} is defined as @math{\lfloor a/2^{-b} \rfloor} and
|
||||||
|
@code{a >> b} is defined as @math{\lfloor a/2^{b} \rfloor}.
|
||||||
|
|
||||||
|
The operator @code{>>>} is supported for backward compatibility and
|
||||||
|
behaves the same way as Javascript i.e. implicit conversion to @code{Uint32}.
|
||||||
|
|
||||||
|
If the result fits a SmallInt it is converted to a SmallInt. Otherwise
|
||||||
|
it is a BigInt.
|
||||||
|
|
||||||
|
@subsection Relational operators
|
||||||
|
|
||||||
|
The relational operators <, <=, >, >=, ==, != work as expected with
|
||||||
|
integers and floating point numbers (e.g. @code{1.0 == 1} is true).
|
||||||
|
|
||||||
|
The strict equality operators === and !== have the usual Javascript
|
||||||
|
semantics. In particular, different types never equal, so @code{1.0
|
||||||
|
=== 1} is false.
|
||||||
|
|
||||||
|
@section Number literals
|
||||||
|
|
||||||
|
Number literals in bigint mode have a slightly different behavior than
|
||||||
|
in standard Javascript:
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
|
||||||
|
@item
|
||||||
|
A number literal without a decimal point or an exponent is considered
|
||||||
|
as an Integer. Otherwise it is a Float.
|
||||||
|
|
||||||
|
@item
|
||||||
|
Hexadecimal, octal or binary floating point literals are accepted with
|
||||||
|
a decimal point or an exponent. The exponent is specified with the
|
||||||
|
@code{p} letter assuming a base 2. The same convention is used by
|
||||||
|
C99. Example: @code{0x1p3} is the same as @code{8.0}.
|
||||||
|
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
@section Builtin Object changes
|
||||||
|
|
||||||
|
@subsection @code{BigInt} function
|
||||||
|
|
||||||
|
The @code{BigInt} function cannot be invoked as a constructor. When
|
||||||
|
invoked as a function, it converts its first parameter to an
|
||||||
|
integer. When a floating point number is given as parameter, it is
|
||||||
|
truncated to an integer with infinite precision.
|
||||||
|
|
||||||
|
@code{BigInt} properties:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
|
||||||
|
@item asIntN(bits, a)
|
||||||
|
Set @math{b=a \pmod{2^{bits}}}. Return @math{b} if @math{b < 2^{bits-1}}
|
||||||
|
otherwise @math{b-2^{bits}}.
|
||||||
|
|
||||||
|
@item asUintN(bits, a)
|
||||||
|
Return @math{a \pmod{2^{bits}}}.
|
||||||
|
|
||||||
|
@item tdiv(a, b)
|
||||||
|
Return @math{trunc(a/b)}. @code{b = 0} raises a RangeError
|
||||||
|
exception.
|
||||||
|
|
||||||
|
@item fdiv(a, b)
|
||||||
|
Return @math{\lfloor a/b \rfloor}. @code{b = 0} raises a RangeError
|
||||||
|
exception.
|
||||||
|
|
||||||
|
@item cdiv(a, b)
|
||||||
|
Return @math{\lceil a/b \rceil}. @code{b = 0} raises a RangeError
|
||||||
|
exception.
|
||||||
|
|
||||||
|
@item ediv(a, b)
|
||||||
|
Return @math{sgn(b) \lfloor a/{|b|} \rfloor} (Euclidian
|
||||||
|
division). @code{b = 0} raises a RangeError exception.
|
||||||
|
|
||||||
|
@item tdivrem(a, b)
|
||||||
|
@item fdivrem(a, b)
|
||||||
|
@item cdivrem(a, b)
|
||||||
|
@item edivrem(a, b)
|
||||||
|
Return an array of two elements. The first element is the quotient,
|
||||||
|
the second is the remainder. The same rounding is done as the
|
||||||
|
corresponding division operation.
|
||||||
|
|
||||||
|
@item sqrt(a)
|
||||||
|
Return @math{\lfloor \sqrt(a) \rfloor}. A RangeError exception is
|
||||||
|
raised if @math{a < 0}.
|
||||||
|
|
||||||
|
@item sqrtrem(a)
|
||||||
|
Return an array of two elements. The first element is @math{\lfloor
|
||||||
|
\sqrt{a} \rfloor}. The second element is @math{a-\lfloor \sqrt{a}
|
||||||
|
\rfloor^2}. A RangeError exception is raised if @math{a < 0}.
|
||||||
|
|
||||||
|
@item floorLog2(a)
|
||||||
|
Return -1 if @math{a \leq 0} otherwise return @math{\lfloor \log2(a) \rfloor}.
|
||||||
|
|
||||||
|
@item ctz(a)
|
||||||
|
Return the number of trailing zeros in the two's complement binary representation of a. Return -1 if @math{a=0}.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{BigInt.prototype}
|
||||||
|
|
||||||
|
It is a normal object.
|
||||||
|
|
||||||
|
@subsection @code{Number} constructor
|
||||||
|
|
||||||
|
The number constructor returns its argument rounded to a Float using
|
||||||
|
the global floating point environement. In bigint mode, the Number
|
||||||
|
constructor returns a Float. In standard mode, it returns a SmallInt
|
||||||
|
if the value fits it, otherwise a Float.
|
||||||
|
|
||||||
|
@subsection @code{Number.prototype}
|
||||||
|
|
||||||
|
The following properties are modified:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item toString(radix)
|
||||||
|
|
||||||
|
In bigint mode, integers are converted to the specified radix with
|
||||||
|
infinite precision.
|
||||||
|
|
||||||
|
@item toPrecision(p)
|
||||||
|
@item toFixed(p)
|
||||||
|
@item toExponential(p)
|
||||||
|
|
||||||
|
In bigint mode, integers are accepted and converted to string with
|
||||||
|
infinite precision.
|
||||||
|
|
||||||
|
@item parseInt(string, radix)
|
||||||
|
|
||||||
|
In bigint mode, an integer is returned and the conversion is done with
|
||||||
|
infinite precision.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{Math} object
|
||||||
|
|
||||||
|
The following properties are modified:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item abs(x)
|
||||||
|
Absolute value. Return an integer if @code{x} is an Integer. Otherwise
|
||||||
|
return a Float. No rounding is performed.
|
||||||
|
|
||||||
|
@item min(a, b)
|
||||||
|
@item max(a, b)
|
||||||
|
No rounding is performed. The returned type is the same one as the
|
||||||
|
minimum (resp. maximum) value.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@chapter Arbitrarily large floating point numbers
|
||||||
|
|
||||||
|
@section Introduction
|
||||||
|
|
||||||
|
This extension adds the @code{BigFloat} primitive type. The
|
||||||
|
@code{BigFloat} type represents floating point numbers are in base 2
|
||||||
|
with the IEEE 754 semantics. A floating
|
||||||
|
point number is represented as a sign, mantissa and exponent. The
|
||||||
|
special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0}
|
||||||
|
are supported. The mantissa and exponent can have any bit length with
|
||||||
|
an implementation specific minimum and maximum.
|
||||||
|
|
||||||
|
@section Floating point rounding
|
||||||
|
|
||||||
|
Each floating point operation operates with infinite precision and
|
||||||
|
then rounds the result according to the specified floating point
|
||||||
|
environment (@code{BigFloatEnv} object). The status flags of the
|
||||||
|
environment are also set according to the result of the operation.
|
||||||
|
|
||||||
|
If no floating point environment is provided, the global floating
|
||||||
|
point environment is used.
|
||||||
|
|
||||||
|
The rounding mode of the global floating point environment is always
|
||||||
|
@code{RNDN} (``round to nearest with ties to even'')@footnote{The
|
||||||
|
rationale is that the rounding mode changes must always be
|
||||||
|
explicit.}. The status flags of the global environment cannot be
|
||||||
|
read@footnote{The rationale is to avoid side effects for the built-in
|
||||||
|
operators.}. The precision of the global environment is
|
||||||
|
@code{BigFloatEnv.prec}. The number of exponent bits of the global
|
||||||
|
environment is @code{BigFloatEnv.expBits}. If @code{BigFloatEnv.expBits} is
|
||||||
|
strictly smaller than the maximum allowed number of exponent bits
|
||||||
|
(@code{BigFloatEnv.expBitsMax}), then the global environment subnormal
|
||||||
|
flag is set to @code{true}. Otherwise it is set to @code{false};
|
||||||
|
|
||||||
|
For example, @code{prec = 53} and @code{ expBits = 11} give exactly
|
||||||
|
the same precision as the IEEE 754 64 bit floating point type. It is
|
||||||
|
the default floating point precision.
|
||||||
|
|
||||||
|
The global floating point environment can only be modified temporarily
|
||||||
|
when calling a function (see @code{BigFloatEnv.setPrec}). Hence a
|
||||||
|
function can change the global floating point environment for its
|
||||||
|
callees but not for its caller.
|
||||||
|
|
||||||
|
@section Operators
|
||||||
|
|
||||||
|
The builtin operators are extended so that a BigFloat is returned if
|
||||||
|
at least one operand is a BigFloat. The computations are always done
|
||||||
|
with infinite precision and rounded according to the global floating
|
||||||
|
point environment.
|
||||||
|
|
||||||
|
@code{typeof} applied on a @code{BigFloat} returns @code{bigfloat}.
|
||||||
|
|
||||||
|
BigFloat can be compared with all the other numeric types and the
|
||||||
|
result follows the expected mathematical relations.
|
||||||
|
|
||||||
|
However, since BigFloat and Number are different types they are never
|
||||||
|
equal when using the strict comparison operators (e.g. @code{0.0 ===
|
||||||
|
0.0l} is false).
|
||||||
|
|
||||||
|
@section BigFloat literals
|
||||||
|
|
||||||
|
BigFloat literals are floating point numbers with a trailing @code{l}
|
||||||
|
suffix. BigFloat literals have an infinite precision. They are rounded
|
||||||
|
according to the global floating point environment when they are
|
||||||
|
evaluated.@footnote{Base 10 floating point literals cannot usually be
|
||||||
|
exactly represented as base 2 floating point number. In order to
|
||||||
|
ensure that the literal is represented accurately with the current
|
||||||
|
precision, it must be evaluated at runtime.}
|
||||||
|
|
||||||
|
@section Builtin Object changes
|
||||||
|
|
||||||
|
@subsection @code{BigFloat} function
|
||||||
|
|
||||||
|
The @code{BigFloat} function cannot be invoked as a constructor. When
|
||||||
|
invoked as a function: the parameter is converted to a primitive
|
||||||
|
type. If the result is a numeric type, it is converted to BigFloat
|
||||||
|
without rounding. If the result is a string, it is converted to
|
||||||
|
BigFloat using the precision of the global floating point environment.
|
||||||
|
|
||||||
|
@code{BigFloat} properties:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
|
||||||
|
@item LN2
|
||||||
|
@item PI
|
||||||
|
Getter. Return the value of the corresponding mathematical constant
|
||||||
|
rounded to nearest, ties to even with the current global
|
||||||
|
precision. The constant values are cached for small precisions.
|
||||||
|
|
||||||
|
@item MIN_VALUE
|
||||||
|
@item MAX_VALUE
|
||||||
|
@item EPSILON
|
||||||
|
Getter. Return the minimum, maximum and epsilon @code{BigFloat} values
|
||||||
|
(same definition as the corresponding @code{Number} constants).
|
||||||
|
|
||||||
|
@item fpRound(a[, e])
|
||||||
|
Round the floating point number @code{a} according to the floating
|
||||||
|
point environment @code{e} or the global environment if @code{e} is
|
||||||
|
undefined.
|
||||||
|
|
||||||
|
@item parseFloat(a[, radix[, e]])
|
||||||
|
Parse the string @code{a} as a floating point number in radix
|
||||||
|
@code{radix}. The radix is 0 (default) or from 2 to 36. The radix 0
|
||||||
|
means radix 10 unless there is a hexadecimal or binary prefix. The
|
||||||
|
result is rounded according to the floating point environment @code{e}
|
||||||
|
or the global environment if @code{e} is undefined.
|
||||||
|
|
||||||
|
@item add(a, b[, e])
|
||||||
|
@item sub(a, b[, e])
|
||||||
|
@item mul(a, b[, e])
|
||||||
|
@item div(a, b[, e])
|
||||||
|
Perform the specified floating point operation and round the floating
|
||||||
|
point number @code{a} according to the floating point environment
|
||||||
|
@code{e} or the global environment if @code{e} is undefined. If
|
||||||
|
@code{e} is specified, the floating point status flags are updated.
|
||||||
|
|
||||||
|
@item floor(x[, e])
|
||||||
|
@item ceil(x[, e])
|
||||||
|
@item round(x[, e])
|
||||||
|
@item trunc(x[, e])
|
||||||
|
Round to integer. A rounded @code{BigFloat} is returned. @code{e} is an
|
||||||
|
optional floating point environment.
|
||||||
|
|
||||||
|
@item fmod(x, y[, e])
|
||||||
|
@item remainder(x, y[, e])
|
||||||
|
Floating point remainder. The quotient is truncated to zero (fmod) or
|
||||||
|
to the nearest integer with ties to even (remainder). @code{e} is an
|
||||||
|
optional floating point environment.
|
||||||
|
|
||||||
|
@item sqrt(x[, e])
|
||||||
|
Square root. Return a rounded floating point number. @code{e} is an
|
||||||
|
optional floating point environment.
|
||||||
|
|
||||||
|
@item sin(x[, e])
|
||||||
|
@item cos(x[, e])
|
||||||
|
@item tan(x[, e])
|
||||||
|
@item asin(x[, e])
|
||||||
|
@item acos(x[, e])
|
||||||
|
@item atan(x[, e])
|
||||||
|
@item atan2(x, y[, e])
|
||||||
|
@item exp(x[, e])
|
||||||
|
@item log(x[, e])
|
||||||
|
@item pow(x, y[, e])
|
||||||
|
Transcendental operations. Return a rounded floating point
|
||||||
|
number. @code{e} is an optional floating point environment.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{BigFloat.prototype}
|
||||||
|
|
||||||
|
The following properties are modified:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item toString(radix)
|
||||||
|
|
||||||
|
For floating point numbers:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item
|
||||||
|
If the radix is a power of two, the conversion is done with infinite
|
||||||
|
precision.
|
||||||
|
@item
|
||||||
|
Otherwise, the number is rounded to nearest with ties to even using
|
||||||
|
the global precision. It is then converted to string using the minimum
|
||||||
|
number of digits so that its conversion back to a floating point using
|
||||||
|
the global precision and round to nearest gives the same number.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@item toPrecision(p[, rnd_mode])
|
||||||
|
@item toFixed(p[, rnd_mode])
|
||||||
|
@item toExponential(p[, rnd_mode])
|
||||||
|
Same semantics as the corresponding @code{Number} functions with
|
||||||
|
BigFloats. There is no limit on the accepted precision @code{p}. The
|
||||||
|
rounding mode can be optionally specified. It is set by default to
|
||||||
|
@code{BigFloatEnv.RNDNA}.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{BigFloatEnv} constructor
|
||||||
|
|
||||||
|
The @code{BigFloatEnv([p, [,rndMode]]} constructor cannot be invoked as a
|
||||||
|
function. The floating point environment contains:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item the mantissa precision in bits
|
||||||
|
|
||||||
|
@item the exponent size in bits assuming an IEEE 754 representation;
|
||||||
|
|
||||||
|
@item the subnormal flag (if true, subnormal floating point numbers can
|
||||||
|
be generated by the floating point operations).
|
||||||
|
|
||||||
|
@item the rounding mode
|
||||||
|
|
||||||
|
@item the floating point status. The status flags can only be set by the floating point operations. They can be reset with @code{BigFloatEnv.prototype.clearStatus()} or with the various status flag setters.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@code{new BigFloatEnv([p, [,rndMode]]} creates a new floating point
|
||||||
|
environment. The status flags are reset. If no parameter is given the
|
||||||
|
precision, exponent bits and subnormal flags are copied from the
|
||||||
|
global floating point environment. Otherwise, the precision is set to
|
||||||
|
@code{p}, the number of exponent bits is set to @code{expBitsMax} and the
|
||||||
|
subnormal flags is set to @code{false}. If @code{rndMode} is
|
||||||
|
@code{undefined}, the rounding mode is set to @code{RNDN}.
|
||||||
|
|
||||||
|
@code{BigFloatEnv} properties:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
|
||||||
|
@item prec
|
||||||
|
Getter. Return the precision in bits of the global floating point
|
||||||
|
environment. The initial value is @code{53}.
|
||||||
|
|
||||||
|
@item expBits
|
||||||
|
Getter. Return the exponent size in bits of the global floating point
|
||||||
|
environment assuming an IEEE 754 representation. If @code{expBits <
|
||||||
|
expBitsMax}, then subnormal numbers are supported. The initial value
|
||||||
|
is @code{11}.
|
||||||
|
|
||||||
|
@item setPrec(f, p[, e])
|
||||||
|
Set the precision of the global floating point environment to @code{p}
|
||||||
|
and the exponent size to @code{e} then call the function
|
||||||
|
@code{f}. Then the Float precision and exponent size are reset to
|
||||||
|
their precious value and the return value of @code{f} is returned (or
|
||||||
|
an exception is raised if @code{f} raised an exception). If @code{e}
|
||||||
|
is @code{undefined} it is set to @code{BigFloatEnv.expBitsMax}. @code{p}
|
||||||
|
must be >= 53 and @code{e} must be >= 11 so that the global precision
|
||||||
|
is at least equivalent to the IEEE 754 64 bit doubles.
|
||||||
|
|
||||||
|
@item precMin
|
||||||
|
Read-only integer. Return the minimum allowed precision. Must be at least 2.
|
||||||
|
|
||||||
|
@item precMax
|
||||||
|
Read-only integer. Return the maximum allowed precision. Must be at least 53.
|
||||||
|
|
||||||
|
@item expBitsMin
|
||||||
|
Read-only integer. Return the minimum allowed exponent size in
|
||||||
|
bits. Must be at least 3.
|
||||||
|
|
||||||
|
@item expBitsMax
|
||||||
|
Read-only integer. Return the maximum allowed exponent size in
|
||||||
|
bits. Must be at least 11.
|
||||||
|
|
||||||
|
@item RNDN
|
||||||
|
Read-only integer. Round to nearest, with ties to even rounding mode.
|
||||||
|
|
||||||
|
@item RNDZ
|
||||||
|
Read-only integer. Round to zero rounding mode.
|
||||||
|
|
||||||
|
@item RNDD
|
||||||
|
Read-only integer. Round to -Infinity rounding mode.
|
||||||
|
|
||||||
|
@item RNDU
|
||||||
|
Read-only integer. Round to +Infinity rounding mode.
|
||||||
|
|
||||||
|
@item RNDNA
|
||||||
|
Read-only integer. Round to nearest, with ties away from zero rounding mode.
|
||||||
|
|
||||||
|
@item RNDNU
|
||||||
|
Read-only integer. Round to nearest, with ties to +Infinity rounding mode.
|
||||||
|
|
||||||
|
@item RNDF@footnote{Could be removed in case a deterministic behvior for floating point operations is required.}
|
||||||
|
Read-only integer. Faithful rounding mode. The result is
|
||||||
|
non-deterministicly rounded to -Infinity or +Infinity. This rounding
|
||||||
|
mode usually gives a faster and deterministic running time for the
|
||||||
|
floating point operations.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@code{BigFloatEnv.prototype} properties:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
|
||||||
|
@item prec
|
||||||
|
Getter and setter (Integer). Return or set the precision in bits.
|
||||||
|
|
||||||
|
@item expBits
|
||||||
|
Getter and setter (Integer). Return or set the exponent size in bits
|
||||||
|
assuming an IEEE 754 representation.
|
||||||
|
|
||||||
|
@item rndMode
|
||||||
|
Getter and setter (Integer). Return or set the rounding mode.
|
||||||
|
|
||||||
|
@item subnormal
|
||||||
|
Getter and setter (Boolean). subnormal flag. It is false when
|
||||||
|
@code{expBits = expBitsMax}.
|
||||||
|
|
||||||
|
@item clearStatus()
|
||||||
|
Clear the status flags.
|
||||||
|
|
||||||
|
@item invalidOperation
|
||||||
|
@item divideByZero
|
||||||
|
@item overflow
|
||||||
|
@item underflow
|
||||||
|
@item inexact
|
||||||
|
Getter and setter (Boolean). Status flags.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{Math} object
|
||||||
|
|
||||||
|
The following properties are modified:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item abs(x)
|
||||||
|
Absolute value. If @code{x} is a BigFloat, its absolute value is
|
||||||
|
returned as a BigFloat. No rounding is performed.
|
||||||
|
|
||||||
|
@item min(a, b)
|
||||||
|
@item max(a, b)
|
||||||
|
The returned type is the same one as the minimum (resp. maximum)
|
||||||
|
value, so @code{BigFloat} values are accepted. When a @code{BigFloat}
|
||||||
|
is returned, no rounding is performed.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@chapter Math mode
|
||||||
|
|
||||||
|
@section Introduction
|
||||||
|
|
||||||
|
A new @emph{math mode} is enabled with the @code{"use math"}
|
||||||
|
directive. @code{"use bigint"} is implied in math mode. With this
|
||||||
|
mode, writing mathematical expressions is more intuitive, exact
|
||||||
|
results (fractions) can be computed for all operators and floating
|
||||||
|
point literals have the @code{BigFloat} type by default.
|
||||||
|
|
||||||
|
It propagates the same way as the @emph{strict mode}. In
|
||||||
|
this mode:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item The @code{^} operator is a similar to the power operator (@code{**}), except that @code{a ^ b} invokes @code{BigInt[Symbol.operatorMathPow]} if @math{a} and @math{b} are integers and @math{|a| \geq 2} and @math{b < 0}.
|
||||||
|
|
||||||
|
@item The power operator (both @code{^} and @code{**}) grammar is modified so that @code{-2^2} is allowed and yields @code{-4}.
|
||||||
|
|
||||||
|
@item The logical xor operator is still available with the @code{^^} operator.
|
||||||
|
|
||||||
|
@item The division operator invokes @code{BigInt[Symbol.operatorMathDiv]} in case both operands are integers.
|
||||||
|
|
||||||
|
@item The modulo operator returns the Euclidian remainder (always positive) instead of the truncated remainder.
|
||||||
|
|
||||||
|
@item Floating point literals are @code{BigFloat} by default (i.e. a @code{l} suffix is implied).
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section Builtin Object changes
|
||||||
|
|
||||||
|
@subsection @code{Symbol} constructor
|
||||||
|
|
||||||
|
The following global symbols are added for the operator overloading:
|
||||||
|
@table @code
|
||||||
|
@item operatorMathDiv
|
||||||
|
@item operatorMathMod
|
||||||
|
@item operatorMathPow
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@section Remaining issues
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
|
||||||
|
@item New functions (e.g. @code{Math.div} and @code{Math.mod}) could be added to be able to call the normal division and modulo operators when in math mode.
|
||||||
|
|
||||||
|
@item A new floating point literal suffix could be added for @code{Number} literals.
|
||||||
|
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
@bye
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,817 @@
|
||||||
|
\input texinfo
|
||||||
|
|
||||||
|
@iftex
|
||||||
|
@afourpaper
|
||||||
|
@headings double
|
||||||
|
@end iftex
|
||||||
|
|
||||||
|
@titlepage
|
||||||
|
@afourpaper
|
||||||
|
@sp 7
|
||||||
|
@center @titlefont{QuickJS Javascript Engine}
|
||||||
|
@sp 3
|
||||||
|
@end titlepage
|
||||||
|
|
||||||
|
@setfilename spec.info
|
||||||
|
@settitle QuickJS Javascript Engine
|
||||||
|
|
||||||
|
@contents
|
||||||
|
|
||||||
|
@chapter Introduction
|
||||||
|
|
||||||
|
QuickJS is a small and embeddable Javascript engine. It supports the
|
||||||
|
ES2019 specification including modules, asynchronous
|
||||||
|
generators and proxies.
|
||||||
|
|
||||||
|
It optionally supports mathematical extensions such as big integers
|
||||||
|
(BigInt), big floating point numbers (BigFloat) and operator
|
||||||
|
overloading.
|
||||||
|
|
||||||
|
@section Main Features
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item Small and easily embeddable: just a few C files, no external dependency, 180 KiB of x86 code for a simple ``hello world'' program.
|
||||||
|
|
||||||
|
@item Fast interpreter with very low startup time: runs the 56000 tests of the ECMAScript Test Suite@footnote{@url{https://github.com/tc39/test262}} in about 100 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
||||||
|
|
||||||
|
@item Almost complete ES2019 support including modules, asynchronous
|
||||||
|
generators and full Annex B support (legacy web compatibility).
|
||||||
|
|
||||||
|
@item Passes 100% of the ECMAScript Test Suite tests.
|
||||||
|
|
||||||
|
@item Can compile Javascript sources to executables with no external dependency.
|
||||||
|
|
||||||
|
@item Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal.
|
||||||
|
|
||||||
|
@item Mathematical extensions: BigInt, BigFloat, operator overloading, bigint mode, math mode.
|
||||||
|
|
||||||
|
@item Command line interpreter with contextual colorization and completion implemented in Javascript.
|
||||||
|
|
||||||
|
@item Small built-in standard library with C library wrappers.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@chapter Usage
|
||||||
|
|
||||||
|
@section Installation
|
||||||
|
|
||||||
|
A Makefile is provided to compile the engine on Linux or MacOS/X. A
|
||||||
|
preliminary Windows support is available thru cross compilation on a
|
||||||
|
Linux host with the MingGW tools.
|
||||||
|
|
||||||
|
Edit the top of the @code{Makefile} if you wish to select specific
|
||||||
|
options then run @code{make}.
|
||||||
|
|
||||||
|
You can type @code{make install} as root if you wish to install the binaries and support files to
|
||||||
|
@code{/usr/local} (this is not necessary to use QuickJS).
|
||||||
|
|
||||||
|
@section Quick start
|
||||||
|
|
||||||
|
@code{qjs} is the command line interpreter (Read-Eval-Print Loop). You can pass
|
||||||
|
Javascript files and/or expressions as arguments to execute them:
|
||||||
|
|
||||||
|
@example
|
||||||
|
./qjs examples/hello.js
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@code{qjsc} is the command line compiler:
|
||||||
|
|
||||||
|
@example
|
||||||
|
./qjsc -o hello examples/hello.js
|
||||||
|
./hello
|
||||||
|
@end example
|
||||||
|
|
||||||
|
generates a @code{hello} executable with no external dependency.
|
||||||
|
|
||||||
|
@code{qjsbn} and @code{qjscbn} are the corresponding interpreter and
|
||||||
|
compiler with the mathematical extensions:
|
||||||
|
|
||||||
|
@example
|
||||||
|
./qjsbn examples/pi.js 1000
|
||||||
|
@end example
|
||||||
|
|
||||||
|
displays 1000 digits of PI.
|
||||||
|
|
||||||
|
@example
|
||||||
|
./qjsbnc -o pi examples/pi.js
|
||||||
|
./pi 1000
|
||||||
|
@end example
|
||||||
|
|
||||||
|
compiles and executes the PI program.
|
||||||
|
|
||||||
|
@section Command line options
|
||||||
|
|
||||||
|
@subsection @code{qjs} interpreter
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
usage: qjs [options] [files]
|
||||||
|
@end verbatim
|
||||||
|
|
||||||
|
Options are:
|
||||||
|
@table @code
|
||||||
|
@item -h
|
||||||
|
@item --help
|
||||||
|
List options.
|
||||||
|
|
||||||
|
@item -e @code{EXPR}
|
||||||
|
@item --eval @code{EXPR}
|
||||||
|
Evaluate EXPR.
|
||||||
|
|
||||||
|
@item -i
|
||||||
|
@item --interactive
|
||||||
|
Go to interactive mode (it is not the default when files are provided on the command line).
|
||||||
|
|
||||||
|
@item -m
|
||||||
|
@item --module
|
||||||
|
Load as ES6 module (default if .mjs file extension).
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
Advanced options are:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item -d
|
||||||
|
@item --dump
|
||||||
|
Dump the memory usage stats.
|
||||||
|
|
||||||
|
@item -q
|
||||||
|
@item --quit
|
||||||
|
just instantiate the interpreter and quit.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{qjsc} compiler
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
usage: qjsc [options] [files]
|
||||||
|
@end verbatim
|
||||||
|
|
||||||
|
Options are:
|
||||||
|
@table @code
|
||||||
|
@item -c
|
||||||
|
Only output bytecode in a C file. The default is to output an executable file.
|
||||||
|
@item -e
|
||||||
|
Output @code{main()} and bytecode in a C file. The default is to output an
|
||||||
|
executable file.
|
||||||
|
@item -o output
|
||||||
|
Set the output filename (default = @file{out.c} or @file{a.out}).
|
||||||
|
|
||||||
|
@item -N cname
|
||||||
|
Set the C name of the generated data.
|
||||||
|
|
||||||
|
@item -m
|
||||||
|
Compile as Javascript module (default if @file{.mjs} extension).
|
||||||
|
|
||||||
|
@item -M module_name[,cname]
|
||||||
|
Add initialization code for an external C module. See the
|
||||||
|
@code{c_module} example.
|
||||||
|
|
||||||
|
@item -x
|
||||||
|
Byte swapped output (only used for cross compilation).
|
||||||
|
|
||||||
|
@item -flto
|
||||||
|
Use link time optimization. The compilation is slower but the
|
||||||
|
executable is smaller and faster. This option is automatically set
|
||||||
|
when the @code{-fno-x} options are used.
|
||||||
|
|
||||||
|
@item -fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise]
|
||||||
|
Disable selected language features to produce a smaller executable file.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@section @code{qjscalc} application
|
||||||
|
|
||||||
|
The @code{qjscalc} application is a superset of the @code{qjsbn}
|
||||||
|
command line interpreter implementing a Javascript calculator with
|
||||||
|
arbitrarily large integer and floating point numbers, fractions,
|
||||||
|
complex numbers, polynomials and matrices. The source code is in
|
||||||
|
@file{qjscalc.js}. More documentation and a web version are available at
|
||||||
|
@url{http://numcalc.com}.
|
||||||
|
|
||||||
|
@section Built-in tests
|
||||||
|
|
||||||
|
Run @code{make test} to run the few built-in tests included in the
|
||||||
|
QuickJS archive.
|
||||||
|
|
||||||
|
@section Test262 (ECMAScript Test Suite)
|
||||||
|
|
||||||
|
A test262 runner is included in the QuickJS archive.
|
||||||
|
|
||||||
|
For reference, the full test262 tests are provided in the archive
|
||||||
|
@file{qjs-tests-yyyy-mm-dd.tar.xz}. You just need to untar it into the
|
||||||
|
QuickJS source code directory.
|
||||||
|
|
||||||
|
Alternatively, the test262 tests can be installed with:
|
||||||
|
|
||||||
|
@example
|
||||||
|
git clone https://github.com/tc39/test262.git test262
|
||||||
|
cd test262
|
||||||
|
git checkout 94b1e80ab3440413df916cd56d29c5a2fa2ac451
|
||||||
|
patch -p1 < ../tests/test262.patch
|
||||||
|
cd ..
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The patch adds the implementation specific @code{harness} functions
|
||||||
|
and optimizes the inefficient RegExp character classes and Unicode
|
||||||
|
property escapes tests (the tests themselves are not modified, only a
|
||||||
|
slow string initialization function is optimized).
|
||||||
|
|
||||||
|
The tests can be run with
|
||||||
|
@example
|
||||||
|
make test2
|
||||||
|
@end example
|
||||||
|
|
||||||
|
For more information, run @code{./run-test262} to see the options of
|
||||||
|
the test262 runner. The configuration files @code{test262.conf} and
|
||||||
|
@code{test262bn.conf} contain the options to run the various tests.
|
||||||
|
|
||||||
|
@chapter Specifications
|
||||||
|
|
||||||
|
@section Language support
|
||||||
|
|
||||||
|
@subsection ES2019 support
|
||||||
|
|
||||||
|
The ES2019 specification
|
||||||
|
@footnote{@url{https://tc39.github.io/ecma262/}} is almost fully
|
||||||
|
supported including the Annex B (legacy web compatibility) and the
|
||||||
|
Unicode related features. The following features are not supported
|
||||||
|
yet:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item Realms (althougth the C API supports different runtimes and contexts)
|
||||||
|
|
||||||
|
@item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.}
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@subsection JSON
|
||||||
|
|
||||||
|
The JSON parser is currently more tolerant than the specification.
|
||||||
|
|
||||||
|
@subsection ECMA402
|
||||||
|
|
||||||
|
ECMA402 (Internationalization API) is not supported.
|
||||||
|
|
||||||
|
@subsection Extensions
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item The directive @code{"use strip"} indicates that the debug information (including the source code of the functions) should not be retained to save memory. As @code{"use strict"}, the directive can be global to a script or local to a function.
|
||||||
|
|
||||||
|
@item The first line of a script beginning with @code{#!} is ignored.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@subsection Mathematical extensions
|
||||||
|
|
||||||
|
The mathematical extensions are available in the @code{qjsbn} version and are fully
|
||||||
|
backward compatible with standard Javascript. See @code{jsbignum.pdf}
|
||||||
|
for more information.
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item The @code{BigInt} (big integers) TC39 proposal is supported.
|
||||||
|
|
||||||
|
@item @code{BigFloat} support: arbitrary large floating point numbers in base 2.
|
||||||
|
|
||||||
|
@item Operator overloading.
|
||||||
|
|
||||||
|
@item The directive @code{"use bigint"} enables the bigint mode where integers are @code{BigInt} by default.
|
||||||
|
|
||||||
|
@item The directive @code{"use math"} enables the math mode where the division and power operators on integers produce fractions. Floating point literals are @code{BigFloat} by default and integers are @code{BigInt} by default.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section Modules
|
||||||
|
|
||||||
|
ES6 modules are fully supported. The default name resolution is the
|
||||||
|
following:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
|
||||||
|
@item Module names with a leading @code{.} or @code{..} are relative
|
||||||
|
to the current module path.
|
||||||
|
|
||||||
|
@item Module names without a leading @code{.} or @code{..} are system
|
||||||
|
modules, such as @code{std} or @code{os}.
|
||||||
|
|
||||||
|
@item Module names ending with @code{.so} are native modules using the
|
||||||
|
QuickJS C API.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@section Standard library
|
||||||
|
|
||||||
|
The standard library is included by default in the command line
|
||||||
|
interpreter. It contains the two modules @code{std} and @code{os} and
|
||||||
|
a few global objects.
|
||||||
|
|
||||||
|
@subsection Global objects
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item scriptArgs
|
||||||
|
Provides the command line arguments. The first argument is the script name.
|
||||||
|
@item print(...args)
|
||||||
|
Print the arguments separated by spaces and a trailing newline.
|
||||||
|
@item console.log(...args)
|
||||||
|
Same as print().
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{std} module
|
||||||
|
|
||||||
|
The @code{std} module provides wrappers to the libc @file{stdlib.h}
|
||||||
|
and @file{stdio.h} and a few other utilities.
|
||||||
|
|
||||||
|
Available exports:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
|
||||||
|
@item exit(n)
|
||||||
|
Exit the process.
|
||||||
|
|
||||||
|
@item evalScript(str)
|
||||||
|
Evaluate the string @code{str} as a script (global eval).
|
||||||
|
|
||||||
|
@item loadScript(filename)
|
||||||
|
Evaluate the file @code{filename} as a script (global eval).
|
||||||
|
|
||||||
|
@item Error(errno)
|
||||||
|
|
||||||
|
@code{std.Error} constructor. Error instances contain the field
|
||||||
|
@code{errno} (error code) and @code{message} (result of
|
||||||
|
@code{std.Error.strerror(errno)}).
|
||||||
|
|
||||||
|
The constructor contains the following fields:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item EINVAL
|
||||||
|
@item EIO
|
||||||
|
@item EACCES
|
||||||
|
@item EEXIST
|
||||||
|
@item ENOSPC
|
||||||
|
@item ENOSYS
|
||||||
|
@item EBUSY
|
||||||
|
@item ENOENT
|
||||||
|
@item EPERM
|
||||||
|
@item EPIPE
|
||||||
|
Integer value of common errors (additional error codes may be defined).
|
||||||
|
@item strerror(errno)
|
||||||
|
Return a string that describes the error @code{errno}.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@item open(filename, flags)
|
||||||
|
Open a file (wrapper to the libc @code{fopen()}). Throws
|
||||||
|
@code{std.Error} in case of I/O error.
|
||||||
|
|
||||||
|
@item tmpfile()
|
||||||
|
Open a temporary file. Throws @code{std.Error} in case of I/O error.
|
||||||
|
|
||||||
|
@item puts(str)
|
||||||
|
Equivalent to @code{std.out.puts(str)}.
|
||||||
|
|
||||||
|
@item printf(fmt, ...args)
|
||||||
|
Equivalent to @code{std.out.printf(fmt, ...args)}
|
||||||
|
|
||||||
|
@item sprintf(fmt, ...args)
|
||||||
|
Equivalent to the libc sprintf().
|
||||||
|
|
||||||
|
@item in
|
||||||
|
@item out
|
||||||
|
@item err
|
||||||
|
Wrappers to the libc file @code{stdin}, @code{stdout}, @code{stderr}.
|
||||||
|
|
||||||
|
@item SEEK_SET
|
||||||
|
@item SEEK_CUR
|
||||||
|
@item SEEK_END
|
||||||
|
Constants for seek().
|
||||||
|
|
||||||
|
@item global
|
||||||
|
Reference to the global object.
|
||||||
|
|
||||||
|
@item gc()
|
||||||
|
Manually invoke the cycle removal algorithm. The cycle removal
|
||||||
|
algorithm is automatically started when needed, so this function is
|
||||||
|
useful in case of specific memory constraints or for testing.
|
||||||
|
|
||||||
|
@item getenv(name)
|
||||||
|
Return the value of the environment variable @code{name} or
|
||||||
|
@code{undefined} if it is not defined.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
FILE prototype:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item close()
|
||||||
|
Close the file.
|
||||||
|
@item puts(str)
|
||||||
|
Outputs the string with the UTF-8 encoding.
|
||||||
|
@item printf(fmt, ...args)
|
||||||
|
Formatted printf, same formats as the libc printf.
|
||||||
|
@item flush()
|
||||||
|
Flush the buffered file.
|
||||||
|
@item seek(offset, whence)
|
||||||
|
Seek to a give file position (whence is @code{std.SEEK_*}). Throws a
|
||||||
|
@code{std.Error} in case of I/O error.
|
||||||
|
@item tell()
|
||||||
|
Return the current file position.
|
||||||
|
@item eof()
|
||||||
|
Return true if end of file.
|
||||||
|
@item fileno()
|
||||||
|
Return the associated OS handle.
|
||||||
|
|
||||||
|
@item read(buffer, position, length)
|
||||||
|
Read @code{length} bytes from the file to the ArrayBuffer @code{buffer} at byte
|
||||||
|
position @code{position} (wrapper to the libc @code{fread}).
|
||||||
|
|
||||||
|
@item write(buffer, position, length)
|
||||||
|
Write @code{length} bytes to the file from the ArrayBuffer @code{buffer} at byte
|
||||||
|
position @code{position} (wrapper to the libc @code{fread}).
|
||||||
|
|
||||||
|
@item getline()
|
||||||
|
Return the next line from the file, assuming UTF-8 encoding, excluding
|
||||||
|
the trailing line feed.
|
||||||
|
|
||||||
|
@item getByte()
|
||||||
|
Return the next byte from the file.
|
||||||
|
|
||||||
|
@item putByte(c)
|
||||||
|
Write one byte to the file.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@subsection @code{os} module
|
||||||
|
|
||||||
|
The @code{os} module provides Operating System specific functions:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item low level file access
|
||||||
|
@item signals
|
||||||
|
@item timers
|
||||||
|
@item asynchronous I/O
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
The OS functions usually return 0 if OK or an OS specific negative
|
||||||
|
error code.
|
||||||
|
|
||||||
|
Available exports:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item open(filename, flags, mode = 0o666)
|
||||||
|
Open a file. Return a handle or < 0 if error.
|
||||||
|
|
||||||
|
@item O_RDONLY
|
||||||
|
@item O_WRONLY
|
||||||
|
@item O_RDWR
|
||||||
|
@item O_APPEND
|
||||||
|
@item O_CREAT
|
||||||
|
@item O_EXCL
|
||||||
|
@item O_TRUNC
|
||||||
|
POSIX open flags.
|
||||||
|
|
||||||
|
@item O_TEXT
|
||||||
|
(Windows specific). Open the file in text mode. The default is binary mode.
|
||||||
|
|
||||||
|
@item close(fd)
|
||||||
|
Close the file handle @code{fd}.
|
||||||
|
|
||||||
|
@item seek(fd, offset, whence)
|
||||||
|
Seek in the file. Use @code{std.SEEK_*} for @code{whence}.
|
||||||
|
|
||||||
|
@item read(fd, buffer, offset, length)
|
||||||
|
Read @code{length} bytes from the file handle @code{fd} to the
|
||||||
|
ArrayBuffer @code{buffer} at byte position @code{offset}.
|
||||||
|
Return the number of read bytes or < 0 if error.
|
||||||
|
|
||||||
|
@item write(fd, buffer, offset, length)
|
||||||
|
Write @code{length} bytes to the file handle @code{fd} from the
|
||||||
|
ArrayBuffer @code{buffer} at byte position @code{offset}.
|
||||||
|
Return the number of written bytes or < 0 if error.
|
||||||
|
|
||||||
|
@item isatty(fd)
|
||||||
|
Return @code{true} is @code{fd} is a TTY (terminal) handle.
|
||||||
|
|
||||||
|
@item ttyGetWinSize(fd)
|
||||||
|
Return the TTY size as @code{[width, height]} or @code{null} if not available.
|
||||||
|
|
||||||
|
@item ttySetRaw(fd)
|
||||||
|
Set the TTY in raw mode.
|
||||||
|
|
||||||
|
@item remove(filename)
|
||||||
|
Remove a file. Return 0 if OK or < 0 if error.
|
||||||
|
|
||||||
|
@item rename(oldname, newname)
|
||||||
|
Rename a file. Return 0 if OK or < 0 if error.
|
||||||
|
|
||||||
|
@item setReadHandler(fd, func)
|
||||||
|
Add a read handler to the file handle @code{fd}. @code{func} is called
|
||||||
|
each time there is data pending for @code{fd}. A single read handler
|
||||||
|
per file handle is supported. Use @code{func = null} to remove the
|
||||||
|
hander.
|
||||||
|
|
||||||
|
@item setWriteHandler(fd, func)
|
||||||
|
Add a write handler to the file handle @code{fd}. @code{func} is
|
||||||
|
called each time data can be written to @code{fd}. A single write
|
||||||
|
handler per file handle is supported. Use @code{func = null} to remove
|
||||||
|
the hander.
|
||||||
|
|
||||||
|
@item signal(signal, func)
|
||||||
|
Call the function @code{func} when the signal @code{signal}
|
||||||
|
happens. Only a single handler per signal number is supported. Use
|
||||||
|
@code{null} to set the default handler or @code{undefined} to ignore
|
||||||
|
the signal.
|
||||||
|
|
||||||
|
@item SIGINT
|
||||||
|
@item SIGABRT
|
||||||
|
@item SIGFPE
|
||||||
|
@item SIGILL
|
||||||
|
@item SIGSEGV
|
||||||
|
@item SIGTERM
|
||||||
|
POSIX signal numbers.
|
||||||
|
|
||||||
|
@item setTimeout(delay, func)
|
||||||
|
Call the function @code{func} after @code{delay} ms. Return a handle
|
||||||
|
to the timer.
|
||||||
|
|
||||||
|
@item clearTimer(handle)
|
||||||
|
Cancel a timer.
|
||||||
|
|
||||||
|
@item platform
|
||||||
|
Return a string representing the platform: @code{"linux"}, @code{"darwin"},
|
||||||
|
@code{"win32"} or @code{"js"}.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@section QuickJS C API
|
||||||
|
|
||||||
|
The C API was designed to be simple and efficient. The C API is
|
||||||
|
defined in the header @code{quickjs.h}.
|
||||||
|
|
||||||
|
@subsection Runtime and contexts
|
||||||
|
|
||||||
|
@code{JSRuntime} represents a Javascript runtime corresponding to an
|
||||||
|
object heap. Several runtimes can exist at the same time but they
|
||||||
|
cannot exchange objects. Inside a given runtime, no multi-threading is
|
||||||
|
supported.
|
||||||
|
|
||||||
|
@code{JSContext} represents a Javascript context (or Realm). Each
|
||||||
|
JSContext has its own global objects and system objects. There can be
|
||||||
|
several JSContexts per JSRuntime and they can share objects, similary
|
||||||
|
to frames of the same origin sharing Javascript objects in a
|
||||||
|
web browser.
|
||||||
|
|
||||||
|
@subsection JSValue
|
||||||
|
|
||||||
|
@code{JSValue} represents a Javascript value which can be a primitive
|
||||||
|
type or an object. Reference counting is used, so it is important to
|
||||||
|
explicitely duplicate (@code{JS_DupValue()}, increment the reference
|
||||||
|
count) or free (@code{JS_FreeValue()}, decrement the reference count)
|
||||||
|
JSValues.
|
||||||
|
|
||||||
|
@subsection C functions
|
||||||
|
|
||||||
|
C functions can be created with
|
||||||
|
@code{JS_NewCFunction()}. @code{JS_SetPropertyFunctionList()} is a
|
||||||
|
shortcut to easily add functions, setters and getters properties to a
|
||||||
|
given object.
|
||||||
|
|
||||||
|
Unlike other embedded Javascript engines, there is no implicit stack,
|
||||||
|
so C functions get their parameters as normal C parameters. As a
|
||||||
|
general rule, C functions take constant @code{JSValue}s as parameters
|
||||||
|
(so they don't need to free them) and return a newly allocated (=live)
|
||||||
|
@code{JSValue}.
|
||||||
|
|
||||||
|
@subsection Exceptions
|
||||||
|
|
||||||
|
Exceptions: most C functions can return a Javascript exception. It
|
||||||
|
must be explicitely tested and handled by the C code. The specific
|
||||||
|
@code{JSValue} @code{JS_EXCEPTION} indicates that an exception
|
||||||
|
occured. The actual exception object is stored in the
|
||||||
|
@code{JSContext} and can be retrieved with @code{JS_GetException()}.
|
||||||
|
|
||||||
|
@subsection Script evaluation
|
||||||
|
|
||||||
|
Use @code{JS_Eval()} to evaluate a script or module source.
|
||||||
|
|
||||||
|
If the script or module was compiled to bytecode with @code{qjsc},
|
||||||
|
@code{JS_EvalBinary()} achieves the same result. The advantage is that
|
||||||
|
no compilation is needed so it is faster and smaller because the compiler
|
||||||
|
can be removed from the executable if no @code{eval} is required.
|
||||||
|
|
||||||
|
Note: the bytecode format is linked to a given QuickJS
|
||||||
|
version. Moreover, no security check is done before its
|
||||||
|
execution. Hence the bytecode should not be loaded from untrusted
|
||||||
|
sources. That's why there is no option to output the bytecode to a
|
||||||
|
binary file in @code{qjsc}.
|
||||||
|
|
||||||
|
@subsection JS Classes
|
||||||
|
|
||||||
|
C opaque data can be attached to a Javascript object. The type of the
|
||||||
|
C opaque data is determined with the class ID (@code{JSClassID}) of
|
||||||
|
the object. Hence the first step is to register a new class ID and JS
|
||||||
|
class (@code{JS_NewClassID()}, @code{JS_NewClass()}). Then you can
|
||||||
|
create objects of this class with @code{JS_NewObjectClass()} and get or
|
||||||
|
set the C opaque point with
|
||||||
|
@code{JS_GetOpaque()}/@code{JS_SetOpaque()}.
|
||||||
|
|
||||||
|
When defining a new JS class, it is possible to declare a finalizer
|
||||||
|
which is called when the object is destroyed. A @code{gc_mark} method
|
||||||
|
can be provided so that the cycle removal algorithm can find the other
|
||||||
|
objects referenced by this object. Other methods are available to
|
||||||
|
define exotic object behaviors.
|
||||||
|
|
||||||
|
The Class ID are globally allocated (i.e. for all runtimes). The
|
||||||
|
JSClass are allocated per @code{JSRuntime}. @code{JS_SetClassProto()}
|
||||||
|
is used to define a prototype for a given class in a given
|
||||||
|
JSContext. @code{JS_NewObjectClass()} sets this prototype in the
|
||||||
|
created object.
|
||||||
|
|
||||||
|
Examples are available in @file{js_libc.c}.
|
||||||
|
|
||||||
|
@subsection C Modules
|
||||||
|
|
||||||
|
Native ES6 modules are supported and can be dynamically or statically
|
||||||
|
linked. Look at the @file{test_bjson} and @file{bjson.so}
|
||||||
|
examples. The standard library @file{js_libc.c} is also a good example
|
||||||
|
of a native module.
|
||||||
|
|
||||||
|
@subsection Memory handling
|
||||||
|
|
||||||
|
Use @code{JS_SetMemoryLimit()} to set a global memory allocation limit
|
||||||
|
to a given JSRuntime.
|
||||||
|
|
||||||
|
Custom memory allocation functions can be provided with
|
||||||
|
@code{JS_NewRuntime2()}.
|
||||||
|
|
||||||
|
The maximum system stack size can be set with @code{JS_SetMaxStackSize()}.
|
||||||
|
|
||||||
|
@subsection Execution timeout and interrupts
|
||||||
|
|
||||||
|
Use @code{JS_SetInterruptHandler()} to set a callback which is
|
||||||
|
regularly called by the engine when it is executing code. This
|
||||||
|
callback can be used to implement an execution timeout.
|
||||||
|
|
||||||
|
It is used by the command line interpreter to implement a
|
||||||
|
@code{Ctrl-C} handler.
|
||||||
|
|
||||||
|
@chapter Internals
|
||||||
|
|
||||||
|
@section Bytecode
|
||||||
|
|
||||||
|
The compiler generates bytecode directly with no intermediate
|
||||||
|
representation such as a parse tree, hence it is very fast. Several
|
||||||
|
optimizations passes are done over the generated bytecode.
|
||||||
|
|
||||||
|
A stack-based bytecode was chosen because it is simple and generates
|
||||||
|
compact code.
|
||||||
|
|
||||||
|
For each function, the maximum stack size is computed at compile time so that
|
||||||
|
no runtime stack overflow tests are needed.
|
||||||
|
|
||||||
|
A separate compressed line number table is maintained for the debug
|
||||||
|
information.
|
||||||
|
|
||||||
|
Access to closure variables is optimized and is almost as fast as local
|
||||||
|
variables.
|
||||||
|
|
||||||
|
Direct @code{eval} in strict mode is optimized.
|
||||||
|
|
||||||
|
@section Executable generation
|
||||||
|
|
||||||
|
@subsection @code{qjsc} compiler
|
||||||
|
|
||||||
|
The @code{qjsc} compiler generates C sources from Javascript files. By
|
||||||
|
default the C sources are compiled with the system compiler
|
||||||
|
(@code{gcc} or @code{clang}).
|
||||||
|
|
||||||
|
The generated C source contains the bytecode of the compiled functions
|
||||||
|
or modules. If a full complete executable is needed, it also
|
||||||
|
contains a @code{main()} function with the necessary C code to initialize the
|
||||||
|
Javascript engine and to load and execute the compiled functions and
|
||||||
|
modules.
|
||||||
|
|
||||||
|
Javascript code can be mixed with C modules.
|
||||||
|
|
||||||
|
In order to have smaller executables, specific Javascript features can
|
||||||
|
be disabled, in particular @code{eval} or the regular expressions. The
|
||||||
|
code removal relies on the Link Time Optimization of the system
|
||||||
|
compiler.
|
||||||
|
|
||||||
|
@subsection Binary JSON
|
||||||
|
|
||||||
|
@code{qjsc} works by compiling scripts or modules and then serializing
|
||||||
|
them to a binary format. A subset of this format (without functions or
|
||||||
|
modules) can be used as binary JSON. The example @file{test_bjson.js}
|
||||||
|
shows how to use it.
|
||||||
|
|
||||||
|
Warning: the binary JSON format may change without notice, so it
|
||||||
|
should not be used to store persistent data. The @file{test_bjson.js}
|
||||||
|
example is only used to test the binary object format functions.
|
||||||
|
|
||||||
|
@section Runtime
|
||||||
|
|
||||||
|
@subsection Strings
|
||||||
|
|
||||||
|
Strings are stored either as an 8 bit or a 16 bit array of
|
||||||
|
characters. Hence random access to characters is always fast.
|
||||||
|
|
||||||
|
The C API provides functions to convert Javascript Strings to C UTF-8 encoded
|
||||||
|
strings. The most common case where the Javascript string contains
|
||||||
|
only ASCII characters involves no copying.
|
||||||
|
|
||||||
|
@subsection Objects
|
||||||
|
|
||||||
|
The object shapes (object prototype, property names and flags) are shared
|
||||||
|
between objects to save memory.
|
||||||
|
|
||||||
|
Arrays with no holes (except at the end of the array) are optimized.
|
||||||
|
|
||||||
|
TypedArray accesses are optimized.
|
||||||
|
|
||||||
|
@subsection Atoms
|
||||||
|
|
||||||
|
Object property names and some strings are stored as Atoms (unique
|
||||||
|
strings) to save memory and allow fast comparison. Atoms are
|
||||||
|
represented as a 32 bit integer. Half of the atom range is reserved for
|
||||||
|
immediate integer literals from @math{0} to @math{2^{31}-1}.
|
||||||
|
|
||||||
|
@subsection Numbers
|
||||||
|
|
||||||
|
Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754
|
||||||
|
floating point values. Most operations have fast paths for the 32-bit
|
||||||
|
integer case.
|
||||||
|
|
||||||
|
@subsection Garbage collection
|
||||||
|
|
||||||
|
Reference counting is used to free objects automatically and
|
||||||
|
deterministically. A separate cycle removal pass is done when the allocated
|
||||||
|
memory becomes too large. The cycle removal algorithm only uses the
|
||||||
|
reference counts and the object content, so no explicit garbage
|
||||||
|
collection roots need to be manipulated in the C code.
|
||||||
|
|
||||||
|
@subsection JSValue
|
||||||
|
|
||||||
|
It is a Javascript value which can be a primitive type (such as
|
||||||
|
Number, String, ...) or an Object. NaN boxing is used in the 32-bit version
|
||||||
|
to store 64-bit floating point numbers. The representation is
|
||||||
|
optimized so that 32-bit integers and reference counted values can be
|
||||||
|
efficiently tested.
|
||||||
|
|
||||||
|
In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The
|
||||||
|
rationale is that in 64-bit code memory usage is less critical.
|
||||||
|
|
||||||
|
In both cases (32 or 64 bits), JSValue exactly fits two CPU registers,
|
||||||
|
so it can be efficiently returned by C functions.
|
||||||
|
|
||||||
|
@subsection Function call
|
||||||
|
|
||||||
|
The engine is optimized so that function calls are fast. The system
|
||||||
|
stack holds the Javascript parameters and local variables.
|
||||||
|
|
||||||
|
@section RegExp
|
||||||
|
|
||||||
|
A specific regular expression engine was developped. It is both small
|
||||||
|
and efficient and supports all the ES2019 features including the
|
||||||
|
Unicode properties. As the Javascript compiler, it directly generates
|
||||||
|
bytecode without a parse tree.
|
||||||
|
|
||||||
|
Backtracking with an explicit stack is used so that there is no
|
||||||
|
recursion on the system stack. Simple quantizers are specifically
|
||||||
|
optimized to avoid recursions.
|
||||||
|
|
||||||
|
Infinite recursions coming from quantizers with empty terms are
|
||||||
|
avoided.
|
||||||
|
|
||||||
|
The full regexp library weights about 15 KiB (x86 code), excluding the
|
||||||
|
Unicode library.
|
||||||
|
|
||||||
|
@section Unicode
|
||||||
|
|
||||||
|
A specific Unicode library was developped so that there is no
|
||||||
|
dependency on an external large Unicode library such as ICU. All the
|
||||||
|
Unicode tables are compressed while keeping a reasonnable access
|
||||||
|
speed.
|
||||||
|
|
||||||
|
The library supports case conversion, Unicode normalization, Unicode
|
||||||
|
script queries, Unicode general category queries and all Unicode
|
||||||
|
binary properties.
|
||||||
|
|
||||||
|
The full Unicode library weights about 45 KiB (x86 code).
|
||||||
|
|
||||||
|
@section BigInt and BigFloat
|
||||||
|
|
||||||
|
BigInt and BigFloat are implemented with the @code{libbf}
|
||||||
|
library@footnote{@url{https://bellard.org/libbf}}. It weights about 60
|
||||||
|
KiB (x86 code) and provides arbitrary precision IEEE 754 floating
|
||||||
|
point operations and transcendental functions with exact rounding.
|
||||||
|
|
||||||
|
@chapter License
|
||||||
|
|
||||||
|
QuickJS is released under the MIT license.
|
||||||
|
|
||||||
|
Unless otherwise specified, the QuickJS sources are copyright Fabrice
|
||||||
|
Bellard and Charlie Gordon.
|
||||||
|
|
||||||
|
@bye
|
|
@ -0,0 +1,6 @@
|
||||||
|
/* example of JS module importing a C module */
|
||||||
|
|
||||||
|
import { fib } from "./fib.so";
|
||||||
|
|
||||||
|
console.log("Hello World");
|
||||||
|
console.log("fib(10)=", fib(10));
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* QuickJS: Example of C module
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "../quickjs.h"
|
||||||
|
|
||||||
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
static int fib(int n)
|
||||||
|
{
|
||||||
|
if (n <= 0)
|
||||||
|
return 0;
|
||||||
|
else if (n == 1)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return fib(n - 1) + fib(n - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_fib(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
int n, res;
|
||||||
|
if (JS_ToInt32(ctx, &n, argv[0]))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
res = fib(n);
|
||||||
|
return JS_NewInt32(ctx, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_fib_funcs[] = {
|
||||||
|
JS_CFUNC_DEF("fib", 1, js_fib ),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int js_fib_init(JSContext *ctx, JSModuleDef *m)
|
||||||
|
{
|
||||||
|
return JS_SetModuleExportList(ctx, m, js_fib_funcs,
|
||||||
|
countof(js_fib_funcs));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JS_SHARED_LIBRARY
|
||||||
|
#define JS_INIT_MODULE js_init_module
|
||||||
|
#else
|
||||||
|
#define JS_INIT_MODULE js_init_module_fib
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
|
||||||
|
{
|
||||||
|
JSModuleDef *m;
|
||||||
|
m = JS_NewCModule(ctx, module_name, js_fib_init);
|
||||||
|
if (!m)
|
||||||
|
return NULL;
|
||||||
|
JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs));
|
||||||
|
return m;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* fib module */
|
||||||
|
export function fib(n)
|
||||||
|
{
|
||||||
|
if (n <= 0)
|
||||||
|
return 0;
|
||||||
|
else if (n == 1)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return fib(n - 1) + fib(n - 2);
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
console.log("Hello World");
|
|
@ -0,0 +1,6 @@
|
||||||
|
/* example of JS module */
|
||||||
|
|
||||||
|
import { fib } from "./fib_module.js";
|
||||||
|
|
||||||
|
console.log("Hello World");
|
||||||
|
console.log("fib(10)=", fib(10));
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* PI computation in Javascript using the QuickJS bignum extensions
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
"use bigint";
|
||||||
|
|
||||||
|
/* compute PI with a precision of 'prec' bits */
|
||||||
|
function calc_pi(prec) {
|
||||||
|
const CHUD_A = 13591409;
|
||||||
|
const CHUD_B = 545140134;
|
||||||
|
const CHUD_C = 640320;
|
||||||
|
const CHUD_C3 = 10939058860032000; /* C^3/24 */
|
||||||
|
const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */
|
||||||
|
|
||||||
|
/* return [P, Q, G] */
|
||||||
|
function chud_bs(a, b, need_G) {
|
||||||
|
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2;
|
||||||
|
if (a == (b - 1)) {
|
||||||
|
G = (2 * b - 1) * (6 * b - 1) * (6 * b - 5);
|
||||||
|
P = BigFloat(G * (CHUD_B * b + CHUD_A));
|
||||||
|
if (b & 1)
|
||||||
|
P = -P;
|
||||||
|
G = BigFloat(G);
|
||||||
|
Q = BigFloat(b * b * b * CHUD_C3);
|
||||||
|
} else {
|
||||||
|
c = (a + b) >> 1;
|
||||||
|
[P1, Q1, G1] = chud_bs(a, c, true);
|
||||||
|
[P2, Q2, G2] = chud_bs(c, b, need_G);
|
||||||
|
P = P1 * Q2 + P2 * G1;
|
||||||
|
Q = Q1 * Q2;
|
||||||
|
if (need_G)
|
||||||
|
G = G1 * G2;
|
||||||
|
else
|
||||||
|
G = 0;
|
||||||
|
}
|
||||||
|
return [P, Q, G];
|
||||||
|
}
|
||||||
|
|
||||||
|
var n, P, Q, G;
|
||||||
|
/* number of serie terms */
|
||||||
|
n = Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM) + 10;
|
||||||
|
[P, Q, G] = chud_bs(0, n, false);
|
||||||
|
Q = Q / (P + Q * CHUD_A);
|
||||||
|
G = (CHUD_C / 12) * BigFloat.sqrt(CHUD_C);
|
||||||
|
return Q * G;
|
||||||
|
}
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var r, n_digits, n_bits;
|
||||||
|
if (typeof scriptArgs != "undefined") {
|
||||||
|
if (scriptArgs.length < 2) {
|
||||||
|
print("usage: pi n_digits");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
n_digits = scriptArgs[1];
|
||||||
|
} else {
|
||||||
|
n_digits = 1000;
|
||||||
|
}
|
||||||
|
n_bits = Math.ceil(n_digits * Math.log2(10));
|
||||||
|
/* we add more bits to reduce the probability of bad rounding for
|
||||||
|
the last digits */
|
||||||
|
BigFloatEnv.setPrec( () => {
|
||||||
|
r = calc_pi();
|
||||||
|
print(r.toFixed(n_digits, BigFloatEnv.RNDZ));
|
||||||
|
}, n_bits + 32);
|
||||||
|
})();
|
|
@ -0,0 +1,918 @@
|
||||||
|
/*
|
||||||
|
* Javascript Compressor
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2018 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
|
||||||
|
typedef struct JSToken {
|
||||||
|
int tok;
|
||||||
|
char buf[20];
|
||||||
|
char *str;
|
||||||
|
int len;
|
||||||
|
int size;
|
||||||
|
int line_num; /* line number for start of token */
|
||||||
|
int lines; /* number of embedded linefeeds in token */
|
||||||
|
} JSToken;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TOK_EOF = 256,
|
||||||
|
TOK_IDENT,
|
||||||
|
TOK_STR1,
|
||||||
|
TOK_STR2,
|
||||||
|
TOK_STR3,
|
||||||
|
TOK_NUM,
|
||||||
|
TOK_COM,
|
||||||
|
TOK_LCOM,
|
||||||
|
};
|
||||||
|
|
||||||
|
void tok_reset(JSToken *tt)
|
||||||
|
{
|
||||||
|
if (tt->str != tt->buf) {
|
||||||
|
free(tt->str);
|
||||||
|
tt->str = tt->buf;
|
||||||
|
tt->size = sizeof(tt->buf);
|
||||||
|
}
|
||||||
|
tt->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tok_add_ch(JSToken *tt, int c)
|
||||||
|
{
|
||||||
|
if (tt->len + 1 > tt->size) {
|
||||||
|
tt->size *= 2;
|
||||||
|
if (tt->str == tt->buf) {
|
||||||
|
tt->str = malloc(tt->size);
|
||||||
|
memcpy(tt->str, tt->buf, tt->len);
|
||||||
|
} else {
|
||||||
|
tt->str = realloc(tt->str, tt->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tt->str[tt->len++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *infile;
|
||||||
|
const char *filename;
|
||||||
|
int output_line_num;
|
||||||
|
int line_num;
|
||||||
|
int ch;
|
||||||
|
JSToken tokc;
|
||||||
|
|
||||||
|
int skip_mask;
|
||||||
|
#define DEFINE_MAX 20
|
||||||
|
char *define_tab[DEFINE_MAX];
|
||||||
|
int define_len;
|
||||||
|
|
||||||
|
void error(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if (filename) {
|
||||||
|
fprintf(stderr, "%s:%d: ", filename, line_num);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "jscompress: ");
|
||||||
|
}
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(ap);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void define_symbol(const char *def)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < define_len; i++) {
|
||||||
|
if (!strcmp(tokc.str, define_tab[i]))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (define_len >= DEFINE_MAX)
|
||||||
|
error("too many defines");
|
||||||
|
define_tab[define_len++] = strdup(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefine_symbol(const char *def)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = j = 0; i < define_len; i++) {
|
||||||
|
if (!strcmp(tokc.str, define_tab[i])) {
|
||||||
|
free(define_tab[i]);
|
||||||
|
} else {
|
||||||
|
define_tab[j++] = define_tab[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
define_len = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *find_symbol(const char *def)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < define_len; i++) {
|
||||||
|
if (!strcmp(tokc.str, define_tab[i]))
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void next(void);
|
||||||
|
|
||||||
|
void nextch(void)
|
||||||
|
{
|
||||||
|
ch = fgetc(infile);
|
||||||
|
if (ch == '\n')
|
||||||
|
line_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skip_blanks(void)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
next();
|
||||||
|
if (tokc.tok != ' ' && tokc.tok != '\t' &&
|
||||||
|
tokc.tok != TOK_COM && tokc.tok != TOK_LCOM)
|
||||||
|
return tokc.tok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_directive(void)
|
||||||
|
{
|
||||||
|
int ifdef, mask = skip_mask;
|
||||||
|
/* simplistic preprocessor:
|
||||||
|
#define / #undef / #ifdef / #ifndef / #else / #endif
|
||||||
|
no symbol substitution.
|
||||||
|
*/
|
||||||
|
skip_mask = 0; /* disable skipping to parse preprocessor line */
|
||||||
|
nextch();
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected preprocessing directive after #");
|
||||||
|
|
||||||
|
if (!strcmp(tokc.str, "define")) {
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected identifier after #define");
|
||||||
|
define_symbol(tokc.str);
|
||||||
|
} else if (!strcmp(tokc.str, "undef")) {
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected identifier after #undef");
|
||||||
|
undefine_symbol(tokc.str);
|
||||||
|
} else if ((ifdef = 1, !strcmp(tokc.str, "ifdef")) ||
|
||||||
|
(ifdef = 0, !strcmp(tokc.str, "ifndef"))) {
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected identifier after #ifdef/#ifndef");
|
||||||
|
mask = (mask << 2) | 2 | ifdef;
|
||||||
|
if (find_symbol(tokc.str))
|
||||||
|
mask ^= 1;
|
||||||
|
} else if (!strcmp(tokc.str, "else")) {
|
||||||
|
if (!(mask & 2))
|
||||||
|
error("#else without a #if");
|
||||||
|
mask ^= 1;
|
||||||
|
} else if (!strcmp(tokc.str, "endif")) {
|
||||||
|
if (!(mask & 2))
|
||||||
|
error("#endif without a #if");
|
||||||
|
mask >>= 2;
|
||||||
|
} else {
|
||||||
|
error("unsupported preprocessing directive");
|
||||||
|
}
|
||||||
|
if (skip_blanks() != '\n')
|
||||||
|
error("extra characters on preprocessing line");
|
||||||
|
skip_mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return -1 if invalid char */
|
||||||
|
static int hex_to_num(int ch)
|
||||||
|
{
|
||||||
|
if (ch >= 'a' && ch <= 'f')
|
||||||
|
return ch - 'a' + 10;
|
||||||
|
else if (ch >= 'A' && ch <= 'F')
|
||||||
|
return ch - 'A' + 10;
|
||||||
|
else if (ch >= '0' && ch <= '9')
|
||||||
|
return ch - '0';
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void next(void)
|
||||||
|
{
|
||||||
|
again:
|
||||||
|
tok_reset(&tokc);
|
||||||
|
tokc.line_num = line_num;
|
||||||
|
tokc.lines = 0;
|
||||||
|
switch(ch) {
|
||||||
|
case EOF:
|
||||||
|
tokc.tok = TOK_EOF;
|
||||||
|
if (skip_mask)
|
||||||
|
error("missing #endif");
|
||||||
|
break;
|
||||||
|
case 'a' ... 'z':
|
||||||
|
case 'A' ... 'Z':
|
||||||
|
case '_':
|
||||||
|
case '$':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
while ((ch >= 'a' && ch <= 'z') ||
|
||||||
|
(ch >= 'A' && ch <= 'Z') ||
|
||||||
|
(ch >= '0' && ch <= '9') ||
|
||||||
|
(ch == '_' || ch == '$')) {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_IDENT;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
nextch();
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, '.');
|
||||||
|
goto has_dot;
|
||||||
|
}
|
||||||
|
tokc.tok = '.';
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
if (ch == 'x' || ch == 'X') {
|
||||||
|
/* hexa */
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
while ((ch >= 'a' && ch <= 'f') ||
|
||||||
|
(ch >= 'A' && ch <= 'F') ||
|
||||||
|
(ch >= '0' && ch <= '9')) {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_NUM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto has_digit;
|
||||||
|
|
||||||
|
case '1' ... '9':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
has_digit:
|
||||||
|
/* decimal */
|
||||||
|
while (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
if (ch == '.') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
has_dot:
|
||||||
|
while (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch == 'e' || ch == 'E') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
if (ch == '+' || ch == '-') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
while (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_NUM;
|
||||||
|
break;
|
||||||
|
case '`':
|
||||||
|
{
|
||||||
|
nextch();
|
||||||
|
while (ch != '`' && ch != EOF) {
|
||||||
|
if (ch == '\\') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
if (ch == EOF) {
|
||||||
|
error("unexpected char after '\\'");
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
} else {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextch();
|
||||||
|
tok_add_ch(&tokc, 0);
|
||||||
|
tokc.tok = TOK_STR3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
{
|
||||||
|
int n, i, c, hex_digit_count;
|
||||||
|
int quote_ch;
|
||||||
|
quote_ch = ch;
|
||||||
|
nextch();
|
||||||
|
while (ch != quote_ch && ch != EOF) {
|
||||||
|
if (ch == '\\') {
|
||||||
|
nextch();
|
||||||
|
switch(ch) {
|
||||||
|
case 'n':
|
||||||
|
tok_add_ch(&tokc, '\n');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
tok_add_ch(&tokc, '\r');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
tok_add_ch(&tokc, '\t');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
tok_add_ch(&tokc, '\v');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
case '\\':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case '0' ... '7':
|
||||||
|
n = 0;
|
||||||
|
while (ch >= '0' && ch <= '7') {
|
||||||
|
n = n * 8 + (ch - '0');
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, n);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'u':
|
||||||
|
if (ch == 'x')
|
||||||
|
hex_digit_count = 2;
|
||||||
|
else
|
||||||
|
hex_digit_count = 4;
|
||||||
|
nextch();
|
||||||
|
n = 0;
|
||||||
|
for(i = 0; i < hex_digit_count; i++) {
|
||||||
|
c = hex_to_num(ch);
|
||||||
|
if (c < 0)
|
||||||
|
error("unexpected char after '\\x'");
|
||||||
|
n = n * 16 + c;
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
if (n >= 256)
|
||||||
|
error("unicode is currently unsupported");
|
||||||
|
tok_add_ch(&tokc, n);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error("unexpected char after '\\'");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* XXX: should refuse embedded newlines */
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextch();
|
||||||
|
tok_add_ch(&tokc, 0);
|
||||||
|
if (quote_ch == '\'')
|
||||||
|
tokc.tok = TOK_STR1;
|
||||||
|
else
|
||||||
|
tokc.tok = TOK_STR2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
nextch();
|
||||||
|
if (ch == '/') {
|
||||||
|
tok_add_ch(&tokc, '/');
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
while (ch != '\n' && ch != EOF) {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_LCOM;
|
||||||
|
} else if (ch == '*') {
|
||||||
|
int last;
|
||||||
|
tok_add_ch(&tokc, '/');
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
last = 0;
|
||||||
|
for(;;) {
|
||||||
|
nextch();
|
||||||
|
if (ch == EOF)
|
||||||
|
error("unterminated comment");
|
||||||
|
if (ch == '\n')
|
||||||
|
tokc.lines++;
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
if (last == '*' && ch == '/')
|
||||||
|
break;
|
||||||
|
last = ch;
|
||||||
|
}
|
||||||
|
nextch();
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_COM;
|
||||||
|
} else {
|
||||||
|
tokc.tok = '/';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
parse_directive();
|
||||||
|
goto again;
|
||||||
|
case '\n':
|
||||||
|
/* adjust line number */
|
||||||
|
tokc.line_num--;
|
||||||
|
tokc.lines++;
|
||||||
|
/* fall thru */
|
||||||
|
default:
|
||||||
|
tokc.tok = ch;
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (skip_mask & 1)
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_tok(FILE *f, JSToken *tt)
|
||||||
|
{
|
||||||
|
/* keep output lines in sync with input lines */
|
||||||
|
while (output_line_num < tt->line_num) {
|
||||||
|
putc('\n', f);
|
||||||
|
output_line_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(tt->tok) {
|
||||||
|
case TOK_IDENT:
|
||||||
|
case TOK_COM:
|
||||||
|
case TOK_LCOM:
|
||||||
|
fprintf(f, "%s", tt->str);
|
||||||
|
break;
|
||||||
|
case TOK_NUM:
|
||||||
|
{
|
||||||
|
unsigned long a;
|
||||||
|
char *p;
|
||||||
|
a = strtoul(tt->str, &p, 0);
|
||||||
|
if (*p == '\0' && a <= 0x7fffffff) {
|
||||||
|
/* must be an integer */
|
||||||
|
fprintf(f, "%d", (int)a);
|
||||||
|
} else {
|
||||||
|
fprintf(f, "%s", tt->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOK_STR3:
|
||||||
|
fprintf(f, "`%s`", tt->str);
|
||||||
|
break;
|
||||||
|
case TOK_STR1:
|
||||||
|
case TOK_STR2:
|
||||||
|
{
|
||||||
|
int i, c, quote_ch;
|
||||||
|
if (tt->tok == TOK_STR1)
|
||||||
|
quote_ch = '\'';
|
||||||
|
else
|
||||||
|
quote_ch = '\"';
|
||||||
|
fprintf(f, "%c", quote_ch);
|
||||||
|
for(i = 0; i < tt->len - 1; i++) {
|
||||||
|
c = (uint8_t)tt->str[i];
|
||||||
|
switch(c) {
|
||||||
|
case '\r':
|
||||||
|
fprintf(f, "\\r");
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
fprintf(f, "\\n");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
fprintf(f, "\\t");
|
||||||
|
break;
|
||||||
|
case '\v':
|
||||||
|
fprintf(f, "\\v");
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
if (c == quote_ch)
|
||||||
|
fprintf(f, "\\%c", c);
|
||||||
|
else
|
||||||
|
fprintf(f, "%c", c);
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
fprintf(f, "\\\\");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* XXX: no utf-8 support! */
|
||||||
|
if (c >= 32 && c <= 255) {
|
||||||
|
fprintf(f, "%c", c);
|
||||||
|
} else if (c <= 255)
|
||||||
|
fprintf(f, "\\x%02x", c);
|
||||||
|
else
|
||||||
|
fprintf(f, "\\u%04x", c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(f, "%c", quote_ch);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (tokc.tok >= 256)
|
||||||
|
error("unsupported token in print_tok: %d", tt->tok);
|
||||||
|
fprintf(f, "%c", tt->tok);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output_line_num += tt->lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if token pasting could occur */
|
||||||
|
static BOOL compat_token(int c1, int c2)
|
||||||
|
{
|
||||||
|
if ((c1 == TOK_IDENT || c1 == TOK_NUM) &&
|
||||||
|
(c2 == TOK_IDENT || c2 == TOK_NUM))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if ((c1 == c2 && strchr("+-<>&|=*/.", c1))
|
||||||
|
|| (c2 == '=' && strchr("+-<>&|!*/^%", c1))
|
||||||
|
|| (c1 == '=' && c2 == '>')
|
||||||
|
|| (c1 == '/' && c2 == '*')
|
||||||
|
|| (c1 == '.' && c2 == TOK_NUM)
|
||||||
|
|| (c1 == TOK_NUM && c2 == '.'))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void js_compress(const char *filename, const char *outfilename,
|
||||||
|
BOOL do_strip, BOOL keep_header)
|
||||||
|
{
|
||||||
|
FILE *outfile;
|
||||||
|
int ltok, seen_space;
|
||||||
|
|
||||||
|
line_num = 1;
|
||||||
|
infile = fopen(filename, "rb");
|
||||||
|
if (!infile) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_line_num = 1;
|
||||||
|
outfile = fopen(outfilename, "wb");
|
||||||
|
if (!outfile) {
|
||||||
|
perror(outfilename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
nextch();
|
||||||
|
next();
|
||||||
|
ltok = 0;
|
||||||
|
seen_space = 0;
|
||||||
|
if (do_strip) {
|
||||||
|
if (keep_header) {
|
||||||
|
while (tokc.tok == ' ' ||
|
||||||
|
tokc.tok == '\n' ||
|
||||||
|
tokc.tok == '\t' ||
|
||||||
|
tokc.tok == '\v' ||
|
||||||
|
tokc.tok == '\b' ||
|
||||||
|
tokc.tok == '\f') {
|
||||||
|
seen_space = 1;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
if (tokc.tok == TOK_COM) {
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
//fprintf(outfile, "\n");
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
if (tokc.tok == TOK_EOF)
|
||||||
|
break;
|
||||||
|
if (tokc.tok == ' ' ||
|
||||||
|
tokc.tok == '\r' ||
|
||||||
|
tokc.tok == '\t' ||
|
||||||
|
tokc.tok == '\v' ||
|
||||||
|
tokc.tok == '\b' ||
|
||||||
|
tokc.tok == '\f' ||
|
||||||
|
tokc.tok == TOK_LCOM ||
|
||||||
|
tokc.tok == TOK_COM) {
|
||||||
|
/* don't print spaces or comments */
|
||||||
|
seen_space = 1;
|
||||||
|
} else if (tokc.tok == TOK_STR3) {
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
} else if (tokc.tok == TOK_STR1 || tokc.tok == TOK_STR2) {
|
||||||
|
int count, i;
|
||||||
|
/* find the optimal quote char */
|
||||||
|
count = 0;
|
||||||
|
for(i = 0; i < tokc.len; i++) {
|
||||||
|
if (tokc.str[i] == '\'')
|
||||||
|
count++;
|
||||||
|
else if (tokc.str[i] == '\"')
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
if (count > 0)
|
||||||
|
tokc.tok = TOK_STR2;
|
||||||
|
else if (count < 0)
|
||||||
|
tokc.tok = TOK_STR1;
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
} else {
|
||||||
|
if (seen_space && !compat_token(ltok, tokc.tok)) {
|
||||||
|
fprintf(outfile, " ");
|
||||||
|
}
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* just handle preprocessing */
|
||||||
|
while (tokc.tok != TOK_EOF) {
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(outfile);
|
||||||
|
fclose(infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HASH_SIZE 30011
|
||||||
|
#define MATCH_LEN_MIN 3
|
||||||
|
#define MATCH_LEN_MAX (4 + 63)
|
||||||
|
#define DIST_MAX 65535
|
||||||
|
|
||||||
|
static int find_longest_match(int *pdist, const uint8_t *src, int src_len,
|
||||||
|
const int *hash_next, int cur_pos)
|
||||||
|
{
|
||||||
|
int pos, i, match_len, match_pos, pos_min, len_max;
|
||||||
|
|
||||||
|
len_max = min_int(src_len - cur_pos, MATCH_LEN_MAX);
|
||||||
|
match_len = 0;
|
||||||
|
match_pos = 0;
|
||||||
|
pos_min = max_int(cur_pos - DIST_MAX - 1, 0);
|
||||||
|
pos = hash_next[cur_pos];
|
||||||
|
while (pos >= pos_min) {
|
||||||
|
for(i = 0; i < len_max; i++) {
|
||||||
|
if (src[cur_pos + i] != src[pos + i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i > match_len) {
|
||||||
|
match_len = i;
|
||||||
|
match_pos = pos;
|
||||||
|
}
|
||||||
|
pos = hash_next[pos];
|
||||||
|
}
|
||||||
|
*pdist = cur_pos - match_pos - 1;
|
||||||
|
return match_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lz_compress(uint8_t **pdst, const uint8_t *src, int src_len)
|
||||||
|
{
|
||||||
|
int *hash_table, *hash_next;
|
||||||
|
uint32_t h, v;
|
||||||
|
int i, dist, len, len1, dist1;
|
||||||
|
uint8_t *dst, *q;
|
||||||
|
|
||||||
|
/* build the hash table */
|
||||||
|
|
||||||
|
hash_table = malloc(sizeof(hash_table[0]) * HASH_SIZE);
|
||||||
|
for(i = 0; i < HASH_SIZE; i++)
|
||||||
|
hash_table[i] = -1;
|
||||||
|
hash_next = malloc(sizeof(hash_next[0]) * src_len);
|
||||||
|
for(i = 0; i < src_len; i++)
|
||||||
|
hash_next[i] = -1;
|
||||||
|
|
||||||
|
for(i = 0; i < src_len - MATCH_LEN_MIN + 1; i++) {
|
||||||
|
h = ((src[i] << 16) | (src[i + 1] << 8) | src[i + 2]) % HASH_SIZE;
|
||||||
|
hash_next[i] = hash_table[h];
|
||||||
|
hash_table[h] = i;
|
||||||
|
}
|
||||||
|
for(;i < src_len; i++) {
|
||||||
|
hash_next[i] = -1;
|
||||||
|
}
|
||||||
|
free(hash_table);
|
||||||
|
|
||||||
|
dst = malloc(src_len + 4); /* never larger than the source */
|
||||||
|
q = dst;
|
||||||
|
*q++ = src_len >> 24;
|
||||||
|
*q++ = src_len >> 16;
|
||||||
|
*q++ = src_len >> 8;
|
||||||
|
*q++ = src_len >> 0;
|
||||||
|
/* compress */
|
||||||
|
i = 0;
|
||||||
|
while (i < src_len) {
|
||||||
|
if (src[i] >= 128)
|
||||||
|
return -1;
|
||||||
|
len = find_longest_match(&dist, src, src_len, hash_next, i);
|
||||||
|
if (len >= MATCH_LEN_MIN) {
|
||||||
|
/* heuristic: see if better length just after */
|
||||||
|
len1 = find_longest_match(&dist1, src, src_len, hash_next, i + 1);
|
||||||
|
if (len1 > len)
|
||||||
|
goto no_match;
|
||||||
|
}
|
||||||
|
if (len < MATCH_LEN_MIN) {
|
||||||
|
no_match:
|
||||||
|
*q++ = src[i];
|
||||||
|
i++;
|
||||||
|
} else if (len <= (3 + 15) && dist < (1 << 10)) {
|
||||||
|
v = 0x8000 | ((len - 3) << 10) | dist;
|
||||||
|
*q++ = v >> 8;
|
||||||
|
*q++ = v;
|
||||||
|
i += len;
|
||||||
|
} else if (len >= 4 && len <= (4 + 63) && dist < (1 << 16)) {
|
||||||
|
v = 0xc00000 | ((len - 4) << 16) | dist;
|
||||||
|
*q++ = v >> 16;
|
||||||
|
*q++ = v >> 8;
|
||||||
|
*q++ = v;
|
||||||
|
i += len;
|
||||||
|
} else {
|
||||||
|
goto no_match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(hash_next);
|
||||||
|
*pdst = dst;
|
||||||
|
return q - dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_file(uint8_t **pbuf, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
uint8_t *buf;
|
||||||
|
int buf_len;
|
||||||
|
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
buf_len = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
buf = malloc(buf_len + 1);
|
||||||
|
fread(buf, 1, buf_len, f);
|
||||||
|
buf[buf_len] = '\0';
|
||||||
|
fclose(f);
|
||||||
|
*pbuf = buf;
|
||||||
|
return buf_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_file(const char *filename, const uint8_t *buf, int buf_len)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (!f) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fwrite(buf, 1, buf_len, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_c_source(const char *filename, const uint8_t *buf, int buf_len,
|
||||||
|
const char *var_name)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (!f) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fprintf(f, "/* This file is automatically generated - do not edit */\n\n");
|
||||||
|
fprintf(f, "const uint8_t %s[] = {\n", var_name);
|
||||||
|
for(i = 0; i < buf_len; i++) {
|
||||||
|
fprintf(f, " 0x%02x,", buf[i]);
|
||||||
|
if ((i % 8) == 7 || (i == buf_len - 1))
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
fprintf(f, "};\n");
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFAULT_OUTPUT_FILENAME "out.js"
|
||||||
|
|
||||||
|
void help(void)
|
||||||
|
{
|
||||||
|
printf("jscompress version 1.0 Copyright (c) 2008-2018 Fabrice Bellard\n"
|
||||||
|
"usage: jscompress [options] filename\n"
|
||||||
|
"Javascript compressor\n"
|
||||||
|
"\n"
|
||||||
|
"-h print this help\n"
|
||||||
|
"-n do not compress spaces\n"
|
||||||
|
"-H keep the first comment\n"
|
||||||
|
"-c compress to file\n"
|
||||||
|
"-C name compress to C source ('name' is the variable name)\n"
|
||||||
|
"-D symbol define preprocessor symbol\n"
|
||||||
|
"-U symbol undefine preprocessor symbol\n"
|
||||||
|
"-o outfile set the output filename (default=%s)\n",
|
||||||
|
DEFAULT_OUTPUT_FILENAME);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c, do_strip, keep_header, compress;
|
||||||
|
const char *out_filename, *c_var, *fname;
|
||||||
|
char tmpfilename[1024];
|
||||||
|
|
||||||
|
do_strip = 1;
|
||||||
|
keep_header = 0;
|
||||||
|
out_filename = DEFAULT_OUTPUT_FILENAME;
|
||||||
|
compress = 0;
|
||||||
|
c_var = NULL;
|
||||||
|
for(;;) {
|
||||||
|
c = getopt(argc, argv, "hno:HcC:D:U:");
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
switch(c) {
|
||||||
|
case 'h':
|
||||||
|
help();
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
do_strip = 0;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
out_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
keep_header = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
compress = 1;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
c_var = optarg;
|
||||||
|
compress = 1;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
define_symbol(optarg);
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
undefine_symbol(optarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (optind >= argc)
|
||||||
|
help();
|
||||||
|
|
||||||
|
filename = argv[optind++];
|
||||||
|
|
||||||
|
if (compress) {
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
/* XXX: use another directory ? */
|
||||||
|
snprintf(tmpfilename, sizeof(tmpfilename), "out.%d", getpid());
|
||||||
|
#else
|
||||||
|
snprintf(tmpfilename, sizeof(tmpfilename), "/tmp/out.%d", getpid());
|
||||||
|
#endif
|
||||||
|
fname = tmpfilename;
|
||||||
|
} else {
|
||||||
|
fname = out_filename;
|
||||||
|
}
|
||||||
|
js_compress(filename, fname, do_strip, keep_header);
|
||||||
|
|
||||||
|
if (compress) {
|
||||||
|
uint8_t *buf1, *buf2;
|
||||||
|
int buf1_len, buf2_len;
|
||||||
|
|
||||||
|
buf1_len = load_file(&buf1, fname);
|
||||||
|
unlink(fname);
|
||||||
|
buf2_len = lz_compress(&buf2, buf1, buf1_len);
|
||||||
|
if (buf2_len < 0) {
|
||||||
|
fprintf(stderr, "Could not compress file (UTF8 chars are forbidden)\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c_var) {
|
||||||
|
save_c_source(out_filename, buf2, buf2_len, c_var);
|
||||||
|
} else {
|
||||||
|
save_file(out_filename, buf2, buf2_len);
|
||||||
|
}
|
||||||
|
free(buf1);
|
||||||
|
free(buf2);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,350 @@
|
||||||
|
/*
|
||||||
|
* Tiny arbitrary precision floating point library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIBBF_H
|
||||||
|
#define LIBBF_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#define LIMB_LOG2_BITS 6
|
||||||
|
#else
|
||||||
|
#define LIMB_LOG2_BITS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
|
||||||
|
|
||||||
|
#if LIMB_BITS == 64
|
||||||
|
typedef __int128 int128_t;
|
||||||
|
typedef unsigned __int128 uint128_t;
|
||||||
|
typedef int64_t slimb_t;
|
||||||
|
typedef uint64_t limb_t;
|
||||||
|
typedef uint128_t dlimb_t;
|
||||||
|
#define EXP_MIN INT64_MIN
|
||||||
|
#define EXP_MAX INT64_MAX
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef int32_t slimb_t;
|
||||||
|
typedef uint32_t limb_t;
|
||||||
|
typedef uint64_t dlimb_t;
|
||||||
|
#define EXP_MIN INT32_MIN
|
||||||
|
#define EXP_MAX INT32_MAX
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* in bits */
|
||||||
|
#define BF_EXP_BITS_MIN 3
|
||||||
|
#define BF_EXP_BITS_MAX (LIMB_BITS - 2)
|
||||||
|
#define BF_PREC_MIN 2
|
||||||
|
#define BF_PREC_MAX (((limb_t)1 << BF_EXP_BITS_MAX) - 2)
|
||||||
|
#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
|
||||||
|
|
||||||
|
#if LIMB_BITS == 64
|
||||||
|
#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
|
||||||
|
#else
|
||||||
|
#define BF_CHKSUM_MOD 975620677U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BF_EXP_ZERO EXP_MIN
|
||||||
|
#define BF_EXP_INF (EXP_MAX - 1)
|
||||||
|
#define BF_EXP_NAN EXP_MAX
|
||||||
|
|
||||||
|
/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
|
||||||
|
+/-infinity is represented with expn = BF_EXP_INF and len = 0,
|
||||||
|
NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
struct bf_context_t *ctx;
|
||||||
|
int sign;
|
||||||
|
slimb_t expn;
|
||||||
|
limb_t len;
|
||||||
|
limb_t *tab;
|
||||||
|
} bf_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BF_RNDN, /* round to nearest, ties to even */
|
||||||
|
BF_RNDZ, /* round to zero */
|
||||||
|
BF_RNDD, /* round to -inf */
|
||||||
|
BF_RNDU, /* round to +inf */
|
||||||
|
BF_RNDNA, /* round to nearest, ties away from zero */
|
||||||
|
BF_RNDNU, /* round to nearest, ties to +inf */
|
||||||
|
BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
|
||||||
|
inexact flag is always set) */
|
||||||
|
} bf_rnd_t;
|
||||||
|
|
||||||
|
/* allow subnormal numbers (only available if the number of exponent
|
||||||
|
bits is < BF_EXP_BITS_MAX and prec != BF_PREC_INF) */
|
||||||
|
#define BF_FLAG_SUBNORMAL (1 << 3)
|
||||||
|
|
||||||
|
#define BF_RND_MASK 0x7
|
||||||
|
#define BF_EXP_BITS_SHIFT 4
|
||||||
|
#define BF_EXP_BITS_MASK 0x3f
|
||||||
|
|
||||||
|
/* contains the rounding mode and number of exponents bits */
|
||||||
|
typedef uint32_t bf_flags_t;
|
||||||
|
|
||||||
|
typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bf_t val;
|
||||||
|
limb_t prec;
|
||||||
|
} BFConstCache;
|
||||||
|
|
||||||
|
typedef struct bf_context_t {
|
||||||
|
void *realloc_opaque;
|
||||||
|
bf_realloc_func_t *realloc_func;
|
||||||
|
BFConstCache log2_cache;
|
||||||
|
BFConstCache pi_cache;
|
||||||
|
struct BFNTTState *ntt_state;
|
||||||
|
} bf_context_t;
|
||||||
|
|
||||||
|
static inline int bf_get_exp_bits(bf_flags_t flags)
|
||||||
|
{
|
||||||
|
return BF_EXP_BITS_MAX - ((flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bf_flags_t bf_set_exp_bits(int n)
|
||||||
|
{
|
||||||
|
return (BF_EXP_BITS_MAX - n) << BF_EXP_BITS_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returned status */
|
||||||
|
#define BF_ST_INVALID_OP (1 << 0)
|
||||||
|
#define BF_ST_DIVIDE_ZERO (1 << 1)
|
||||||
|
#define BF_ST_OVERFLOW (1 << 2)
|
||||||
|
#define BF_ST_UNDERFLOW (1 << 3)
|
||||||
|
#define BF_ST_INEXACT (1 << 4)
|
||||||
|
/* not used yet, indicate that a memory allocation error occured. NaN
|
||||||
|
is returned */
|
||||||
|
#define BF_ST_MEM_ERROR (1 << 5)
|
||||||
|
|
||||||
|
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
|
||||||
|
|
||||||
|
static inline slimb_t bf_max(slimb_t a, slimb_t b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline slimb_t bf_min(slimb_t a, slimb_t b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
|
||||||
|
void *realloc_opaque);
|
||||||
|
void bf_context_end(bf_context_t *s);
|
||||||
|
/* free memory allocated for the bf cache data */
|
||||||
|
void bf_clear_cache(bf_context_t *s);
|
||||||
|
|
||||||
|
static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
return s->realloc_func(s->realloc_opaque, ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bf_init(bf_context_t *s, bf_t *r);
|
||||||
|
|
||||||
|
static inline void bf_delete(bf_t *r)
|
||||||
|
{
|
||||||
|
bf_context_t *s = r->ctx;
|
||||||
|
/* we accept to delete a zeroed bf_t structure */
|
||||||
|
if (s) {
|
||||||
|
bf_realloc(s, r->tab, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bf_neg(bf_t *r)
|
||||||
|
{
|
||||||
|
r->sign ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_is_finite(const bf_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn < BF_EXP_INF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_is_nan(const bf_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn == BF_EXP_NAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_is_zero(const bf_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn == BF_EXP_ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bf_set_ui(bf_t *r, uint64_t a);
|
||||||
|
void bf_set_si(bf_t *r, int64_t a);
|
||||||
|
void bf_set_nan(bf_t *r);
|
||||||
|
void bf_set_zero(bf_t *r, int is_neg);
|
||||||
|
void bf_set_inf(bf_t *r, int is_neg);
|
||||||
|
void bf_set(bf_t *r, const bf_t *a);
|
||||||
|
void bf_move(bf_t *r, bf_t *a);
|
||||||
|
int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
|
||||||
|
void bf_set_float64(bf_t *a, double d);
|
||||||
|
|
||||||
|
int bf_cmpu(const bf_t *a, const bf_t *b);
|
||||||
|
int bf_cmp_full(const bf_t *a, const bf_t *b);
|
||||||
|
int bf_cmp_eq(const bf_t *a, const bf_t *b);
|
||||||
|
int bf_cmp_le(const bf_t *a, const bf_t *b);
|
||||||
|
int bf_cmp_lt(const bf_t *a, const bf_t *b);
|
||||||
|
int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
#define BF_DIVREM_EUCLIDIAN BF_RNDF
|
||||||
|
int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
|
||||||
|
limb_t prec, bf_flags_t flags, int rnd_mode);
|
||||||
|
int bf_fmod(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bf_remainder(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bf_pow_ui(bf_t *r, const bf_t *a, limb_t b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_rint(bf_t *r, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
|
||||||
|
int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
slimb_t bf_get_exp_min(const bf_t *a);
|
||||||
|
void bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
|
||||||
|
void bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
|
||||||
|
void bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
|
||||||
|
|
||||||
|
/* additional flags for bf_atof */
|
||||||
|
/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
|
||||||
|
#define BF_ATOF_NO_HEX (1 << 16)
|
||||||
|
/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
|
||||||
|
#define BF_ATOF_BIN_OCT (1 << 17)
|
||||||
|
/* Only accept integers (no decimal point, no exponent, no infinity nor NaN */
|
||||||
|
#define BF_ATOF_INT_ONLY (1 << 18)
|
||||||
|
/* Do not accept radix prefix after sign */
|
||||||
|
#define BF_ATOF_NO_PREFIX_AFTER_SIGN (1 << 19)
|
||||||
|
/* Do not parse NaN and parse case sensitive 'Infinity' */
|
||||||
|
#define BF_ATOF_JS_QUIRKS (1 << 20)
|
||||||
|
/* Do not round integers to the indicated precision */
|
||||||
|
#define BF_ATOF_INT_PREC_INF (1 << 21)
|
||||||
|
/* Support legacy octal syntax for well formed numbers */
|
||||||
|
#define BF_ATOF_LEGACY_OCTAL (1 << 22)
|
||||||
|
/* accept _ between digits as a digit separator */
|
||||||
|
#define BF_ATOF_UNDERSCORE_SEP (1 << 23)
|
||||||
|
/* if a 'n' suffix is present, force integer parsing (XXX: remove) */
|
||||||
|
#define BF_ATOF_INT_N_SUFFIX (1 << 24)
|
||||||
|
/* if set return NaN if empty number string (instead of 0) */
|
||||||
|
#define BF_ATOF_NAN_IF_EMPTY (1 << 25)
|
||||||
|
/* only accept decimal floating point if radix = 0 */
|
||||||
|
#define BF_ATOF_ONLY_DEC_FLOAT (1 << 26)
|
||||||
|
|
||||||
|
/* one more return flag: indicate that the parsed number is an integer
|
||||||
|
(only set when the flags BF_ATOF_INT_PREC_INF or
|
||||||
|
BF_ATOF_INT_N_SUFFIX are used) */
|
||||||
|
#define BF_ATOF_ST_INTEGER (1 << 5)
|
||||||
|
|
||||||
|
int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
|
||||||
|
limb_t prec, bf_flags_t flags);
|
||||||
|
/* this version accepts prec = BF_PREC_INF and returns the radix
|
||||||
|
exponent */
|
||||||
|
int bf_atof2(bf_t *r, slimb_t *pexponent,
|
||||||
|
const char *str, const char **pnext, int radix,
|
||||||
|
limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
|
||||||
|
slimb_t expn, limb_t prec, bf_flags_t flags);
|
||||||
|
|
||||||
|
#define BF_FTOA_FORMAT_MASK (3 << 16)
|
||||||
|
/* fixed format: prec significant digits rounded with (flags &
|
||||||
|
BF_RND_MASK). Exponential notation is used if too many zeros are
|
||||||
|
needed. */
|
||||||
|
#define BF_FTOA_FORMAT_FIXED (0 << 16)
|
||||||
|
/* fractional format: prec digits after the decimal point rounded with
|
||||||
|
(flags & BF_RND_MASK) */
|
||||||
|
#define BF_FTOA_FORMAT_FRAC (1 << 16)
|
||||||
|
/* free format: use as many digits as necessary so that bf_atof()
|
||||||
|
return the same number when using precision 'prec', rounding to
|
||||||
|
nearest and the subnormal+exponent configuration of 'flags'. The
|
||||||
|
result is meaningful only if 'a' is already rounded to the wanted
|
||||||
|
precision.
|
||||||
|
|
||||||
|
Infinite precision (BF_PREC_INF) is supported when the radix is a
|
||||||
|
power of two. */
|
||||||
|
#define BF_FTOA_FORMAT_FREE (2 << 16)
|
||||||
|
/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
|
||||||
|
(takes more computation time). */
|
||||||
|
#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
|
||||||
|
|
||||||
|
/* force exponential notation for fixed or free format */
|
||||||
|
#define BF_FTOA_FORCE_EXP (1 << 20)
|
||||||
|
/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
|
||||||
|
base 2 if non zero value */
|
||||||
|
#define BF_FTOA_ADD_PREFIX (1 << 21)
|
||||||
|
#define BF_FTOA_JS_QUIRKS (1 << 22)
|
||||||
|
|
||||||
|
size_t bf_ftoa(char **pbuf, const bf_t *a, int radix, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
|
||||||
|
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
|
||||||
|
#define BF_GET_INT_MOD (1 << 0)
|
||||||
|
int bf_get_int32(int *pres, const bf_t *a, int flags);
|
||||||
|
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
|
||||||
|
|
||||||
|
/* the following functions are exported for testing only. */
|
||||||
|
void bf_print_str(const char *str, const bf_t *a);
|
||||||
|
void bf_resize(bf_t *r, limb_t len);
|
||||||
|
int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
|
||||||
|
void bf_recip(bf_t *r, const bf_t *a, limb_t prec);
|
||||||
|
void bf_rsqrt(bf_t *a, const bf_t *x, limb_t prec);
|
||||||
|
int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
|
||||||
|
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
|
||||||
|
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
|
||||||
|
int is_ceil1);
|
||||||
|
|
||||||
|
/* transcendental functions */
|
||||||
|
int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
#define BF_POW_JS_QUICKS (1 << 16)
|
||||||
|
int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
|
||||||
|
limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
|
||||||
|
#endif /* LIBBF_H */
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Regular Expression Engine
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEF
|
||||||
|
|
||||||
|
DEF(invalid, 1) /* never used */
|
||||||
|
DEF(char, 3)
|
||||||
|
DEF(char32, 5)
|
||||||
|
DEF(dot, 1)
|
||||||
|
DEF(any, 1) /* same as dot but match any character including line terminator */
|
||||||
|
DEF(line_start, 1)
|
||||||
|
DEF(line_end, 1)
|
||||||
|
DEF(goto, 5)
|
||||||
|
DEF(split_goto_first, 5)
|
||||||
|
DEF(split_next_first, 5)
|
||||||
|
DEF(match, 1)
|
||||||
|
DEF(save_start, 2) /* save start position */
|
||||||
|
DEF(save_end, 2) /* save end position, must come after saved_start */
|
||||||
|
DEF(save_reset, 3) /* reset save positions */
|
||||||
|
DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
|
||||||
|
DEF(push_i32, 5) /* push integer on the stack */
|
||||||
|
DEF(drop, 1)
|
||||||
|
DEF(word_boundary, 1)
|
||||||
|
DEF(not_word_boundary, 1)
|
||||||
|
DEF(back_reference, 2)
|
||||||
|
DEF(backward_back_reference, 2) /* must come after back_reference */
|
||||||
|
DEF(range, 3) /* variable length */
|
||||||
|
DEF(range32, 3) /* variable length */
|
||||||
|
DEF(lookahead, 5)
|
||||||
|
DEF(negative_lookahead, 5)
|
||||||
|
DEF(push_char_pos, 1) /* push the character position on the stack */
|
||||||
|
DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character
|
||||||
|
position */
|
||||||
|
DEF(prev, 1) /* go to the previous char */
|
||||||
|
DEF(simple_greedy_quant, 17)
|
||||||
|
|
||||||
|
#endif /* DEF */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Regular Expression Engine
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIBREGEXP_H
|
||||||
|
#define LIBREGEXP_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "libunicode.h"
|
||||||
|
|
||||||
|
#define LRE_BOOL int /* for documentation purposes */
|
||||||
|
|
||||||
|
#define LRE_FLAG_GLOBAL (1 << 0)
|
||||||
|
#define LRE_FLAG_IGNORECASE (1 << 1)
|
||||||
|
#define LRE_FLAG_MULTILINE (1 << 2)
|
||||||
|
#define LRE_FLAG_DOTALL (1 << 3)
|
||||||
|
#define LRE_FLAG_UTF16 (1 << 4)
|
||||||
|
#define LRE_FLAG_STICKY (1 << 5)
|
||||||
|
|
||||||
|
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
|
||||||
|
|
||||||
|
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
|
||||||
|
const char *buf, size_t buf_len, int re_flags,
|
||||||
|
void *opaque);
|
||||||
|
int lre_get_capture_count(const uint8_t *bc_buf);
|
||||||
|
int lre_get_flags(const uint8_t *bc_buf);
|
||||||
|
int lre_exec(uint8_t **capture,
|
||||||
|
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
|
||||||
|
int cbuf_type, void *opaque);
|
||||||
|
|
||||||
|
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
|
||||||
|
LRE_BOOL lre_is_space(int c);
|
||||||
|
|
||||||
|
/* must be provided by the user */
|
||||||
|
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
|
||||||
|
void *lre_realloc(void *opaque, void *ptr, size_t size);
|
||||||
|
|
||||||
|
/* JS identifier test */
|
||||||
|
extern uint32_t const lre_id_start_table_ascii[4];
|
||||||
|
extern uint32_t const lre_id_continue_table_ascii[4];
|
||||||
|
|
||||||
|
static inline int lre_js_is_ident_first(int c)
|
||||||
|
{
|
||||||
|
if ((uint32_t)c < 128) {
|
||||||
|
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||||
|
} else {
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
return lre_is_id_start(c);
|
||||||
|
#else
|
||||||
|
return !lre_is_space(c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int lre_js_is_ident_next(int c)
|
||||||
|
{
|
||||||
|
if ((uint32_t)c < 128) {
|
||||||
|
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||||
|
} else {
|
||||||
|
/* ZWNJ and ZWJ are accepted in identifiers */
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
|
||||||
|
#else
|
||||||
|
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LRE_BOOL
|
||||||
|
|
||||||
|
#endif /* LIBREGEXP_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Unicode utilities
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIBUNICODE_H
|
||||||
|
#define LIBUNICODE_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#define LRE_BOOL int /* for documentation purposes */
|
||||||
|
|
||||||
|
/* define it to include all the unicode tables (40KB larger) */
|
||||||
|
#define CONFIG_ALL_UNICODE
|
||||||
|
|
||||||
|
#define LRE_CC_RES_LEN_MAX 3
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UNICODE_NFC,
|
||||||
|
UNICODE_NFD,
|
||||||
|
UNICODE_NFKC,
|
||||||
|
UNICODE_NFKD,
|
||||||
|
} UnicodeNormalizationEnum;
|
||||||
|
|
||||||
|
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
||||||
|
LRE_BOOL lre_is_cased(uint32_t c);
|
||||||
|
LRE_BOOL lre_is_case_ignorable(uint32_t c);
|
||||||
|
|
||||||
|
/* char ranges */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int len; /* in points, always even */
|
||||||
|
int size;
|
||||||
|
uint32_t *points; /* points sorted by increasing value */
|
||||||
|
void *mem_opaque;
|
||||||
|
void *(*realloc_func)(void *opaque, void *ptr, size_t size);
|
||||||
|
} CharRange;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CR_OP_UNION,
|
||||||
|
CR_OP_INTER,
|
||||||
|
CR_OP_XOR,
|
||||||
|
} CharRangeOpEnum;
|
||||||
|
|
||||||
|
void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||||
|
void cr_free(CharRange *cr);
|
||||||
|
int cr_realloc(CharRange *cr, int size);
|
||||||
|
int cr_copy(CharRange *cr, const CharRange *cr1);
|
||||||
|
|
||||||
|
static inline int cr_add_point(CharRange *cr, uint32_t v)
|
||||||
|
{
|
||||||
|
if (cr->len >= cr->size) {
|
||||||
|
if (cr_realloc(cr, cr->len + 1))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cr->points[cr->len++] = v;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||||
|
{
|
||||||
|
if ((cr->len + 2) > cr->size) {
|
||||||
|
if (cr_realloc(cr, cr->len + 2))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cr->points[cr->len++] = c1;
|
||||||
|
cr->points[cr->len++] = c2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len);
|
||||||
|
|
||||||
|
static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||||
|
{
|
||||||
|
uint32_t b_pt[2];
|
||||||
|
b_pt[0] = c1;
|
||||||
|
b_pt[1] = c2 + 1;
|
||||||
|
return cr_union1(cr, b_pt, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
|
||||||
|
const uint32_t *b_pt, int b_len, int op);
|
||||||
|
|
||||||
|
int cr_invert(CharRange *cr);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
|
||||||
|
LRE_BOOL lre_is_id_start(uint32_t c);
|
||||||
|
LRE_BOOL lre_is_id_continue(uint32_t c);
|
||||||
|
|
||||||
|
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
||||||
|
UnicodeNormalizationEnum n_type,
|
||||||
|
void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||||
|
|
||||||
|
/* Unicode character range functions */
|
||||||
|
|
||||||
|
int unicode_script(CharRange *cr,
|
||||||
|
const char *script_name, LRE_BOOL is_ext);
|
||||||
|
int unicode_general_category(CharRange *cr, const char *gc_name);
|
||||||
|
int unicode_prop(CharRange *cr, const char *prop_name);
|
||||||
|
|
||||||
|
#endif /* CONFIG_ALL_UNICODE */
|
||||||
|
|
||||||
|
#undef LRE_BOOL
|
||||||
|
|
||||||
|
#endif /* LIBUNICODE_H */
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Linux klist like system
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016-2017 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIST_H
|
||||||
|
#define LIST_H
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct list_head {
|
||||||
|
struct list_head *prev;
|
||||||
|
struct list_head *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LIST_HEAD_INIT(el) { &(el), &(el) }
|
||||||
|
|
||||||
|
/* return the pointer of type 'type *' containing 'el' as field 'member' */
|
||||||
|
#define list_entry(el, type, member) \
|
||||||
|
((type *)((uint8_t *)(el) - offsetof(type, member)))
|
||||||
|
|
||||||
|
static inline void init_list_head(struct list_head *head)
|
||||||
|
{
|
||||||
|
head->prev = head;
|
||||||
|
head->next = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert 'el' between 'prev' and 'next' */
|
||||||
|
static inline void __list_add(struct list_head *el,
|
||||||
|
struct list_head *prev, struct list_head *next)
|
||||||
|
{
|
||||||
|
prev->next = el;
|
||||||
|
el->prev = prev;
|
||||||
|
el->next = next;
|
||||||
|
next->prev = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add 'el' at the head of the list 'head' (= after element head) */
|
||||||
|
static inline void list_add(struct list_head *el, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(el, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add 'el' at the end of the list 'head' (= before element head) */
|
||||||
|
static inline void list_add_tail(struct list_head *el, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(el, head->prev, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_del(struct list_head *el)
|
||||||
|
{
|
||||||
|
struct list_head *prev, *next;
|
||||||
|
prev = el->prev;
|
||||||
|
next = el->next;
|
||||||
|
prev->next = next;
|
||||||
|
next->prev = prev;
|
||||||
|
el->prev = NULL; /* fail safe */
|
||||||
|
el->next = NULL; /* fail safe */
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int list_empty(struct list_head *el)
|
||||||
|
{
|
||||||
|
return el->next == el;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define list_for_each(el, head) \
|
||||||
|
for(el = (head)->next; el != (head); el = el->next)
|
||||||
|
|
||||||
|
#define list_for_each_safe(el, el1, head) \
|
||||||
|
for(el = (head)->next, el1 = el->next; el != (head); \
|
||||||
|
el = el1, el1 = el->next)
|
||||||
|
|
||||||
|
#define list_for_each_prev(el, head) \
|
||||||
|
for(el = (head)->prev; el != (head); el = el->prev)
|
||||||
|
|
||||||
|
#define list_for_each_prev_safe(el, el1, head) \
|
||||||
|
for(el = (head)->prev, el1 = el->prev; el != (head); \
|
||||||
|
el = el1, el1 = el->prev)
|
||||||
|
|
||||||
|
#endif /* LIST_H */
|
|
@ -0,0 +1,466 @@
|
||||||
|
/*
|
||||||
|
* QuickJS stand alone interpreter
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <malloc/malloc.h>
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
#include "quickjs-libc.h"
|
||||||
|
|
||||||
|
extern const uint8_t repl[];
|
||||||
|
extern const uint32_t repl_size;
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
extern const uint8_t qjscalc[];
|
||||||
|
extern const uint32_t qjscalc_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
||||||
|
const char *filename, int eval_flags)
|
||||||
|
{
|
||||||
|
JSValue val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
|
||||||
|
if (JS_IsException(val)) {
|
||||||
|
js_std_dump_error(ctx);
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
JS_FreeValue(ctx, val);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int eval_file(JSContext *ctx, const char *filename, int eval_flags)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
int ret;
|
||||||
|
size_t buf_len;
|
||||||
|
|
||||||
|
buf = js_load_file(ctx, &buf_len, filename);
|
||||||
|
if (!buf) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ret = eval_buf(ctx, buf, buf_len, filename, eval_flags);
|
||||||
|
js_free(ctx, buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#define MALLOC_OVERHEAD 0
|
||||||
|
#else
|
||||||
|
#define MALLOC_OVERHEAD 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct trace_malloc_data {
|
||||||
|
uint8_t *base;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr,
|
||||||
|
struct trace_malloc_data *dp)
|
||||||
|
{
|
||||||
|
return ptr - dp->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default memory allocation functions with memory limitation */
|
||||||
|
static inline size_t js_trace_malloc_usable_size(void *ptr)
|
||||||
|
{
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
return malloc_size(ptr);
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
return _msize(ptr);
|
||||||
|
#elif defined(EMSCRIPTEN)
|
||||||
|
return 0;
|
||||||
|
#elif defined(__linux__)
|
||||||
|
return malloc_usable_size(ptr);
|
||||||
|
#else
|
||||||
|
/* change this to `return 0;` if compilation fails */
|
||||||
|
return malloc_usable_size(ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((format(printf, 2, 3)))
|
||||||
|
js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
while ((c = *fmt++) != '\0') {
|
||||||
|
if (c == '%') {
|
||||||
|
/* only handle %p and %zd */
|
||||||
|
if (*fmt == 'p') {
|
||||||
|
uint8_t *ptr = va_arg(ap, void *);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
printf("NULL");
|
||||||
|
} else {
|
||||||
|
printf("H%+06lld.%zd",
|
||||||
|
js_trace_malloc_ptr_offset(ptr, s->opaque),
|
||||||
|
js_trace_malloc_usable_size(ptr));
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fmt[0] == 'z' && fmt[1] == 'd') {
|
||||||
|
size_t sz = va_arg(ap, size_t);
|
||||||
|
printf("%zd", sz);
|
||||||
|
fmt += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putc(c, stdout);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_trace_malloc_init(struct trace_malloc_data *s)
|
||||||
|
{
|
||||||
|
free(s->base = malloc(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *js_trace_malloc(JSMallocState *s, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
/* Do not allocate zero bytes: behavior is platform dependent */
|
||||||
|
assert(size != 0);
|
||||||
|
|
||||||
|
if (unlikely(s->malloc_size + size > s->malloc_limit))
|
||||||
|
return NULL;
|
||||||
|
ptr = malloc(size);
|
||||||
|
js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr);
|
||||||
|
if (ptr) {
|
||||||
|
s->malloc_count++;
|
||||||
|
s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_trace_free(JSMallocState *s, void *ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
js_trace_malloc_printf(s, "F %p\n", ptr);
|
||||||
|
s->malloc_count--;
|
||||||
|
s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
size_t old_size;
|
||||||
|
|
||||||
|
if (!ptr) {
|
||||||
|
if (size == 0)
|
||||||
|
return NULL;
|
||||||
|
return js_trace_malloc(s, size);
|
||||||
|
}
|
||||||
|
old_size = js_trace_malloc_usable_size(ptr);
|
||||||
|
if (size == 0) {
|
||||||
|
js_trace_malloc_printf(s, "R %zd %p\n", size, ptr);
|
||||||
|
s->malloc_count--;
|
||||||
|
s->malloc_size -= old_size + MALLOC_OVERHEAD;
|
||||||
|
free(ptr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (s->malloc_size + size - old_size > s->malloc_limit)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
js_trace_malloc_printf(s, "R %zd %p", size, ptr);
|
||||||
|
|
||||||
|
ptr = realloc(ptr, size);
|
||||||
|
js_trace_malloc_printf(s, " -> %p\n", ptr);
|
||||||
|
if (ptr) {
|
||||||
|
s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JSMallocFunctions trace_mf = {
|
||||||
|
js_trace_malloc,
|
||||||
|
js_trace_free,
|
||||||
|
js_trace_realloc,
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
malloc_size,
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
(size_t (*)(const void *))_msize,
|
||||||
|
#elif defined(EMSCRIPTEN)
|
||||||
|
NULL,
|
||||||
|
#elif defined(__linux__)
|
||||||
|
(size_t (*)(const void *))malloc_usable_size,
|
||||||
|
#else
|
||||||
|
/* change this to `NULL,` if compilation fails */
|
||||||
|
malloc_usable_size,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
#define PROG_NAME "qjsbn"
|
||||||
|
#else
|
||||||
|
#define PROG_NAME "qjs"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void help(void)
|
||||||
|
{
|
||||||
|
printf("QuickJS version " CONFIG_VERSION "\n"
|
||||||
|
"usage: " PROG_NAME " [options] [files]\n"
|
||||||
|
"-h --help list options\n"
|
||||||
|
"-e --eval EXPR evaluate EXPR\n"
|
||||||
|
"-i --interactive go to interactive mode\n"
|
||||||
|
"-m --module load as ES6 module (default if .mjs file extension)\n"
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
" --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n"
|
||||||
|
#endif
|
||||||
|
"-T --trace trace memory allocation\n"
|
||||||
|
"-d --dump dump the memory usage stats\n"
|
||||||
|
"-q --quit just instantiate the interpreter and quit\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
JSRuntime *rt;
|
||||||
|
JSContext *ctx;
|
||||||
|
struct trace_malloc_data trace_data = { NULL };
|
||||||
|
int optind;
|
||||||
|
char *expr = NULL;
|
||||||
|
int interactive = 0;
|
||||||
|
int dump_memory = 0;
|
||||||
|
int trace_memory = 0;
|
||||||
|
int empty_run = 0;
|
||||||
|
int module = 0;
|
||||||
|
int load_std = 1;
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
int load_jscalc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
/* load jscalc runtime if invoked as 'qjscalc' */
|
||||||
|
{
|
||||||
|
const char *p, *exename;
|
||||||
|
exename = argv[0];
|
||||||
|
p = strrchr(exename, '/');
|
||||||
|
if (p)
|
||||||
|
exename = p + 1;
|
||||||
|
load_jscalc = !strcmp(exename, "qjscalc");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* cannot use getopt because we want to pass the command line to
|
||||||
|
the script */
|
||||||
|
optind = 1;
|
||||||
|
while (optind < argc && *argv[optind] == '-') {
|
||||||
|
char *arg = argv[optind] + 1;
|
||||||
|
const char *longopt = "";
|
||||||
|
/* a single - is not an option, it also stops argument scanning */
|
||||||
|
if (!*arg)
|
||||||
|
break;
|
||||||
|
optind++;
|
||||||
|
if (*arg == '-') {
|
||||||
|
longopt = arg + 1;
|
||||||
|
arg += strlen(arg);
|
||||||
|
/* -- stops argument scanning */
|
||||||
|
if (!*longopt)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (; *arg || *longopt; longopt = "") {
|
||||||
|
char opt = *arg;
|
||||||
|
if (opt)
|
||||||
|
arg++;
|
||||||
|
if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) {
|
||||||
|
help();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'e' || !strcmp(longopt, "eval")) {
|
||||||
|
if (*arg) {
|
||||||
|
expr = arg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (optind < argc) {
|
||||||
|
expr = argv[optind++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "qjs: missing expression for -e\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
if (opt == 'i' || !strcmp(longopt, "interactive")) {
|
||||||
|
interactive++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'm' || !strcmp(longopt, "module")) {
|
||||||
|
module = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'd' || !strcmp(longopt, "dump")) {
|
||||||
|
dump_memory++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'T' || !strcmp(longopt, "trace")) {
|
||||||
|
trace_memory++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(longopt, "nostd")) {
|
||||||
|
load_std = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
if (!strcmp(longopt, "qjscalc")) {
|
||||||
|
load_jscalc = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (opt == 'q' || !strcmp(longopt, "quit")) {
|
||||||
|
empty_run++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt) {
|
||||||
|
fprintf(stderr, "qjs: unknown option '-%c'\n", opt);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "qjs: unknown option '--%s'\n", longopt);
|
||||||
|
}
|
||||||
|
help();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trace_memory) {
|
||||||
|
js_trace_malloc_init(&trace_data);
|
||||||
|
rt = JS_NewRuntime2(&trace_mf, &trace_data);
|
||||||
|
} else {
|
||||||
|
rt = JS_NewRuntime();
|
||||||
|
}
|
||||||
|
if (!rt) {
|
||||||
|
fprintf(stderr, "qjs: cannot allocate JS runtime\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
ctx = JS_NewContext(rt);
|
||||||
|
if (!ctx) {
|
||||||
|
fprintf(stderr, "qjs: cannot allocate JS context\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* loader for ES6 modules */
|
||||||
|
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||||
|
|
||||||
|
if (!empty_run) {
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
if (load_jscalc) {
|
||||||
|
js_std_eval_binary(ctx, qjscalc, qjscalc_size, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
js_std_add_helpers(ctx, argc - optind, argv + optind);
|
||||||
|
|
||||||
|
/* system modules */
|
||||||
|
js_init_module_std(ctx, "std");
|
||||||
|
js_init_module_os(ctx, "os");
|
||||||
|
|
||||||
|
/* make 'std' and 'os' visible to non module code */
|
||||||
|
if (load_std) {
|
||||||
|
const char *str = "import * as std from 'std';\n"
|
||||||
|
"import * as os from 'os';\n"
|
||||||
|
"std.global.std = std;\n"
|
||||||
|
"std.global.os = os;\n";
|
||||||
|
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expr) {
|
||||||
|
if (eval_buf(ctx, expr, strlen(expr), "<cmdline>", 0))
|
||||||
|
goto fail;
|
||||||
|
} else
|
||||||
|
if (optind >= argc) {
|
||||||
|
/* interactive mode */
|
||||||
|
interactive = 1;
|
||||||
|
} else {
|
||||||
|
int eval_flags;
|
||||||
|
const char *filename;
|
||||||
|
filename = argv[optind];
|
||||||
|
|
||||||
|
if (module || has_suffix(filename, ".mjs"))
|
||||||
|
eval_flags = JS_EVAL_TYPE_MODULE;
|
||||||
|
else
|
||||||
|
eval_flags = JS_EVAL_TYPE_GLOBAL;
|
||||||
|
eval_flags |= JS_EVAL_FLAG_SHEBANG;
|
||||||
|
if (eval_file(ctx, filename, eval_flags))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (interactive) {
|
||||||
|
js_std_eval_binary(ctx, repl, repl_size, 0);
|
||||||
|
}
|
||||||
|
js_std_loop(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dump_memory) {
|
||||||
|
JSMemoryUsage stats;
|
||||||
|
JS_ComputeMemoryUsage(rt, &stats);
|
||||||
|
JS_DumpMemoryUsage(stdout, &stats, rt);
|
||||||
|
}
|
||||||
|
js_std_free_handlers(rt);
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
|
||||||
|
if (empty_run && dump_memory) {
|
||||||
|
clock_t t[5];
|
||||||
|
double best[5];
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < 100; i++) {
|
||||||
|
t[0] = clock();
|
||||||
|
rt = JS_NewRuntime();
|
||||||
|
t[1] = clock();
|
||||||
|
ctx = JS_NewContext(rt);
|
||||||
|
t[2] = clock();
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
t[3] = clock();
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
t[4] = clock();
|
||||||
|
for (j = 4; j > 0; j--) {
|
||||||
|
double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC;
|
||||||
|
if (i == 0 || best[j] > ms)
|
||||||
|
best[j] = ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n",
|
||||||
|
best[1] + best[2] + best[3] + best[4],
|
||||||
|
best[1], best[2], best[3], best[4]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
fail:
|
||||||
|
js_std_free_handlers(rt);
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,636 @@
|
||||||
|
/*
|
||||||
|
* QuickJS command line compiler
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018-2019 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
#include "quickjs-libc.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
char *short_name;
|
||||||
|
int flags;
|
||||||
|
} namelist_entry_t;
|
||||||
|
|
||||||
|
typedef struct namelist_t {
|
||||||
|
namelist_entry_t *array;
|
||||||
|
int count;
|
||||||
|
int size;
|
||||||
|
} namelist_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *option_name;
|
||||||
|
const char *init_name;
|
||||||
|
} FeatureEntry;
|
||||||
|
|
||||||
|
#define FE_ALL (-1)
|
||||||
|
|
||||||
|
static namelist_t cname_list;
|
||||||
|
static namelist_t cmodule_list;
|
||||||
|
static namelist_t init_module_list;
|
||||||
|
static uint64_t feature_bitmap;
|
||||||
|
static FILE *outfile;
|
||||||
|
static BOOL byte_swap;
|
||||||
|
|
||||||
|
static const FeatureEntry feature_list[] = {
|
||||||
|
{ "eval", "Eval" },
|
||||||
|
{ "string-normalize", "StringNormalize" },
|
||||||
|
{ "regexp", "RegExp" },
|
||||||
|
{ "json", "JSON" },
|
||||||
|
{ "proxy", "Proxy" },
|
||||||
|
{ "map", "MapSet" },
|
||||||
|
{ "typedarray", "TypedArrays" },
|
||||||
|
{ "promise", "Promise" },
|
||||||
|
};
|
||||||
|
|
||||||
|
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
namelist_entry_t *e;
|
||||||
|
if (lp->count == lp->size) {
|
||||||
|
size_t newsize = lp->size + (lp->size >> 1) + 4;
|
||||||
|
namelist_entry_t *a =
|
||||||
|
realloc(lp->array, sizeof(lp->array[0]) * newsize);
|
||||||
|
/* XXX: check for realloc failure */
|
||||||
|
lp->array = a;
|
||||||
|
lp->size = newsize;
|
||||||
|
}
|
||||||
|
e = &lp->array[lp->count++];
|
||||||
|
e->name = strdup(name);
|
||||||
|
if (short_name)
|
||||||
|
e->short_name = strdup(short_name);
|
||||||
|
else
|
||||||
|
e->short_name = NULL;
|
||||||
|
e->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void namelist_free(namelist_t *lp)
|
||||||
|
{
|
||||||
|
while (lp->count > 0) {
|
||||||
|
namelist_entry_t *e = &lp->array[--lp->count];
|
||||||
|
free(e->name);
|
||||||
|
free(e->short_name);
|
||||||
|
}
|
||||||
|
free(lp->array);
|
||||||
|
lp->array = NULL;
|
||||||
|
lp->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namelist_entry_t *namelist_find(namelist_t *lp, const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < lp->count; i++) {
|
||||||
|
namelist_entry_t *e = &lp->array[i];
|
||||||
|
if (!strcmp(e->name, name))
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void get_c_name(char *buf, int buf_size, const char *file)
|
||||||
|
{
|
||||||
|
const char *p, *r;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
p = strrchr(file, '/');
|
||||||
|
if (!p)
|
||||||
|
p = file;
|
||||||
|
else
|
||||||
|
p++;
|
||||||
|
r = strrchr(p, '.');
|
||||||
|
if (!r)
|
||||||
|
r = p + strlen(p);
|
||||||
|
len = r - p;
|
||||||
|
if (len > buf_size - 1)
|
||||||
|
len = buf_size - 1;
|
||||||
|
memcpy(buf, p, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t i, col;
|
||||||
|
col = 0;
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
fprintf(f, " 0x%02x,", buf[i]);
|
||||||
|
if (++col == 8) {
|
||||||
|
fprintf(f, "\n");
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (col != 0)
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_object_code(JSContext *ctx,
|
||||||
|
FILE *fo, JSValueConst obj, const char *c_name,
|
||||||
|
BOOL load_only)
|
||||||
|
{
|
||||||
|
uint8_t *out_buf;
|
||||||
|
size_t out_buf_len;
|
||||||
|
int flags;
|
||||||
|
flags = JS_WRITE_OBJ_BYTECODE;
|
||||||
|
if (byte_swap)
|
||||||
|
flags |= JS_WRITE_OBJ_BSWAP;
|
||||||
|
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
|
||||||
|
if (!out_buf) {
|
||||||
|
js_std_dump_error(ctx);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
namelist_add(&cname_list, c_name, NULL, load_only);
|
||||||
|
|
||||||
|
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
|
||||||
|
c_name, (unsigned int)out_buf_len);
|
||||||
|
fprintf(fo, "const uint8_t %s[%u] = {\n",
|
||||||
|
c_name, (unsigned int)out_buf_len);
|
||||||
|
dump_hex(fo, out_buf, out_buf_len);
|
||||||
|
fprintf(fo, "};\n\n");
|
||||||
|
|
||||||
|
js_free(ctx, out_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m)
|
||||||
|
{
|
||||||
|
/* should never be called when compiling JS code */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||||
|
const char *module_name, void *opaque)
|
||||||
|
{
|
||||||
|
JSModuleDef *m;
|
||||||
|
namelist_entry_t *e;
|
||||||
|
|
||||||
|
/* check if it is a declared C or system module */
|
||||||
|
e = namelist_find(&cmodule_list, module_name);
|
||||||
|
if (e) {
|
||||||
|
/* add in the static init module list */
|
||||||
|
namelist_add(&init_module_list, e->name, e->short_name, 0);
|
||||||
|
/* create a dummy module */
|
||||||
|
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||||
|
} else if (has_suffix(module_name, ".so")) {
|
||||||
|
fprintf(stderr, "Warning: binary module '%s' is not compiled\n", module_name);
|
||||||
|
/* create a dummy module */
|
||||||
|
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||||
|
} else {
|
||||||
|
size_t buf_len;
|
||||||
|
uint8_t *buf;
|
||||||
|
JSValue func_val;
|
||||||
|
char cname[1024];
|
||||||
|
|
||||||
|
buf = js_load_file(ctx, &buf_len, module_name);
|
||||||
|
if (!buf) {
|
||||||
|
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
|
||||||
|
module_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compile the module */
|
||||||
|
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
|
||||||
|
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||||
|
js_free(ctx, buf);
|
||||||
|
if (JS_IsException(func_val))
|
||||||
|
return NULL;
|
||||||
|
get_c_name(cname, sizeof(cname), module_name);
|
||||||
|
output_object_code(ctx, outfile, func_val, cname, TRUE);
|
||||||
|
|
||||||
|
/* the module is already referenced, so we must free it */
|
||||||
|
m = JS_VALUE_GET_PTR(func_val);
|
||||||
|
JS_FreeValue(ctx, func_val);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compile_file(JSContext *ctx, FILE *fo,
|
||||||
|
const char *filename,
|
||||||
|
const char *c_name1,
|
||||||
|
BOOL is_module)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
char c_name[1024];
|
||||||
|
int eval_flags;
|
||||||
|
JSValue obj;
|
||||||
|
size_t buf_len;
|
||||||
|
|
||||||
|
buf = js_load_file(ctx, &buf_len, filename);
|
||||||
|
if (!buf) {
|
||||||
|
fprintf(stderr, "Could not load '%s'\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
eval_flags = JS_EVAL_FLAG_SHEBANG | JS_EVAL_FLAG_COMPILE_ONLY;
|
||||||
|
if (is_module)
|
||||||
|
eval_flags |= JS_EVAL_TYPE_MODULE;
|
||||||
|
else
|
||||||
|
eval_flags |= JS_EVAL_TYPE_GLOBAL;
|
||||||
|
obj = JS_Eval(ctx, (char *)buf, buf_len, filename, eval_flags);
|
||||||
|
if (JS_IsException(obj)) {
|
||||||
|
js_std_dump_error(ctx);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
js_free(ctx, buf);
|
||||||
|
if (c_name1) {
|
||||||
|
pstrcpy(c_name, sizeof(c_name), c_name1);
|
||||||
|
} else {
|
||||||
|
get_c_name(c_name, sizeof(c_name), filename);
|
||||||
|
}
|
||||||
|
output_object_code(ctx, fo, obj, c_name, FALSE);
|
||||||
|
JS_FreeValue(ctx, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char main_c_template1[] =
|
||||||
|
"int main(int argc, char **argv)\n"
|
||||||
|
"{\n"
|
||||||
|
" JSRuntime *rt;\n"
|
||||||
|
" JSContext *ctx;\n"
|
||||||
|
" rt = JS_NewRuntime();\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static const char main_c_template2[] =
|
||||||
|
" js_std_loop(ctx);\n"
|
||||||
|
" JS_FreeContext(ctx);\n"
|
||||||
|
" JS_FreeRuntime(rt);\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
#define PROG_NAME "qjscbn"
|
||||||
|
#else
|
||||||
|
#define PROG_NAME "qjsc"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void help(void)
|
||||||
|
{
|
||||||
|
printf("QuickJS Compiler version " CONFIG_VERSION "\n"
|
||||||
|
"usage: " PROG_NAME " [options] [files]\n"
|
||||||
|
"\n"
|
||||||
|
"options are:\n"
|
||||||
|
"-c only output bytecode in a C file\n"
|
||||||
|
"-e output main() and bytecode in a C file (default = executable output)\n"
|
||||||
|
"-o output set the output filename\n"
|
||||||
|
"-N cname set the C name of the generated data\n"
|
||||||
|
"-m compile as Javascript module\n"
|
||||||
|
"-M module_name[,cname] add initialization code for an external C module\n"
|
||||||
|
"-x byte swapped output\n"
|
||||||
|
);
|
||||||
|
#ifdef CONFIG_LTO
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
printf("-flto use link time optimization\n");
|
||||||
|
printf("-fno-[");
|
||||||
|
for(i = 0; i < countof(feature_list); i++) {
|
||||||
|
if (i != 0)
|
||||||
|
printf("|");
|
||||||
|
printf("%s", feature_list[i].option_name);
|
||||||
|
}
|
||||||
|
printf("]\n"
|
||||||
|
" disable selected language features (smaller code size)\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_CC) && !defined(_WIN32)
|
||||||
|
|
||||||
|
int exec_cmd(char **argv)
|
||||||
|
{
|
||||||
|
int pid, status, ret;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
ret = waitpid(pid, &status, 0);
|
||||||
|
if (ret == pid && WIFEXITED(status))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int output_executable(const char *out_filename, const char *cfilename,
|
||||||
|
BOOL use_lto, BOOL verbose, const char *exename)
|
||||||
|
{
|
||||||
|
const char *argv[64];
|
||||||
|
const char **arg, *bn_suffix, *lto_suffix;
|
||||||
|
char libjsname[1024];
|
||||||
|
char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* get the directory of the executable */
|
||||||
|
pstrcpy(exe_dir, sizeof(exe_dir), exename);
|
||||||
|
p = strrchr(exe_dir, '/');
|
||||||
|
if (p) {
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
pstrcpy(exe_dir, sizeof(exe_dir), ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if 'quickjs.h' is present at the same path as the executable, we
|
||||||
|
use it as include and lib directory */
|
||||||
|
snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir);
|
||||||
|
if (access(buf, R_OK) == 0) {
|
||||||
|
pstrcpy(inc_dir, sizeof(inc_dir), exe_dir);
|
||||||
|
pstrcpy(lib_dir, sizeof(lib_dir), exe_dir);
|
||||||
|
} else {
|
||||||
|
snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX);
|
||||||
|
snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
lto_suffix = "";
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
bn_suffix = ".bn";
|
||||||
|
#else
|
||||||
|
bn_suffix = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
arg = argv;
|
||||||
|
*arg++ = CONFIG_CC;
|
||||||
|
*arg++ = "-O2";
|
||||||
|
#ifdef CONFIG_LTO
|
||||||
|
if (use_lto) {
|
||||||
|
*arg++ = "-flto";
|
||||||
|
lto_suffix = ".lto";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* XXX: use the executable path to find the includes files and
|
||||||
|
libraries */
|
||||||
|
*arg++ = "-D";
|
||||||
|
*arg++ = "_GNU_SOURCE";
|
||||||
|
*arg++ = "-I";
|
||||||
|
*arg++ = inc_dir;
|
||||||
|
*arg++ = "-o";
|
||||||
|
*arg++ = out_filename;
|
||||||
|
*arg++ = cfilename;
|
||||||
|
snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a",
|
||||||
|
lib_dir, bn_suffix, lto_suffix);
|
||||||
|
*arg++ = libjsname;
|
||||||
|
*arg++ = "-lm";
|
||||||
|
*arg++ = "-ldl";
|
||||||
|
*arg = NULL;
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
for(arg = argv; *arg != NULL; arg++)
|
||||||
|
printf("%s ", *arg);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = exec_cmd((char **)argv);
|
||||||
|
unlink(cfilename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int output_executable(const char *out_filename, const char *cfilename,
|
||||||
|
BOOL use_lto, BOOL verbose, const char *exename)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Executable output is not supported for this target\n");
|
||||||
|
exit(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OUTPUT_C,
|
||||||
|
OUTPUT_C_MAIN,
|
||||||
|
OUTPUT_EXECUTABLE,
|
||||||
|
} OutputTypeEnum;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c, i, verbose;
|
||||||
|
const char *out_filename, *cname;
|
||||||
|
char cfilename[1024];
|
||||||
|
FILE *fo;
|
||||||
|
JSRuntime *rt;
|
||||||
|
JSContext *ctx;
|
||||||
|
BOOL module, use_lto;
|
||||||
|
OutputTypeEnum output_type;
|
||||||
|
|
||||||
|
out_filename = NULL;
|
||||||
|
output_type = OUTPUT_EXECUTABLE;
|
||||||
|
cname = NULL;
|
||||||
|
feature_bitmap = FE_ALL;
|
||||||
|
module = FALSE;
|
||||||
|
byte_swap = FALSE;
|
||||||
|
verbose = 0;
|
||||||
|
use_lto = FALSE;
|
||||||
|
|
||||||
|
/* add system modules */
|
||||||
|
namelist_add(&cmodule_list, "std", "std", 0);
|
||||||
|
namelist_add(&cmodule_list, "os", "os", 0);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
c = getopt(argc, argv, "ho:cN:f:mxevM:");
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
switch(c) {
|
||||||
|
case 'h':
|
||||||
|
help();
|
||||||
|
case 'o':
|
||||||
|
out_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
output_type = OUTPUT_C;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
output_type = OUTPUT_C_MAIN;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
cname = optarg;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
p = optarg;
|
||||||
|
if (!strcmp(optarg, "lto")) {
|
||||||
|
use_lto = TRUE;
|
||||||
|
} else if (strstart(p, "no-", &p)) {
|
||||||
|
use_lto = TRUE;
|
||||||
|
for(i = 0; i < countof(feature_list); i++) {
|
||||||
|
if (!strcmp(p, feature_list[i].option_name)) {
|
||||||
|
feature_bitmap &= ~((uint64_t)1 << i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == countof(feature_list))
|
||||||
|
goto bad_feature;
|
||||||
|
} else {
|
||||||
|
bad_feature:
|
||||||
|
fprintf(stderr, "unsupported feature: %s\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
module = TRUE;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char path[1024];
|
||||||
|
char cname[1024];
|
||||||
|
pstrcpy(path, sizeof(path), optarg);
|
||||||
|
p = strchr(path, ',');
|
||||||
|
if (p) {
|
||||||
|
*p = '\0';
|
||||||
|
pstrcpy(cname, sizeof(cname), p + 1);
|
||||||
|
} else {
|
||||||
|
get_c_name(cname, sizeof(cname), path);
|
||||||
|
}
|
||||||
|
namelist_add(&cmodule_list, path, cname, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
byte_swap = TRUE;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc)
|
||||||
|
help();
|
||||||
|
|
||||||
|
if (!out_filename) {
|
||||||
|
if (output_type == OUTPUT_EXECUTABLE) {
|
||||||
|
out_filename = "a.out";
|
||||||
|
} else {
|
||||||
|
out_filename = "out.c";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_type == OUTPUT_EXECUTABLE) {
|
||||||
|
#if defined(_WIN32) || defined(__ANDROID__)
|
||||||
|
/* XXX: find a /tmp directory ? */
|
||||||
|
snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid());
|
||||||
|
#else
|
||||||
|
snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid());
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
fo = fopen(cfilename, "w");
|
||||||
|
if (!fo) {
|
||||||
|
perror(cfilename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
outfile = fo;
|
||||||
|
|
||||||
|
rt = JS_NewRuntime();
|
||||||
|
ctx = JS_NewContextRaw(rt);
|
||||||
|
JS_AddIntrinsicEval(ctx);
|
||||||
|
JS_AddIntrinsicRegExpCompiler(ctx);
|
||||||
|
|
||||||
|
/* loader for ES6 modules */
|
||||||
|
JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
|
||||||
|
|
||||||
|
fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (output_type != OUTPUT_C) {
|
||||||
|
fprintf(fo, "#include \"quickjs-libc.h\"\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
fprintf(fo, "#include <inttypes.h>\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = optind; i < argc; i++) {
|
||||||
|
const char *filename = argv[i];
|
||||||
|
BOOL module1 = module || has_suffix(filename, ".mjs");
|
||||||
|
compile_file(ctx, fo, filename, cname, module1);
|
||||||
|
cname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_type != OUTPUT_C) {
|
||||||
|
fputs(main_c_template1, fo);
|
||||||
|
fprintf(fo, " ctx = JS_NewContextRaw(rt);\n");
|
||||||
|
|
||||||
|
/* add the basic objects */
|
||||||
|
|
||||||
|
fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
|
||||||
|
for(i = 0; i < countof(feature_list); i++) {
|
||||||
|
if (feature_bitmap & ((uint64_t)1 << i)) {
|
||||||
|
fprintf(fo, " JS_AddIntrinsic%s(ctx);\n",
|
||||||
|
feature_list[i].init_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fo, " js_std_add_helpers(ctx, argc, argv);\n");
|
||||||
|
|
||||||
|
for(i = 0; i < init_module_list.count; i++) {
|
||||||
|
namelist_entry_t *e = &init_module_list.array[i];
|
||||||
|
/* initialize the static C modules */
|
||||||
|
|
||||||
|
fprintf(fo,
|
||||||
|
" {\n"
|
||||||
|
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
|
||||||
|
" js_init_module_%s(ctx, \"%s\");\n"
|
||||||
|
" }\n",
|
||||||
|
e->short_name, e->short_name, e->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < cname_list.count; i++) {
|
||||||
|
namelist_entry_t *e = &cname_list.array[i];
|
||||||
|
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, %s);\n",
|
||||||
|
e->name, e->name,
|
||||||
|
e->flags ? "JS_EVAL_BINARY_LOAD_ONLY" : "0");
|
||||||
|
}
|
||||||
|
fputs(main_c_template2, fo);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
|
||||||
|
fclose(fo);
|
||||||
|
|
||||||
|
if (output_type == OUTPUT_EXECUTABLE) {
|
||||||
|
return output_executable(out_filename, cfilename, use_lto, verbose,
|
||||||
|
argv[0]);
|
||||||
|
}
|
||||||
|
namelist_free(&cname_list);
|
||||||
|
namelist_free(&cmodule_list);
|
||||||
|
namelist_free(&init_module_list);
|
||||||
|
return 0;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,274 @@
|
||||||
|
/*
|
||||||
|
* QuickJS atom definitions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEF
|
||||||
|
|
||||||
|
/* Note: first atoms are considered as keywords in the parser */
|
||||||
|
DEF(null, "null") /* must be first */
|
||||||
|
DEF(false, "false")
|
||||||
|
DEF(true, "true")
|
||||||
|
DEF(if, "if")
|
||||||
|
DEF(else, "else")
|
||||||
|
DEF(return, "return")
|
||||||
|
DEF(var, "var")
|
||||||
|
DEF(this, "this")
|
||||||
|
DEF(delete, "delete")
|
||||||
|
DEF(void, "void")
|
||||||
|
DEF(typeof, "typeof")
|
||||||
|
DEF(new, "new")
|
||||||
|
DEF(in, "in")
|
||||||
|
DEF(instanceof, "instanceof")
|
||||||
|
DEF(do, "do")
|
||||||
|
DEF(while, "while")
|
||||||
|
DEF(for, "for")
|
||||||
|
DEF(break, "break")
|
||||||
|
DEF(continue, "continue")
|
||||||
|
DEF(switch, "switch")
|
||||||
|
DEF(case, "case")
|
||||||
|
DEF(default, "default")
|
||||||
|
DEF(throw, "throw")
|
||||||
|
DEF(try, "try")
|
||||||
|
DEF(catch, "catch")
|
||||||
|
DEF(finally, "finally")
|
||||||
|
DEF(function, "function")
|
||||||
|
DEF(debugger, "debugger")
|
||||||
|
DEF(with, "with")
|
||||||
|
/* FutureReservedWord */
|
||||||
|
DEF(class, "class")
|
||||||
|
DEF(const, "const")
|
||||||
|
DEF(enum, "enum")
|
||||||
|
DEF(export, "export")
|
||||||
|
DEF(extends, "extends")
|
||||||
|
DEF(import, "import")
|
||||||
|
DEF(super, "super")
|
||||||
|
/* FutureReservedWords when parsing strict mode code */
|
||||||
|
DEF(implements, "implements")
|
||||||
|
DEF(interface, "interface")
|
||||||
|
DEF(let, "let")
|
||||||
|
DEF(package, "package")
|
||||||
|
DEF(private, "private")
|
||||||
|
DEF(protected, "protected")
|
||||||
|
DEF(public, "public")
|
||||||
|
DEF(static, "static")
|
||||||
|
DEF(yield, "yield")
|
||||||
|
DEF(await, "await")
|
||||||
|
|
||||||
|
/* empty string */
|
||||||
|
DEF(empty_string, "")
|
||||||
|
/* identifiers */
|
||||||
|
DEF(length, "length")
|
||||||
|
DEF(fileName, "fileName")
|
||||||
|
DEF(lineNumber, "lineNumber")
|
||||||
|
DEF(message, "message")
|
||||||
|
DEF(stack, "stack")
|
||||||
|
DEF(name, "name")
|
||||||
|
DEF(toString, "toString")
|
||||||
|
DEF(toLocaleString, "toLocaleString")
|
||||||
|
DEF(valueOf, "valueOf")
|
||||||
|
DEF(eval, "eval")
|
||||||
|
DEF(prototype, "prototype")
|
||||||
|
DEF(constructor, "constructor")
|
||||||
|
DEF(configurable, "configurable")
|
||||||
|
DEF(writable, "writable")
|
||||||
|
DEF(enumerable, "enumerable")
|
||||||
|
DEF(value, "value")
|
||||||
|
DEF(get, "get")
|
||||||
|
DEF(set, "set")
|
||||||
|
DEF(of, "of")
|
||||||
|
DEF(__proto__, "__proto__")
|
||||||
|
DEF(undefined, "undefined")
|
||||||
|
DEF(number, "number")
|
||||||
|
DEF(boolean, "boolean")
|
||||||
|
DEF(string, "string")
|
||||||
|
DEF(object, "object")
|
||||||
|
DEF(symbol, "symbol")
|
||||||
|
DEF(integer, "integer")
|
||||||
|
DEF(unknown, "unknown")
|
||||||
|
DEF(arguments, "arguments")
|
||||||
|
DEF(callee, "callee")
|
||||||
|
DEF(caller, "caller")
|
||||||
|
DEF(_eval_, "<eval>")
|
||||||
|
DEF(_ret_, "<ret>")
|
||||||
|
DEF(_var_, "<var>")
|
||||||
|
DEF(_with_, "<with>")
|
||||||
|
DEF(lastIndex, "lastIndex")
|
||||||
|
DEF(target, "target")
|
||||||
|
DEF(index, "index")
|
||||||
|
DEF(input, "input")
|
||||||
|
DEF(defineProperties, "defineProperties")
|
||||||
|
DEF(apply, "apply")
|
||||||
|
DEF(join, "join")
|
||||||
|
DEF(concat, "concat")
|
||||||
|
DEF(split, "split")
|
||||||
|
DEF(construct, "construct")
|
||||||
|
DEF(getPrototypeOf, "getPrototypeOf")
|
||||||
|
DEF(setPrototypeOf, "setPrototypeOf")
|
||||||
|
DEF(isExtensible, "isExtensible")
|
||||||
|
DEF(preventExtensions, "preventExtensions")
|
||||||
|
DEF(has, "has")
|
||||||
|
DEF(deleteProperty, "deleteProperty")
|
||||||
|
DEF(defineProperty, "defineProperty")
|
||||||
|
DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor")
|
||||||
|
DEF(ownKeys, "ownKeys")
|
||||||
|
DEF(add, "add")
|
||||||
|
DEF(done, "done")
|
||||||
|
DEF(next, "next")
|
||||||
|
DEF(values, "values")
|
||||||
|
DEF(source, "source")
|
||||||
|
DEF(flags, "flags")
|
||||||
|
DEF(global, "global")
|
||||||
|
DEF(unicode, "unicode")
|
||||||
|
DEF(raw, "raw")
|
||||||
|
DEF(new_target, "new.target")
|
||||||
|
DEF(this_active_func, "this.active_func")
|
||||||
|
DEF(home_object, "<home_object>")
|
||||||
|
DEF(as, "as")
|
||||||
|
DEF(from, "from")
|
||||||
|
DEF(_default_, "*default*")
|
||||||
|
DEF(_star_, "*")
|
||||||
|
DEF(Module, "Module")
|
||||||
|
DEF(then, "then")
|
||||||
|
DEF(resolve, "resolve")
|
||||||
|
DEF(reject, "reject")
|
||||||
|
DEF(promise, "promise")
|
||||||
|
DEF(proxy, "proxy")
|
||||||
|
DEF(revoke, "revoke")
|
||||||
|
DEF(async, "async")
|
||||||
|
DEF(exec, "exec")
|
||||||
|
DEF(groups, "groups")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(bigint, "bigint")
|
||||||
|
DEF(bigfloat, "bigfloat")
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_ATOMICS
|
||||||
|
DEF(not_equal, "not-equal")
|
||||||
|
DEF(timed_out, "timed-out")
|
||||||
|
DEF(ok, "ok")
|
||||||
|
#endif
|
||||||
|
DEF(toJSON, "toJSON")
|
||||||
|
/* class names */
|
||||||
|
DEF(Object, "Object")
|
||||||
|
DEF(Array, "Array")
|
||||||
|
DEF(Error, "Error")
|
||||||
|
DEF(Number, "Number")
|
||||||
|
DEF(String, "String")
|
||||||
|
DEF(Boolean, "Boolean")
|
||||||
|
DEF(Symbol, "Symbol")
|
||||||
|
DEF(Arguments, "Arguments")
|
||||||
|
DEF(Math, "Math")
|
||||||
|
DEF(JSON, "JSON")
|
||||||
|
DEF(Date, "Date")
|
||||||
|
DEF(Function, "Function")
|
||||||
|
DEF(GeneratorFunction, "GeneratorFunction")
|
||||||
|
DEF(ForInIterator, "ForInIterator")
|
||||||
|
DEF(RegExp, "RegExp")
|
||||||
|
DEF(ArrayBuffer, "ArrayBuffer")
|
||||||
|
DEF(SharedArrayBuffer, "SharedArrayBuffer")
|
||||||
|
/* must keep same order as class IDs for typed arrays */
|
||||||
|
DEF(Uint8ClampedArray, "Uint8ClampedArray")
|
||||||
|
DEF(Int8Array, "Int8Array")
|
||||||
|
DEF(Uint8Array, "Uint8Array")
|
||||||
|
DEF(Int16Array, "Int16Array")
|
||||||
|
DEF(Uint16Array, "Uint16Array")
|
||||||
|
DEF(Int32Array, "Int32Array")
|
||||||
|
DEF(Uint32Array, "Uint32Array")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(BigInt64Array, "BigInt64Array")
|
||||||
|
DEF(BigUint64Array, "BigUint64Array")
|
||||||
|
#endif
|
||||||
|
DEF(Float32Array, "Float32Array")
|
||||||
|
DEF(Float64Array, "Float64Array")
|
||||||
|
DEF(DataView, "DataView")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(BigInt, "BigInt")
|
||||||
|
DEF(BigFloat, "BigFloat")
|
||||||
|
DEF(BigFloatEnv, "BigFloatEnv")
|
||||||
|
#endif
|
||||||
|
DEF(Map, "Map")
|
||||||
|
DEF(Set, "Set") /* Map + 1 */
|
||||||
|
DEF(WeakMap, "WeakMap") /* Map + 2 */
|
||||||
|
DEF(WeakSet, "WeakSet") /* Map + 3 */
|
||||||
|
DEF(Map_Iterator, "Map Iterator")
|
||||||
|
DEF(Set_Iterator, "Set Iterator")
|
||||||
|
DEF(Array_Iterator, "Array Iterator")
|
||||||
|
DEF(String_Iterator, "String Iterator")
|
||||||
|
DEF(Generator, "Generator")
|
||||||
|
DEF(Proxy, "Proxy")
|
||||||
|
DEF(Promise, "Promise")
|
||||||
|
DEF(PromiseResolveFunction, "PromiseResolveFunction")
|
||||||
|
DEF(PromiseRejectFunction, "PromiseRejectFunction")
|
||||||
|
DEF(AsyncFunction, "AsyncFunction")
|
||||||
|
DEF(AsyncFunctionResolve, "AsyncFunctionResolve")
|
||||||
|
DEF(AsyncFunctionReject, "AsyncFunctionReject")
|
||||||
|
DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction")
|
||||||
|
DEF(AsyncGenerator, "AsyncGenerator")
|
||||||
|
DEF(EvalError, "EvalError")
|
||||||
|
DEF(RangeError, "RangeError")
|
||||||
|
DEF(ReferenceError, "ReferenceError")
|
||||||
|
DEF(SyntaxError, "SyntaxError")
|
||||||
|
DEF(TypeError, "TypeError")
|
||||||
|
DEF(URIError, "URIError")
|
||||||
|
DEF(InternalError, "InternalError")
|
||||||
|
|
||||||
|
/* symbols */
|
||||||
|
DEF(Symbol_toPrimitive, "Symbol.toPrimitive")
|
||||||
|
DEF(Symbol_iterator, "Symbol.iterator")
|
||||||
|
DEF(Symbol_match, "Symbol.match")
|
||||||
|
DEF(Symbol_replace, "Symbol.replace")
|
||||||
|
DEF(Symbol_search, "Symbol.search")
|
||||||
|
DEF(Symbol_split, "Symbol.split")
|
||||||
|
DEF(Symbol_toStringTag, "Symbol.toStringTag")
|
||||||
|
DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable")
|
||||||
|
DEF(Symbol_hasInstance, "Symbol.hasInstance")
|
||||||
|
DEF(Symbol_species, "Symbol.species")
|
||||||
|
DEF(Symbol_unscopables, "Symbol.unscopables")
|
||||||
|
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(Symbol_operatorOrder, "Symbol.operatorOrder")
|
||||||
|
DEF(Symbol_operatorAdd, "Symbol.operatorAdd")
|
||||||
|
DEF(Symbol_operatorSub, "Symbol.operatorSub")
|
||||||
|
DEF(Symbol_operatorMul, "Symbol.operatorMul")
|
||||||
|
DEF(Symbol_operatorDiv, "Symbol.operatorDiv")
|
||||||
|
DEF(Symbol_operatorMod, "Symbol.operatorMod")
|
||||||
|
DEF(Symbol_operatorPow, "Symbol.operatorPow")
|
||||||
|
DEF(Symbol_operatorShl, "Symbol.operatorShl")
|
||||||
|
DEF(Symbol_operatorShr, "Symbol.operatorShr")
|
||||||
|
DEF(Symbol_operatorAnd, "Symbol.operatorAnd")
|
||||||
|
DEF(Symbol_operatorOr, "Symbol.operatorOr")
|
||||||
|
DEF(Symbol_operatorXor, "Symbol.operatorXor")
|
||||||
|
DEF(Symbol_operatorCmpLT, "Symbol.operatorCmpLT")
|
||||||
|
DEF(Symbol_operatorCmpLE, "Symbol.operatorCmpLE")
|
||||||
|
DEF(Symbol_operatorCmpEQ, "Symbol.operatorCmpEQ")
|
||||||
|
DEF(Symbol_operatorPlus, "Symbol.operatorPlus")
|
||||||
|
DEF(Symbol_operatorNeg, "Symbol.operatorNeg")
|
||||||
|
DEF(Symbol_operatorNot, "Symbol.operatorNot")
|
||||||
|
DEF(Symbol_operatorInc, "Symbol.operatorInc")
|
||||||
|
DEF(Symbol_operatorDec, "Symbol.operatorDec")
|
||||||
|
DEF(Symbol_operatorMathDiv, "Symbol.operatorMathDiv")
|
||||||
|
DEF(Symbol_operatorMathMod, "Symbol.operatorMathMod")
|
||||||
|
DEF(Symbol_operatorMathPow, "Symbol.operatorMathPow")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DEF */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* QuickJS C library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef QUICKJS_LIBC_H
|
||||||
|
#define QUICKJS_LIBC_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "quickjs.h"
|
||||||
|
|
||||||
|
JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);
|
||||||
|
JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);
|
||||||
|
void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
|
||||||
|
void js_std_loop(JSContext *ctx);
|
||||||
|
void js_std_free_handlers(JSRuntime *rt);
|
||||||
|
void js_std_dump_error(JSContext *ctx);
|
||||||
|
uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
|
||||||
|
JSModuleDef *js_module_loader(JSContext *ctx,
|
||||||
|
const char *module_name, void *opaque);
|
||||||
|
void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
|
||||||
|
int flags);
|
||||||
|
|
||||||
|
#endif /* QUICKJS_LIBC_H */
|
|
@ -0,0 +1,354 @@
|
||||||
|
/*
|
||||||
|
* QuickJS opcode definitions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef FMT
|
||||||
|
FMT(none)
|
||||||
|
FMT(none_int)
|
||||||
|
FMT(none_loc)
|
||||||
|
FMT(none_arg)
|
||||||
|
FMT(none_var_ref)
|
||||||
|
FMT(u8)
|
||||||
|
FMT(i8)
|
||||||
|
FMT(loc8)
|
||||||
|
FMT(const8)
|
||||||
|
FMT(label8)
|
||||||
|
FMT(u16)
|
||||||
|
FMT(i16)
|
||||||
|
FMT(label16)
|
||||||
|
FMT(npop)
|
||||||
|
FMT(npopx)
|
||||||
|
FMT(loc)
|
||||||
|
FMT(arg)
|
||||||
|
FMT(var_ref)
|
||||||
|
FMT(u32)
|
||||||
|
FMT(i32)
|
||||||
|
FMT(const)
|
||||||
|
FMT(label)
|
||||||
|
FMT(atom)
|
||||||
|
FMT(atom_u8)
|
||||||
|
FMT(atom_u16)
|
||||||
|
FMT(atom_label_u8)
|
||||||
|
FMT(atom_label_u16)
|
||||||
|
FMT(label_u16)
|
||||||
|
#undef FMT
|
||||||
|
#endif /* FMT */
|
||||||
|
|
||||||
|
#ifdef DEF
|
||||||
|
|
||||||
|
#ifndef def
|
||||||
|
#define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
def(invalid, 1, 0, 0, none) /* never emitted */
|
||||||
|
|
||||||
|
/* push values */
|
||||||
|
DEF( push_i32, 5, 0, 1, i32)
|
||||||
|
DEF( push_const, 5, 0, 1, const)
|
||||||
|
DEF( fclosure, 5, 0, 1, const) /* must follow push_const */
|
||||||
|
DEF(push_atom_value, 5, 0, 1, atom)
|
||||||
|
DEF( undefined, 1, 0, 1, none)
|
||||||
|
DEF( null, 1, 0, 1, none)
|
||||||
|
DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */
|
||||||
|
DEF( push_false, 1, 0, 1, none)
|
||||||
|
DEF( push_true, 1, 0, 1, none)
|
||||||
|
DEF( object, 1, 0, 1, none)
|
||||||
|
DEF( var_object, 1, 0, 1, none)
|
||||||
|
DEF( this_func, 1, 0, 1, none) /* only used at the start of a function */
|
||||||
|
DEF( arguments, 2, 0, 1, none) /* only used at the start of a function */
|
||||||
|
DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */
|
||||||
|
DEF( new_target, 1, 0, 1, none) /* only used at the start of a function */
|
||||||
|
DEF( home_object, 1, 0, 1, none) /* only used at the start of a function */
|
||||||
|
|
||||||
|
DEF( drop, 1, 1, 0, none) /* a -> */
|
||||||
|
DEF( nip, 1, 2, 1, none) /* a b -> b */
|
||||||
|
DEF( nip1, 1, 3, 2, none) /* a b c -> b c */
|
||||||
|
DEF( dup, 1, 1, 2, none) /* a -> a a */
|
||||||
|
DEF( dup1, 1, 2, 3, none) /* a b -> a a b */
|
||||||
|
DEF( dup2, 1, 2, 4, none) /* a b -> a b a b */
|
||||||
|
DEF( dup3, 1, 3, 6, none) /* a b c -> a b c a b c */
|
||||||
|
DEF( insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */
|
||||||
|
DEF( insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */
|
||||||
|
DEF( insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */
|
||||||
|
DEF( perm3, 1, 3, 3, none) /* obj a b -> a obj b */
|
||||||
|
DEF( perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */
|
||||||
|
DEF( perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */
|
||||||
|
DEF( swap, 1, 2, 2, none) /* a b -> b a */
|
||||||
|
DEF( swap2, 1, 4, 4, none) /* a b c d -> c d a b */
|
||||||
|
DEF( rot3l, 1, 3, 3, none) /* x a b -> a b x */
|
||||||
|
DEF( rot3r, 1, 3, 3, none) /* a b x -> x a b */
|
||||||
|
DEF( rot4l, 1, 4, 4, none) /* x a b c -> a b c x */
|
||||||
|
DEF( rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */
|
||||||
|
|
||||||
|
DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */
|
||||||
|
DEF( call, 3, 1, 1, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( apply, 3, 3, 1, u16)
|
||||||
|
DEF( return, 1, 1, 0, none)
|
||||||
|
DEF( return_undef, 1, 0, 0, none)
|
||||||
|
DEF(check_ctor_return, 1, 1, 2, none)
|
||||||
|
DEF( check_ctor, 1, 0, 0, none)
|
||||||
|
DEF( return_async, 1, 1, 0, none)
|
||||||
|
DEF( throw, 1, 1, 0, none)
|
||||||
|
DEF( throw_var, 6, 0, 0, atom_u8)
|
||||||
|
DEF( eval, 3, 1, 1, u16)
|
||||||
|
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||||
|
bytecode string */
|
||||||
|
DEF( get_super_ctor, 1, 1, 1, none)
|
||||||
|
DEF( get_super, 1, 1, 1, none)
|
||||||
|
|
||||||
|
DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */
|
||||||
|
DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */
|
||||||
|
DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */
|
||||||
|
DEF( put_var, 5, 1, 0, atom) /* must come after get_var */
|
||||||
|
DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */
|
||||||
|
DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */
|
||||||
|
|
||||||
|
DEF( get_ref_value, 1, 2, 3, none)
|
||||||
|
DEF( put_ref_value, 1, 3, 0, none)
|
||||||
|
|
||||||
|
DEF( define_var, 6, 0, 0, atom_u8)
|
||||||
|
DEF(check_define_var, 6, 0, 0, atom_u8)
|
||||||
|
DEF( define_func, 6, 1, 0, atom_u8)
|
||||||
|
DEF( get_field, 5, 1, 1, atom)
|
||||||
|
DEF( get_field2, 5, 1, 2, atom)
|
||||||
|
DEF( put_field, 5, 2, 0, atom)
|
||||||
|
DEF( get_array_el, 1, 2, 1, none)
|
||||||
|
DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */
|
||||||
|
DEF( put_array_el, 1, 3, 0, none)
|
||||||
|
DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */
|
||||||
|
DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */
|
||||||
|
DEF( define_field, 5, 2, 1, atom)
|
||||||
|
DEF( set_name, 5, 1, 1, atom)
|
||||||
|
DEF(set_name_computed, 1, 2, 2, none)
|
||||||
|
DEF( set_proto, 1, 2, 1, none)
|
||||||
|
DEF(define_array_el, 1, 3, 2, none)
|
||||||
|
DEF( append, 1, 3, 2, none) /* append enumerated object, update length */
|
||||||
|
DEF(copy_data_properties, 2, 3, 3, u8)
|
||||||
|
DEF( define_method, 6, 2, 1, atom_u8)
|
||||||
|
DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */
|
||||||
|
DEF( define_class, 2, 2, 2, u8)
|
||||||
|
|
||||||
|
DEF( get_loc, 3, 0, 1, loc)
|
||||||
|
DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */
|
||||||
|
DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
|
||||||
|
DEF( get_arg, 3, 0, 1, arg)
|
||||||
|
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
|
||||||
|
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
|
||||||
|
DEF( get_var_ref, 3, 0, 1, var_ref)
|
||||||
|
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
|
||||||
|
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
|
||||||
|
DEF(set_loc_uninitialized, 3, 0, 0, loc)
|
||||||
|
def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
DEF( get_loc_check, 3, 0, 1, loc)
|
||||||
|
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
||||||
|
DEF( put_loc_check_init, 3, 1, 0, loc)
|
||||||
|
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||||
|
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
||||||
|
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
||||||
|
DEF( close_loc, 3, 0, 0, loc)
|
||||||
|
def(close_var_object, 1, 0, 0, none) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
|
DEF( if_false, 5, 1, 0, label)
|
||||||
|
DEF( if_true, 5, 1, 0, label) /* must come after if_false */
|
||||||
|
DEF( goto, 5, 0, 0, label) /* must come after if_true */
|
||||||
|
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
|
||||||
|
DEF( catch, 5, 0, 1, label)
|
||||||
|
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
|
||||||
|
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
|
||||||
|
|
||||||
|
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
|
DEF( to_object, 1, 1, 1, none)
|
||||||
|
//DEF( to_string, 1, 1, 1, none)
|
||||||
|
DEF( to_propkey, 1, 1, 1, none)
|
||||||
|
DEF( to_propkey2, 1, 2, 2, none)
|
||||||
|
|
||||||
|
DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8)
|
||||||
|
|
||||||
|
DEF( make_loc_ref, 7, 0, 2, atom_u16)
|
||||||
|
DEF( make_arg_ref, 7, 0, 2, atom_u16)
|
||||||
|
DEF(make_var_ref_ref, 7, 0, 2, atom_u16)
|
||||||
|
DEF( make_var_ref, 5, 0, 2, atom)
|
||||||
|
|
||||||
|
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
||||||
|
|
||||||
|
DEF( for_in_start, 1, 1, 1, none)
|
||||||
|
DEF( for_of_start, 1, 1, 3, none)
|
||||||
|
DEF(for_await_of_start, 1, 1, 3, none)
|
||||||
|
DEF( for_in_next, 1, 1, 3, none)
|
||||||
|
DEF( for_of_next, 2, 3, 5, u8)
|
||||||
|
DEF(for_await_of_next, 1, 3, 4, none)
|
||||||
|
DEF(iterator_get_value_done, 1, 1, 2, none)
|
||||||
|
DEF( iterator_close, 1, 3, 0, none)
|
||||||
|
DEF(iterator_close_return, 1, 4, 4, none)
|
||||||
|
DEF(async_iterator_close, 1, 3, 2, none)
|
||||||
|
DEF(async_iterator_next, 1, 4, 4, none)
|
||||||
|
DEF(async_iterator_get, 2, 4, 5, u8)
|
||||||
|
DEF( initial_yield, 1, 0, 0, none)
|
||||||
|
DEF( yield, 1, 1, 2, none)
|
||||||
|
DEF( yield_star, 1, 2, 2, none)
|
||||||
|
DEF(async_yield_star, 1, 1, 2, none)
|
||||||
|
DEF( await, 1, 1, 1, none)
|
||||||
|
|
||||||
|
/* arithmetic/logic operations */
|
||||||
|
DEF( neg, 1, 1, 1, none)
|
||||||
|
DEF( plus, 1, 1, 1, none)
|
||||||
|
DEF( dec, 1, 1, 1, none)
|
||||||
|
DEF( inc, 1, 1, 1, none)
|
||||||
|
DEF( post_dec, 1, 1, 2, none)
|
||||||
|
DEF( post_inc, 1, 1, 2, none)
|
||||||
|
DEF( dec_loc, 2, 0, 0, loc8)
|
||||||
|
DEF( inc_loc, 2, 0, 0, loc8)
|
||||||
|
DEF( add_loc, 2, 1, 0, loc8)
|
||||||
|
DEF( not, 1, 1, 1, none)
|
||||||
|
DEF( lnot, 1, 1, 1, none)
|
||||||
|
DEF( typeof, 1, 1, 1, none)
|
||||||
|
DEF( delete, 1, 2, 1, none)
|
||||||
|
DEF( delete_var, 5, 0, 1, atom)
|
||||||
|
|
||||||
|
DEF( mul, 1, 2, 1, none)
|
||||||
|
DEF( div, 1, 2, 1, none)
|
||||||
|
DEF( mod, 1, 2, 1, none)
|
||||||
|
DEF( add, 1, 2, 1, none)
|
||||||
|
DEF( sub, 1, 2, 1, none)
|
||||||
|
DEF( pow, 1, 2, 1, none)
|
||||||
|
DEF( shl, 1, 2, 1, none)
|
||||||
|
DEF( sar, 1, 2, 1, none)
|
||||||
|
DEF( shr, 1, 2, 1, none)
|
||||||
|
DEF( lt, 1, 2, 1, none)
|
||||||
|
DEF( lte, 1, 2, 1, none)
|
||||||
|
DEF( gt, 1, 2, 1, none)
|
||||||
|
DEF( gte, 1, 2, 1, none)
|
||||||
|
DEF( instanceof, 1, 2, 1, none)
|
||||||
|
DEF( in, 1, 2, 1, none)
|
||||||
|
DEF( eq, 1, 2, 1, none)
|
||||||
|
DEF( neq, 1, 2, 1, none)
|
||||||
|
DEF( strict_eq, 1, 2, 1, none)
|
||||||
|
DEF( strict_neq, 1, 2, 1, none)
|
||||||
|
DEF( and, 1, 2, 1, none)
|
||||||
|
DEF( xor, 1, 2, 1, none)
|
||||||
|
DEF( or, 1, 2, 1, none)
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF( mul_pow10, 1, 2, 1, none)
|
||||||
|
DEF( math_div, 1, 2, 1, none)
|
||||||
|
DEF( math_mod, 1, 2, 1, none)
|
||||||
|
DEF( math_pow, 1, 2, 1, none)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SHORT_OPCODES
|
||||||
|
DEF( push_minus1, 1, 0, 1, none_int)
|
||||||
|
DEF( push_0, 1, 0, 1, none_int)
|
||||||
|
DEF( push_1, 1, 0, 1, none_int)
|
||||||
|
DEF( push_2, 1, 0, 1, none_int)
|
||||||
|
DEF( push_3, 1, 0, 1, none_int)
|
||||||
|
DEF( push_4, 1, 0, 1, none_int)
|
||||||
|
DEF( push_5, 1, 0, 1, none_int)
|
||||||
|
DEF( push_6, 1, 0, 1, none_int)
|
||||||
|
DEF( push_7, 1, 0, 1, none_int)
|
||||||
|
DEF( push_i8, 2, 0, 1, i8)
|
||||||
|
DEF( push_i16, 3, 0, 1, i16)
|
||||||
|
DEF( push_const8, 2, 0, 1, const8)
|
||||||
|
DEF( fclosure8, 2, 0, 1, const8) /* must follow push_const8 */
|
||||||
|
DEF(push_empty_string, 1, 0, 1, none)
|
||||||
|
|
||||||
|
DEF( get_loc8, 2, 0, 1, loc8)
|
||||||
|
DEF( put_loc8, 2, 1, 0, loc8)
|
||||||
|
DEF( set_loc8, 2, 1, 1, loc8)
|
||||||
|
|
||||||
|
DEF( get_loc0, 1, 0, 1, none_loc)
|
||||||
|
DEF( get_loc1, 1, 0, 1, none_loc)
|
||||||
|
DEF( get_loc2, 1, 0, 1, none_loc)
|
||||||
|
DEF( get_loc3, 1, 0, 1, none_loc)
|
||||||
|
DEF( put_loc0, 1, 1, 0, none_loc)
|
||||||
|
DEF( put_loc1, 1, 1, 0, none_loc)
|
||||||
|
DEF( put_loc2, 1, 1, 0, none_loc)
|
||||||
|
DEF( put_loc3, 1, 1, 0, none_loc)
|
||||||
|
DEF( set_loc0, 1, 1, 1, none_loc)
|
||||||
|
DEF( set_loc1, 1, 1, 1, none_loc)
|
||||||
|
DEF( set_loc2, 1, 1, 1, none_loc)
|
||||||
|
DEF( set_loc3, 1, 1, 1, none_loc)
|
||||||
|
DEF( get_arg0, 1, 0, 1, none_arg)
|
||||||
|
DEF( get_arg1, 1, 0, 1, none_arg)
|
||||||
|
DEF( get_arg2, 1, 0, 1, none_arg)
|
||||||
|
DEF( get_arg3, 1, 0, 1, none_arg)
|
||||||
|
DEF( put_arg0, 1, 1, 0, none_arg)
|
||||||
|
DEF( put_arg1, 1, 1, 0, none_arg)
|
||||||
|
DEF( put_arg2, 1, 1, 0, none_arg)
|
||||||
|
DEF( put_arg3, 1, 1, 0, none_arg)
|
||||||
|
DEF( set_arg0, 1, 1, 1, none_arg)
|
||||||
|
DEF( set_arg1, 1, 1, 1, none_arg)
|
||||||
|
DEF( set_arg2, 1, 1, 1, none_arg)
|
||||||
|
DEF( set_arg3, 1, 1, 1, none_arg)
|
||||||
|
DEF( get_var_ref0, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( get_var_ref1, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( get_var_ref2, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( get_var_ref3, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( put_var_ref0, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( put_var_ref1, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( put_var_ref2, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( put_var_ref3, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( set_var_ref0, 1, 1, 1, none_var_ref)
|
||||||
|
DEF( set_var_ref1, 1, 1, 1, none_var_ref)
|
||||||
|
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
||||||
|
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
||||||
|
|
||||||
|
DEF( get_length, 1, 1, 1, none)
|
||||||
|
|
||||||
|
DEF( if_false8, 2, 1, 0, label8)
|
||||||
|
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
||||||
|
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
|
||||||
|
DEF( goto16, 3, 0, 0, label16)
|
||||||
|
|
||||||
|
DEF( call0, 1, 1, 1, npopx)
|
||||||
|
DEF( call1, 1, 1, 1, npopx)
|
||||||
|
DEF( call2, 1, 1, 1, npopx)
|
||||||
|
DEF( call3, 1, 1, 1, npopx)
|
||||||
|
|
||||||
|
DEF( is_undefined, 1, 1, 1, none)
|
||||||
|
DEF( is_null, 1, 1, 1, none)
|
||||||
|
DEF( is_function, 1, 1, 1, none)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DEF( nop, 1, 0, 0, none) /* temporary use during code generation */
|
||||||
|
|
||||||
|
#undef DEF
|
||||||
|
#undef def
|
||||||
|
#endif /* DEF */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,909 @@
|
||||||
|
/*
|
||||||
|
* QuickJS Javascript Engine
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2019 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2019 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef QUICKJS_H
|
||||||
|
#define QUICKJS_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
#define CastToJSValue(v) v
|
||||||
|
#define CastToJSValueConst(v) v
|
||||||
|
#else
|
||||||
|
#define CastToJSValue(v) (JSValue)v
|
||||||
|
#define CastToJSValueConst(v) (JSValueConst)v
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define js_likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define js_unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
#define js_force_inline inline __attribute__((always_inline))
|
||||||
|
#define __js_printf_like(f, a) __attribute__((format(printf, f, a)))
|
||||||
|
#else
|
||||||
|
#define js_likely(x) (x)
|
||||||
|
#define js_unlikely(x) (x)
|
||||||
|
#define js_force_inline inline
|
||||||
|
#define __js_printf_like(a, b)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define JS_BOOL int
|
||||||
|
|
||||||
|
typedef struct JSRuntime JSRuntime;
|
||||||
|
typedef struct JSContext JSContext;
|
||||||
|
typedef struct JSObject JSObject;
|
||||||
|
typedef struct JSClass JSClass;
|
||||||
|
typedef uint32_t JSClassID;
|
||||||
|
typedef uint32_t JSAtom;
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(__aarch64__) || defined(_WIN64)
|
||||||
|
#define JS_PTR64
|
||||||
|
#define JS_PTR64_DEF(a) a
|
||||||
|
#else
|
||||||
|
#define JS_PTR64_DEF(a)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JS_PTR64
|
||||||
|
#define JS_NAN_BOXING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/* all tags with a reference count are negative */
|
||||||
|
JS_TAG_FIRST = -10, /* first negative tag */
|
||||||
|
JS_TAG_BIG_INT = -10,
|
||||||
|
JS_TAG_BIG_FLOAT = -9,
|
||||||
|
JS_TAG_SYMBOL = -8,
|
||||||
|
JS_TAG_STRING = -7,
|
||||||
|
JS_TAG_SHAPE = -6, /* used internally during GC */
|
||||||
|
JS_TAG_ASYNC_FUNCTION = -5, /* used internally during GC */
|
||||||
|
JS_TAG_VAR_REF = -4, /* used internally during GC */
|
||||||
|
JS_TAG_MODULE = -3, /* used internally */
|
||||||
|
JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */
|
||||||
|
JS_TAG_OBJECT = -1,
|
||||||
|
|
||||||
|
JS_TAG_INT = 0,
|
||||||
|
JS_TAG_BOOL = 1,
|
||||||
|
JS_TAG_NULL = 2,
|
||||||
|
JS_TAG_UNDEFINED = 3,
|
||||||
|
JS_TAG_UNINITIALIZED = 4,
|
||||||
|
JS_TAG_CATCH_OFFSET = 5,
|
||||||
|
JS_TAG_EXCEPTION = 6,
|
||||||
|
JS_TAG_FLOAT64 = 7,
|
||||||
|
/* any larger tag is FLOAT64 if JS_NAN_BOXING */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct JSRefCountHeader {
|
||||||
|
int ref_count;
|
||||||
|
} JSRefCountHeader;
|
||||||
|
|
||||||
|
#define JS_FLOAT64_NAN NAN
|
||||||
|
|
||||||
|
#ifdef CONFIG_CHECK_JSVALUE
|
||||||
|
/* JSValue consistency : it is not possible to run the code in this
|
||||||
|
mode, but it is useful to detect simple reference counting
|
||||||
|
errors. It would be interesting to modify a static C analyzer to
|
||||||
|
handle specific annotations (clang has such annotations but only
|
||||||
|
for objective C) */
|
||||||
|
typedef struct __JSValue *JSValue;
|
||||||
|
typedef const struct __JSValue *JSValueConst;
|
||||||
|
|
||||||
|
#define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf)
|
||||||
|
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
|
||||||
|
#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
|
||||||
|
#define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4)
|
||||||
|
#define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v)
|
||||||
|
#define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v)
|
||||||
|
#define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf)
|
||||||
|
|
||||||
|
#define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag))
|
||||||
|
#define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag))
|
||||||
|
|
||||||
|
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
|
||||||
|
|
||||||
|
#define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1)
|
||||||
|
|
||||||
|
static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
|
||||||
|
{
|
||||||
|
return JS_MKVAL(JS_TAG_FLOAT64, (int)d);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(JS_NAN_BOXING)
|
||||||
|
|
||||||
|
typedef uint64_t JSValue;
|
||||||
|
|
||||||
|
#define JSValueConst JSValue
|
||||||
|
|
||||||
|
#define JS_VALUE_GET_TAG(v) (int)((v) >> 32)
|
||||||
|
#define JS_VALUE_GET_INT(v) (int)(v)
|
||||||
|
#define JS_VALUE_GET_BOOL(v) (int)(v)
|
||||||
|
#define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v)
|
||||||
|
|
||||||
|
#define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val))
|
||||||
|
#define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr))
|
||||||
|
|
||||||
|
#define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */
|
||||||
|
|
||||||
|
static inline double JS_VALUE_GET_FLOAT64(JSValue v)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
JSValue v;
|
||||||
|
double d;
|
||||||
|
} u;
|
||||||
|
u.v = v;
|
||||||
|
u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32;
|
||||||
|
return u.d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32))
|
||||||
|
|
||||||
|
static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
double d;
|
||||||
|
uint64_t u64;
|
||||||
|
} u;
|
||||||
|
JSValue v;
|
||||||
|
u.d = d;
|
||||||
|
/* normalize NaN */
|
||||||
|
if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000))
|
||||||
|
v = JS_NAN;
|
||||||
|
else
|
||||||
|
v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST))
|
||||||
|
|
||||||
|
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
|
||||||
|
static inline int JS_VALUE_GET_NORM_TAG(JSValue v)
|
||||||
|
{
|
||||||
|
uint32_t tag;
|
||||||
|
tag = JS_VALUE_GET_TAG(v);
|
||||||
|
if (JS_TAG_IS_FLOAT64(tag))
|
||||||
|
return JS_TAG_FLOAT64;
|
||||||
|
else
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !JS_NAN_BOXING */
|
||||||
|
|
||||||
|
typedef union JSValueUnion {
|
||||||
|
int32_t int32;
|
||||||
|
double float64;
|
||||||
|
void *ptr;
|
||||||
|
} JSValueUnion;
|
||||||
|
|
||||||
|
typedef struct JSValue {
|
||||||
|
JSValueUnion u;
|
||||||
|
int64_t tag;
|
||||||
|
} JSValue;
|
||||||
|
|
||||||
|
#define JSValueConst JSValue
|
||||||
|
|
||||||
|
#define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag)
|
||||||
|
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
|
||||||
|
#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
|
||||||
|
#define JS_VALUE_GET_INT(v) ((v).u.int32)
|
||||||
|
#define JS_VALUE_GET_BOOL(v) ((v).u.int32)
|
||||||
|
#define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
|
||||||
|
#define JS_VALUE_GET_PTR(v) ((v).u.ptr)
|
||||||
|
|
||||||
|
//#define JS_MKVAL(tag, val) (JSValue){ .u.int32 = val, tag }
|
||||||
|
static inline JSValue JS_MKVAL(uint64_t tag, int32_t val)
|
||||||
|
{
|
||||||
|
JSValue value = {0};
|
||||||
|
value.u.int32 = val;
|
||||||
|
value.tag = tag;
|
||||||
|
return value;
|
||||||
|
|
||||||
|
}
|
||||||
|
//#define JS_MKPTR(tag, p) (JSValue){ .u.ptr = p, tag }
|
||||||
|
static inline JSValue JS_MKPTR(uint64_t tag, void *ptr)
|
||||||
|
{
|
||||||
|
JSValue value = {0};
|
||||||
|
value.u.ptr = ptr;
|
||||||
|
value.tag = tag;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
|
||||||
|
|
||||||
|
#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
|
||||||
|
/*
|
||||||
|
static inline JSValue JS_NAN_()
|
||||||
|
{
|
||||||
|
JSValue value = {};
|
||||||
|
value.u.float64 = JS_FLOAT64_NAN;
|
||||||
|
value.tag = JS_TAG_FLOAT64;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define JS_NAN JS_NAN_()
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
|
||||||
|
{
|
||||||
|
JSValue v;
|
||||||
|
v.tag = JS_TAG_FLOAT64;
|
||||||
|
v.u.float64 = d;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !JS_NAN_BOXING */
|
||||||
|
|
||||||
|
#define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0)
|
||||||
|
#define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2)))
|
||||||
|
|
||||||
|
#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v))
|
||||||
|
#define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v))
|
||||||
|
#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
|
||||||
|
|
||||||
|
/* special values */
|
||||||
|
#define JS_NULL JS_MKVAL(JS_TAG_NULL, 0)
|
||||||
|
#define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0)
|
||||||
|
#define JS_FALSE JS_MKVAL(JS_TAG_BOOL, 0)
|
||||||
|
#define JS_TRUE JS_MKVAL(JS_TAG_BOOL, 1)
|
||||||
|
#define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0)
|
||||||
|
#define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0)
|
||||||
|
|
||||||
|
/* flags for object properties */
|
||||||
|
#define JS_PROP_CONFIGURABLE (1 << 0)
|
||||||
|
#define JS_PROP_WRITABLE (1 << 1)
|
||||||
|
#define JS_PROP_ENUMERABLE (1 << 2)
|
||||||
|
#define JS_PROP_C_W_E (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)
|
||||||
|
#define JS_PROP_LENGTH (1 << 3) /* used internally in Arrays */
|
||||||
|
#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */
|
||||||
|
#define JS_PROP_NORMAL (0 << 4)
|
||||||
|
#define JS_PROP_GETSET (1 << 4)
|
||||||
|
#define JS_PROP_VARREF (2 << 4) /* used internally */
|
||||||
|
#define JS_PROP_AUTOINIT (3 << 4) /* used internally */
|
||||||
|
|
||||||
|
/* flags for JS_DefineProperty */
|
||||||
|
#define JS_PROP_HAS_SHIFT 8
|
||||||
|
#define JS_PROP_HAS_CONFIGURABLE (1 << 8)
|
||||||
|
#define JS_PROP_HAS_WRITABLE (1 << 9)
|
||||||
|
#define JS_PROP_HAS_ENUMERABLE (1 << 10)
|
||||||
|
#define JS_PROP_HAS_GET (1 << 11)
|
||||||
|
#define JS_PROP_HAS_SET (1 << 12)
|
||||||
|
#define JS_PROP_HAS_VALUE (1 << 13)
|
||||||
|
|
||||||
|
/* throw an exception if false would be returned
|
||||||
|
(JS_DefineProperty/JS_SetProperty) */
|
||||||
|
#define JS_PROP_THROW (1 << 14)
|
||||||
|
/* throw an exception if false would be returned in strict mode
|
||||||
|
(JS_SetProperty) */
|
||||||
|
#define JS_PROP_THROW_STRICT (1 << 15)
|
||||||
|
|
||||||
|
#define JS_PROP_NO_ADD (1 << 16) /* internal use */
|
||||||
|
#define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */
|
||||||
|
|
||||||
|
#define JS_DEFAULT_STACK_SIZE (256 * 1024)
|
||||||
|
|
||||||
|
/* JS_Eval() flags */
|
||||||
|
#define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */
|
||||||
|
#define JS_EVAL_TYPE_MODULE (1 << 0) /* module code */
|
||||||
|
#define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */
|
||||||
|
#define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */
|
||||||
|
#define JS_EVAL_TYPE_MASK (3 << 0)
|
||||||
|
|
||||||
|
#define JS_EVAL_FLAG_SHEBANG (1 << 2) /* skip first line beginning with '#!' */
|
||||||
|
#define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */
|
||||||
|
#define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */
|
||||||
|
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) /* internal use */
|
||||||
|
|
||||||
|
typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
|
||||||
|
typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
|
||||||
|
typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data);
|
||||||
|
|
||||||
|
typedef struct JSMallocState {
|
||||||
|
size_t malloc_count;
|
||||||
|
size_t malloc_size;
|
||||||
|
size_t malloc_limit;
|
||||||
|
void *opaque; /* user opaque */
|
||||||
|
} JSMallocState;
|
||||||
|
|
||||||
|
typedef struct JSMallocFunctions {
|
||||||
|
void *(*js_malloc)(JSMallocState *s, size_t size);
|
||||||
|
void (*js_free)(JSMallocState *s, void *ptr);
|
||||||
|
void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
|
||||||
|
size_t (*js_malloc_usable_size)(const void *ptr);
|
||||||
|
} JSMallocFunctions;
|
||||||
|
|
||||||
|
JSRuntime *JS_NewRuntime(void);
|
||||||
|
/* info lifetime must exceed that of rt */
|
||||||
|
void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
|
||||||
|
void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
|
||||||
|
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
|
||||||
|
JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
|
||||||
|
void JS_FreeRuntime(JSRuntime *rt);
|
||||||
|
typedef void JS_MarkFunc(JSRuntime *rt, JSValueConst val);
|
||||||
|
void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
|
||||||
|
void JS_RunGC(JSRuntime *rt);
|
||||||
|
JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
|
||||||
|
JS_BOOL JS_IsInGCSweep(JSRuntime *rt);
|
||||||
|
|
||||||
|
JSContext *JS_NewContext(JSRuntime *rt);
|
||||||
|
void JS_FreeContext(JSContext *s);
|
||||||
|
void *JS_GetContextOpaque(JSContext *ctx);
|
||||||
|
void JS_SetContextOpaque(JSContext *ctx, void *opaque);
|
||||||
|
JSRuntime *JS_GetRuntime(JSContext *ctx);
|
||||||
|
void JS_SetMaxStackSize(JSContext *ctx, size_t stack_size);
|
||||||
|
void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
|
||||||
|
JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
|
||||||
|
|
||||||
|
/* the following functions are used to select the intrinsic object to
|
||||||
|
save memory */
|
||||||
|
JSContext *JS_NewContextRaw(JSRuntime *rt);
|
||||||
|
void JS_AddIntrinsicBaseObjects(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicDate(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicEval(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicStringNormalize(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicRegExpCompiler(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicRegExp(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicJSON(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicProxy(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicMapSet(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicTypedArrays(JSContext *ctx);
|
||||||
|
void JS_AddIntrinsicPromise(JSContext *ctx);
|
||||||
|
JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv);
|
||||||
|
|
||||||
|
void *js_malloc_rt(JSRuntime *rt, size_t size);
|
||||||
|
void js_free_rt(JSRuntime *rt, void *ptr);
|
||||||
|
void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size);
|
||||||
|
size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr);
|
||||||
|
void *js_mallocz_rt(JSRuntime *rt, size_t size);
|
||||||
|
|
||||||
|
void *js_malloc(JSContext *ctx, size_t size);
|
||||||
|
void js_free(JSContext *ctx, void *ptr);
|
||||||
|
void *js_realloc(JSContext *ctx, void *ptr, size_t size);
|
||||||
|
size_t js_malloc_usable_size(JSContext *ctx, const void *ptr);
|
||||||
|
void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack);
|
||||||
|
void *js_mallocz(JSContext *ctx, size_t size);
|
||||||
|
char *js_strdup(JSContext *ctx, const char *str);
|
||||||
|
char *js_strndup(JSContext *ctx, const char *s, size_t n);
|
||||||
|
|
||||||
|
typedef struct JSMemoryUsage {
|
||||||
|
int64_t malloc_size, malloc_limit, memory_used_size;
|
||||||
|
int64_t malloc_count;
|
||||||
|
int64_t memory_used_count;
|
||||||
|
int64_t atom_count, atom_size;
|
||||||
|
int64_t str_count, str_size;
|
||||||
|
int64_t obj_count, obj_size;
|
||||||
|
int64_t prop_count, prop_size;
|
||||||
|
int64_t shape_count, shape_size;
|
||||||
|
int64_t js_func_count, js_func_size, js_func_code_size;
|
||||||
|
int64_t js_func_pc2line_count, js_func_pc2line_size;
|
||||||
|
int64_t c_func_count, array_count;
|
||||||
|
int64_t fast_array_count, fast_array_elements;
|
||||||
|
int64_t binary_object_count, binary_object_size;
|
||||||
|
} JSMemoryUsage;
|
||||||
|
|
||||||
|
void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
|
||||||
|
void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
|
||||||
|
|
||||||
|
/* atom support */
|
||||||
|
JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, int len);
|
||||||
|
JSAtom JS_NewAtom(JSContext *ctx, const char *str);
|
||||||
|
JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
|
||||||
|
JSAtom JS_DupAtom(JSContext *ctx, JSAtom v);
|
||||||
|
void JS_FreeAtom(JSContext *ctx, JSAtom v);
|
||||||
|
void JS_FreeAtomRT(JSRuntime *rt, JSAtom v);
|
||||||
|
JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom);
|
||||||
|
JSValue JS_AtomToString(JSContext *ctx, JSAtom atom);
|
||||||
|
const char *JS_AtomToCString(JSContext *ctx, JSAtom atom);
|
||||||
|
|
||||||
|
/* object class support */
|
||||||
|
|
||||||
|
typedef struct JSPropertyEnum {
|
||||||
|
JS_BOOL is_enumerable;
|
||||||
|
JSAtom atom;
|
||||||
|
} JSPropertyEnum;
|
||||||
|
|
||||||
|
typedef struct JSPropertyDescriptor {
|
||||||
|
int flags;
|
||||||
|
JSValue value;
|
||||||
|
JSValue getter;
|
||||||
|
JSValue setter;
|
||||||
|
} JSPropertyDescriptor;
|
||||||
|
|
||||||
|
typedef struct JSClassExoticMethods {
|
||||||
|
/* Return -1 if exception (can only happen in case of Proxy object),
|
||||||
|
FALSE if the property does not exists, TRUE if it exists. If 1 is
|
||||||
|
returned, the property descriptor 'desc' is filled if != NULL. */
|
||||||
|
int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc,
|
||||||
|
JSValueConst obj, JSAtom prop);
|
||||||
|
/* '*ptab' should hold the '*plen' property keys. Return 0 if OK,
|
||||||
|
-1 if exception. The 'is_enumerable' field is ignored.
|
||||||
|
*/
|
||||||
|
int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab,
|
||||||
|
uint32_t *plen,
|
||||||
|
JSValueConst obj);
|
||||||
|
/* return < 0 if exception, or TRUE/FALSE */
|
||||||
|
int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop);
|
||||||
|
/* return < 0 if exception or TRUE/FALSE */
|
||||||
|
int (*define_own_property)(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
JSAtom prop, JSValueConst val,
|
||||||
|
JSValueConst getter, JSValueConst setter,
|
||||||
|
int flags);
|
||||||
|
/* The following methods can be emulated with the previous ones,
|
||||||
|
so they are usually not needed */
|
||||||
|
/* return < 0 if exception or TRUE/FALSE */
|
||||||
|
int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom);
|
||||||
|
JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
|
||||||
|
JSValueConst receiver);
|
||||||
|
/* return < 0 if exception or TRUE/FALSE */
|
||||||
|
int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
|
||||||
|
JSValueConst value, JSValueConst receiver, int flags);
|
||||||
|
} JSClassExoticMethods;
|
||||||
|
|
||||||
|
typedef void JSClassFinalizer(JSRuntime *rt, JSValue val);
|
||||||
|
typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val,
|
||||||
|
JS_MarkFunc *mark_func);
|
||||||
|
typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj,
|
||||||
|
JSValueConst this_val, int argc, JSValueConst *argv);
|
||||||
|
|
||||||
|
typedef struct JSClassDef {
|
||||||
|
const char *class_name;
|
||||||
|
JSClassFinalizer *finalizer;
|
||||||
|
JSClassGCMark *gc_mark;
|
||||||
|
JSClassCall *call;
|
||||||
|
/* XXX: suppress this indirection ? It is here only to save memory
|
||||||
|
because only a few classes need these methods */
|
||||||
|
JSClassExoticMethods *exotic;
|
||||||
|
} JSClassDef;
|
||||||
|
|
||||||
|
JSClassID JS_NewClassID(JSClassID *pclass_id);
|
||||||
|
int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
|
||||||
|
int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
|
||||||
|
|
||||||
|
/* value handling */
|
||||||
|
|
||||||
|
static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)
|
||||||
|
{
|
||||||
|
return JS_MKVAL(JS_TAG_BOOL, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
|
||||||
|
{
|
||||||
|
return JS_MKVAL(JS_TAG_INT, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
|
||||||
|
{
|
||||||
|
return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValue JS_NewInt64(JSContext *ctx, int64_t v);
|
||||||
|
|
||||||
|
static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d)
|
||||||
|
{
|
||||||
|
JSValue v;
|
||||||
|
int32_t val;
|
||||||
|
union {
|
||||||
|
double d;
|
||||||
|
uint64_t u;
|
||||||
|
} u, t;
|
||||||
|
u.d = d;
|
||||||
|
val = (int32_t)d;
|
||||||
|
t.d = val;
|
||||||
|
/* -0 cannot be represented as integer, so we compare the bit
|
||||||
|
representation */
|
||||||
|
if (u.u == t.u) {
|
||||||
|
v = JS_MKVAL(JS_TAG_INT, val);
|
||||||
|
} else {
|
||||||
|
v = __JS_NewFloat64(ctx, d);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_BOOL JS_IsNumber(JSValueConst v);
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsInteger(JSValueConst v)
|
||||||
|
{
|
||||||
|
int tag = JS_VALUE_GET_TAG(v);
|
||||||
|
return tag == JS_TAG_INT || tag == JS_TAG_BIG_INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsBigFloat(JSValueConst v)
|
||||||
|
{
|
||||||
|
int tag = JS_VALUE_GET_TAG(v);
|
||||||
|
return tag == JS_TAG_BIG_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsBool(JSValueConst v)
|
||||||
|
{
|
||||||
|
return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsNull(JSValueConst v)
|
||||||
|
{
|
||||||
|
return JS_VALUE_GET_TAG(v) == JS_TAG_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsUndefined(JSValueConst v)
|
||||||
|
{
|
||||||
|
return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsException(JSValueConst v)
|
||||||
|
{
|
||||||
|
return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsUninitialized(JSValueConst v)
|
||||||
|
{
|
||||||
|
return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsString(JSValueConst v)
|
||||||
|
{
|
||||||
|
return JS_VALUE_GET_TAG(v) == JS_TAG_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsSymbol(JSValueConst v)
|
||||||
|
{
|
||||||
|
return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JS_BOOL JS_IsObject(JSValueConst v)
|
||||||
|
{
|
||||||
|
return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValue JS_Throw(JSContext *ctx, JSValue obj);
|
||||||
|
JSValue JS_GetException(JSContext *ctx);
|
||||||
|
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
|
||||||
|
void JS_EnableIsErrorProperty(JSContext *ctx, JS_BOOL enable);
|
||||||
|
void JS_ResetUncatchableError(JSContext *ctx);
|
||||||
|
JSValue JS_NewError(JSContext *ctx);
|
||||||
|
JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
|
||||||
|
JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...);
|
||||||
|
JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...);
|
||||||
|
JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...);
|
||||||
|
JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
|
||||||
|
JSValue JS_ThrowOutOfMemory(JSContext *ctx);
|
||||||
|
|
||||||
|
void __JS_FreeValue(JSContext *ctx, JSValue v);
|
||||||
|
static inline void JS_FreeValue(JSContext *ctx, JSValue v)
|
||||||
|
{
|
||||||
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
||||||
|
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
|
||||||
|
if (--p->ref_count <= 0) {
|
||||||
|
__JS_FreeValue(ctx, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void __JS_FreeValueRT(JSRuntime *rt, JSValue v);
|
||||||
|
static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v)
|
||||||
|
{
|
||||||
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
||||||
|
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
|
||||||
|
if (--p->ref_count <= 0) {
|
||||||
|
__JS_FreeValueRT(rt, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v)
|
||||||
|
{
|
||||||
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
||||||
|
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
|
||||||
|
p->ref_count++;
|
||||||
|
}
|
||||||
|
return CastToJSValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
|
||||||
|
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
|
||||||
|
static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
|
||||||
|
{
|
||||||
|
return JS_ToInt32(ctx, (int32_t*)pres, val);
|
||||||
|
}
|
||||||
|
int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
|
||||||
|
int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val);
|
||||||
|
int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val);
|
||||||
|
|
||||||
|
JSValue JS_NewStringLen(JSContext *ctx, const char *str1, int len1);
|
||||||
|
JSValue JS_NewString(JSContext *ctx, const char *str);
|
||||||
|
JSValue JS_NewAtomString(JSContext *ctx, const char *str);
|
||||||
|
JSValue JS_ToString(JSContext *ctx, JSValueConst val);
|
||||||
|
JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val);
|
||||||
|
const char *JS_ToCStringLen(JSContext *ctx, int *plen, JSValueConst val1, JS_BOOL cesu8);
|
||||||
|
static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1)
|
||||||
|
{
|
||||||
|
return JS_ToCStringLen(ctx, NULL, val1, 0);
|
||||||
|
}
|
||||||
|
void JS_FreeCString(JSContext *ctx, const char *ptr);
|
||||||
|
|
||||||
|
JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id);
|
||||||
|
JSValue JS_NewObjectClass(JSContext *ctx, int class_id);
|
||||||
|
JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto);
|
||||||
|
JSValue JS_NewObject(JSContext *ctx);
|
||||||
|
|
||||||
|
JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
|
||||||
|
JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
|
||||||
|
|
||||||
|
JSValue JS_NewArray(JSContext *ctx);
|
||||||
|
int JS_IsArray(JSContext *ctx, JSValueConst val);
|
||||||
|
|
||||||
|
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||||
|
JSAtom prop, JSValueConst receiver,
|
||||||
|
JS_BOOL throw_ref_error);
|
||||||
|
static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
JSAtom prop)
|
||||||
|
{
|
||||||
|
return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0);
|
||||||
|
}
|
||||||
|
JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
const char *prop);
|
||||||
|
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
uint32_t idx);
|
||||||
|
|
||||||
|
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
JSAtom prop, JSValue val,
|
||||||
|
int flags);
|
||||||
|
static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
JSAtom prop, JSValue val)
|
||||||
|
{
|
||||||
|
return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW);
|
||||||
|
}
|
||||||
|
int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
uint32_t idx, JSValue val);
|
||||||
|
int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
int64_t idx, JSValue val);
|
||||||
|
int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
const char *prop, JSValue val);
|
||||||
|
int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop);
|
||||||
|
int JS_IsExtensible(JSContext *ctx, JSValueConst obj);
|
||||||
|
int JS_PreventExtensions(JSContext *ctx, JSValueConst obj);
|
||||||
|
int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags);
|
||||||
|
int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
|
||||||
|
JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val);
|
||||||
|
|
||||||
|
JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
|
||||||
|
const char *filename);
|
||||||
|
JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
|
||||||
|
int argc, JSValueConst *argv);
|
||||||
|
JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
|
||||||
|
int argc, JSValueConst *argv);
|
||||||
|
JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
|
||||||
|
int argc, JSValueConst *argv);
|
||||||
|
JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
|
||||||
|
JSValueConst new_target,
|
||||||
|
int argc, JSValueConst *argv);
|
||||||
|
JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
|
||||||
|
const char *filename, int eval_flags);
|
||||||
|
#define JS_EVAL_BINARY_LOAD_ONLY (1 << 0) /* only load the module */
|
||||||
|
JSValue JS_EvalBinary(JSContext *ctx,
|
||||||
|
const uint8_t *buf, size_t buf_len, int flags);
|
||||||
|
JSValue JS_GetGlobalObject(JSContext *ctx);
|
||||||
|
int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj);
|
||||||
|
int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
JSAtom prop, JSValueConst val,
|
||||||
|
JSValueConst getter, JSValueConst setter, int flags);
|
||||||
|
int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
JSAtom prop, JSValue val, int flags);
|
||||||
|
int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
uint32_t idx, JSValue val, int flags);
|
||||||
|
int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
const char *prop, JSValue val, int flags);
|
||||||
|
int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,
|
||||||
|
JSAtom prop, JSValue getter, JSValue setter,
|
||||||
|
int flags);
|
||||||
|
void JS_SetOpaque(JSValue obj, void *opaque);
|
||||||
|
void *JS_GetOpaque(JSValueConst obj, JSClassID class_id);
|
||||||
|
void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id);
|
||||||
|
|
||||||
|
typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr);
|
||||||
|
JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
|
||||||
|
JSFreeArrayBufferDataFunc *free_func, void *opaque,
|
||||||
|
JS_BOOL is_shared);
|
||||||
|
JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
|
||||||
|
void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
|
||||||
|
uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
|
||||||
|
|
||||||
|
/* return != 0 if the JS code needs to be interrupted */
|
||||||
|
typedef int JSInterruptHandler(JSRuntime *rt, void *opaque);
|
||||||
|
void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
|
||||||
|
/* if can_block is TRUE, Atomics.wait() can be used */
|
||||||
|
void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);
|
||||||
|
|
||||||
|
typedef struct JSModuleDef JSModuleDef;
|
||||||
|
|
||||||
|
/* return the module specifier (allocated with js_malloc()) or NULL if
|
||||||
|
exception */
|
||||||
|
typedef char *JSModuleNormalizeFunc(JSContext *ctx,
|
||||||
|
const char *module_base_name,
|
||||||
|
const char *module_name, void *opaque);
|
||||||
|
typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx,
|
||||||
|
const char *module_name, void *opaque);
|
||||||
|
|
||||||
|
/* module_normalize = NULL is allowed and invokes the default module
|
||||||
|
filename normalizer */
|
||||||
|
void JS_SetModuleLoaderFunc(JSRuntime *rt,
|
||||||
|
JSModuleNormalizeFunc *module_normalize,
|
||||||
|
JSModuleLoaderFunc *module_loader, void *opaque);
|
||||||
|
|
||||||
|
/* JS Job support */
|
||||||
|
|
||||||
|
typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv);
|
||||||
|
int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv);
|
||||||
|
|
||||||
|
JS_BOOL JS_IsJobPending(JSRuntime *rt);
|
||||||
|
int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);
|
||||||
|
|
||||||
|
/* Object Writer/Reader (currently only used to handle precompiled code) */
|
||||||
|
#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */
|
||||||
|
#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */
|
||||||
|
uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
|
||||||
|
int flags);
|
||||||
|
#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */
|
||||||
|
#define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */
|
||||||
|
JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
|
||||||
|
int flags);
|
||||||
|
JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj, JSValueConst this_obj);
|
||||||
|
|
||||||
|
/* C function definition */
|
||||||
|
typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
|
||||||
|
JS_CFUNC_generic,
|
||||||
|
JS_CFUNC_generic_magic,
|
||||||
|
JS_CFUNC_constructor,
|
||||||
|
JS_CFUNC_constructor_magic,
|
||||||
|
JS_CFUNC_constructor_or_func,
|
||||||
|
JS_CFUNC_constructor_or_func_magic,
|
||||||
|
JS_CFUNC_f_f,
|
||||||
|
JS_CFUNC_f_f_f,
|
||||||
|
JS_CFUNC_getter,
|
||||||
|
JS_CFUNC_setter,
|
||||||
|
JS_CFUNC_getter_magic,
|
||||||
|
JS_CFUNC_setter_magic,
|
||||||
|
JS_CFUNC_iterator_next,
|
||||||
|
} JSCFunctionEnum;
|
||||||
|
|
||||||
|
typedef union JSCFunctionType {
|
||||||
|
JSCFunction *generic;
|
||||||
|
JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
|
||||||
|
JSCFunction *constructor;
|
||||||
|
JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic);
|
||||||
|
JSCFunction *constructor_or_func;
|
||||||
|
double (*f_f)(double);
|
||||||
|
double (*f_f_f)(double, double);
|
||||||
|
JSValue (*getter)(JSContext *ctx, JSValueConst this_val);
|
||||||
|
JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val);
|
||||||
|
JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic);
|
||||||
|
JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic);
|
||||||
|
JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv, int *pdone, int magic);
|
||||||
|
} JSCFunctionType;
|
||||||
|
|
||||||
|
JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
|
||||||
|
const char *name,
|
||||||
|
int length, JSCFunctionEnum cproto, int magic);
|
||||||
|
JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
|
||||||
|
int length, int magic, int data_len,
|
||||||
|
JSValueConst *data);
|
||||||
|
|
||||||
|
static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
|
||||||
|
int length)
|
||||||
|
{
|
||||||
|
return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
|
||||||
|
const char *name,
|
||||||
|
int length, JSCFunctionEnum cproto, int magic)
|
||||||
|
{
|
||||||
|
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* C property definition */
|
||||||
|
|
||||||
|
typedef struct JSCFunctionListEntry {
|
||||||
|
const char *name;
|
||||||
|
uint8_t prop_flags;
|
||||||
|
uint8_t def_type;
|
||||||
|
int16_t magic;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t length; /* XXX: should move outside union */
|
||||||
|
uint8_t cproto; /* XXX: should move outside union */
|
||||||
|
JSCFunctionType cfunc;
|
||||||
|
} func;
|
||||||
|
struct {
|
||||||
|
JSCFunctionType get;
|
||||||
|
JSCFunctionType set;
|
||||||
|
} getset;
|
||||||
|
struct {
|
||||||
|
const char *name;
|
||||||
|
int base;
|
||||||
|
} alias;
|
||||||
|
struct {
|
||||||
|
const struct JSCFunctionListEntry *tab;
|
||||||
|
int len;
|
||||||
|
} prop_list;
|
||||||
|
const char *str;
|
||||||
|
int32_t i32;
|
||||||
|
int64_t i64;
|
||||||
|
double f64;
|
||||||
|
} u;
|
||||||
|
} JSCFunctionListEntry;
|
||||||
|
|
||||||
|
#define JS_DEF_CFUNC 0
|
||||||
|
#define JS_DEF_CGETSET 1
|
||||||
|
#define JS_DEF_CGETSET_MAGIC 2
|
||||||
|
#define JS_DEF_PROP_STRING 3
|
||||||
|
#define JS_DEF_PROP_INT32 4
|
||||||
|
#define JS_DEF_PROP_INT64 5
|
||||||
|
#define JS_DEF_PROP_DOUBLE 6
|
||||||
|
#define JS_DEF_PROP_UNDEFINED 7
|
||||||
|
#define JS_DEF_OBJECT 8
|
||||||
|
#define JS_DEF_ALIAS 9
|
||||||
|
|
||||||
|
#define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u.func = { length, JS_CFUNC_generic, { .generic = func1 } } }
|
||||||
|
#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u.func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } }
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, /*.u.func = */{ length, JS_CFUNC_ ## cproto, { /*.cproto = */func1 } } }
|
||||||
|
#else
|
||||||
|
#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u.func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } }
|
||||||
|
#endif
|
||||||
|
#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u.func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } }
|
||||||
|
#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u.getset.get.getter = fgetter, .u.getset.set.setter = fsetter }
|
||||||
|
#define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u.getset.get.getter_magic = fgetter, .u.getset.set.setter_magic = fsetter }
|
||||||
|
#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u.str = cstr }
|
||||||
|
#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u.i32 = val }
|
||||||
|
#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u.i64 = val }
|
||||||
|
#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u.f64 = val }
|
||||||
|
#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u.i32 = 0 }
|
||||||
|
#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u.prop_list = { tab, len } }
|
||||||
|
#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u.alias = { from, -1 } }
|
||||||
|
#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u.alias = { from, base } }
|
||||||
|
|
||||||
|
void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
|
||||||
|
const JSCFunctionListEntry *tab,
|
||||||
|
int len);
|
||||||
|
|
||||||
|
/* C module definition */
|
||||||
|
|
||||||
|
typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m);
|
||||||
|
|
||||||
|
JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
|
||||||
|
JSModuleInitFunc *func);
|
||||||
|
/* can only be called before the module is instantiated */
|
||||||
|
int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str);
|
||||||
|
int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
|
||||||
|
const JSCFunctionListEntry *tab, int len);
|
||||||
|
/* can only be called after the module is instantiated */
|
||||||
|
int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
|
||||||
|
JSValue val);
|
||||||
|
int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
|
||||||
|
const JSCFunctionListEntry *tab, int len);
|
||||||
|
|
||||||
|
#undef js_unlikely
|
||||||
|
#undef js_force_inline
|
||||||
|
|
||||||
|
// https://www.freelists.org/post/quickjs-devel/how-to-iterator-over-a-JSValue-object,1
|
||||||
|
int js_get_fast_array(JSContext *ctx, JSValueConst obj,
|
||||||
|
JSValue **arrpp, uint32_t *countp);
|
||||||
|
|
||||||
|
#endif /* QUICKJS_H */
|
|
@ -0,0 +1 @@
|
||||||
|
The main documentation is in doc/quickjs.pdf or doc/quickjs.html.
|
|
@ -0,0 +1,85 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Release the QuickJS source code
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
version=`cat VERSION`
|
||||||
|
|
||||||
|
if [ "$1" = "-h" ] ; then
|
||||||
|
echo "release.sh [all]"
|
||||||
|
echo ""
|
||||||
|
echo "all: build all the archives. Otherwise only build the quickjs source archive."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$1" = "all" ] ; then
|
||||||
|
|
||||||
|
#################################################"
|
||||||
|
# unicode data
|
||||||
|
|
||||||
|
d="quickjs-${version}"
|
||||||
|
name="quickjs-unicode-data-${version}"
|
||||||
|
outdir="/tmp/${d}"
|
||||||
|
|
||||||
|
rm -rf $outdir
|
||||||
|
mkdir -p $outdir $outdir/unicode
|
||||||
|
|
||||||
|
cp unicode/* $outdir/unicode
|
||||||
|
|
||||||
|
( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} )
|
||||||
|
|
||||||
|
#################################################"
|
||||||
|
# all tests
|
||||||
|
|
||||||
|
d="quickjs-${version}"
|
||||||
|
name="quickjs-tests-${version}"
|
||||||
|
outdir="/tmp/${d}"
|
||||||
|
|
||||||
|
rm -rf $outdir
|
||||||
|
mkdir -p $outdir $outdir/test262o $outdir/test262 $outdir/tests
|
||||||
|
|
||||||
|
cp -a test262o/test $outdir/test262o
|
||||||
|
|
||||||
|
cp -a test262/test test262/harness $outdir/test262
|
||||||
|
|
||||||
|
cp -a tests/bench-v8 $outdir/tests
|
||||||
|
|
||||||
|
( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} )
|
||||||
|
|
||||||
|
fi # all
|
||||||
|
|
||||||
|
#################################################"
|
||||||
|
# quickjs
|
||||||
|
|
||||||
|
make build_doc
|
||||||
|
|
||||||
|
d="quickjs-${version}"
|
||||||
|
outdir="/tmp/${d}"
|
||||||
|
|
||||||
|
rm -rf $outdir
|
||||||
|
mkdir -p $outdir $outdir/doc $outdir/tests $outdir/examples
|
||||||
|
|
||||||
|
cp Makefile VERSION TODO readme.txt release.sh \
|
||||||
|
qjs.c qjsc.c qjscalc.js repl.js \
|
||||||
|
quickjs.c quickjs.h quickjs-atom.h \
|
||||||
|
quickjs-libc.c quickjs-libc.h quickjs-opcode.h \
|
||||||
|
cutils.c cutils.h list.h \
|
||||||
|
libregexp.c libregexp.h libregexp-opcode.h \
|
||||||
|
libunicode.c libunicode.h libunicode-table.h \
|
||||||
|
libbf.c libbf.h \
|
||||||
|
jscompress.c unicode_gen.c unicode_gen_def.h \
|
||||||
|
bjson.c \
|
||||||
|
run-test262.c test262o.conf test262.conf test262bn.conf \
|
||||||
|
test262o_errors.txt test262_errors.txt test262bn_errors.txt \
|
||||||
|
$outdir
|
||||||
|
|
||||||
|
cp tests/*.js tests/*.patch $outdir/tests
|
||||||
|
|
||||||
|
cp examples/*.js examples/*.c $outdir/examples
|
||||||
|
|
||||||
|
cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \
|
||||||
|
doc/jsbignum.texi doc/jsbignum.html doc/jsbignum.pdf \
|
||||||
|
$outdir/doc
|
||||||
|
|
||||||
|
( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} )
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,173 @@
|
||||||
|
[config]
|
||||||
|
# general settings for test262 ES6 version
|
||||||
|
|
||||||
|
# framework style: old, new
|
||||||
|
style=new
|
||||||
|
|
||||||
|
# handle tests tagged as [noStrict]: yes, no, skip
|
||||||
|
nostrict=yes
|
||||||
|
|
||||||
|
# handle tests tagged as [strictOnly]: yes, no, skip
|
||||||
|
strict=yes
|
||||||
|
|
||||||
|
# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all
|
||||||
|
mode=default
|
||||||
|
|
||||||
|
# handle tests flagged as [async]: yes, no, skip
|
||||||
|
# for these, load 'harness/doneprintHandle.js' prior to test
|
||||||
|
# and expect `print('Test262:AsyncTestComplete')` to be called for
|
||||||
|
# successful termination
|
||||||
|
async=yes
|
||||||
|
|
||||||
|
# handle tests flagged as [module]: yes, no, skip
|
||||||
|
module=yes
|
||||||
|
|
||||||
|
# output error messages: yes, no
|
||||||
|
verbose=yes
|
||||||
|
|
||||||
|
# load harness files from this directory
|
||||||
|
harnessdir=test262/harness
|
||||||
|
|
||||||
|
# names of harness include files to skip
|
||||||
|
#harnessexclude=
|
||||||
|
|
||||||
|
# name of the error file for known errors
|
||||||
|
errorfile=test262_errors.txt
|
||||||
|
|
||||||
|
# exclude tests enumerated in this file (see also [exclude] section)
|
||||||
|
#excludefile=test262_exclude.txt
|
||||||
|
|
||||||
|
# report test results to this file
|
||||||
|
reportfile=test262_report.txt
|
||||||
|
|
||||||
|
# enumerate tests from this directory
|
||||||
|
testdir=test262/test
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# Standard language features and proposed extensions
|
||||||
|
# list the features that are included
|
||||||
|
# skipped features are tagged as such to avoid warnings
|
||||||
|
|
||||||
|
Array.prototype.flat
|
||||||
|
Array.prototype.flatMap
|
||||||
|
Array.prototype.flatten
|
||||||
|
Array.prototype.values
|
||||||
|
ArrayBuffer
|
||||||
|
arrow-function
|
||||||
|
async-functions
|
||||||
|
async-iteration
|
||||||
|
Atomics
|
||||||
|
BigInt=skip
|
||||||
|
caller
|
||||||
|
class
|
||||||
|
class-fields-private=skip
|
||||||
|
class-fields-public=skip
|
||||||
|
computed-property-names
|
||||||
|
const
|
||||||
|
cross-realm=skip
|
||||||
|
DataView
|
||||||
|
DataView.prototype.getFloat32
|
||||||
|
DataView.prototype.getFloat64
|
||||||
|
DataView.prototype.getInt16
|
||||||
|
DataView.prototype.getInt32
|
||||||
|
DataView.prototype.getInt8
|
||||||
|
DataView.prototype.getUint16
|
||||||
|
DataView.prototype.getUint32
|
||||||
|
DataView.prototype.setUint8
|
||||||
|
default-arg
|
||||||
|
default-parameters
|
||||||
|
destructuring-assignment
|
||||||
|
destructuring-binding
|
||||||
|
export-star-as-namespace-from-module=skip
|
||||||
|
Float32Array
|
||||||
|
Float64Array
|
||||||
|
for-of
|
||||||
|
generators
|
||||||
|
global
|
||||||
|
Int8Array
|
||||||
|
IsHTMLDDA=skip
|
||||||
|
json-superset
|
||||||
|
let
|
||||||
|
Map
|
||||||
|
new.target
|
||||||
|
numeric-separator-literal
|
||||||
|
object-rest
|
||||||
|
object-spread
|
||||||
|
Object.is
|
||||||
|
optional-catch-binding
|
||||||
|
Promise.prototype.finally
|
||||||
|
Proxy
|
||||||
|
Reflect
|
||||||
|
Reflect.construct
|
||||||
|
Reflect.set
|
||||||
|
Reflect.setPrototypeOf
|
||||||
|
regexp-dotall
|
||||||
|
regexp-lookbehind
|
||||||
|
regexp-named-groups
|
||||||
|
regexp-unicode-property-escapes
|
||||||
|
Set
|
||||||
|
SharedArrayBuffer
|
||||||
|
string-trimming
|
||||||
|
String.fromCodePoint
|
||||||
|
String.prototype.endsWith
|
||||||
|
String.prototype.includes
|
||||||
|
String.prototype.matchAll=skip
|
||||||
|
String.prototype.trimEnd
|
||||||
|
String.prototype.trimStart
|
||||||
|
super
|
||||||
|
Symbol
|
||||||
|
Symbol.asyncIterator
|
||||||
|
Symbol.hasInstance
|
||||||
|
Symbol.isConcatSpreadable
|
||||||
|
Symbol.iterator
|
||||||
|
Symbol.match
|
||||||
|
Symbol.matchAll=skip
|
||||||
|
Symbol.prototype.description
|
||||||
|
Symbol.replace
|
||||||
|
Symbol.search
|
||||||
|
Symbol.species
|
||||||
|
Symbol.split
|
||||||
|
Symbol.toPrimitive
|
||||||
|
Symbol.toStringTag
|
||||||
|
Symbol.unscopables
|
||||||
|
tail-call-optimization=skip
|
||||||
|
template
|
||||||
|
TypedArray
|
||||||
|
u180e
|
||||||
|
Uint16Array
|
||||||
|
Uint8Array
|
||||||
|
Uint8ClampedArray
|
||||||
|
WeakMap
|
||||||
|
WeakSet
|
||||||
|
|
||||||
|
[exclude]
|
||||||
|
# list excluded tests and directories here
|
||||||
|
|
||||||
|
# intl not supported
|
||||||
|
test262/test/intl402/
|
||||||
|
|
||||||
|
# these builtins are not supported:
|
||||||
|
test262/test/built-ins/BigInt/
|
||||||
|
|
||||||
|
# mislabelled feature Symbol.match -> Symbol.matchAll
|
||||||
|
test262/test/built-ins/Symbol/matchAll/prop-desc.js
|
||||||
|
|
||||||
|
# incompatible with the "caller" feature
|
||||||
|
test262/test/built-ins/Function/prototype/restricted-property-caller.js
|
||||||
|
test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
|
||||||
|
|
||||||
|
# no debugger keyword support
|
||||||
|
test262/test/language/statements/debugger/statement.js
|
||||||
|
|
||||||
|
# bogus html close comment test with syntax error
|
||||||
|
test262/test/annexB/built-ins/Function/createdynfn-html-close-comment-params.js
|
||||||
|
|
||||||
|
# bogus test #14 compares 2 consecutive calls to Date(), may be different if unlucky
|
||||||
|
#test262/test/built-ins/Date/S15.9.2.1_A2.js
|
||||||
|
|
||||||
|
# slow tests
|
||||||
|
#test262/test/built-ins/RegExp/CharacterClassEscapes/
|
||||||
|
#test262/test/built-ins/RegExp/property-escapes/
|
||||||
|
|
||||||
|
[tests]
|
||||||
|
# list test files or use config.testdir
|
|
@ -0,0 +1,175 @@
|
||||||
|
[config]
|
||||||
|
# general settings for test262 ES6 bignum version
|
||||||
|
|
||||||
|
# framework style: old, new
|
||||||
|
style=new
|
||||||
|
|
||||||
|
# handle tests tagged as [noStrict]: yes, no, skip
|
||||||
|
nostrict=yes
|
||||||
|
|
||||||
|
# handle tests tagged as [strictOnly]: yes, no, skip
|
||||||
|
strict=yes
|
||||||
|
|
||||||
|
# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all
|
||||||
|
mode=default
|
||||||
|
|
||||||
|
# handle tests flagged as [async]: yes, no, skip
|
||||||
|
# for these, load 'harness/doneprintHandle.js' prior to test
|
||||||
|
# and expect `print('Test262:AsyncTestComplete')` to be called for
|
||||||
|
# successful termination
|
||||||
|
async=yes
|
||||||
|
|
||||||
|
# handle tests flagged as [module]: yes, no, skip
|
||||||
|
module=yes
|
||||||
|
|
||||||
|
# output error messages: yes, no
|
||||||
|
verbose=yes
|
||||||
|
|
||||||
|
# load harness files from this directory
|
||||||
|
harnessdir=test262/harness
|
||||||
|
|
||||||
|
# names of harness include files to skip
|
||||||
|
# bignum version does not support Atomics
|
||||||
|
harnessexclude=testAtomics.js
|
||||||
|
|
||||||
|
# name of the error file for known errors
|
||||||
|
errorfile=test262bn_errors.txt
|
||||||
|
|
||||||
|
# exclude tests enumerated in this file (see also [exclude] section)
|
||||||
|
#excludefile=test262bn_exclude.txt
|
||||||
|
|
||||||
|
# report test results to this file
|
||||||
|
reportfile=test262bn_report.txt
|
||||||
|
|
||||||
|
# enumerate tests from this directory
|
||||||
|
testdir=test262/test
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# Standard language features and proposed extensions
|
||||||
|
# list the features that are included
|
||||||
|
# skipped features are tagged as such to avoid warnings
|
||||||
|
|
||||||
|
Array.prototype.flat
|
||||||
|
Array.prototype.flatMap
|
||||||
|
Array.prototype.flatten
|
||||||
|
Array.prototype.values
|
||||||
|
ArrayBuffer
|
||||||
|
arrow-function
|
||||||
|
async-functions
|
||||||
|
async-iteration
|
||||||
|
Atomics=skip
|
||||||
|
BigInt
|
||||||
|
caller
|
||||||
|
class
|
||||||
|
class-fields-private=skip
|
||||||
|
class-fields-public=skip
|
||||||
|
computed-property-names
|
||||||
|
const
|
||||||
|
cross-realm=skip
|
||||||
|
DataView
|
||||||
|
DataView.prototype.getFloat32
|
||||||
|
DataView.prototype.getFloat64
|
||||||
|
DataView.prototype.getInt16
|
||||||
|
DataView.prototype.getInt32
|
||||||
|
DataView.prototype.getInt8
|
||||||
|
DataView.prototype.getUint16
|
||||||
|
DataView.prototype.getUint32
|
||||||
|
DataView.prototype.setUint8
|
||||||
|
default-arg
|
||||||
|
default-parameters
|
||||||
|
destructuring-assignment
|
||||||
|
destructuring-binding
|
||||||
|
export-star-as-namespace-from-module=skip
|
||||||
|
Float32Array
|
||||||
|
Float64Array
|
||||||
|
for-of
|
||||||
|
generators
|
||||||
|
global
|
||||||
|
Int8Array
|
||||||
|
IsHTMLDDA=skip
|
||||||
|
json-superset
|
||||||
|
let
|
||||||
|
Map
|
||||||
|
new.target
|
||||||
|
numeric-separator-literal
|
||||||
|
object-rest
|
||||||
|
object-spread
|
||||||
|
Object.is
|
||||||
|
optional-catch-binding
|
||||||
|
Promise.prototype.finally
|
||||||
|
Proxy
|
||||||
|
Reflect
|
||||||
|
Reflect.construct
|
||||||
|
Reflect.set
|
||||||
|
Reflect.setPrototypeOf
|
||||||
|
regexp-dotall
|
||||||
|
regexp-lookbehind
|
||||||
|
regexp-named-groups
|
||||||
|
regexp-unicode-property-escapes
|
||||||
|
Set
|
||||||
|
SharedArrayBuffer=skip
|
||||||
|
string-trimming
|
||||||
|
String.fromCodePoint
|
||||||
|
String.prototype.endsWith
|
||||||
|
String.prototype.includes
|
||||||
|
String.prototype.matchAll=skip
|
||||||
|
String.prototype.trimEnd
|
||||||
|
String.prototype.trimStart
|
||||||
|
super
|
||||||
|
Symbol
|
||||||
|
Symbol.asyncIterator
|
||||||
|
Symbol.hasInstance
|
||||||
|
Symbol.isConcatSpreadable
|
||||||
|
Symbol.iterator
|
||||||
|
Symbol.match
|
||||||
|
Symbol.matchAll=skip
|
||||||
|
Symbol.prototype.description
|
||||||
|
Symbol.replace
|
||||||
|
Symbol.search
|
||||||
|
Symbol.species
|
||||||
|
Symbol.split
|
||||||
|
Symbol.toPrimitive
|
||||||
|
Symbol.toStringTag
|
||||||
|
Symbol.unscopables
|
||||||
|
tail-call-optimization=skip
|
||||||
|
template
|
||||||
|
TypedArray
|
||||||
|
u180e
|
||||||
|
Uint16Array
|
||||||
|
Uint8Array
|
||||||
|
Uint8ClampedArray
|
||||||
|
WeakMap
|
||||||
|
WeakSet
|
||||||
|
|
||||||
|
[exclude]
|
||||||
|
# list excluded tests and directories here
|
||||||
|
|
||||||
|
# intl not supported
|
||||||
|
test262/test/intl402/
|
||||||
|
|
||||||
|
# these builtins are not supported:
|
||||||
|
test262/test/built-ins/Atomics/
|
||||||
|
test262/test/built-ins/SharedArrayBuffer/
|
||||||
|
|
||||||
|
# mislabelled feature Symbol.match -> Symbol.matchAll
|
||||||
|
test262/test/built-ins/Symbol/matchAll/prop-desc.js
|
||||||
|
|
||||||
|
# incompatible with the "caller" feature
|
||||||
|
test262/test/built-ins/Function/prototype/restricted-property-caller.js
|
||||||
|
test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
|
||||||
|
|
||||||
|
# no debugger keyword support
|
||||||
|
test262/test/language/statements/debugger/statement.js
|
||||||
|
|
||||||
|
# bogus html close comment test with syntax error
|
||||||
|
test262/test/annexB/built-ins/Function/createdynfn-html-close-comment-params.js
|
||||||
|
|
||||||
|
# bogus test #14 compares 2 consecutive calls to Date(), may be different if unlucky
|
||||||
|
#test262/test/built-ins/Date/S15.9.2.1_A2.js
|
||||||
|
|
||||||
|
# slow tests
|
||||||
|
#test262/test/built-ins/RegExp/CharacterClassEscapes/
|
||||||
|
#test262/test/built-ins/RegExp/property-escapes/
|
||||||
|
|
||||||
|
[tests]
|
||||||
|
# list test files or use config.testdir
|
|
@ -0,0 +1,404 @@
|
||||||
|
[config]
|
||||||
|
# general settings for test262 ES5 version
|
||||||
|
|
||||||
|
# framework style: old, new
|
||||||
|
style=old
|
||||||
|
|
||||||
|
# handle tests tagged as @noStrict: yes, no, skip
|
||||||
|
nostrict=yes
|
||||||
|
|
||||||
|
# handle tests tagged as @strictOnly: yes, no, skip
|
||||||
|
strict=yes
|
||||||
|
|
||||||
|
# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all
|
||||||
|
mode=default
|
||||||
|
|
||||||
|
# output error messages: yes, no
|
||||||
|
verbose=yes
|
||||||
|
|
||||||
|
# load harness files this directory
|
||||||
|
harnessdir=test262o/test/harness
|
||||||
|
|
||||||
|
# name of the error file for known errors
|
||||||
|
errorfile=test262o_errors.txt
|
||||||
|
|
||||||
|
# exclude tests enumerated in this file
|
||||||
|
#excludefile=test262o_excluded.txt
|
||||||
|
|
||||||
|
# report test results to this file
|
||||||
|
reportfile=test262o_report.txt
|
||||||
|
|
||||||
|
# enumerate tests from this directory
|
||||||
|
testdir=test262o/test/suite
|
||||||
|
|
||||||
|
[exclude]
|
||||||
|
# list excluded tests and directories here
|
||||||
|
|
||||||
|
# intl not supported
|
||||||
|
test262o/test/suite/intl402/
|
||||||
|
|
||||||
|
# ES6 != ES5: block scoped function definitions allowed in strict mode
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A1_T1.js
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A2_T1.js
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A2_T2.js
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A3_T1.js
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A3_T2.js
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A4_T1.js
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A4_T2.js
|
||||||
|
test262o/test/suite/bestPractice/Sbp_A5_T2.js
|
||||||
|
|
||||||
|
# ES6 != ES5: `y={x};` is shorthand for `y={x:x}`
|
||||||
|
test262o/test/suite/ch12/12.1/S12.1_A4_T2.js
|
||||||
|
test262o/test/suite/ch12/12.6/12.6.4/S12.6.4_A15.js
|
||||||
|
|
||||||
|
# ES6 != ES5: function length property is configurable
|
||||||
|
test262o/test/suite/ch11/11.4/11.4.1/11.4.1-5-a-28-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-15-1.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.1/S15.1.2.1_A4.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A9.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A7.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.4/S15.1.2.4_A2.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.5/S15.1.2.5_A2.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.3/S15.1.3.3_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.4/S15.1.3.4_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-186.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-187.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-191.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-194.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-201.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.2/S15.2.4.2_A9.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.3/S15.2.4.3_A9.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.4/S15.2.4.4_A9.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.5/S15.2.4.5_A9.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.6/S15.2.4.6_A9.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.7/S15.2.4.7_A9.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.3/15.3.3.2/15.3.3.2-1.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.2/S15.3.4.2_A9.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.3/S15.3.4.3_A9.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.4/S15.3.4.4_A9.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-15-2.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T1.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T2.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.3/S15.4.3_A2.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.2/S15.4.4.2_A4.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.3/S15.4.4.3_A4.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.4/S15.4.4.4_A4.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A6.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A6.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A7.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A5.2.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.4/S15.5.4.4_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.5/S15.5.4.5_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.6/S15.5.4.6_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.7/S15.5.4.7_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.8/S15.5.4.8_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.9/S15.5.4.9_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.10/S15.5.4.10_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.11/S15.5.4.11_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.12/S15.5.4.12_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.13/S15.5.4.13_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.14/S15.5.4.14_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.15/S15.5.4.15_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.16/S15.5.4.16_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.17/S15.5.4.17_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.18/S15.5.4.18_A9.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.19/S15.5.4.19_A9.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.4/15.9.4.2/S15.9.4.2_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.4/15.9.4.3/S15.9.4.3_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.1/S15.9.5.1_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.2/S15.9.5.2_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.3/S15.9.5.3_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.4/S15.9.5.4_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.5/S15.9.5.5_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.6/S15.9.5.6_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.7/S15.9.5.7_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.8/S15.9.5.8_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.9/S15.9.5.9_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.10/S15.9.5.10_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.11/S15.9.5.11_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.12/S15.9.5.12_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.13/S15.9.5.13_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.14/S15.9.5.14_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.15/S15.9.5.15_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.16/S15.9.5.16_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.17/S15.9.5.17_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.18/S15.9.5.18_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.19/S15.9.5.19_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.20/S15.9.5.20_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.21/S15.9.5.21_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.22/S15.9.5.22_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.23/S15.9.5.23_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.24/S15.9.5.24_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.25/S15.9.5.25_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.26/S15.9.5.26_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.27/S15.9.5.27_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.28/S15.9.5.28_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.29/S15.9.5.29_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.30/S15.9.5.30_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.31/S15.9.5.31_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.32/S15.9.5.32_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.33/S15.9.5.33_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.34/S15.9.5.34_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.35/S15.9.5.35_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.36/S15.9.5.36_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.37/S15.9.5.37_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.38/S15.9.5.38_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.39/S15.9.5.39_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/S15.9.5.40_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.41/S15.9.5.41_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.42/S15.9.5.42_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A9.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.3/S15.10.6.3_A9.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.4/S15.10.6.4_A9.js
|
||||||
|
|
||||||
|
# ES6 != ES5: object literals may have duplicates
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5-4-4-a-1-s.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-1.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-2.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-1.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-2.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-1.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-2.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-3.js
|
||||||
|
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-4.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Date.prototype is no longer an instance of Date
|
||||||
|
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/15.9.5.40_1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.getPrototypeOf converts argument to object
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-3.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.getPrototypeOf(NativeError)
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-12.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-13.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-14.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-15.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-16.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-17.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.getOwnPropertyDescriptor converts argument to object
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-3.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.getOwnPropertyNames converts argument to object
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-5.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.seal accepts all types
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-1.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-2.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-3.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.freeze accepts all types
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-1.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-2.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-3.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.preventExtensions accepts all types
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-1.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-2.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-3.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.isSealed accepts all types
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.11/15.2.3.11-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.isFrozen accepts all types
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-1.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-2.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-3.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.isExtensible accepts all types
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-1.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-2.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-3.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-4.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Object.keys converts argument to object
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-1.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-2.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-3.js
|
||||||
|
|
||||||
|
# ES6 != ES5: source and other properties of RegExp.prototype are not own properties
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-212.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-213.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214.js
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215.js
|
||||||
|
|
||||||
|
# ES6 != ES5: String numeric object properties are enumerated first
|
||||||
|
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-44.js
|
||||||
|
|
||||||
|
# ES6: new RegExp(regex, flags) is valid
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T2.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.4/15.10.4.1/15.10.4.1-1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T2.js
|
||||||
|
|
||||||
|
# ES6 != ES5: RegExp.prototype.test behavior
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A5_T3.js
|
||||||
|
|
||||||
|
# ES6 != ES5: source, global, ignoreCase, multiline, lastIndex are not data properties
|
||||||
|
# of RegExp objects and RegExp.prototype is not a RegExp object
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-2.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A8.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A9.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A10.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-2.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A8.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A9.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A10.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-2.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A8.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A9.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A10.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-2.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A8.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A9.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A10.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-2.js
|
||||||
|
|
||||||
|
# ES6 != ES5: Error.prototype is a normal object
|
||||||
|
test262o/test/suite/ch15/15.11/15.11.4/S15.11.4_A2.js
|
||||||
|
|
||||||
|
# ES6 different ToLength() semantics
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A4_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A2_T2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T1.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A2_T2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T1.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A3_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A3_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T1.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A4_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T1.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T3.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-8.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-28.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-29.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-28.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-8.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-29.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-8.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-28.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-29.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-8.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-28.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-29.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-25.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-7.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-12.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-25.js
|
||||||
|
|
||||||
|
# ES6 different ToLength() semantics causes near infinite runtime
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-14.js
|
||||||
|
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-14.js
|
||||||
|
|
||||||
|
# ES6 arguments/caller changes
|
||||||
|
test262o/test/suite/ch10/10.6/10.6-13-b-1-s.js
|
||||||
|
test262o/test/suite/ch10/10.6/10.6-13-b-2-s.js
|
||||||
|
test262o/test/suite/ch10/10.6/10.6-13-b-3-s.js
|
||||||
|
test262o/test/suite/ch10/10.6/10.6-14-1-s.js
|
||||||
|
test262o/test/suite/ch10/10.6/10.6-14-b-1-s.js
|
||||||
|
test262o/test/suite/ch10/10.6/10.6-14-b-4-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-29-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-30-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-31-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-32-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-33-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-34-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-35-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/13.2-36-s.js
|
||||||
|
test262o/test/suite/ch13/13.2/S13.2.3_A1.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-1.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-4.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-5.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-1.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-4.js
|
||||||
|
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-5.js
|
||||||
|
|
||||||
|
# u180e is no longer considered as a space
|
||||||
|
test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A2.js
|
||||||
|
test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T1.js
|
||||||
|
test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T2.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A2_T10.js
|
||||||
|
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A2_T10.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-2.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-3.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-4.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-5.js
|
||||||
|
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-6.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A1_T1.js
|
||||||
|
test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A2_T1.js
|
||||||
|
|
||||||
|
# E6 eval return value is different
|
||||||
|
test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.js
|
||||||
|
test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.1.js
|
||||||
|
|
||||||
|
# ECMA 2019 optional-catch-binding feature allows try{}catch{}
|
||||||
|
test262o/test/suite/ch12/12.14/S12.14_A16_T4.js
|
||||||
|
|
||||||
|
[tests]
|
||||||
|
# list test files or use config.testdir
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,683 @@
|
||||||
|
diff --git a/harness/doneprintHandle.js b/harness/doneprintHandle.js
|
||||||
|
index 2b4ab88..6c95f9f 100644
|
||||||
|
--- a/harness/doneprintHandle.js
|
||||||
|
+++ b/harness/doneprintHandle.js
|
||||||
|
@@ -11,7 +11,7 @@ function __consolePrintHandle__(msg){
|
||||||
|
|
||||||
|
function $DONE(){
|
||||||
|
if(!arguments[0])
|
||||||
|
- __consolePrintHandle__('Test262:AsyncTestComplete');
|
||||||
|
+ $async_done = true;
|
||||||
|
else
|
||||||
|
- __consolePrintHandle__('Test262:AsyncTestFailure:' + arguments[0]);
|
||||||
|
+ __consolePrintHandle__('Error:' + arguments[0]);
|
||||||
|
}
|
||||||
|
diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js
|
||||||
|
index 362a6d16..d3dde03 100644
|
||||||
|
--- a/harness/regExpUtils.js
|
||||||
|
+++ b/harness/regExpUtils.js
|
||||||
|
@@ -5,6 +5,7 @@ description: |
|
||||||
|
Collection of functions used to assert the correctness of RegExp objects.
|
||||||
|
---*/
|
||||||
|
|
||||||
|
+/*
|
||||||
|
function buildString({ loneCodePoints, ranges }) {
|
||||||
|
const CHUNK_SIZE = 10000;
|
||||||
|
let result = String.fromCodePoint(...loneCodePoints);
|
||||||
|
@@ -21,6 +22,32 @@ function buildString({ loneCodePoints, ranges }) {
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+var codePointRange;
|
||||||
|
+
|
||||||
|
+if ($262 && typeof $262.codePointRange === "function") {
|
||||||
|
+ /* use C function to build the codePointRange (much faster with
|
||||||
|
+ slow JS engines) */
|
||||||
|
+ codePointRange = $262.codePointRange;
|
||||||
|
+} else {
|
||||||
|
+ codePointRange = function codePointRange(start, end) {
|
||||||
|
+ const codePoints = [];
|
||||||
|
+ let length = 0;
|
||||||
|
+ for (codePoint = start; codePoint < end; codePoint++) {
|
||||||
|
+ codePoints[length++] = codePoint;
|
||||||
|
+ }
|
||||||
|
+ return String.fromCodePoint.apply(null, codePoints);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function buildString({ loneCodePoints, ranges }) {
|
||||||
|
+ let result = String.fromCodePoint.apply(null, loneCodePoints);
|
||||||
|
+ for (const [start, end] of ranges) {
|
||||||
|
+ result += codePointRange(start, end + 1);
|
||||||
|
+ }
|
||||||
|
+ return result;
|
||||||
|
+}
|
||||||
|
|
||||||
|
function testPropertyEscapes(regex, string, expression) {
|
||||||
|
if (!regex.test(string)) {
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-flags-u.js
|
||||||
|
index 652ef43..8d1a7ed 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\d/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier-flags-u.js
|
||||||
|
index 8683600..36d9f1c 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\d+/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier.js
|
||||||
|
index 20d6b38..e9c91f8 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-plus-quantifier.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\d+/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape.js
|
||||||
|
index d3aef45..b2c949b 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\d/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js
|
||||||
|
index ead3d68..beaf9cf 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\D/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier-flags-u.js
|
||||||
|
index 5c02690..0030b23 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\D+/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier.js
|
||||||
|
index 960d9cf..b663be0 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\D+/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape.js
|
||||||
|
index 85b1dcc..dcbd2eb 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\D/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js
|
||||||
|
index eda913b..cb57074 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\S/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier-flags-u.js
|
||||||
|
index 8e21a55..026309c 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\S+/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier.js
|
||||||
|
index f7cc4a3..98cfdff 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\S+/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape.js
|
||||||
|
index 3bca8ae..4ec88be 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\S/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js
|
||||||
|
index 3da454a..0a94a16 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\W/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier-flags-u.js
|
||||||
|
index 7e7faad..0a10667 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\W+/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier.js
|
||||||
|
index 41ffa53..55447f8 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\W+/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape.js
|
||||||
|
index ca47608..c1580cb 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\W/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-flags-u.js
|
||||||
|
index 82bb950..ac17d3b 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\s/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier-flags-u.js
|
||||||
|
index 7a3b57d..f74a350 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\s+/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier.js
|
||||||
|
index e1084ff..ba93158 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-plus-quantifier.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\s+/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape.js
|
||||||
|
index d1a3fda..0de155f 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\s/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-flags-u.js
|
||||||
|
index 0b8b183..2ccf8bf 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\w/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier-flags-u.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier-flags-u.js
|
||||||
|
index d824426..b389118 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier-flags-u.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier-flags-u.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0x10ffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0x10FFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0x10ffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\w+/ug;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier.js
|
||||||
|
index bafffd7..334290d 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-plus-quantifier.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\w+/g;
|
||||||
|
diff --git a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape.js b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape.js
|
||||||
|
index cba30b0..afc5615 100644
|
||||||
|
--- a/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape.js
|
||||||
|
+++ b/test/built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape.js
|
||||||
|
@@ -33,14 +33,16 @@ info: |
|
||||||
|
The production CharacterClassEscape :: W evaluates as follows:
|
||||||
|
Return the set of all characters not included in the set returned by CharacterClassEscape :: w.
|
||||||
|
features: [String.fromCodePoint]
|
||||||
|
+includes: [regExpUtils.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
const chunks = [];
|
||||||
|
-const totalChunks = Math.ceil(0xffff / 0x10000);
|
||||||
|
-
|
||||||
|
-for (let codePoint = 0; codePoint < 0xFFFF; codePoint++) {
|
||||||
|
- // split strings to avoid a super long one;
|
||||||
|
- chunks[codePoint % totalChunks] += String.fromCodePoint(codePoint);
|
||||||
|
+const lastCodePoint = 0xffff;
|
||||||
|
+let codePoint = 0;
|
||||||
|
+while (codePoint <= lastCodePoint) {
|
||||||
|
+ let n = Math.min(0x10000, lastCodePoint - codePoint + 1);
|
||||||
|
+ chunks.push(codePointRange(codePoint, codePoint + n));
|
||||||
|
+ codePoint += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const re = /\w/g;
|
|
@ -0,0 +1,269 @@
|
||||||
|
"use math";
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function assert(actual, expected, message) {
|
||||||
|
if (arguments.length == 1)
|
||||||
|
expected = true;
|
||||||
|
|
||||||
|
if (actual === expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (actual !== null && expected !== null
|
||||||
|
&& typeof actual == 'object' && typeof expected == 'object'
|
||||||
|
&& actual.toString() === expected.toString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw Error("assertion failed: got |" + actual + "|" +
|
||||||
|
", expected |" + expected + "|" +
|
||||||
|
(message ? " (" + message + ")" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load more elaborate version of assert if available
|
||||||
|
try { __loadScript("test_assert.js"); } catch(e) {}
|
||||||
|
|
||||||
|
/*----------------*/
|
||||||
|
|
||||||
|
function pow(a, n)
|
||||||
|
{
|
||||||
|
var r, i;
|
||||||
|
r = 1;
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
r *= a;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_integer()
|
||||||
|
{
|
||||||
|
var a, r;
|
||||||
|
a = pow(3, 100);
|
||||||
|
assert((a - 1) != a);
|
||||||
|
assert(a == 515377520732011331036461129765621272702107522001);
|
||||||
|
assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1);
|
||||||
|
assert(Integer.isInteger(1) === true);
|
||||||
|
assert(Integer.isInteger(1.0) === false);
|
||||||
|
|
||||||
|
assert(Integer.floorLog2(0) === -1);
|
||||||
|
assert(Integer.floorLog2(7) === 2);
|
||||||
|
|
||||||
|
r = 1 << 31;
|
||||||
|
assert(r, 2147483648, "1 << 31 === 2147483648");
|
||||||
|
|
||||||
|
r = 1 << 32;
|
||||||
|
assert(r, 4294967296, "1 << 32 === 4294967296");
|
||||||
|
|
||||||
|
r = (1 << 31) < 0;
|
||||||
|
assert(r, false, "(1 << 31) < 0 === false");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_divrem(div1, a, b, q)
|
||||||
|
{
|
||||||
|
var div, divrem, t;
|
||||||
|
div = Integer[div1];
|
||||||
|
divrem = Integer[div1 + "rem"];
|
||||||
|
assert(div(a, b) == q);
|
||||||
|
t = divrem(a, b);
|
||||||
|
assert(t[0] == q);
|
||||||
|
assert(a == b * q + t[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_idiv1(div, a, b, r)
|
||||||
|
{
|
||||||
|
test_divrem(div, a, b, r[0]);
|
||||||
|
test_divrem(div, -a, b, r[1]);
|
||||||
|
test_divrem(div, a, -b, r[2]);
|
||||||
|
test_divrem(div, -a, -b, r[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_idiv()
|
||||||
|
{
|
||||||
|
test_idiv1("tdiv", 3, 2, [1, -1, -1, 1]);
|
||||||
|
test_idiv1("fdiv", 3, 2, [1, -2, -2, 1]);
|
||||||
|
test_idiv1("cdiv", 3, 2, [2, -1, -1, 2]);
|
||||||
|
test_idiv1("ediv", 3, 2, [1, -2, -1, 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_float()
|
||||||
|
{
|
||||||
|
var e, a, b, sqrt2;
|
||||||
|
|
||||||
|
assert(typeof 1 === "bigint");
|
||||||
|
assert(typeof 1.0 === "bigfloat");
|
||||||
|
assert(1 == 1.0);
|
||||||
|
assert(1 !== 1.0);
|
||||||
|
|
||||||
|
e = new BigFloatEnv(128);
|
||||||
|
assert(e.prec == 128);
|
||||||
|
a = BigFloat.sqrt(2, e);
|
||||||
|
assert(a == BigFloat.parseFloat("0x1.6a09e667f3bcc908b2fb1366ea957d3e", 0, e));
|
||||||
|
assert(e.inexact === true);
|
||||||
|
assert(BigFloat.fpRound(a) == 0x1.6a09e667f3bcd);
|
||||||
|
|
||||||
|
b = BigFloatEnv.setPrec(BigFloat.sqrt.bind(null, 2), 128);
|
||||||
|
assert(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* jscalc tests */
|
||||||
|
|
||||||
|
function test_modulo()
|
||||||
|
{
|
||||||
|
var i, p, a, b;
|
||||||
|
|
||||||
|
/* Euclidian modulo operator */
|
||||||
|
assert((-3) % 2 == 1);
|
||||||
|
assert(3 % (-2) == 1);
|
||||||
|
|
||||||
|
p = 101;
|
||||||
|
for(i = 1; i < p; i++) {
|
||||||
|
a = Integer.invmod(i, p);
|
||||||
|
assert(a >= 0 && a < p);
|
||||||
|
assert((i * a) % p == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(Integer.isPrime(2^107-1));
|
||||||
|
assert(!Integer.isPrime((2^107-1) * (2^89-1)));
|
||||||
|
a = Integer.factor((2^89-1)*2^3*11*13^2*1009);
|
||||||
|
assert(a == [ 2,2,2,11,13,13,1009,618970019642690137449562111 ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_mod()
|
||||||
|
{
|
||||||
|
var a, b, p;
|
||||||
|
|
||||||
|
a = Mod(3, 101);
|
||||||
|
b = Mod(-1, 101);
|
||||||
|
assert((a + b) == Mod(2, 101));
|
||||||
|
assert(a ^ 100 == Mod(1, 101));
|
||||||
|
|
||||||
|
p = 2 ^ 607 - 1; /* mersenne prime */
|
||||||
|
a = Mod(3, p) ^ (p - 1);
|
||||||
|
assert(a == Mod(1, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_polynomial()
|
||||||
|
{
|
||||||
|
var a, b, q, r, t, i;
|
||||||
|
a = (1 + X) ^ 4;
|
||||||
|
assert(a == X^4+4*X^3+6*X^2+4*X+1);
|
||||||
|
|
||||||
|
r = (1 + X);
|
||||||
|
q = (1+X+X^2);
|
||||||
|
b = (1 - X^2);
|
||||||
|
a = q * b + r;
|
||||||
|
t = Polynomial.divrem(a, b);
|
||||||
|
assert(t[0] == q);
|
||||||
|
assert(t[1] == r);
|
||||||
|
|
||||||
|
a = 1 + 2*X + 3*X^2;
|
||||||
|
assert(a.apply(0.1) == 1.23);
|
||||||
|
|
||||||
|
a = 1-2*X^2+2*X^3;
|
||||||
|
assert(deriv(a) == (6*X^2-4*X));
|
||||||
|
assert(deriv(integ(a)) == a);
|
||||||
|
|
||||||
|
a = (X-1)*(X-2)*(X-3)*(X-4)*(X-0.1);
|
||||||
|
r = polroots(a);
|
||||||
|
for(i = 0; i < r.length; i++) {
|
||||||
|
b = abs(a.apply(r[i]));
|
||||||
|
assert(b <= 1e-13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_poly_mod()
|
||||||
|
{
|
||||||
|
var a, p;
|
||||||
|
|
||||||
|
/* modulo using polynomials */
|
||||||
|
p = X^2 + X + 1;
|
||||||
|
a = PolyMod(3+X, p) ^ 10;
|
||||||
|
assert(a == PolyMod(-3725*X-18357, p));
|
||||||
|
|
||||||
|
a = PolyMod(1/X, 1+X^2);
|
||||||
|
assert(a == PolyMod(-X, X^2+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_rfunc()
|
||||||
|
{
|
||||||
|
var a;
|
||||||
|
a = (X+1)/((X+1)*(X-1));
|
||||||
|
assert(a == 1/(X-1));
|
||||||
|
a = (X + 2) / (X - 2);
|
||||||
|
assert(a.apply(1/3) == -7/5);
|
||||||
|
|
||||||
|
assert(deriv((X^2-X+1)/(X-1)) == (X^2-2*X)/(X^2-2*X+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_series()
|
||||||
|
{
|
||||||
|
var a, b;
|
||||||
|
a = 1+X+O(X^5);
|
||||||
|
b = a.inverse();
|
||||||
|
assert(b == 1-X+X^2-X^3+X^4+O(X^5));
|
||||||
|
assert(deriv(b) == -1+2*X-3*X^2+4*X^3+O(X^4));
|
||||||
|
assert(deriv(integ(b)) == b);
|
||||||
|
|
||||||
|
a = Series(1/(1-X), 5);
|
||||||
|
assert(a == 1+X+X^2+X^3+X^4+O(X^5));
|
||||||
|
b = a.apply(0.1);
|
||||||
|
assert(b == 1.1111);
|
||||||
|
|
||||||
|
assert(exp(3*X^2+O(X^10)) == 1+3*X^2+9/2*X^4+9/2*X^6+27/8*X^8+O(X^10));
|
||||||
|
assert(sin(X+O(X^6)) == X-1/6*X^3+1/120*X^5+O(X^6));
|
||||||
|
assert(cos(X+O(X^6)) == 1-1/2*X^2+1/24*X^4+O(X^6));
|
||||||
|
assert(tan(X+O(X^8)) == X+1/3*X^3+2/15*X^5+17/315*X^7+O(X^8));
|
||||||
|
assert((1+X+O(X^6))^(2+X) == 1+2*X+2*X^2+3/2*X^3+5/6*X^4+5/12*X^5+O(X^6));
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_matrix()
|
||||||
|
{
|
||||||
|
var a, b, r;
|
||||||
|
a = [[1, 2],[3, 4]];
|
||||||
|
b = [3, 4];
|
||||||
|
r = a * b;
|
||||||
|
assert(r == [11, 25]);
|
||||||
|
r = (a^-1) * 2;
|
||||||
|
assert(r == [[-4, 2],[3, -1]]);
|
||||||
|
|
||||||
|
assert(norm2([1,2,3]) == 14);
|
||||||
|
|
||||||
|
assert(diag([1,2,3]) == [ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 3 ] ]);
|
||||||
|
assert(trans(a) == [ [ 1, 3 ], [ 2, 4 ] ]);
|
||||||
|
assert(trans([1,2,3]) == [[1,2,3]]);
|
||||||
|
assert(trace(a) == 5);
|
||||||
|
|
||||||
|
assert(charpoly(Matrix.hilbert(4)) == X^4-176/105*X^3+3341/12600*X^2-41/23625*X+1/6048000);
|
||||||
|
assert(det(Matrix.hilbert(4)) == 1/6048000);
|
||||||
|
|
||||||
|
a = [[1,2,1],[-2,-3,1],[3,5,0]];
|
||||||
|
assert(rank(a) == 2);
|
||||||
|
assert(ker(a) == [ [ 5 ], [ -3 ], [ 1 ] ]);
|
||||||
|
|
||||||
|
assert(dp([1, 2, 3], [3, -4, -7]) === -26);
|
||||||
|
assert(cp([1, 2, 3], [3, -4, -7]) == [ -2, 16, -10 ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert_eq(a, ref)
|
||||||
|
{
|
||||||
|
assert(abs(a / ref - 1.0) <= 1e-15);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_trig()
|
||||||
|
{
|
||||||
|
assert_eq(sin(1/2), 0.479425538604203);
|
||||||
|
assert_eq(sin(2+3*I), 9.154499146911428-4.168906959966565*I);
|
||||||
|
assert_eq(cos(2+3*I), -4.189625690968807-9.109227893755337*I);
|
||||||
|
assert_eq((2+0.5*I)^(1.1-0.5*I), 2.494363021357619-0.23076804554558092*I);
|
||||||
|
assert_eq(sqrt(2*I), 1 + I);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_integer();
|
||||||
|
test_idiv();
|
||||||
|
test_float();
|
||||||
|
|
||||||
|
test_modulo();
|
||||||
|
test_mod();
|
||||||
|
test_polynomial();
|
||||||
|
test_poly_mod();
|
||||||
|
test_rfunc();
|
||||||
|
test_series();
|
||||||
|
test_matrix();
|
||||||
|
test_trig();
|
|
@ -0,0 +1,119 @@
|
||||||
|
import * as bjson from "../bjson.so";
|
||||||
|
|
||||||
|
function assert(b, str)
|
||||||
|
{
|
||||||
|
if (b) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
throw Error("assertion failed: " + str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toHex(a)
|
||||||
|
{
|
||||||
|
var i, s = "", tab, v;
|
||||||
|
tab = new Uint8Array(a);
|
||||||
|
for(i = 0; i < tab.length; i++) {
|
||||||
|
v = tab[i].toString(16);
|
||||||
|
if (v.length < 2)
|
||||||
|
v = "0" + v;
|
||||||
|
if (i !== 0)
|
||||||
|
s += " ";
|
||||||
|
s += v;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toStr(a)
|
||||||
|
{
|
||||||
|
var s, i, props, prop;
|
||||||
|
|
||||||
|
switch(typeof(a)) {
|
||||||
|
case "object":
|
||||||
|
if (a === null)
|
||||||
|
return "null";
|
||||||
|
if (Array.isArray(a)) {
|
||||||
|
s = "[";
|
||||||
|
for(i = 0; i < a.length; i++) {
|
||||||
|
if (i != 0)
|
||||||
|
s += ",";
|
||||||
|
s += toStr(a[i]);
|
||||||
|
}
|
||||||
|
s += "]";
|
||||||
|
} else {
|
||||||
|
props = Object.keys(a);
|
||||||
|
s = "{";
|
||||||
|
for(i = 0; i < props.length; i++) {
|
||||||
|
if (i != 0)
|
||||||
|
s += ",";
|
||||||
|
prop = props[i];
|
||||||
|
s += prop + ":" + toStr(a[prop]);
|
||||||
|
}
|
||||||
|
s += "}";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
case "undefined":
|
||||||
|
return "undefined";
|
||||||
|
case "string":
|
||||||
|
return a.__quote();
|
||||||
|
case "number":
|
||||||
|
case "bigfloat":
|
||||||
|
if (a == 0 && 1 / a < 0)
|
||||||
|
return "-0";
|
||||||
|
else
|
||||||
|
return a.toString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return a.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bjson_test(a)
|
||||||
|
{
|
||||||
|
var buf, r, a_str, r_str;
|
||||||
|
a_str = toStr(a);
|
||||||
|
buf = bjson.write(a);
|
||||||
|
if (0) {
|
||||||
|
print(a_str, "->", toHex(buf));
|
||||||
|
}
|
||||||
|
r = bjson.read(buf, 0, buf.byteLength);
|
||||||
|
r_str = toStr(r);
|
||||||
|
if (a_str != r_str) {
|
||||||
|
print(a_str);
|
||||||
|
print(r_str);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bjson_test_all()
|
||||||
|
{
|
||||||
|
var obj;
|
||||||
|
|
||||||
|
bjson_test({x:1, y:2, if:3});
|
||||||
|
bjson_test([1, 2, 3]);
|
||||||
|
bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]);
|
||||||
|
if (typeof BigInt !== "undefined") {
|
||||||
|
bjson_test([BigInt("1"), -BigInt("0x123456789"),
|
||||||
|
BigInt("0x123456789abcdef123456789abcdef")]);
|
||||||
|
}
|
||||||
|
if (typeof BigFloat !== "undefined") {
|
||||||
|
BigFloatEnv.setPrec(function () {
|
||||||
|
bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"),
|
||||||
|
BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"),
|
||||||
|
0.0 / BigFloat("0"), BigFloat.MAX_VALUE,
|
||||||
|
BigFloat.MIN_VALUE]);
|
||||||
|
}, 113, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tested with a circular reference */
|
||||||
|
obj = {};
|
||||||
|
obj.x = obj;
|
||||||
|
try {
|
||||||
|
bjson.write(obj);
|
||||||
|
assert(false);
|
||||||
|
} catch(e) {
|
||||||
|
assert(e instanceof TypeError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bjson_test_all();
|
|
@ -0,0 +1,598 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function assert(actual, expected, message) {
|
||||||
|
if (arguments.length == 1)
|
||||||
|
expected = true;
|
||||||
|
|
||||||
|
if (actual === expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (actual !== null && expected !== null
|
||||||
|
&& typeof actual == 'object' && typeof expected == 'object'
|
||||||
|
&& actual.toString() === expected.toString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw Error("assertion failed: got |" + actual + "|" +
|
||||||
|
", expected |" + expected + "|" +
|
||||||
|
(message ? " (" + message + ")" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load more elaborate version of assert if available
|
||||||
|
try { __loadScript("test_assert.js"); } catch(e) {}
|
||||||
|
|
||||||
|
/*----------------*/
|
||||||
|
|
||||||
|
function my_func(a, b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_function()
|
||||||
|
{
|
||||||
|
function f(a, b) {
|
||||||
|
var i, tab = [];
|
||||||
|
tab.push(this);
|
||||||
|
for(i = 0; i < arguments.length; i++)
|
||||||
|
tab.push(arguments[i]);
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
function constructor1(a) {
|
||||||
|
this.x = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
var r, g;
|
||||||
|
|
||||||
|
r = my_func.call(null, 1, 2);
|
||||||
|
assert(r, 3, "call");
|
||||||
|
|
||||||
|
r = my_func.apply(null, [1, 2]);
|
||||||
|
assert(r, 3, "apply");
|
||||||
|
|
||||||
|
r = new Function("a", "b", "return a + b;");
|
||||||
|
assert(r(2,3), 5, "function");
|
||||||
|
|
||||||
|
g = f.bind(1, 2);
|
||||||
|
assert(g.length, 1);
|
||||||
|
assert(g.name, "bound f");
|
||||||
|
assert(g(3), [1,2,3]);
|
||||||
|
|
||||||
|
g = constructor1.bind(null, 1);
|
||||||
|
r = new g();
|
||||||
|
assert(r.x, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
var r, a, b, c, err;
|
||||||
|
|
||||||
|
r = Error("hello");
|
||||||
|
assert(r.message, "hello", "Error");
|
||||||
|
|
||||||
|
a = new Object();
|
||||||
|
a.x = 1;
|
||||||
|
assert(a.x, 1, "Object");
|
||||||
|
|
||||||
|
assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf");
|
||||||
|
Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true });
|
||||||
|
assert(a.y, 3, "defineProperty");
|
||||||
|
|
||||||
|
Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true });
|
||||||
|
assert(a.z, 4, "get");
|
||||||
|
a.z = 5;
|
||||||
|
assert(a.z_val, 5, "set");
|
||||||
|
|
||||||
|
a = { get z() { return 4; }, set z(val) { this.z_val = val; } };
|
||||||
|
assert(a.z, 4, "get");
|
||||||
|
a.z = 5;
|
||||||
|
assert(a.z_val, 5, "set");
|
||||||
|
|
||||||
|
b = Object.create(a);
|
||||||
|
assert(Object.getPrototypeOf(b), a, "create");
|
||||||
|
c = {u:2};
|
||||||
|
/* XXX: refcount bug in 'b' instead of 'a' */
|
||||||
|
Object.setPrototypeOf(a, c);
|
||||||
|
assert(Object.getPrototypeOf(a), c, "setPrototypeOf");
|
||||||
|
|
||||||
|
a = {};
|
||||||
|
assert(a.toString(), "[object Object]", "toString");
|
||||||
|
|
||||||
|
a = {x:1};
|
||||||
|
assert(Object.isExtensible(a), true, "extensible");
|
||||||
|
Object.preventExtensions(a);
|
||||||
|
|
||||||
|
err = false;
|
||||||
|
try {
|
||||||
|
a.y = 2;
|
||||||
|
} catch(e) {
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
assert(Object.isExtensible(a), false, "extensible");
|
||||||
|
assert(typeof a.y, "undefined", "extensible");
|
||||||
|
assert(err, true, "extensible");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_enum()
|
||||||
|
{
|
||||||
|
var a, tab;
|
||||||
|
a = {x:1,
|
||||||
|
"18014398509481984": 1,
|
||||||
|
"9007199254740992": 1,
|
||||||
|
"9007199254740991": 1,
|
||||||
|
"4294967296": 1,
|
||||||
|
"4294967295": 1,
|
||||||
|
y:1,
|
||||||
|
"4294967294": 1,
|
||||||
|
"1": 2};
|
||||||
|
tab = Object.keys(a);
|
||||||
|
// console.log("tab=" + tab.toString());
|
||||||
|
assert(tab, ["1","4294967294","4294967295","4294967296","9007199254740991","x","18014398509481984","9007199254740992","y"], "keys");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_array()
|
||||||
|
{
|
||||||
|
var a, err;
|
||||||
|
|
||||||
|
a = [1, 2, 3];
|
||||||
|
assert(a.length, 3, "array");
|
||||||
|
assert(a[2], 3, "array1");
|
||||||
|
|
||||||
|
a = new Array(10);
|
||||||
|
assert(a.length, 10, "array2");
|
||||||
|
|
||||||
|
a = new Array(1, 2);
|
||||||
|
assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3");
|
||||||
|
|
||||||
|
a = [1, 2, 3];
|
||||||
|
a.length = 2;
|
||||||
|
assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4");
|
||||||
|
|
||||||
|
a = [];
|
||||||
|
a[1] = 10;
|
||||||
|
a[4] = 3;
|
||||||
|
assert(a.length, 5);
|
||||||
|
|
||||||
|
a = [1,2];
|
||||||
|
a.length = 5;
|
||||||
|
a[4] = 1;
|
||||||
|
a.length = 4;
|
||||||
|
assert(a[4] !== 1, true, "array5");
|
||||||
|
|
||||||
|
a = [1,2];
|
||||||
|
a.push(3,4);
|
||||||
|
assert(a.join(), "1,2,3,4", "join");
|
||||||
|
|
||||||
|
a = [1,2,3,4,5];
|
||||||
|
Object.defineProperty(a, "3", { configurable: false });
|
||||||
|
err = false;
|
||||||
|
try {
|
||||||
|
a.length = 2;
|
||||||
|
} catch(e) {
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
assert(err && a.toString() === "1,2,3,4");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_string()
|
||||||
|
{
|
||||||
|
var a;
|
||||||
|
a = String("abc");
|
||||||
|
assert(a.length, 3, "string");
|
||||||
|
assert(a[1], "b", "string");
|
||||||
|
assert(a.charCodeAt(1), 0x62, "string");
|
||||||
|
assert(String.fromCharCode(65), "A", "string");
|
||||||
|
assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string");
|
||||||
|
assert(a.charAt(1), "b");
|
||||||
|
assert(a.charAt(-1), "");
|
||||||
|
assert(a.charAt(3), "");
|
||||||
|
|
||||||
|
a = "abcd";
|
||||||
|
assert(a.substring(1, 3), "bc", "substring");
|
||||||
|
a = String.fromCharCode(0x20ac);
|
||||||
|
assert(a.charCodeAt(0), 0x20ac, "unicode");
|
||||||
|
assert(a, "€", "unicode");
|
||||||
|
assert(a, "\u20ac", "unicode");
|
||||||
|
assert(a, "\u{20ac}", "unicode");
|
||||||
|
assert("a", "\x61", "unicode");
|
||||||
|
|
||||||
|
a = "\u{10ffff}";
|
||||||
|
assert(a.length, 2, "unicode");
|
||||||
|
assert(a, "\u{dbff}\u{dfff}", "unicode");
|
||||||
|
assert(a.codePointAt(0), 0x10ffff);
|
||||||
|
assert(String.fromCodePoint(0x10ffff), a);
|
||||||
|
|
||||||
|
assert("a".concat("b", "c"), "abc");
|
||||||
|
|
||||||
|
assert("abcabc".indexOf("cab"), 2);
|
||||||
|
assert("abcabc".indexOf("cab2"), -1);
|
||||||
|
assert("abc".indexOf("c"), 2);
|
||||||
|
|
||||||
|
assert("aaa".indexOf("a"), 0);
|
||||||
|
assert("aaa".indexOf("a", NaN), 0);
|
||||||
|
assert("aaa".indexOf("a", -Infinity), 0);
|
||||||
|
assert("aaa".indexOf("a", -1), 0);
|
||||||
|
assert("aaa".indexOf("a", -0), 0);
|
||||||
|
assert("aaa".indexOf("a", 0), 0);
|
||||||
|
assert("aaa".indexOf("a", 1), 1);
|
||||||
|
assert("aaa".indexOf("a", 2), 2);
|
||||||
|
assert("aaa".indexOf("a", 3), -1);
|
||||||
|
assert("aaa".indexOf("a", 4), -1);
|
||||||
|
assert("aaa".indexOf("a", Infinity), -1);
|
||||||
|
|
||||||
|
assert("aaa".indexOf(""), 0);
|
||||||
|
assert("aaa".indexOf("", NaN), 0);
|
||||||
|
assert("aaa".indexOf("", -Infinity), 0);
|
||||||
|
assert("aaa".indexOf("", -1), 0);
|
||||||
|
assert("aaa".indexOf("", -0), 0);
|
||||||
|
assert("aaa".indexOf("", 0), 0);
|
||||||
|
assert("aaa".indexOf("", 1), 1);
|
||||||
|
assert("aaa".indexOf("", 2), 2);
|
||||||
|
assert("aaa".indexOf("", 3), 3);
|
||||||
|
assert("aaa".indexOf("", 4), 3);
|
||||||
|
assert("aaa".indexOf("", Infinity), 3);
|
||||||
|
|
||||||
|
assert("aaa".lastIndexOf("a"), 2);
|
||||||
|
assert("aaa".lastIndexOf("a", NaN), 2);
|
||||||
|
assert("aaa".lastIndexOf("a", -Infinity), 0);
|
||||||
|
assert("aaa".lastIndexOf("a", -1), 0);
|
||||||
|
assert("aaa".lastIndexOf("a", -0), 0);
|
||||||
|
assert("aaa".lastIndexOf("a", 0), 0);
|
||||||
|
assert("aaa".lastIndexOf("a", 1), 1);
|
||||||
|
assert("aaa".lastIndexOf("a", 2), 2);
|
||||||
|
assert("aaa".lastIndexOf("a", 3), 2);
|
||||||
|
assert("aaa".lastIndexOf("a", 4), 2);
|
||||||
|
assert("aaa".lastIndexOf("a", Infinity), 2);
|
||||||
|
|
||||||
|
assert("aaa".lastIndexOf(""), 3);
|
||||||
|
assert("aaa".lastIndexOf("", NaN), 3);
|
||||||
|
assert("aaa".lastIndexOf("", -Infinity), 0);
|
||||||
|
assert("aaa".lastIndexOf("", -1), 0);
|
||||||
|
assert("aaa".lastIndexOf("", -0), 0);
|
||||||
|
assert("aaa".lastIndexOf("", 0), 0);
|
||||||
|
assert("aaa".lastIndexOf("", 1), 1);
|
||||||
|
assert("aaa".lastIndexOf("", 2), 2);
|
||||||
|
assert("aaa".lastIndexOf("", 3), 3);
|
||||||
|
assert("aaa".lastIndexOf("", 4), 3);
|
||||||
|
assert("aaa".lastIndexOf("", Infinity), 3);
|
||||||
|
|
||||||
|
assert("a,b,c".split(","), ["a","b","c"]);
|
||||||
|
assert(",b,c".split(","), ["","b","c"]);
|
||||||
|
assert("a,b,".split(","), ["a","b",""]);
|
||||||
|
|
||||||
|
assert("aaaa".split(), [ "aaaa" ]);
|
||||||
|
assert("aaaa".split(undefined, 0), [ ]);
|
||||||
|
assert("aaaa".split(""), [ "a", "a", "a", "a" ]);
|
||||||
|
assert("aaaa".split("", 0), [ ]);
|
||||||
|
assert("aaaa".split("", 1), [ "a" ]);
|
||||||
|
assert("aaaa".split("", 2), [ "a", "a" ]);
|
||||||
|
assert("aaaa".split("a"), [ "", "", "", "", "" ]);
|
||||||
|
assert("aaaa".split("a", 2), [ "", "" ]);
|
||||||
|
assert("aaaa".split("aa"), [ "", "", "" ]);
|
||||||
|
assert("aaaa".split("aa", 0), [ ]);
|
||||||
|
assert("aaaa".split("aa", 1), [ "" ]);
|
||||||
|
assert("aaaa".split("aa", 2), [ "", "" ]);
|
||||||
|
assert("aaaa".split("aaa"), [ "", "a" ]);
|
||||||
|
assert("aaaa".split("aaaa"), [ "", "" ]);
|
||||||
|
assert("aaaa".split("aaaaa"), [ "aaaa" ]);
|
||||||
|
assert("aaaa".split("aaaaa", 0), [ ]);
|
||||||
|
assert("aaaa".split("aaaaa", 1), [ "aaaa" ]);
|
||||||
|
|
||||||
|
assert(eval('"\0"'), "\0");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_math()
|
||||||
|
{
|
||||||
|
var a;
|
||||||
|
a = 1.4;
|
||||||
|
assert(Math.floor(a), 1);
|
||||||
|
assert(Math.ceil(a), 2);
|
||||||
|
assert(Math.imul(0x12345678, 123), -1088058456);
|
||||||
|
assert(Math.fround(0.1), 0.10000000149011612);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_number()
|
||||||
|
{
|
||||||
|
assert(parseInt("123"), 123);
|
||||||
|
assert(parseInt(" 123r"), 123);
|
||||||
|
assert(parseInt("0x123"), 0x123);
|
||||||
|
assert(parseInt("0o123"), 0);
|
||||||
|
assert(+" 123 ", 123);
|
||||||
|
assert(+"0b111", 7);
|
||||||
|
assert(+"0o123", 83);
|
||||||
|
assert(parseFloat("0x1234"), 0);
|
||||||
|
assert(parseFloat("Infinity"), Infinity);
|
||||||
|
assert(parseFloat("-Infinity"), -Infinity);
|
||||||
|
assert(parseFloat("123.2"), 123.2);
|
||||||
|
assert(parseFloat("123.2e3"), 123200);
|
||||||
|
|
||||||
|
assert((25).toExponential(0), "3e+1");
|
||||||
|
assert((-25).toExponential(0), "-3e+1");
|
||||||
|
assert((2.5).toPrecision(1), "3");
|
||||||
|
assert((-2.5).toPrecision(1), "-3");
|
||||||
|
assert((1.125).toFixed(2), "1.13");
|
||||||
|
assert((-1.125).toFixed(2), "-1.13");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_eval()
|
||||||
|
{
|
||||||
|
function f(b) {
|
||||||
|
var x = 1;
|
||||||
|
return eval(b);
|
||||||
|
}
|
||||||
|
var r, a;
|
||||||
|
|
||||||
|
r = eval("1+1;");
|
||||||
|
assert(r, 2, "eval");
|
||||||
|
|
||||||
|
r = eval("var my_var=2; my_var;");
|
||||||
|
assert(r, 2, "eval");
|
||||||
|
assert(typeof my_var, "undefined");
|
||||||
|
|
||||||
|
assert(eval("if (1) 2; else 3;"), 2);
|
||||||
|
assert(eval("if (0) 2; else 3;"), 3);
|
||||||
|
|
||||||
|
assert(f.call(1, "this"), 1);
|
||||||
|
|
||||||
|
a = 2;
|
||||||
|
assert(eval("a"), 2);
|
||||||
|
|
||||||
|
eval("a = 3");
|
||||||
|
assert(a, 3);
|
||||||
|
|
||||||
|
assert(f("arguments.length", 1), 2);
|
||||||
|
assert(f("arguments[1]", 1), 1);
|
||||||
|
|
||||||
|
a = 4;
|
||||||
|
assert(f("a"), 4);
|
||||||
|
f("a=3");
|
||||||
|
assert(a, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_typed_array()
|
||||||
|
{
|
||||||
|
var buffer, a, i;
|
||||||
|
|
||||||
|
a = new Uint8Array(4);
|
||||||
|
assert(a.length, 4);
|
||||||
|
for(i = 0; i < a.length; i++)
|
||||||
|
a[i] = i;
|
||||||
|
assert(a.join(","), "0,1,2,3");
|
||||||
|
a[0] = -1;
|
||||||
|
assert(a[0], 255);
|
||||||
|
|
||||||
|
a = new Int8Array(3);
|
||||||
|
a[0] = 255;
|
||||||
|
assert(a[0], -1);
|
||||||
|
|
||||||
|
a = new Int32Array(3);
|
||||||
|
a[0] = Math.pow(2, 32) - 1;
|
||||||
|
assert(a[0], -1);
|
||||||
|
assert(a.BYTES_PER_ELEMENT, 4);
|
||||||
|
|
||||||
|
a = new Uint8ClampedArray(4);
|
||||||
|
a[0] = -100;
|
||||||
|
a[1] = 1.5;
|
||||||
|
a[2] = 0.5;
|
||||||
|
a[3] = 1233.5;
|
||||||
|
assert(a.toString(), "0,2,0,255");
|
||||||
|
|
||||||
|
buffer = new ArrayBuffer(16);
|
||||||
|
assert(buffer.byteLength, 16);
|
||||||
|
a = new Uint32Array(buffer, 12, 1);
|
||||||
|
assert(a.length, 1);
|
||||||
|
a[0] = -1;
|
||||||
|
|
||||||
|
a = new Uint16Array(buffer, 2);
|
||||||
|
a[0] = -1;
|
||||||
|
|
||||||
|
a = new Float32Array(buffer, 8, 1);
|
||||||
|
a[0] = 1;
|
||||||
|
|
||||||
|
a = new Uint8Array(buffer);
|
||||||
|
|
||||||
|
assert(a.toString(), "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255");
|
||||||
|
|
||||||
|
assert(a.buffer, buffer);
|
||||||
|
|
||||||
|
a = new Uint8Array([1, 2, 3, 4]);
|
||||||
|
assert(a.toString(), "1,2,3,4");
|
||||||
|
a.set([10, 11], 2);
|
||||||
|
assert(a.toString(), "1,2,10,11");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_json()
|
||||||
|
{
|
||||||
|
var a, s;
|
||||||
|
s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}';
|
||||||
|
a = JSON.parse(s);
|
||||||
|
assert(a.x, 1);
|
||||||
|
assert(a.y, true);
|
||||||
|
assert(a.z, null);
|
||||||
|
assert(JSON.stringify(a), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_date()
|
||||||
|
{
|
||||||
|
var d = new Date(1506098258091), a;
|
||||||
|
assert(d.toISOString(), "2017-09-22T16:37:38.091Z");
|
||||||
|
d.setUTCHours(18, 10, 11);
|
||||||
|
assert(d.toISOString(), "2017-09-22T18:10:11.091Z");
|
||||||
|
a = Date.parse(d.toISOString());
|
||||||
|
assert((new Date(a)).toISOString(), d.toISOString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_regexp()
|
||||||
|
{
|
||||||
|
var a, str;
|
||||||
|
str = "abbbbbc";
|
||||||
|
a = /(b+)c/.exec(str);
|
||||||
|
assert(a[0], "bbbbbc");
|
||||||
|
assert(a[1], "bbbbb");
|
||||||
|
assert(a.index, 1);
|
||||||
|
assert(a.input, str);
|
||||||
|
a = /(b+)c/.test(str);
|
||||||
|
assert(a, true);
|
||||||
|
assert(/\x61/.exec("a")[0], "a");
|
||||||
|
assert(/\u0061/.exec("a")[0], "a");
|
||||||
|
assert(/\ca/.exec("\x01")[0], "\x01");
|
||||||
|
assert(/\\a/.exec("\\a")[0], "\\a");
|
||||||
|
assert(/\c0/.exec("\\c0")[0], "\\c0");
|
||||||
|
|
||||||
|
a = /(\.(?=com|org)|\/)/.exec("ah.com");
|
||||||
|
assert(a.index === 2 && a[0] === ".");
|
||||||
|
|
||||||
|
a = /(\.(?!com|org)|\/)/.exec("ah.com");
|
||||||
|
assert(a, null);
|
||||||
|
|
||||||
|
a = /(?=(a+))/.exec("baaabac");
|
||||||
|
assert(a.index === 1 && a[0] === "" && a[1] === "aaa");
|
||||||
|
|
||||||
|
a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac");
|
||||||
|
assert(a, ["zaacbbbcac","z","ac","a",,"c"]);
|
||||||
|
|
||||||
|
a = eval("/\0a/");
|
||||||
|
assert(a.toString(), "/\0a/");
|
||||||
|
assert(a.exec("\0a")[0], "\0a");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_symbol()
|
||||||
|
{
|
||||||
|
var a, b, obj, c;
|
||||||
|
a = Symbol("abc");
|
||||||
|
obj = {};
|
||||||
|
obj[a] = 2;
|
||||||
|
assert(obj[a], 2);
|
||||||
|
assert(typeof obj["abc"], "undefined");
|
||||||
|
assert(String(a), "Symbol(abc)");
|
||||||
|
b = Symbol("abc");
|
||||||
|
assert(a == a);
|
||||||
|
assert(a === a);
|
||||||
|
assert(a != b);
|
||||||
|
assert(a !== b);
|
||||||
|
|
||||||
|
b = Symbol.for("abc");
|
||||||
|
c = Symbol.for("abc");
|
||||||
|
assert(b === c);
|
||||||
|
assert(b !== a);
|
||||||
|
|
||||||
|
assert(Symbol.keyFor(b), "abc");
|
||||||
|
assert(Symbol.keyFor(a), undefined);
|
||||||
|
|
||||||
|
a = Symbol("aaa");
|
||||||
|
assert(a.valueOf(), a);
|
||||||
|
assert(a.toString(), "Symbol(aaa)");
|
||||||
|
|
||||||
|
b = Object(a);
|
||||||
|
assert(b.valueOf(), a);
|
||||||
|
assert(b.toString(), "Symbol(aaa)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_map()
|
||||||
|
{
|
||||||
|
var a, i, n, tab, o, v;
|
||||||
|
n = 1000;
|
||||||
|
a = new Map();
|
||||||
|
tab = [];
|
||||||
|
for(i = 0; i < n; i++) {
|
||||||
|
v = { };
|
||||||
|
o = { id: i };
|
||||||
|
tab[i] = [o, v];
|
||||||
|
a.set(o, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(a.size, n);
|
||||||
|
for(i = 0; i < n; i++) {
|
||||||
|
assert(a.get(tab[i][0]), tab[i][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
a.forEach(function (v, o) {
|
||||||
|
assert(o, tab[i++][0]);
|
||||||
|
assert(a.has(o));
|
||||||
|
assert(a.delete(o));
|
||||||
|
assert(!a.has(o));
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(a.size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_weak_map()
|
||||||
|
{
|
||||||
|
var a, i, n, tab, o, v, n2;
|
||||||
|
a = new WeakMap();
|
||||||
|
n = 10;
|
||||||
|
tab = [];
|
||||||
|
for(i = 0; i < n; i++) {
|
||||||
|
v = { };
|
||||||
|
o = { id: i };
|
||||||
|
tab[i] = [o, v];
|
||||||
|
a.set(o, v);
|
||||||
|
}
|
||||||
|
o = null;
|
||||||
|
|
||||||
|
n2 = n >> 1;
|
||||||
|
for(i = 0; i < n2; i++) {
|
||||||
|
a.delete(tab[i][0]);
|
||||||
|
}
|
||||||
|
for(i = n2; i < n; i++) {
|
||||||
|
tab[i][0] = null; /* should remove the object from the WeakMap too */
|
||||||
|
}
|
||||||
|
/* the WeakMap should be empty here */
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_generator()
|
||||||
|
{
|
||||||
|
function *f() {
|
||||||
|
var ret;
|
||||||
|
yield 1;
|
||||||
|
ret = yield 2;
|
||||||
|
assert(ret, "next_arg");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
function *f2() {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
return "ret_val";
|
||||||
|
}
|
||||||
|
function *f1() {
|
||||||
|
var ret = yield *f2();
|
||||||
|
assert(ret, "ret_val");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
var g, v;
|
||||||
|
g = f();
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === 1 && v.done === false);
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === 2 && v.done === false);
|
||||||
|
v = g.next("next_arg");
|
||||||
|
assert(v.value === 3 && v.done === true);
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === undefined && v.done === true);
|
||||||
|
|
||||||
|
g = f1();
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === 1 && v.done === false);
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === 2 && v.done === false);
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === 3 && v.done === true);
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === undefined && v.done === true);
|
||||||
|
}
|
||||||
|
|
||||||
|
test();
|
||||||
|
test_function();
|
||||||
|
test_enum();
|
||||||
|
test_array();
|
||||||
|
test_string();
|
||||||
|
test_math();
|
||||||
|
test_number();
|
||||||
|
test_eval();
|
||||||
|
test_typed_array();
|
||||||
|
test_json();
|
||||||
|
test_date();
|
||||||
|
test_regexp();
|
||||||
|
test_symbol();
|
||||||
|
test_map();
|
||||||
|
test_weak_map();
|
||||||
|
test_generator();
|
|
@ -0,0 +1,221 @@
|
||||||
|
function assert(actual, expected, message) {
|
||||||
|
if (arguments.length == 1)
|
||||||
|
expected = true;
|
||||||
|
|
||||||
|
if (actual === expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (actual !== null && expected !== null
|
||||||
|
&& typeof actual == 'object' && typeof expected == 'object'
|
||||||
|
&& actual.toString() === expected.toString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw Error("assertion failed: got |" + actual + "|" +
|
||||||
|
", expected |" + expected + "|" +
|
||||||
|
(message ? " (" + message + ")" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load more elaborate version of assert if available
|
||||||
|
try { __loadScript("test_assert.js"); } catch(e) {}
|
||||||
|
|
||||||
|
/*----------------*/
|
||||||
|
|
||||||
|
var log_str = "";
|
||||||
|
|
||||||
|
function log(str)
|
||||||
|
{
|
||||||
|
log_str += str + ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
function f(a, b, c)
|
||||||
|
{
|
||||||
|
var x = 10;
|
||||||
|
log("a="+a);
|
||||||
|
function g(d) {
|
||||||
|
function h() {
|
||||||
|
log("d=" + d);
|
||||||
|
log("x=" + x);
|
||||||
|
}
|
||||||
|
log("b=" + b);
|
||||||
|
log("c=" + c);
|
||||||
|
h();
|
||||||
|
}
|
||||||
|
g(4);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
var g1 = f(1, 2, 3);
|
||||||
|
g1(5);
|
||||||
|
|
||||||
|
assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1");
|
||||||
|
|
||||||
|
function test_closure1()
|
||||||
|
{
|
||||||
|
function f2()
|
||||||
|
{
|
||||||
|
var val = 1;
|
||||||
|
|
||||||
|
function set(a) {
|
||||||
|
val = a;
|
||||||
|
}
|
||||||
|
function get(a) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return { "set": set, "get": get };
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = f2();
|
||||||
|
obj.set(10);
|
||||||
|
var r;
|
||||||
|
r = obj.get();
|
||||||
|
assert(r, 10, "closure2");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_closure2()
|
||||||
|
{
|
||||||
|
var expr_func = function myfunc1(n) {
|
||||||
|
function myfunc2(n) {
|
||||||
|
return myfunc1(n - 1);
|
||||||
|
}
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return myfunc2(n);
|
||||||
|
};
|
||||||
|
var r;
|
||||||
|
r = expr_func(1);
|
||||||
|
assert(r, 0, "expr_func");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_closure3()
|
||||||
|
{
|
||||||
|
function fib(n)
|
||||||
|
{
|
||||||
|
if (n <= 0)
|
||||||
|
return 0;
|
||||||
|
else if (n == 1)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return fib(n - 1) + fib(n - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
var fib_func = function fib1(n)
|
||||||
|
{
|
||||||
|
if (n <= 0)
|
||||||
|
return 0;
|
||||||
|
else if (n == 1)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return fib1(n - 1) + fib1(n - 2);
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(fib(6), 8, "fib");
|
||||||
|
assert(fib_func(6), 8, "fib_func");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_arrow_function()
|
||||||
|
{
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function f1() {
|
||||||
|
return (() => arguments)();
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
return (() => this)();
|
||||||
|
}
|
||||||
|
function f3() {
|
||||||
|
return (() => eval("this"))();
|
||||||
|
}
|
||||||
|
function f4() {
|
||||||
|
return (() => eval("new.target"))();
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
|
||||||
|
a = f1(1, 2);
|
||||||
|
assert(a.length, 2);
|
||||||
|
assert(a[0] === 1 && a[1] === 2);
|
||||||
|
|
||||||
|
assert(f2.call("this_val") === "this_val");
|
||||||
|
assert(f3.call("this_val") === "this_val");
|
||||||
|
assert(new f4() === f4);
|
||||||
|
|
||||||
|
var o1 = { f() { return this; } };
|
||||||
|
var o2 = { f() {
|
||||||
|
return (() => eval("super.f()"))();
|
||||||
|
} };
|
||||||
|
o2.__proto__ = o1;
|
||||||
|
|
||||||
|
assert(o2.f() === o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_with()
|
||||||
|
{
|
||||||
|
var o1 = { x: "o1", y: "o1" };
|
||||||
|
var x = "local";
|
||||||
|
eval('var z="var_obj";');
|
||||||
|
assert(z === "var_obj");
|
||||||
|
with (o1) {
|
||||||
|
assert(x === "o1");
|
||||||
|
assert(eval("x") === "o1");
|
||||||
|
var f = function () {
|
||||||
|
o2 = { x: "o2" };
|
||||||
|
with (o2) {
|
||||||
|
assert(x === "o2");
|
||||||
|
assert(y === "o1");
|
||||||
|
assert(z === "var_obj");
|
||||||
|
assert(eval("x") === "o2");
|
||||||
|
assert(eval("y") === "o1");
|
||||||
|
assert(eval("z") === "var_obj");
|
||||||
|
assert(eval('eval("x")') === "o2");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_eval_closure()
|
||||||
|
{
|
||||||
|
var tab;
|
||||||
|
|
||||||
|
tab = [];
|
||||||
|
for(let i = 0; i < 3; i++) {
|
||||||
|
eval("tab.push(function g1() { return i; })");
|
||||||
|
}
|
||||||
|
for(let i = 0; i < 3; i++) {
|
||||||
|
assert(tab[i]() === i);
|
||||||
|
}
|
||||||
|
|
||||||
|
tab = [];
|
||||||
|
for(let i = 0; i < 3; i++) {
|
||||||
|
let f = function f() {
|
||||||
|
eval("tab.push(function g2() { return i; })");
|
||||||
|
};
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
for(let i = 0; i < 3; i++) {
|
||||||
|
assert(tab[i]() === i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_eval_const()
|
||||||
|
{
|
||||||
|
const a = 1;
|
||||||
|
var success = false;
|
||||||
|
var f = function () {
|
||||||
|
eval("a = 1");
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
f();
|
||||||
|
} catch(e) {
|
||||||
|
success = (e instanceof TypeError);
|
||||||
|
}
|
||||||
|
assert(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_closure1();
|
||||||
|
test_closure2();
|
||||||
|
test_closure3();
|
||||||
|
test_arrow_function();
|
||||||
|
test_with();
|
||||||
|
test_eval_closure();
|
||||||
|
test_eval_const();
|
|
@ -0,0 +1,368 @@
|
||||||
|
function assert(actual, expected, message) {
|
||||||
|
if (arguments.length == 1)
|
||||||
|
expected = true;
|
||||||
|
|
||||||
|
if (actual === expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (actual !== null && expected !== null
|
||||||
|
&& typeof actual == 'object' && typeof expected == 'object'
|
||||||
|
&& actual.toString() === expected.toString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw Error("assertion failed: got |" + actual + "|" +
|
||||||
|
", expected |" + expected + "|" +
|
||||||
|
(message ? " (" + message + ")" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load more elaborate version of assert if available
|
||||||
|
try { __loadScript("test_assert.js"); } catch(e) {}
|
||||||
|
|
||||||
|
/*----------------*/
|
||||||
|
|
||||||
|
function test_while()
|
||||||
|
{
|
||||||
|
var i, c;
|
||||||
|
i = 0;
|
||||||
|
c = 0;
|
||||||
|
while (i < 3) {
|
||||||
|
c++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
assert(c === 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_while_break()
|
||||||
|
{
|
||||||
|
var i, c;
|
||||||
|
i = 0;
|
||||||
|
c = 0;
|
||||||
|
while (i < 3) {
|
||||||
|
c++;
|
||||||
|
if (i == 1)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
assert(c === 2 && i === 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_do_while()
|
||||||
|
{
|
||||||
|
var i, c;
|
||||||
|
i = 0;
|
||||||
|
c = 0;
|
||||||
|
do {
|
||||||
|
c++;
|
||||||
|
i++;
|
||||||
|
} while (i < 3);
|
||||||
|
assert(c === 3 && i === 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_for()
|
||||||
|
{
|
||||||
|
var i, c;
|
||||||
|
c = 0;
|
||||||
|
for(i = 0; i < 3; i++) {
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
assert(c === 3 && i === 3);
|
||||||
|
|
||||||
|
c = 0;
|
||||||
|
for(var j = 0; j < 3; j++) {
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
assert(c === 3 && j === 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_for_in()
|
||||||
|
{
|
||||||
|
var i, tab, a, b;
|
||||||
|
|
||||||
|
tab = [];
|
||||||
|
for(i in {x:1, y: 2}) {
|
||||||
|
tab.push(i);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "x,y", "for_in");
|
||||||
|
|
||||||
|
/* prototype chain test */
|
||||||
|
a = {x:2, y: 2, "1": 3};
|
||||||
|
b = {"4" : 3 };
|
||||||
|
Object.setPrototypeOf(a, b);
|
||||||
|
tab = [];
|
||||||
|
for(i in a) {
|
||||||
|
tab.push(i);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "1,x,y,4", "for_in");
|
||||||
|
|
||||||
|
/* non enumerable properties hide enumerables ones in the
|
||||||
|
prototype chain */
|
||||||
|
a = {y: 2, "1": 3};
|
||||||
|
Object.defineProperty(a, "x", { value: 1 });
|
||||||
|
b = {"x" : 3 };
|
||||||
|
Object.setPrototypeOf(a, b);
|
||||||
|
tab = [];
|
||||||
|
for(i in a) {
|
||||||
|
tab.push(i);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "1,y", "for_in");
|
||||||
|
|
||||||
|
/* array optimization */
|
||||||
|
a = [];
|
||||||
|
for(i = 0; i < 10; i++)
|
||||||
|
a.push(i);
|
||||||
|
tab = [];
|
||||||
|
for(i in a) {
|
||||||
|
tab.push(i);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "0,1,2,3,4,5,6,7,8,9", "for_in");
|
||||||
|
|
||||||
|
/* iterate with a field */
|
||||||
|
a={x:0};
|
||||||
|
tab = [];
|
||||||
|
for(a.x in {x:1, y: 2}) {
|
||||||
|
tab.push(a.x);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "x,y", "for_in");
|
||||||
|
|
||||||
|
/* iterate with a variable field */
|
||||||
|
a=[0];
|
||||||
|
tab = [];
|
||||||
|
for(a[0] in {x:1, y: 2}) {
|
||||||
|
tab.push(a[0]);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "x,y", "for_in");
|
||||||
|
|
||||||
|
/* variable definition in the for in */
|
||||||
|
tab = [];
|
||||||
|
for(var j in {x:1, y: 2}) {
|
||||||
|
tab.push(j);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "x,y", "for_in");
|
||||||
|
|
||||||
|
/* variable assigment in the for in */
|
||||||
|
tab = [];
|
||||||
|
for(var k = 2 in {x:1, y: 2}) {
|
||||||
|
tab.push(k);
|
||||||
|
}
|
||||||
|
assert(tab.toString(), "x,y", "for_in");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_for_in2()
|
||||||
|
{
|
||||||
|
var i;
|
||||||
|
tab = [];
|
||||||
|
for(i in {x:1, y: 2, z:3}) {
|
||||||
|
if (i === "y")
|
||||||
|
continue;
|
||||||
|
tab.push(i);
|
||||||
|
}
|
||||||
|
assert(tab.toString() == "x,z");
|
||||||
|
|
||||||
|
tab = [];
|
||||||
|
for(i in {x:1, y: 2, z:3}) {
|
||||||
|
if (i === "z")
|
||||||
|
break;
|
||||||
|
tab.push(i);
|
||||||
|
}
|
||||||
|
assert(tab.toString() == "x,y");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_for_break()
|
||||||
|
{
|
||||||
|
var i, c;
|
||||||
|
c = 0;
|
||||||
|
L1: for(i = 0; i < 3; i++) {
|
||||||
|
c++;
|
||||||
|
if (i == 0)
|
||||||
|
continue;
|
||||||
|
while (1) {
|
||||||
|
break L1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(c === 2 && i === 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_switch1()
|
||||||
|
{
|
||||||
|
var i, a, s;
|
||||||
|
s = "";
|
||||||
|
for(i = 0; i < 3; i++) {
|
||||||
|
a = "?";
|
||||||
|
switch(i) {
|
||||||
|
case 0:
|
||||||
|
a = "a";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
a = "b";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
a = "c";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s += a;
|
||||||
|
}
|
||||||
|
assert(s === "abc" && i === 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_switch2()
|
||||||
|
{
|
||||||
|
var i, a, s;
|
||||||
|
s = "";
|
||||||
|
for(i = 0; i < 4; i++) {
|
||||||
|
a = "?";
|
||||||
|
switch(i) {
|
||||||
|
case 0:
|
||||||
|
a = "a";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
a = "b";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
a = "" + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s += a;
|
||||||
|
}
|
||||||
|
assert(s === "ab3" && i === 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch1()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
throw "hello";
|
||||||
|
} catch (e) {
|
||||||
|
assert(e, "hello", "catch");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(false, "catch");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch2()
|
||||||
|
{
|
||||||
|
var a;
|
||||||
|
try {
|
||||||
|
a = 1;
|
||||||
|
} catch (e) {
|
||||||
|
a = 2;
|
||||||
|
}
|
||||||
|
assert(a, 1, "catch");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch3()
|
||||||
|
{
|
||||||
|
var s;
|
||||||
|
s = "";
|
||||||
|
try {
|
||||||
|
s += "t";
|
||||||
|
} catch (e) {
|
||||||
|
s += "c";
|
||||||
|
} finally {
|
||||||
|
s += "f";
|
||||||
|
}
|
||||||
|
assert(s, "tf", "catch");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch4()
|
||||||
|
{
|
||||||
|
var s;
|
||||||
|
s = "";
|
||||||
|
try {
|
||||||
|
s += "t";
|
||||||
|
throw "c";
|
||||||
|
} catch (e) {
|
||||||
|
s += e;
|
||||||
|
} finally {
|
||||||
|
s += "f";
|
||||||
|
}
|
||||||
|
assert(s, "tcf", "catch");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch5()
|
||||||
|
{
|
||||||
|
var s;
|
||||||
|
s = "";
|
||||||
|
for(;;) {
|
||||||
|
try {
|
||||||
|
s += "t";
|
||||||
|
break;
|
||||||
|
s += "b";
|
||||||
|
} finally {
|
||||||
|
s += "f";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(s, "tf", "catch");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch6()
|
||||||
|
{
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
s += 't';
|
||||||
|
return 1;
|
||||||
|
} finally {
|
||||||
|
s += "f";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var s = "";
|
||||||
|
assert(f() === 1);
|
||||||
|
assert(s, "tf", "catch6");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch7()
|
||||||
|
{
|
||||||
|
var s;
|
||||||
|
s = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
s += "t";
|
||||||
|
throw "a";
|
||||||
|
} finally {
|
||||||
|
s += "f";
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
s += e;
|
||||||
|
} finally {
|
||||||
|
s += "g";
|
||||||
|
}
|
||||||
|
assert(s, "tfag", "catch");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_try_catch8()
|
||||||
|
{
|
||||||
|
var i, s;
|
||||||
|
|
||||||
|
s = "";
|
||||||
|
for(var i in {x:1, y:2}) {
|
||||||
|
try {
|
||||||
|
s += i;
|
||||||
|
throw "a";
|
||||||
|
} catch (e) {
|
||||||
|
s += e;
|
||||||
|
} finally {
|
||||||
|
s += "f";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(s === "xafyaf");
|
||||||
|
}
|
||||||
|
|
||||||
|
test_while();
|
||||||
|
test_while_break();
|
||||||
|
test_do_while();
|
||||||
|
test_for();
|
||||||
|
test_for_break();
|
||||||
|
test_switch1();
|
||||||
|
test_switch2();
|
||||||
|
test_for_in();
|
||||||
|
test_for_in2();
|
||||||
|
|
||||||
|
test_try_catch1();
|
||||||
|
test_try_catch2();
|
||||||
|
test_try_catch3();
|
||||||
|
test_try_catch4();
|
||||||
|
test_try_catch5();
|
||||||
|
test_try_catch6();
|
||||||
|
test_try_catch7();
|
||||||
|
test_try_catch8();
|
|
@ -0,0 +1,302 @@
|
||||||
|
function assert(actual, expected, message) {
|
||||||
|
if (arguments.length == 1)
|
||||||
|
expected = true;
|
||||||
|
|
||||||
|
if (actual === expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (actual !== null && expected !== null
|
||||||
|
&& typeof actual == 'object' && typeof expected == 'object'
|
||||||
|
&& actual.toString() === expected.toString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw Error("assertion failed: got |" + actual + "|" +
|
||||||
|
", expected |" + expected + "|" +
|
||||||
|
(message ? " (" + message + ")" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load more elaborate version of assert if available
|
||||||
|
try { __loadScript("test_assert.js"); } catch(e) {}
|
||||||
|
|
||||||
|
/*----------------*/
|
||||||
|
|
||||||
|
function test_op1()
|
||||||
|
{
|
||||||
|
var r, a;
|
||||||
|
r = 1 + 2;
|
||||||
|
assert(r, 3, "1 + 2 === 3");
|
||||||
|
|
||||||
|
r = 1 - 2;
|
||||||
|
assert(r, -1, "1 - 2 === -1");
|
||||||
|
|
||||||
|
r = -1;
|
||||||
|
assert(r, -1, "-1 === -1");
|
||||||
|
|
||||||
|
r = +2;
|
||||||
|
assert(r, 2, "+2 === 2");
|
||||||
|
|
||||||
|
r = 2 * 3;
|
||||||
|
assert(r, 6, "2 * 3 === 6");
|
||||||
|
|
||||||
|
r = 4 / 2;
|
||||||
|
assert(r, 2, "4 / 2 === 2");
|
||||||
|
|
||||||
|
r = 4 % 3;
|
||||||
|
assert(r, 1, "4 % 3 === 3");
|
||||||
|
|
||||||
|
r = 4 << 2;
|
||||||
|
assert(r, 16, "4 << 2 === 16");
|
||||||
|
|
||||||
|
r = 1 << 0;
|
||||||
|
assert(r, 1, "1 << 0 === 1");
|
||||||
|
|
||||||
|
r = 1 << 31;
|
||||||
|
assert(r, -2147483648, "1 << 31 === -2147483648");
|
||||||
|
|
||||||
|
r = 1 << 32;
|
||||||
|
assert(r, 1, "1 << 32 === 1");
|
||||||
|
|
||||||
|
r = (1 << 31) < 0;
|
||||||
|
assert(r, true, "(1 << 31) < 0 === true");
|
||||||
|
|
||||||
|
r = -4 >> 1;
|
||||||
|
assert(r, -2, "-4 >> 1 === -2");
|
||||||
|
|
||||||
|
r = -4 >>> 1;
|
||||||
|
assert(r, 0x7ffffffe, "-4 >>> 1 === 0x7ffffffe");
|
||||||
|
|
||||||
|
r = 1 & 1;
|
||||||
|
assert(r, 1, "1 & 1 === 1");
|
||||||
|
|
||||||
|
r = 0 | 1;
|
||||||
|
assert(r, 1, "0 | 1 === 1");
|
||||||
|
|
||||||
|
r = 1 ^ 1;
|
||||||
|
assert(r, 0, "1 ^ 1 === 0");
|
||||||
|
|
||||||
|
r = ~1;
|
||||||
|
assert(r, -2, "~1 === -2");
|
||||||
|
|
||||||
|
r = !1;
|
||||||
|
assert(r, false, "!1 === false");
|
||||||
|
|
||||||
|
assert((1 < 2), true, "(1 < 2) === true");
|
||||||
|
|
||||||
|
assert((2 > 1), true, "(2 > 1) === true");
|
||||||
|
|
||||||
|
assert(('b' > 'a'), true, "('b' > 'a') === true");
|
||||||
|
|
||||||
|
assert(2 ** 8, 256, "2 ** 8 === 256");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_cvt()
|
||||||
|
{
|
||||||
|
assert((NaN | 0) === 0);
|
||||||
|
assert((Infinity | 0) === 0);
|
||||||
|
assert(((-Infinity) | 0) === 0);
|
||||||
|
assert(("12345" | 0) === 12345);
|
||||||
|
assert(("0x12345" | 0) === 0x12345);
|
||||||
|
assert(((4294967296 * 3 - 4) | 0) === -4);
|
||||||
|
|
||||||
|
assert(("12345" >>> 0) === 12345);
|
||||||
|
assert(("0x12345" >>> 0) === 0x12345);
|
||||||
|
assert((NaN >>> 0) === 0);
|
||||||
|
assert((Infinity >>> 0) === 0);
|
||||||
|
assert(((-Infinity) >>> 0) === 0);
|
||||||
|
assert(((4294967296 * 3 - 4) >>> 0) === (4294967296 - 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_eq()
|
||||||
|
{
|
||||||
|
assert(null == undefined);
|
||||||
|
assert(undefined == null);
|
||||||
|
assert(true == 1);
|
||||||
|
assert(0 == false);
|
||||||
|
assert("" == 0);
|
||||||
|
assert("123" == 123);
|
||||||
|
assert("122" != 123);
|
||||||
|
assert((new Number(1)) == 1);
|
||||||
|
assert(2 == (new Number(2)));
|
||||||
|
assert((new String("abc")) == "abc");
|
||||||
|
assert({} != "abc");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_inc_dec()
|
||||||
|
{
|
||||||
|
var a, r;
|
||||||
|
|
||||||
|
a = 1;
|
||||||
|
r = a++;
|
||||||
|
assert(r === 1 && a === 2, true, "++");
|
||||||
|
|
||||||
|
a = 1;
|
||||||
|
r = ++a;
|
||||||
|
assert(r === 2 && a === 2, true, "++");
|
||||||
|
|
||||||
|
a = 1;
|
||||||
|
r = a--;
|
||||||
|
assert(r === 1 && a === 0, true, "--");
|
||||||
|
|
||||||
|
a = 1;
|
||||||
|
r = --a;
|
||||||
|
assert(r === 0 && a === 0, true, "--");
|
||||||
|
|
||||||
|
a = {x:true};
|
||||||
|
a.x++;
|
||||||
|
assert(a.x, 2, "++");
|
||||||
|
|
||||||
|
a = {x:true};
|
||||||
|
a.x--;
|
||||||
|
assert(a.x, 0, "--");
|
||||||
|
|
||||||
|
a = [true];
|
||||||
|
a[0]++;
|
||||||
|
assert(a[0], 2, "++");
|
||||||
|
|
||||||
|
a = {x:true};
|
||||||
|
r = a.x++;
|
||||||
|
assert(r === 1 && a.x === 2, true, "++");
|
||||||
|
|
||||||
|
a = {x:true};
|
||||||
|
r = a.x--;
|
||||||
|
assert(r === 1 && a.x === 0, true, "--");
|
||||||
|
|
||||||
|
a = [true];
|
||||||
|
r = a[0]++;
|
||||||
|
assert(r === 1 && a[0] === 2, true, "++");
|
||||||
|
|
||||||
|
a = [true];
|
||||||
|
r = a[0]--;
|
||||||
|
assert(r === 1 && a[0] === 0, true, "--");
|
||||||
|
}
|
||||||
|
|
||||||
|
function F(x)
|
||||||
|
{
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_op2()
|
||||||
|
{
|
||||||
|
var a, b;
|
||||||
|
a = new Object;
|
||||||
|
a.x = 1;
|
||||||
|
assert(a.x, 1, "new");
|
||||||
|
b = new F(2);
|
||||||
|
assert(b.x, 2, "new");
|
||||||
|
|
||||||
|
a = {x : 2};
|
||||||
|
assert(("x" in a), true, "in");
|
||||||
|
assert(("y" in a), false, "in");
|
||||||
|
|
||||||
|
a = {};
|
||||||
|
assert((a instanceof Object), true, "instanceof");
|
||||||
|
assert((a instanceof String), false, "instanceof");
|
||||||
|
|
||||||
|
assert((typeof 1), "number", "typeof");
|
||||||
|
assert((typeof Object), "function", "typeof");
|
||||||
|
assert((typeof null), "object", "typeof");
|
||||||
|
assert((typeof unknown_var), "undefined", "typeof");
|
||||||
|
|
||||||
|
a = {x: 1, y: 1};
|
||||||
|
assert((delete a.x), true, "delete");
|
||||||
|
assert(("x" in a), false, "delete");
|
||||||
|
|
||||||
|
a = {x: 1, if: 2};
|
||||||
|
assert(a.if === 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_prototype()
|
||||||
|
{
|
||||||
|
function f() { }
|
||||||
|
assert(f.prototype.constructor, f, "prototype");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_arguments()
|
||||||
|
{
|
||||||
|
function f2() {
|
||||||
|
assert(arguments.length, 2, "arguments");
|
||||||
|
assert(arguments[0], 1, "arguments");
|
||||||
|
assert(arguments[1], 3, "arguments");
|
||||||
|
}
|
||||||
|
f2(1, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_class()
|
||||||
|
{
|
||||||
|
var o;
|
||||||
|
class C {
|
||||||
|
constructor() {
|
||||||
|
this.x = 10;
|
||||||
|
}
|
||||||
|
f() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static F() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
get y() {
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class D extends C {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.z = 20;
|
||||||
|
}
|
||||||
|
g() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
static G() {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
h() {
|
||||||
|
return super.f();
|
||||||
|
}
|
||||||
|
static H() {
|
||||||
|
return super["F"]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(C.F() === -1);
|
||||||
|
assert(Object.getOwnPropertyDescriptor(C.prototype, "y").get.name === "get y");
|
||||||
|
|
||||||
|
o = new C();
|
||||||
|
assert(o.f() === 1);
|
||||||
|
assert(o.x === 10);
|
||||||
|
|
||||||
|
assert(D.F() === -1);
|
||||||
|
assert(D.G() === -2);
|
||||||
|
assert(D.H() === -1);
|
||||||
|
|
||||||
|
o = new D();
|
||||||
|
assert(o.f() === 1);
|
||||||
|
assert(o.g() === 2);
|
||||||
|
assert(o.x === 10);
|
||||||
|
assert(o.z === 20);
|
||||||
|
assert(o.h() === 1);
|
||||||
|
|
||||||
|
/* test class name scope */
|
||||||
|
var E1 = class E { static F() { return E; } };
|
||||||
|
assert(E1 === E1.F());
|
||||||
|
};
|
||||||
|
|
||||||
|
function test_template()
|
||||||
|
{
|
||||||
|
var a, b;
|
||||||
|
b = 123;
|
||||||
|
a = `abc${b}d`;
|
||||||
|
assert(a === "abc123d");
|
||||||
|
|
||||||
|
a = String.raw `abc${b}d`;
|
||||||
|
assert(a === "abc123d");
|
||||||
|
}
|
||||||
|
|
||||||
|
test_op1();
|
||||||
|
test_cvt();
|
||||||
|
test_eq();
|
||||||
|
test_inc_dec();
|
||||||
|
test_op2();
|
||||||
|
test_prototype();
|
||||||
|
test_arguments();
|
||||||
|
test_class();
|
||||||
|
test_template();
|
|
@ -0,0 +1,147 @@
|
||||||
|
import * as std from "std";
|
||||||
|
import * as os from "os";
|
||||||
|
|
||||||
|
function assert(actual, expected, message) {
|
||||||
|
if (arguments.length == 1)
|
||||||
|
expected = true;
|
||||||
|
|
||||||
|
if (actual === expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (actual !== null && expected !== null
|
||||||
|
&& typeof actual == 'object' && typeof expected == 'object'
|
||||||
|
&& actual.toString() === expected.toString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw Error("assertion failed: got |" + actual + "|" +
|
||||||
|
", expected |" + expected + "|" +
|
||||||
|
(message ? " (" + message + ")" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load more elaborate version of assert if available
|
||||||
|
try { std.loadScript("test_assert.js"); } catch(e) {}
|
||||||
|
|
||||||
|
/*----------------*/
|
||||||
|
|
||||||
|
function test_printf()
|
||||||
|
{
|
||||||
|
assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_file1()
|
||||||
|
{
|
||||||
|
var f, len, str, size, buf, ret, i, str1;
|
||||||
|
|
||||||
|
f = std.tmpfile();
|
||||||
|
str = "hello world\n";
|
||||||
|
f.puts(str);
|
||||||
|
|
||||||
|
f.seek(0, std.SEEK_SET);
|
||||||
|
str1 = f.readAsString();
|
||||||
|
assert(str1 === str);
|
||||||
|
|
||||||
|
f.seek(0, std.SEEK_END);
|
||||||
|
size = f.tell();
|
||||||
|
assert(size === str.length);
|
||||||
|
|
||||||
|
f.seek(0, std.SEEK_SET);
|
||||||
|
|
||||||
|
buf = new Uint8Array(size);
|
||||||
|
ret = f.read(buf.buffer, 0, size);
|
||||||
|
assert(ret === size);
|
||||||
|
for(i = 0; i < size; i++)
|
||||||
|
assert(buf[i] === str.charCodeAt(i));
|
||||||
|
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_file2()
|
||||||
|
{
|
||||||
|
var f, str, i, size;
|
||||||
|
f = std.tmpfile();
|
||||||
|
str = "hello world\n";
|
||||||
|
size = str.length;
|
||||||
|
for(i = 0; i < size; i++)
|
||||||
|
f.putByte(str.charCodeAt(i));
|
||||||
|
f.seek(0, std.SEEK_SET);
|
||||||
|
for(i = 0; i < size; i++) {
|
||||||
|
assert(str.charCodeAt(i) === f.getByte());
|
||||||
|
}
|
||||||
|
assert(f.getByte() === -1);
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_getline()
|
||||||
|
{
|
||||||
|
var f, line, line_count, lines, i;
|
||||||
|
|
||||||
|
lines = ["hello world", "line 1", "line 2" ];
|
||||||
|
f = std.tmpfile();
|
||||||
|
for(i = 0; i < lines.length; i++) {
|
||||||
|
f.puts(lines[i], "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
f.seek(0, std.SEEK_SET);
|
||||||
|
assert(!f.eof());
|
||||||
|
line_count = 0;
|
||||||
|
for(;;) {
|
||||||
|
line = f.getline();
|
||||||
|
if (line === null)
|
||||||
|
break;
|
||||||
|
assert(line == lines[line_count]);
|
||||||
|
line_count++;
|
||||||
|
}
|
||||||
|
assert(f.eof());
|
||||||
|
assert(line_count === lines.length);
|
||||||
|
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_os()
|
||||||
|
{
|
||||||
|
var fd, fname, buf, buf2, i;
|
||||||
|
|
||||||
|
assert(os.isatty(0));
|
||||||
|
|
||||||
|
fname = "tmp_file.txt";
|
||||||
|
fd = os.open(fname, os.O_RDWR | os.O_CREAT | os.O_TRUNC);
|
||||||
|
assert(fd >= 0);
|
||||||
|
|
||||||
|
buf = new Uint8Array(10);
|
||||||
|
for(i = 0; i < buf.length; i++)
|
||||||
|
buf[i] = i;
|
||||||
|
assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length);
|
||||||
|
|
||||||
|
assert(os.seek(fd, 0, os.SEEK_SET) === 0);
|
||||||
|
buf2 = new Uint8Array(buf.length);
|
||||||
|
assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length);
|
||||||
|
|
||||||
|
for(i = 0; i < buf.length; i++)
|
||||||
|
assert(buf[i] == buf2[i]);
|
||||||
|
|
||||||
|
assert(os.close(fd) === 0);
|
||||||
|
|
||||||
|
assert(os.remove(fname) === 0);
|
||||||
|
|
||||||
|
fd = os.open(fname, os.O_RDONLY);
|
||||||
|
assert(fd < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_timer()
|
||||||
|
{
|
||||||
|
var th, i;
|
||||||
|
|
||||||
|
/* just test that a timer can be inserted and removed */
|
||||||
|
th = [];
|
||||||
|
for(i = 0; i < 3; i++)
|
||||||
|
th[i] = os.setTimeout(1000, function () { });
|
||||||
|
for(i = 0; i < 3; i++)
|
||||||
|
os.clearTimeout(th[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_printf();
|
||||||
|
test_file1();
|
||||||
|
test_file2();
|
||||||
|
test_getline();
|
||||||
|
test_os();
|
||||||
|
test_timer();
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,275 @@
|
||||||
|
#ifdef UNICODE_GENERAL_CATEGORY
|
||||||
|
DEF(Cn, "Unassigned") /* must be zero */
|
||||||
|
DEF(Lu, "Uppercase_Letter")
|
||||||
|
DEF(Ll, "Lowercase_Letter")
|
||||||
|
DEF(Lt, "Titlecase_Letter")
|
||||||
|
DEF(Lm, "Modifier_Letter")
|
||||||
|
DEF(Lo, "Other_Letter")
|
||||||
|
DEF(Mn, "Nonspacing_Mark")
|
||||||
|
DEF(Mc, "Spacing_Mark")
|
||||||
|
DEF(Me, "Enclosing_Mark")
|
||||||
|
DEF(Nd, "Decimal_Number,digit")
|
||||||
|
DEF(Nl, "Letter_Number")
|
||||||
|
DEF(No, "Other_Number")
|
||||||
|
DEF(Sm, "Math_Symbol")
|
||||||
|
DEF(Sc, "Currency_Symbol")
|
||||||
|
DEF(Sk, "Modifier_Symbol")
|
||||||
|
DEF(So, "Other_Symbol")
|
||||||
|
DEF(Pc, "Connector_Punctuation")
|
||||||
|
DEF(Pd, "Dash_Punctuation")
|
||||||
|
DEF(Ps, "Open_Punctuation")
|
||||||
|
DEF(Pe, "Close_Punctuation")
|
||||||
|
DEF(Pi, "Initial_Punctuation")
|
||||||
|
DEF(Pf, "Final_Punctuation")
|
||||||
|
DEF(Po, "Other_Punctuation")
|
||||||
|
DEF(Zs, "Space_Separator")
|
||||||
|
DEF(Zl, "Line_Separator")
|
||||||
|
DEF(Zp, "Paragraph_Separator")
|
||||||
|
DEF(Cc, "Control,cntrl")
|
||||||
|
DEF(Cf, "Format")
|
||||||
|
DEF(Cs, "Surrogate")
|
||||||
|
DEF(Co, "Private_Use")
|
||||||
|
/* synthetic properties */
|
||||||
|
DEF(LC, "Cased_Letter")
|
||||||
|
DEF(L, "Letter")
|
||||||
|
DEF(M, "Mark,Combining_Mark")
|
||||||
|
DEF(N, "Number")
|
||||||
|
DEF(S, "Symbol")
|
||||||
|
DEF(P, "Punctuation,punct")
|
||||||
|
DEF(Z, "Separator")
|
||||||
|
DEF(C, "Other")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE_SCRIPT
|
||||||
|
DEF(Unknown, "Zzzz")
|
||||||
|
DEF(Adlam, "Adlm")
|
||||||
|
DEF(Ahom, "Ahom")
|
||||||
|
DEF(Anatolian_Hieroglyphs, "Hluw")
|
||||||
|
DEF(Arabic, "Arab")
|
||||||
|
DEF(Armenian, "Armn")
|
||||||
|
DEF(Avestan, "Avst")
|
||||||
|
DEF(Balinese, "Bali")
|
||||||
|
DEF(Bamum, "Bamu")
|
||||||
|
DEF(Bassa_Vah, "Bass")
|
||||||
|
DEF(Batak, "Batk")
|
||||||
|
DEF(Bengali, "Beng")
|
||||||
|
DEF(Bhaiksuki, "Bhks")
|
||||||
|
DEF(Bopomofo, "Bopo")
|
||||||
|
DEF(Brahmi, "Brah")
|
||||||
|
DEF(Braille, "Brai")
|
||||||
|
DEF(Buginese, "Bugi")
|
||||||
|
DEF(Buhid, "Buhd")
|
||||||
|
DEF(Canadian_Aboriginal, "Cans")
|
||||||
|
DEF(Carian, "Cari")
|
||||||
|
DEF(Caucasian_Albanian, "Aghb")
|
||||||
|
DEF(Chakma, "Cakm")
|
||||||
|
DEF(Cham, "Cham")
|
||||||
|
DEF(Cherokee, "Cher")
|
||||||
|
DEF(Common, "Zyyy")
|
||||||
|
DEF(Coptic, "Copt,Qaac")
|
||||||
|
DEF(Cuneiform, "Xsux")
|
||||||
|
DEF(Cypriot, "Cprt")
|
||||||
|
DEF(Cyrillic, "Cyrl")
|
||||||
|
DEF(Deseret, "Dsrt")
|
||||||
|
DEF(Devanagari, "Deva")
|
||||||
|
DEF(Dogra, "Dogr")
|
||||||
|
DEF(Duployan, "Dupl")
|
||||||
|
DEF(Egyptian_Hieroglyphs, "Egyp")
|
||||||
|
DEF(Elbasan, "Elba")
|
||||||
|
DEF(Ethiopic, "Ethi")
|
||||||
|
DEF(Georgian, "Geor")
|
||||||
|
DEF(Glagolitic, "Glag")
|
||||||
|
DEF(Gothic, "Goth")
|
||||||
|
DEF(Grantha, "Gran")
|
||||||
|
DEF(Greek, "Grek")
|
||||||
|
DEF(Gujarati, "Gujr")
|
||||||
|
DEF(Gunjala_Gondi, "Gong")
|
||||||
|
DEF(Gurmukhi, "Guru")
|
||||||
|
DEF(Han, "Hani")
|
||||||
|
DEF(Hangul, "Hang")
|
||||||
|
DEF(Hanifi_Rohingya, "Rohg")
|
||||||
|
DEF(Hanunoo, "Hano")
|
||||||
|
DEF(Hatran, "Hatr")
|
||||||
|
DEF(Hebrew, "Hebr")
|
||||||
|
DEF(Hiragana, "Hira")
|
||||||
|
DEF(Imperial_Aramaic, "Armi")
|
||||||
|
DEF(Inherited, "Zinh,Qaai")
|
||||||
|
DEF(Inscriptional_Pahlavi, "Phli")
|
||||||
|
DEF(Inscriptional_Parthian, "Prti")
|
||||||
|
DEF(Javanese, "Java")
|
||||||
|
DEF(Kaithi, "Kthi")
|
||||||
|
DEF(Kannada, "Knda")
|
||||||
|
DEF(Katakana, "Kana")
|
||||||
|
DEF(Kayah_Li, "Kali")
|
||||||
|
DEF(Kharoshthi, "Khar")
|
||||||
|
DEF(Khmer, "Khmr")
|
||||||
|
DEF(Khojki, "Khoj")
|
||||||
|
DEF(Khudawadi, "Sind")
|
||||||
|
DEF(Lao, "Laoo")
|
||||||
|
DEF(Latin, "Latn")
|
||||||
|
DEF(Lepcha, "Lepc")
|
||||||
|
DEF(Limbu, "Limb")
|
||||||
|
DEF(Linear_A, "Lina")
|
||||||
|
DEF(Linear_B, "Linb")
|
||||||
|
DEF(Lisu, "Lisu")
|
||||||
|
DEF(Lycian, "Lyci")
|
||||||
|
DEF(Lydian, "Lydi")
|
||||||
|
DEF(Makasar, "Maka")
|
||||||
|
DEF(Mahajani, "Mahj")
|
||||||
|
DEF(Malayalam, "Mlym")
|
||||||
|
DEF(Mandaic, "Mand")
|
||||||
|
DEF(Manichaean, "Mani")
|
||||||
|
DEF(Marchen, "Marc")
|
||||||
|
DEF(Masaram_Gondi, "Gonm")
|
||||||
|
DEF(Medefaidrin, "Medf")
|
||||||
|
DEF(Meetei_Mayek, "Mtei")
|
||||||
|
DEF(Mende_Kikakui, "Mend")
|
||||||
|
DEF(Meroitic_Cursive, "Merc")
|
||||||
|
DEF(Meroitic_Hieroglyphs, "Mero")
|
||||||
|
DEF(Miao, "Plrd")
|
||||||
|
DEF(Modi, "Modi")
|
||||||
|
DEF(Mongolian, "Mong")
|
||||||
|
DEF(Mro, "Mroo")
|
||||||
|
DEF(Multani, "Mult")
|
||||||
|
DEF(Myanmar, "Mymr")
|
||||||
|
DEF(Nabataean, "Nbat")
|
||||||
|
DEF(New_Tai_Lue, "Talu")
|
||||||
|
DEF(Newa, "Newa")
|
||||||
|
DEF(Nko, "Nkoo")
|
||||||
|
DEF(Nushu, "Nshu")
|
||||||
|
DEF(Ogham, "Ogam")
|
||||||
|
DEF(Ol_Chiki, "Olck")
|
||||||
|
DEF(Old_Hungarian, "Hung")
|
||||||
|
DEF(Old_Italic, "Ital")
|
||||||
|
DEF(Old_North_Arabian, "Narb")
|
||||||
|
DEF(Old_Permic, "Perm")
|
||||||
|
DEF(Old_Persian, "Xpeo")
|
||||||
|
DEF(Old_Sogdian, "Sogo")
|
||||||
|
DEF(Old_South_Arabian, "Sarb")
|
||||||
|
DEF(Old_Turkic, "Orkh")
|
||||||
|
DEF(Oriya, "Orya")
|
||||||
|
DEF(Osage, "Osge")
|
||||||
|
DEF(Osmanya, "Osma")
|
||||||
|
DEF(Pahawh_Hmong, "Hmng")
|
||||||
|
DEF(Palmyrene, "Palm")
|
||||||
|
DEF(Pau_Cin_Hau, "Pauc")
|
||||||
|
DEF(Phags_Pa, "Phag")
|
||||||
|
DEF(Phoenician, "Phnx")
|
||||||
|
DEF(Psalter_Pahlavi, "Phlp")
|
||||||
|
DEF(Rejang, "Rjng")
|
||||||
|
DEF(Runic, "Runr")
|
||||||
|
DEF(Samaritan, "Samr")
|
||||||
|
DEF(Saurashtra, "Saur")
|
||||||
|
DEF(Sharada, "Shrd")
|
||||||
|
DEF(Shavian, "Shaw")
|
||||||
|
DEF(Siddham, "Sidd")
|
||||||
|
DEF(SignWriting, "Sgnw")
|
||||||
|
DEF(Sinhala, "Sinh")
|
||||||
|
DEF(Sogdian, "Sogd")
|
||||||
|
DEF(Sora_Sompeng, "Sora")
|
||||||
|
DEF(Soyombo, "Soyo")
|
||||||
|
DEF(Sundanese, "Sund")
|
||||||
|
DEF(Syloti_Nagri, "Sylo")
|
||||||
|
DEF(Syriac, "Syrc")
|
||||||
|
DEF(Tagalog, "Tglg")
|
||||||
|
DEF(Tagbanwa, "Tagb")
|
||||||
|
DEF(Tai_Le, "Tale")
|
||||||
|
DEF(Tai_Tham, "Lana")
|
||||||
|
DEF(Tai_Viet, "Tavt")
|
||||||
|
DEF(Takri, "Takr")
|
||||||
|
DEF(Tamil, "Taml")
|
||||||
|
DEF(Tangut, "Tang")
|
||||||
|
DEF(Telugu, "Telu")
|
||||||
|
DEF(Thaana, "Thaa")
|
||||||
|
DEF(Thai, "Thai")
|
||||||
|
DEF(Tibetan, "Tibt")
|
||||||
|
DEF(Tifinagh, "Tfng")
|
||||||
|
DEF(Tirhuta, "Tirh")
|
||||||
|
DEF(Ugaritic, "Ugar")
|
||||||
|
DEF(Vai, "Vaii")
|
||||||
|
DEF(Warang_Citi, "Wara")
|
||||||
|
DEF(Yi, "Yiii")
|
||||||
|
DEF(Zanabazar_Square, "Zanb")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE_PROP_LIST
|
||||||
|
/* Prop list not exported to regexp */
|
||||||
|
DEF(Hyphen, "")
|
||||||
|
DEF(Other_Math, "")
|
||||||
|
DEF(Other_Alphabetic, "")
|
||||||
|
DEF(Other_Lowercase, "")
|
||||||
|
DEF(Other_Uppercase, "")
|
||||||
|
DEF(Other_Grapheme_Extend, "")
|
||||||
|
DEF(Other_Default_Ignorable_Code_Point, "")
|
||||||
|
DEF(Other_ID_Start, "")
|
||||||
|
DEF(Other_ID_Continue, "")
|
||||||
|
DEF(Prepended_Concatenation_Mark, "")
|
||||||
|
/* additional computed properties for smaller tables */
|
||||||
|
DEF(ID_Continue1, "")
|
||||||
|
DEF(XID_Start1, "")
|
||||||
|
DEF(XID_Continue1, "")
|
||||||
|
DEF(Changes_When_Titlecased1, "")
|
||||||
|
DEF(Changes_When_Casefolded1, "")
|
||||||
|
DEF(Changes_When_NFKC_Casefolded1, "")
|
||||||
|
|
||||||
|
/* Prop list exported to JS */
|
||||||
|
DEF(ASCII_Hex_Digit, "AHex")
|
||||||
|
DEF(Bidi_Control, "Bidi_C")
|
||||||
|
DEF(Dash, "")
|
||||||
|
DEF(Deprecated, "Dep")
|
||||||
|
DEF(Diacritic, "Dia")
|
||||||
|
DEF(Extender, "Ext")
|
||||||
|
DEF(Hex_Digit, "Hex")
|
||||||
|
DEF(IDS_Binary_Operator, "IDSB")
|
||||||
|
DEF(IDS_Trinary_Operator, "IDST")
|
||||||
|
DEF(Ideographic, "Ideo")
|
||||||
|
DEF(Join_Control, "Join_C")
|
||||||
|
DEF(Logical_Order_Exception, "LOE")
|
||||||
|
DEF(Noncharacter_Code_Point, "NChar")
|
||||||
|
DEF(Pattern_Syntax, "Pat_Syn")
|
||||||
|
DEF(Pattern_White_Space, "Pat_WS")
|
||||||
|
DEF(Quotation_Mark, "QMark")
|
||||||
|
DEF(Radical, "")
|
||||||
|
DEF(Regional_Indicator, "RI")
|
||||||
|
DEF(Sentence_Terminal, "STerm")
|
||||||
|
DEF(Soft_Dotted, "SD")
|
||||||
|
DEF(Terminal_Punctuation, "Term")
|
||||||
|
DEF(Unified_Ideograph, "UIdeo")
|
||||||
|
DEF(Variation_Selector, "VS")
|
||||||
|
DEF(White_Space, "space")
|
||||||
|
DEF(Bidi_Mirrored, "Bidi_M")
|
||||||
|
DEF(Emoji, "")
|
||||||
|
DEF(Emoji_Component, "")
|
||||||
|
DEF(Emoji_Modifier, "")
|
||||||
|
DEF(Emoji_Modifier_Base, "")
|
||||||
|
DEF(Emoji_Presentation, "")
|
||||||
|
DEF(Extended_Pictographic, "")
|
||||||
|
DEF(Default_Ignorable_Code_Point, "DI")
|
||||||
|
DEF(ID_Start, "IDS")
|
||||||
|
DEF(Case_Ignorable, "CI")
|
||||||
|
|
||||||
|
/* other binary properties */
|
||||||
|
DEF(ASCII,"")
|
||||||
|
DEF(Alphabetic, "Alpha")
|
||||||
|
DEF(Any, "")
|
||||||
|
DEF(Assigned,"")
|
||||||
|
DEF(Cased, "")
|
||||||
|
DEF(Changes_When_Casefolded, "CWCF")
|
||||||
|
DEF(Changes_When_Casemapped, "CWCM")
|
||||||
|
DEF(Changes_When_Lowercased, "CWL")
|
||||||
|
DEF(Changes_When_NFKC_Casefolded, "CWKCF")
|
||||||
|
DEF(Changes_When_Titlecased, "CWT")
|
||||||
|
DEF(Changes_When_Uppercased, "CWU")
|
||||||
|
DEF(Grapheme_Base, "Gr_Base")
|
||||||
|
DEF(Grapheme_Extend, "Gr_Ext")
|
||||||
|
DEF(ID_Continue, "IDC")
|
||||||
|
DEF(Lowercase, "Lower")
|
||||||
|
DEF(Math, "")
|
||||||
|
DEF(Uppercase, "Upper")
|
||||||
|
DEF(XID_Continue, "XIDC")
|
||||||
|
DEF(XID_Start, "XIDS")
|
||||||
|
|
||||||
|
/* internal tables with index */
|
||||||
|
DEF(Cased1, "")
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright © 2010-2019 three.js authors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1 @@
|
||||||
|
This is a modified version, which only includes limited 3D Math libraries for Dust3D, please check [three.js](https://threejs.org/) for full version.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue